mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 02:44:55 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
f2ec28907e
4
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
4
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
@ -18,8 +18,8 @@ about: Create a report to help us improve 🤔.
|
||||
<!-- The latest version of Strapi. -->
|
||||
|
||||
**Informations**
|
||||
- **Node.js version**:
|
||||
- **npm version**:
|
||||
- **Node.js version**: <!-- Please ensure you are using the Node LTS version (v10) -->
|
||||
- **NPM version**:
|
||||
- **Strapi version**: <!-- Please make sure you are on the latest version -->
|
||||
- **Database**:
|
||||
- **Operating system**:
|
||||
|
||||
12
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
12
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
@ -7,6 +7,16 @@ about: Suggest an idea for this project 💡!
|
||||
|
||||
<!-- ⚠️ Make sure to browse the opened and closed issues before submitting your issue. -->
|
||||
|
||||
**What is the expected behavior?**
|
||||
<!--
|
||||
Please also submit your idea on the Strapi Product Board:
|
||||
https://portal.productboard.com/strapi/tabs/2-under-consideration/submit-idea
|
||||
|
||||
If your request on the product board is accepted this feature request issue will be closed,
|
||||
but will still accept public discussion.
|
||||
-->
|
||||
|
||||
- [ ] **I have created my request on the Product Board before I submitted this issue**
|
||||
- [ ] **I have looked at all the other requests on the Product Board before I submitted this issue**
|
||||
|
||||
**Please describe your feature request:**
|
||||
|
||||
|
||||
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -3,15 +3,17 @@
|
||||
<!-- Uncomment the correct contribution type. !-->
|
||||
|
||||
My PR is a:
|
||||
<!-- 💥 Breaking change -->
|
||||
<!-- 🐛 Bug fix -->
|
||||
<!-- 💅 Enhancement -->
|
||||
<!-- 🚀 New feature -->
|
||||
- [ ] 💥 Breaking change
|
||||
- [ ] 🐛 Bug fix #issueNumber
|
||||
- [ ] 💅 Enhancement
|
||||
- [ ] 🚀 New feature
|
||||
|
||||
Main update on the:
|
||||
<!-- Admin -->
|
||||
<!-- Documentation -->
|
||||
<!-- Framework -->
|
||||
<!-- Plugin -->
|
||||
- [ ] Admin
|
||||
- [ ] Documentation
|
||||
- [ ] Framework
|
||||
- [ ] Plugin
|
||||
|
||||
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
|
||||
|
||||
<!-- ⚠️ Please link issue(s) you close / fix by using GitHub keywords https://help.github.com/articles/closing-issues-using-keywords/ !-->
|
||||
|
||||
@ -6,13 +6,14 @@ git:
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- "9"
|
||||
- "10"
|
||||
- "11"
|
||||
|
||||
before_install:
|
||||
- export CHROME_BIN=chromium-browser
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- git fetch -a
|
||||
# - sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
|
||||
# - npm cache clean --force
|
||||
# - rm -rf node_modules/
|
||||
|
||||
@ -16,7 +16,7 @@ This project and everyone participating in it is governed by the [Strapi Code of
|
||||
Strapi is open-source under the [MIT license](https://github.com/strapi/strapi/blob/master/LICENSE.md). All the work done is available on GitHub.
|
||||
The core team and the contributors send pull requests which go through the same validation process.
|
||||
|
||||
Every user can send a feature request using the [issues](https://github.com/strapi/strapi/issues/new?template=FEATURE_REQUEST.md) on GitHub. Feel free to upvote 👍 [existing feature request](https://github.com/strapi/strapi/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+feature+request+%F0%9F%99%8F%22)
|
||||
Every user can send a feature request using the [issues](https://github.com/strapi/strapi/issues/new?template=FEATURE_REQUEST.md) on GitHub. Feel free to upvote 👍 [existing feature request](https://portal.productboard.com/strapi)
|
||||
|
||||
## 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.
|
||||
|
||||
11
README.md
11
README.md
@ -44,10 +44,21 @@
|
||||
|
||||
#### 🖐 Requirements
|
||||
|
||||
Operating system:
|
||||
* Ubuntu/Debian
|
||||
* CentOS/RHEL
|
||||
* MacOS
|
||||
* Windows - [WSL Only](https://github.com/strapi/strapi/wiki/Frequently-Asked-Questions#windows)
|
||||
* Docker - [Docker-Repo](https://github.com/strapi/strapi-docker)
|
||||
|
||||
**Please note that Strapi may work on other Operating Systems, but are not tested at this time.**
|
||||
|
||||
Node:
|
||||
* NodeJS >= 10.x
|
||||
* NPM >= 6.x
|
||||
|
||||
**Please note that right now Node 11 is not Officially supported, and the current Node LTS (v10) should be used.**
|
||||
|
||||
Database:
|
||||
* MongoDB >= 3.x
|
||||
* MySQL >= 5.6
|
||||
|
||||
@ -74,7 +74,7 @@ To use the providers authentication, set your credentials in
|
||||
|
||||
Redirect your user to: `GET /connect/:provider`.
|
||||
|
||||
After his approval, he will be redirected to `/auth/:provider/callback`. The jwt and user will be available in the querystring.
|
||||
After their approval, they will be redirected to `/auth/:provider/callback`. The jwt and user will be available in the querystring.
|
||||
|
||||
Response payload:
|
||||
|
||||
|
||||
@ -363,7 +363,7 @@ The session doesn't work with `mongo` as a client. The package that we should us
|
||||
- `port` (integer): Port on which the server should be running. Default value: `1337`.
|
||||
- `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.
|
||||
- `emitErrors` (boolean): Enable errors to be emitted 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Quick start
|
||||
|
||||
This section explains how to handle Strapi for the first time, ([check out our tutorial video](https://www.youtube.com/watch?v=yMl5IcFHA74)).
|
||||
This section explains how to handle Strapi for the first time, ([check out our video tutorial](https://www.youtube.com/watch?v=yMl5IcFHA74)).
|
||||
|
||||
**Table of contents:**
|
||||
- [1. Create your first project](#_1-create-a-project)
|
||||
@ -126,7 +126,7 @@ After creating [your first Content Type](#_3-create-a-content-type), you probabl
|
||||
Your API is now ready and [contains data](#_4-add-content). At this point, you'll probably want to use this data in mobile or desktop applications.
|
||||
In order to do so, you'll need to allow access to other users (identified as 'Public').
|
||||
|
||||
**1 -** Go to the [**Auth & Permissions View**](http://localhost:1337/admin/plugins/users-permissions/roles) by clicking on **Auth & Permissions** link in the left menu.
|
||||
**1 -** Go to the [**Roles & Permissions View**](http://localhost:1337/admin/plugins/users-permissions/roles) by clicking on **Roles & Permissions** link in the left menu.
|
||||
|
||||

|
||||
|
||||
@ -170,7 +170,7 @@ axios
|
||||
|
||||
If you want to get a specific entry, add the `id` of the wanted post at the end of the url.
|
||||
|
||||
Examble with Axios:
|
||||
Example with Axios:
|
||||
|
||||
```js
|
||||
import axios from 'axios';
|
||||
@ -194,7 +194,7 @@ axios
|
||||
|
||||
Use the `POST` route to create a new entry.
|
||||
|
||||
Examble with Axios:
|
||||
Example with Axios:
|
||||
|
||||
```js
|
||||
import axios from 'axios';
|
||||
@ -221,7 +221,7 @@ axios
|
||||
|
||||
Use the `PUT` route to update an existing entry.
|
||||
|
||||
Examble with Axios:
|
||||
Example with Axios:
|
||||
|
||||
```js
|
||||
import axios from 'axios';
|
||||
@ -250,7 +250,7 @@ axios
|
||||
|
||||
Use the `DELETE` route to delete an existing entry.
|
||||
|
||||
Examble with Axios:
|
||||
Example with Axios:
|
||||
|
||||
```js
|
||||
import axios from 'axios';
|
||||
|
||||
@ -26,11 +26,11 @@ By default Strapi provides a local email system. You might want to send email wi
|
||||
To install a new provider run:
|
||||
|
||||
```
|
||||
$ npm install strapi-email-sendgrid@alpha --save
|
||||
$ npm install strapi-provider-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` on your web browser and configure the provider.
|
||||
We have two providers available `strapi-provider-email-sendgrid` and `strapi-provider-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.
|
||||
If you want to create your own, make sure the name starts with `strapi-provider-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-provider-email-)
|
||||
|
||||
@ -37,6 +37,16 @@ Find products having a price equal or greater than `3`.
|
||||
|
||||
`GET /products?price_gte=3`
|
||||
|
||||
#### Relations
|
||||
You can also use filters into a relation attribute which will be applied to the first level of the request.
|
||||
Find users having written a post named `Title`.
|
||||
`GET /users?posts.name=Title`
|
||||
Find posts written by a user having more than 12 years old.
|
||||
`GET /posts?author.age_gt=12`
|
||||
> Note: You can't use filter to have specific results inside relation, like "Find users and only their posts older than yesterday" as example. If you need it, you can modify or create your own service ou use [GraphQL](./graphql.md#query-api).
|
||||
|
||||
> Warning: this filter isn't available for `upload` plugin
|
||||
|
||||
### Sort
|
||||
|
||||
Sort according to a specific field.
|
||||
|
||||
@ -672,15 +672,10 @@ module.exports = {
|
||||
|
||||
In this example, the policy `isAuthenticated` located in `./plugins/users-permissions/config/policies/isAuthenticated.js` will be executed first. Then, the `isOwner` policy located in the `Post` API `./api/post/config/policies/isOwner.js`. Next, it will execute the `logging` policy located in `./config/policies/logging.js`. Finally, the resolver will be executed.
|
||||
|
||||
<<<<<<< HEAD:docs/3.x.x/guides/graphql.md
|
||||
|
||||
::: note
|
||||
There is no custom resolver in that case, so it will execute the default resolver (Post.find) provided by the Shadow CRUD feature.
|
||||
:::
|
||||
=======
|
||||
The same process is applied to the `createPost` mutation.
|
||||
|
||||
> Note: There is no custom resolver in that case, so it will execute the default resolver (Post.find) provided by the Shadow CRUD feature.
|
||||
>>>>>>> 5705158a4368b144541493e08570ce0e93734ed8:docs/3.x.x/en/guides/graphql.md
|
||||
|
||||
### Link a query or mutation to a controller action
|
||||
|
||||
|
||||
@ -296,7 +296,7 @@ A `product` can be related to many `categories`, so a `category` can have many `
|
||||
```
|
||||
|
||||
::: note
|
||||
The `dominant` key allows you to define in which table/collection (only for NoSQL databases) should be stored the array that defines the relationship. Because there is no join table in NoSQL, this key is required for NoSQL databases (ex: MongoDB).
|
||||
(NoSQL databases only) The `dominant` key defines which table/collection should store the array that defines the relationship. Because there are no join tables in NoSQL, this key is required for NoSQL databases (ex: MongoDB).
|
||||
:::
|
||||
|
||||
**Path —** `./api/category/models/Category.settings.json`.
|
||||
|
||||
@ -17,7 +17,7 @@ Please send the request using multipart/form-data encoding
|
||||
**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).
|
||||
- `path`: (optional): The folder where the file(s) will be uploaded to (only supported on strapi-provider-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.
|
||||
@ -136,11 +136,11 @@ By default Strapi provides a local file upload system. You might want to upload
|
||||
To install a new provider run:
|
||||
|
||||
```
|
||||
$ npm install strapi-upload-aws-s3@alpha --save
|
||||
$ npm install strapi-provider-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` on your web browser and configure the provider.
|
||||
We have two providers available `strapi-provider-upload-aws-s3` and `strapi-provider-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.
|
||||
If you want to create your own, make sure the name starts with `strapi-provider-upload-` (duplicating an existing one will be easier to create), modify the `auth` config object and customize the `upload` and `delete` functions.
|
||||
|
||||
Check all community providers available on npmjs.org - [Providers list](https://www.npmjs.com/search?q=strapi-upload-)
|
||||
Check all community providers available on npmjs.org - [Providers list](https://www.npmjs.com/search?q=strapi-provider-upload-)
|
||||
|
||||
12
package.json
12
package.json
@ -1,16 +1,16 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"assert": "~1.3.0",
|
||||
"axios": "^0.18.0",
|
||||
"babel-eslint": "^6.1.2",
|
||||
"chalk": "^2.4.1",
|
||||
"eslint": "^3.12.2",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-plugin-babel": "^4.0.0",
|
||||
"eslint-plugin-react": "^6.8.0",
|
||||
"eslint-plugin-redux-saga": "^0.3.0",
|
||||
"eslint-plugin-react": "^7.7.0",
|
||||
"eslint-plugin-redux-saga": "^0.8.0",
|
||||
"istanbul": "~0.4.2",
|
||||
"jest": "^22.4.3",
|
||||
"jest-cli": "^22.4.4",
|
||||
@ -59,8 +59,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright@React-FullStory (https://github.com/cereallarceny/react-fullstory)
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const canUseDOM = !!(
|
||||
typeof window !== 'undefined' &&
|
||||
window.document &&
|
||||
window.document.createElement
|
||||
);
|
||||
|
||||
export const getWindowFullStory = () => window[window['_fs_namespace']];
|
||||
|
||||
class FullStory extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
window['_fs_debug'] = false;
|
||||
window['_fs_host'] = 'fullstory.com';
|
||||
window['_fs_org'] = props.org;
|
||||
window['_fs_namespace'] = 'FS';
|
||||
(function(m,n,e,t,l,o,g,y) {
|
||||
if (e in m) {
|
||||
if(m.console && m.console.log) {
|
||||
m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
g = m[e]= function(a,b,s) {
|
||||
g.q ? g.q.push([a,b,s]) : g._api(a,b,s);
|
||||
};
|
||||
g.q=[];
|
||||
o = n.createElement(t);
|
||||
o.async = 1;
|
||||
o.src = `https://${window._fs_host}/s/fs.js`;
|
||||
y = n.getElementsByTagName(t)[0];
|
||||
y.parentNode.insertBefore(o,y);
|
||||
g.identify = function(i,v,s) {
|
||||
g(l,{ uid:i },s);
|
||||
|
||||
if (v) {
|
||||
g(l,v,s);
|
||||
}
|
||||
};
|
||||
g.setUserVars = function(v,s) {
|
||||
g(l,v,s);
|
||||
};
|
||||
g.event = function(i,v,s) {
|
||||
g('event',{ n:i,p:v },s);
|
||||
};
|
||||
g.shutdown = function() {
|
||||
g("rec",!1);
|
||||
};
|
||||
g.restart = function() {
|
||||
g("rec",!0);
|
||||
};
|
||||
g.consent = function(a) {
|
||||
g("consent",!arguments.length||a);
|
||||
};
|
||||
g.identifyAccount = function(i,v) {
|
||||
o = 'account';
|
||||
v = v||{};
|
||||
v.acctId = i;
|
||||
g(o,v);
|
||||
};
|
||||
g.clearUserCookie = function() {};
|
||||
})(window, document, window['_fs_namespace'], 'script', 'user');
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (!canUseDOM || !getWindowFullStory()) return false;
|
||||
|
||||
getWindowFullStory().shutdown();
|
||||
|
||||
delete getWindowFullStory();
|
||||
}
|
||||
|
||||
render() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FullStory.propTypes = {
|
||||
org: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default FullStory;
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"languages": ["en", "ar", "es", "fr", "de", "it", "ko", "nl", "pl", "pt", "pt-BR", "ru", "tr", "zh", "zh-Hans", "ja"]
|
||||
"languages": ["en", "ar", "es", "fa", "fr", "de", "it", "ko", "nl", "pl", "pt", "pt-BR", "ru", "tr", "zh", "zh-Hans", "ja"]
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -43,6 +43,7 @@ import Logout from 'components/Logout';
|
||||
import NotFoundPage from 'containers/NotFoundPage/Loadable';
|
||||
import OverlayBlocker from 'components/OverlayBlocker';
|
||||
import PluginPage from 'containers/PluginPage';
|
||||
import FullStory from 'components/FullStory';
|
||||
// Utils
|
||||
import auth from 'utils/auth';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
@ -73,12 +74,12 @@ export class AdminPage extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { adminPage: { allowGa }, location: { pathname }, plugins } = this.props;
|
||||
const { adminPage: { uuid }, location: { pathname }, plugins } = this.props;
|
||||
|
||||
if (prevProps.location.pathname !== pathname) {
|
||||
this.checkLogin(this.props);
|
||||
|
||||
if (allowGa) {
|
||||
if (uuid) {
|
||||
ReactGA.pageview(pathname);
|
||||
}
|
||||
}
|
||||
@ -198,6 +199,7 @@ export class AdminPage extends React.Component {
|
||||
|
||||
return (
|
||||
<div className={styles.adminPage}>
|
||||
{this.props.adminPage.uuid ? <FullStory org="GK708" /> : ''}
|
||||
{this.showLeftMenu() && (
|
||||
<LeftMenu
|
||||
plugins={this.retrievePlugins()}
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
allowGa: true,
|
||||
uuid: false,
|
||||
currentEnvironment: 'development',
|
||||
isLoading: true,
|
||||
layout: Map({}),
|
||||
@ -22,7 +22,7 @@ function adminPageReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case GET_ADMIN_DATA_SUCCEEDED:
|
||||
return state
|
||||
.update('allowGa', () => action.data.allowGa)
|
||||
.update('uuid', () => action.data.uuid)
|
||||
.update('currentEnvironment', () => action.data.currentEnvironment)
|
||||
.update('layout', () => Map(action.data.layout))
|
||||
.update('strapiVersion', () => action.data.strapiVersion)
|
||||
|
||||
@ -16,13 +16,13 @@ function* getData() {
|
||||
yield call(request, `${strapi.backendURL}/users/me`, { method: 'GET' });
|
||||
}
|
||||
|
||||
const [{ allowGa }, { strapiVersion }, { currentEnvironment }, { layout }] = yield all([
|
||||
const [{ uuid }, { strapiVersion }, { currentEnvironment }, { layout }] = yield all([
|
||||
call(request, '/admin/gaConfig', { method: 'GET' }),
|
||||
call(request, '/admin/strapiVersion', { method: 'GET' }),
|
||||
call(request, '/admin/currentEnvironment', { method: 'GET' }),
|
||||
call(request, '/admin/layout', { method: 'GET' }),
|
||||
]);
|
||||
yield put(getAdminDataSucceeded({ allowGa, strapiVersion, currentEnvironment, layout }));
|
||||
yield put(getAdminDataSucceeded({ uuid, strapiVersion, currentEnvironment, layout }));
|
||||
|
||||
} catch(err) {
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
|
||||
@ -14,14 +14,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
|
||||
import AdminPage from 'containers/AdminPage';
|
||||
import NotFoundPage from 'containers/NotFoundPage';
|
||||
|
||||
import NotificationProvider from 'containers/NotificationProvider';
|
||||
|
||||
import AppLoader from 'containers/AppLoader';
|
||||
import LoadingIndicatorPage from 'components/LoadingIndicatorPage';
|
||||
import '../../styles/main.scss';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export class App extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
@ -29,12 +27,22 @@ export class App extends React.Component { // eslint-disable-line react/prefer-s
|
||||
return (
|
||||
<div>
|
||||
<NotificationProvider />
|
||||
<div className={styles.container}>
|
||||
<Switch>
|
||||
<Route path="/" component={AdminPage} />
|
||||
<Route path="" component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
<AppLoader>
|
||||
{({ shouldLoad }) => {
|
||||
if (shouldLoad) {
|
||||
return <LoadingIndicatorPage />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Switch>
|
||||
<Route path="/" component={AdminPage} />
|
||||
<Route path="" component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</AppLoader>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -14,6 +14,11 @@ const selectPlugins = () => createSelector(
|
||||
(appState) => appState.get('plugins')
|
||||
);
|
||||
|
||||
const makeSelectApp = () => createSelector(
|
||||
selectApp(),
|
||||
appState => appState.toJS(),
|
||||
);
|
||||
|
||||
const selectHasUserPlugin = () => createSelector(
|
||||
selectApp(),
|
||||
(appState) => appState.get('hasUserPlugin'),
|
||||
@ -38,7 +43,7 @@ const makeSelectAppPlugins = () => createSelector(
|
||||
selectApp(),
|
||||
appState => appState.get('appPlugins').toJS(),
|
||||
);
|
||||
|
||||
export default makeSelectApp;
|
||||
export {
|
||||
selectApp,
|
||||
selectHasUserPlugin,
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
/**
|
||||
*
|
||||
* AppLoader
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import makeSelectApp from 'containers/App/selectors';
|
||||
|
||||
class AppLoader extends React.Component {
|
||||
shouldLoad = () => {
|
||||
const { appPlugins, plugins: mountedPlugins } = this.props;
|
||||
|
||||
return appPlugins.length !== Object.keys(mountedPlugins).length;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
|
||||
return children({ shouldLoad: this.shouldLoad() });
|
||||
}
|
||||
}
|
||||
|
||||
AppLoader.propTypes = {
|
||||
appPlugins: PropTypes.array.isRequired,
|
||||
children: PropTypes.func.isRequired,
|
||||
plugins: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = makeSelectApp();
|
||||
|
||||
export default connect(mapStateToProps, null)(AppLoader);
|
||||
@ -2,15 +2,14 @@ import 'whatwg-fetch';
|
||||
import { dropRight, take } from 'lodash';
|
||||
import removeMd from 'remove-markdown';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
fork,
|
||||
put,
|
||||
select,
|
||||
takeLatest,
|
||||
} from 'redux-saga/effects';
|
||||
|
||||
import request from 'utils/request';
|
||||
|
||||
import { getArticlesSucceeded, submitSucceeded } from './actions';
|
||||
import { GET_ARTICLES, SUBMIT } from './constants';
|
||||
import { makeSelectBody } from './selectors';
|
||||
@ -51,8 +50,10 @@ function* submit() {
|
||||
}
|
||||
|
||||
function* defaultSaga() {
|
||||
yield fork(takeLatest, SUBMIT, submit);
|
||||
yield fork(takeLatest, GET_ARTICLES, getArticles);
|
||||
yield all([
|
||||
fork(takeLatest, SUBMIT, submit),
|
||||
fork(takeLatest, GET_ARTICLES, getArticles),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
.containerFluid {
|
||||
padding: 18px 30px !important;
|
||||
> div:first-child {
|
||||
max-height: 33px;
|
||||
margin-bottom: 48px;
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { get } from 'lodash';
|
||||
import { fork, call, put, select, takeLatest, take, cancel } from 'redux-saga/effects';
|
||||
import { all, fork, call, put, select, takeLatest, take, cancel } from 'redux-saga/effects';
|
||||
import { pluginDeleted } from 'containers/App/actions';
|
||||
import auth from 'utils/auth';
|
||||
import request from 'utils/request';
|
||||
|
||||
import { selectLocale } from '../LanguageProvider/selectors';
|
||||
import { deletePluginSucceeded, getAppCurrentEnvSucceeded, getPluginsSucceeded } from './actions';
|
||||
import { GET_PLUGINS, ON_DELETE_PLUGIN_CONFIRM } from './constants';
|
||||
@ -36,10 +35,10 @@ export function* deletePlugin() {
|
||||
export function* pluginsGet() {
|
||||
try {
|
||||
// Fetch plugins.
|
||||
const response = yield [
|
||||
const response = yield all([
|
||||
call(request, '/admin/plugins', { method: 'GET' }),
|
||||
call(request, '/admin/currentEnvironment', { method: 'GET' }),
|
||||
];
|
||||
]);
|
||||
const locale = yield select(selectLocale());
|
||||
|
||||
const opts = {
|
||||
|
||||
@ -37,6 +37,8 @@ export class LocaleToggle extends React.Component { // eslint-disable-line
|
||||
return 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/kr.svg';
|
||||
case 'ja':
|
||||
return 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/jp.svg';
|
||||
case 'fa':
|
||||
return 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/ir.svg';
|
||||
default:
|
||||
return `https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/flags/4x3/${locale}.svg`;
|
||||
}
|
||||
|
||||
@ -28,19 +28,19 @@
|
||||
"app.components.EmptyAttributes.title": "Aún no hay campos",
|
||||
"app.components.HomePage.button.blog": "VER MÁS EN EL BLOG",
|
||||
"app.components.HomePage.button.quickStart": "INICIAR EL TUTORIAL DE INICIO RÁPIDO",
|
||||
"app.components.HomePage.community": "Encuentra la comunidad en la web",
|
||||
"app.components.HomePage.community.content": "Discutir con los miembros del equipo, colaboradores y desarrolladores en diferentes canales.",
|
||||
"app.components.HomePage.community": "Encuentre la comunidad en la web",
|
||||
"app.components.HomePage.community.content": "Hable con los miembros del equipo, colaboradores y desarrolladores en diferentes canales.",
|
||||
"app.components.HomePage.create": "Crea tu primer Tipo de Contenido",
|
||||
"app.components.HomePage.createBlock.content.first": "El ",
|
||||
"app.components.HomePage.createBlock.content.second": " le ayudará a definir la estructura de datos de sus modelos. Si eres nuevo aquí, te recomendamos encarecidamente que sigas nuestro ",
|
||||
"app.components.HomePage.createBlock.content.second": " le ayudará a definir la estructura de datos de sus modelos. Si es nuevo aquí, le recomendamos encarecidamente que siga nuestro ",
|
||||
"app.components.HomePage.createBlock.content.tutorial": " ",
|
||||
"app.components.HomePage.cta": "CONFIRMAR",
|
||||
"app.components.HomePage.newsLetter": "Suscríbase al boletín de noticias para ponerse en contacto con Strapi",
|
||||
"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.HomePage.support.link": "CONSIGA SU CAMISETA AHORA",
|
||||
"app.components.HomePage.welcome": "¡Bienvenido a bordo!",
|
||||
"app.components.HomePage.welcome.again": "Bienvenido ",
|
||||
"app.components.HomePage.welcome.again": "¡Bienvenido ",
|
||||
"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 ",
|
||||
"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.",
|
||||
|
||||
141
packages/strapi-admin/admin/src/translations/fa.json
Normal file
141
packages/strapi-admin/admin/src/translations/fa.json
Normal file
@ -0,0 +1,141 @@
|
||||
{
|
||||
"Analytics": "آنالیز",
|
||||
"Content Manager": "مدیریت محتوا",
|
||||
"Content Type Builder": "سازنده ی الگوی محتوایی",
|
||||
"Email": "ایمیل",
|
||||
"Files Upload": "آپلود فایل",
|
||||
"HomePage.notification.newsLetter.success": "موفقیت در اشتراک خبر نامه",
|
||||
"New entry": "رکورد جدید",
|
||||
"Password": "رمز عبور",
|
||||
"Provider": "سرویس دهنده",
|
||||
"ResetPasswordToken": "بازنشانی رمز عبور",
|
||||
"Role": "نقش",
|
||||
"Roles & Permissions": "نقش ها و دسترسی ها",
|
||||
"Settings Manager": "مدیریت تنظیمات",
|
||||
"Username": "نام کاربری",
|
||||
"Users": "کاربران",
|
||||
"Users & Permissions": "کاربران و دسترسی ها",
|
||||
"app.components.BlockLink.code": "نمونه کد",
|
||||
"app.components.BlockLink.code.content": "با بررسی و آزمایش پروژه های واقعی توسط جامعه توسعه دهنده Strapi را یاد بگیرید.",
|
||||
"app.components.BlockLink.documentation": "خواندن مستندات",
|
||||
"app.components.BlockLink.documentation.content": "مفاهیم، راهنمای مرجع و آموزش ها را فرا بگیرید.",
|
||||
"app.components.Button.cancel": "کنسل",
|
||||
"app.components.Button.save": "ذخیره",
|
||||
"app.components.ComingSoonPage.comingSoon": "بزودی",
|
||||
"app.components.ComingSoonPage.featuresNotAvailable": "این ویژگی هنوز در حال توسعه است.",
|
||||
"app.components.DownloadInfo.download": "در حال دانلود...",
|
||||
"app.components.DownloadInfo.text": "ممکن است دقایقی طول بکشد، با تشکر از شکیبایی شما.",
|
||||
"app.components.EmptyAttributes.title": "هیچ فیلدی وجود ندارد",
|
||||
"app.components.HomePage.button.blog": "مشاهده بیشتر در بلاگ",
|
||||
"app.components.HomePage.button.quickStart": "شروع آموزش سریع",
|
||||
"app.components.HomePage.community": "جستجوی جامعه توسعه دهنده در اینترنت",
|
||||
"app.components.HomePage.community.content": "گفتگو با اعضای تیم و توسعه دهندگان در کانال های مختلف ارتباطی",
|
||||
"app.components.HomePage.create": "ساخت اولین الگوی محتوا",
|
||||
"app.components.HomePage.createBlock.content.first": "این ",
|
||||
"app.components.HomePage.createBlock.content.second": " افزونه به شما کمک میکند مدل ساختاری داده های خود را تعریف کنید،اگر شما جدیدا به اینجا مراجعه کردید، پس حتما مارا دنبال کنید ",
|
||||
"app.components.HomePage.createBlock.content.tutorial": " آموزش.",
|
||||
"app.components.HomePage.cta": "تایید",
|
||||
"app.components.HomePage.newsLetter": "برای آگاهی از آخرین اخبار Strapi مشترک خبرنامه شوید.",
|
||||
"app.components.HomePage.support": "مارا حمایت کنید",
|
||||
"app.components.HomePage.support.content": "با خرید تی شرت ما میتوانیم به توسعه Strapi ادامه داده و بهترین تجربه را برای شما فراهم کنیم!",
|
||||
"app.components.HomePage.support.link": "هم اکنون تی شرت خود را دریافت کنید",
|
||||
"app.components.HomePage.welcome": "خوش آمدید!",
|
||||
"app.components.HomePage.welcome.again": "خوش آمدید ",
|
||||
"app.components.HomePage.welcomeBlock.content": "خرسندیم که شما را به عنوان عضوی از جامعه توسعه دهنده بشناسیم، ما هر لحظه به دنبال دریافت بازخورد شما هستیم، در ارسال بازخورد تردید نکنید ",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "امیدواریم در پروژه خود پیشرفت کنید... میتوانید در مورد آخرین های Strapi مطالعه کنید. بر اساس بازخورد شما ما موثر ترین اقدامات را برای بهبود محصول انجام خواهیم داد.",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "مشکلات.",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": " یا ارتقاء دهید ",
|
||||
"app.components.ImgPreview.hint": "برای آپلود، فایل خود را بکشید و در این نقطه رها کنید یا {browse}",
|
||||
"app.components.ImgPreview.hint.browse": "مرور کردن",
|
||||
"app.components.InputFile.newFile": "افزودن فایل جدید",
|
||||
"app.components.InputFileDetails.open": "باز کردن در تب جدید",
|
||||
"app.components.InputFileDetails.originalName": "نام اصلی:",
|
||||
"app.components.InputFileDetails.remove": "حذف این فایل",
|
||||
"app.components.InputFileDetails.size": "حجم:",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "جستجوی افزونه... (برای مثال: authentication)",
|
||||
"app.components.InstallPluginPage.description": "به راحتی برنامه خود را توسعه دهید.",
|
||||
"app.components.InstallPluginPage.helmet": "فروشگاه - افزونه ها",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "با خرید تی شرت ما میتوانیم به توسعه Strapi ادامه داده و بهترین تجربه را برای شما فراهم کنیم!",
|
||||
"app.components.InstallPluginPage.title": "فروشگاه - افزونه ها",
|
||||
"app.components.InstallPluginPopup.downloads": "دانلود",
|
||||
"app.components.InstallPluginPopup.navLink.avis": "مشاهده",
|
||||
"app.components.InstallPluginPopup.navLink.changelog": "تغییرات",
|
||||
"app.components.InstallPluginPopup.navLink.description": "توضیحات",
|
||||
"app.components.InstallPluginPopup.navLink.faq": "پرسش و پاسخ",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "تصاویر",
|
||||
"app.components.InstallPluginPopup.noDescription": "توضیحاتی وجود ندارد",
|
||||
"app.components.LeftMenuFooter.poweredBy": "قدرت گرفته از ",
|
||||
"app.components.LeftMenuLinkContainer.configuration": "پیکربندی",
|
||||
"app.components.LeftMenuLinkContainer.general": "عمومی",
|
||||
"app.components.LeftMenuLinkContainer.installNewPlugin": "فروشگاه",
|
||||
"app.components.LeftMenuLinkContainer.listPlugins": "افزونه ها",
|
||||
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "هیچ افزونه ای نصب نشده است",
|
||||
"app.components.LeftMenuLinkContainer.plugins": "افزونه ها",
|
||||
"app.components.ListPluginsPage.description": "فهرست افزونه های نصب شده در پروژه.",
|
||||
"app.components.ListPluginsPage.helmet.title": "فهرست افزونه ها",
|
||||
"app.components.ListPluginsPage.title": "افزونه ها",
|
||||
"app.components.NotFoundPage.back": "بازگشت به صفحه اصلی",
|
||||
"app.components.NotFoundPage.description": "یافت نشد",
|
||||
"app.components.Official": "رسمی",
|
||||
"app.components.PluginCard.Button.label.download": "دانلود",
|
||||
"app.components.PluginCard.Button.label.install": "قبلا نصب شده است",
|
||||
"app.components.PluginCard.Button.label.support": "حمایت از ما",
|
||||
"app.components.PluginCard.compatible": "سازگار با برنامه ی شما",
|
||||
"app.components.PluginCard.compatibleCommunity": "سازگار با جامعه ی توسعه دهنده",
|
||||
"app.components.PluginCard.more-details": "اطلاعات بیشتر",
|
||||
"app.components.PluginCard.price.free": "ریگان",
|
||||
"app.components.listPlugins.button": "افزودن افزونه جدید",
|
||||
"app.components.listPlugins.title.none": "هیچ افزونه ای نصب نشده است",
|
||||
"app.components.listPlugins.title.plural": "{number} افزونه نصب شده",
|
||||
"app.components.listPlugins.title.singular": "{number} افزونه نصب شده",
|
||||
"app.components.listPluginsPage.deletePlugin.error": "خطا در هنگام حذف این افزونه",
|
||||
"app.utils.SelectOption.defaultMessage": " ",
|
||||
"app.utils.defaultMessage": " ",
|
||||
"app.utils.placeholder.defaultMessage": " ",
|
||||
"components.AutoReloadBlocker.description": "فایل را باز کرده و این ویژگی را فعال کنید.",
|
||||
"components.AutoReloadBlocker.header": "بارگذاری مجدد برای این افزونه ضروری است.",
|
||||
"components.ErrorBoundary.title": "خطایی رخ داده است...",
|
||||
"components.Input.error.attribute.key.taken": "این مقدار در حال حاضر وجود دارد",
|
||||
"components.Input.error.attribute.sameKeyAndName": "نمیتواند برابر باشد",
|
||||
"components.Input.error.attribute.taken": "نام فیلد در حال حاضر وجود دارد",
|
||||
"components.Input.error.contentTypeName.taken": "این نام هم اکنون وجود دارد",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
"components.Input.error.validation.email": "این مقدار پست الکترونیک صحیح نیست",
|
||||
"components.Input.error.validation.json": "این مقدار با فرمت استاندارد JSON مطابقت ندارد",
|
||||
"components.Input.error.validation.max": "این مقدار زیاد است.",
|
||||
"components.Input.error.validation.maxLength": "این مقدار طولانی است.",
|
||||
"components.Input.error.validation.min": "این مقدار کوچک است.",
|
||||
"components.Input.error.validation.minLength": "طول این مقدار کم است.",
|
||||
"components.Input.error.validation.minSupMax": "نمی تواند بالاتر باشد",
|
||||
"components.Input.error.validation.regex": "این مقدار با عبارت منظم مطابقت ندارد.",
|
||||
"components.Input.error.validation.required": "این مقدار ضروری است.",
|
||||
"components.ListRow.empty": "داده ای جهت نمایش وجود ندارد.",
|
||||
"components.OverlayBlocker.description": "اقدام مورد نظر نیازمند راه اندازی مجدد سرور است. لطفا منتظر بمانید.",
|
||||
"components.OverlayBlocker.title": "در انتظار راه اندازی مجدد...",
|
||||
"components.PageFooter.select": "تعداد سطر در هر صفحه",
|
||||
"components.ProductionBlocker.description": "به جهت موارد امنیتی ما باید این افزونه را در محیط های دیگر غیرفعال کنیم.",
|
||||
"components.ProductionBlocker.header": "این افزونه فقط در حالت توسعه در دسترس است.",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "تبدیل به حالت markdown",
|
||||
"components.Wysiwyg.ToggleMode.preview": "تبدیل به حالت نمایشی",
|
||||
"components.Wysiwyg.collapse": "کوچک کردن",
|
||||
"components.Wysiwyg.selectOptions.H1": "عنوان H1",
|
||||
"components.Wysiwyg.selectOptions.H2": "عنوان H2",
|
||||
"components.Wysiwyg.selectOptions.H3": "عنوان H3",
|
||||
"components.Wysiwyg.selectOptions.H4": "عنوان H4",
|
||||
"components.Wysiwyg.selectOptions.H5": "عنوان H5",
|
||||
"components.Wysiwyg.selectOptions.H6": "عنوان H6",
|
||||
"components.Wysiwyg.selectOptions.title": "افزدون عنوان",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "حروف",
|
||||
"components.WysiwygBottomControls.fullscreen": "تمام صفحه",
|
||||
"components.WysiwygBottomControls.uploadFiles": "کشیدن و رها کردن فایل، خواندن از حافظه یا {browse}.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "انتخاب کنید",
|
||||
"components.popUpWarning.button.cancel": "کنسل",
|
||||
"components.popUpWarning.button.confirm": "تایید",
|
||||
"components.popUpWarning.message": "آیا از حذف این مقدار اطمینان دارید؟",
|
||||
"components.popUpWarning.title": "لطفا تایید کنید",
|
||||
"notification.error": "خطایی رخ داده است",
|
||||
"notification.error.layout": "خطا در بازیابی طرح",
|
||||
"request.error.model.unknown": "این مدل وجود ندارد",
|
||||
"app.utils.delete": "حذف"
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
"Auth & Permissions": "Auth & Permissions",
|
||||
"Content Manager": "Content Manager",
|
||||
"Content Type Builder": "Content Type Builder",
|
||||
"Email": "Email",
|
||||
"Email": "E-mail",
|
||||
"Files Upload": "Téléversement de fichiers",
|
||||
"HomePage.notification.newsLetter.success": "Vous avez souscrit à la newsletter",
|
||||
"New entry": "Nouvelle entrée",
|
||||
@ -20,8 +20,8 @@
|
||||
"app.components.BlockLink.code.content": "Apprenez en testant les projets développés par la communauté.",
|
||||
"app.components.BlockLink.documentation": "Voir la documentation",
|
||||
"app.components.BlockLink.documentation.content": "Découvrez les concepts, guides et tutoriaux.",
|
||||
"app.components.Button.cancel": "Cancel",
|
||||
"app.components.Button.save": "Save",
|
||||
"app.components.Button.cancel": "Annuler",
|
||||
"app.components.Button.save": "Sauvegarder",
|
||||
"app.components.ComingSoonPage.comingSoon": "Bientôt disponible",
|
||||
"app.components.ComingSoonPage.featuresNotAvailable": "Cette fonctionnalité est toujours en cours de développement.",
|
||||
"app.components.DownloadInfo.download": "Téléchargement en cours...",
|
||||
@ -39,32 +39,32 @@
|
||||
"app.components.HomePage.newsLetter": "Inscrivez-vous à la newsletter pour être contacté à propos de Strapi",
|
||||
"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.welcome": "Bienvenue à bord!",
|
||||
"app.components.HomePage.support.link": "OBTENEZ VOTRE T-SHIRT !",
|
||||
"app.components.HomePage.welcome": "Bienvenue à bord !",
|
||||
"app.components.HomePage.welcome.again": "Bienvenue ",
|
||||
"app.components.HomePage.welcomeBlock.content": "Nous sommes heureux de vous compter parmi nos membres. Nous sommes à l'écoute de vos retours alors, n'hésitez pas à nous envoyer des DM sur ",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "Nous espérons que votre projet avance bien... Découvrez les derniers articles à propos de Strapi. Nous faisons de notre mieux pour améliorer le produit selon vos retours.",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "issues",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": " ou soumetez des ",
|
||||
"app.components.ImgPreview.hint": "Drag & drop dans cette zone ou {browse} un fichier à télécharger",
|
||||
"app.components.ImgPreview.hint": "Glissez-déposez dans cette zone ou {browse} un fichier à télécharger",
|
||||
"app.components.ImgPreview.hint.browse": "recherchez",
|
||||
"app.components.InputFile.newFile": "Ajouter un nouveau fichier",
|
||||
"app.components.InputFile.newFile": "Ajouter un nouveau fichier",
|
||||
"app.components.InputFileDetails.open": "Ouvrir dans une nouvelle fenêtre",
|
||||
"app.components.InputFileDetails.originalName": "Nom d'origine:",
|
||||
"app.components.InputFileDetails.originalName": "Nom d'origine :",
|
||||
"app.components.InputFileDetails.remove": "Supprimer ce fichier",
|
||||
"app.components.InputFileDetails.size": "Taille:",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "Recherchez un plugin... (ex: authentification)",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "Recherchez un plugin... (ex : authentification)",
|
||||
"app.components.InstallPluginPage.description": "Améliorez votre app sans efforts",
|
||||
"app.components.InstallPluginPage.helmet": "Marketplace - Plugins",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "Soutenez-nous en achetant un Strapi tee shirt. Cela nous aidera a continuer de travailler sur le projet pour vous donner la meilleure expérience possible!",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "Soutenez-nous en achetant un t-shirt Strapi. Cela nous aidera a continuer de travailler sur le projet pour vous donner la meilleure expérience possible!",
|
||||
"app.components.InstallPluginPage.title": "Marketplace - Plugins",
|
||||
"app.components.InstallPluginPopup.downloads": "téléchargements",
|
||||
"app.components.InstallPluginPopup.navLink.avis": "avis",
|
||||
"app.components.InstallPluginPopup.navLink.changelog": "changelog",
|
||||
"app.components.InstallPluginPopup.navLink.description": "Description",
|
||||
"app.components.InstallPluginPopup.navLink.faq": "faq",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "Screenshots",
|
||||
"app.components.InstallPluginPopup.navLink.faq": "FAQ",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "Captures d'écran",
|
||||
"app.components.InstallPluginPopup.noDescription": "Aucune description disponible",
|
||||
"app.components.LeftMenuFooter.poweredBy": "Propulsé par ",
|
||||
"app.components.LeftMenuLinkContainer.configuration": "Configurations",
|
||||
@ -82,8 +82,8 @@
|
||||
"app.components.PluginCard.Button.label.download": "Télécharger",
|
||||
"app.components.PluginCard.Button.label.install": "Déjà installé",
|
||||
"app.components.PluginCard.Button.label.support": "Nous soutenir",
|
||||
"app.components.PluginCard.compatible": "Compatble avec votre app",
|
||||
"app.components.PluginCard.compatibleCommunity": "Compatble avec la communauté",
|
||||
"app.components.PluginCard.compatible": "Compatible avec votre app",
|
||||
"app.components.PluginCard.compatibleCommunity": "Compatible avec la communauté",
|
||||
"app.components.PluginCard.more-details": "Plus de détails",
|
||||
"app.components.PluginCard.price.free": "Gratuit",
|
||||
"app.components.listPlugins.button": "Ajouter un Nouveau Plugin",
|
||||
@ -102,13 +102,13 @@
|
||||
"components.Input.error.attribute.taken": "Ce champ existe déjà",
|
||||
"components.Input.error.contentTypeName.taken": "Ce nom existe déjà",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
"components.Input.error.validation.email": "Le format n'est pas de type email",
|
||||
"components.Input.error.validation.email": "Le format n'est pas de type e-mail",
|
||||
"components.Input.error.validation.json": "Le format JSON n'est pas respecté",
|
||||
"components.Input.error.validation.max": "La valeur est trop grande.",
|
||||
"components.Input.error.validation.maxLength": "La valeur est trop longue.",
|
||||
"components.Input.error.validation.min": "La valeur est trop basse.",
|
||||
"components.Input.error.validation.minLength": "La valeur est trop courte.",
|
||||
"components.Input.error.validation.minSupMax": "Ne peut pas être plus grand",
|
||||
"components.Input.error.validation.minSupMax": "Ne peut pas être plus grand.",
|
||||
"components.Input.error.validation.regex": "La valeur ne correspond pas au format attendu.",
|
||||
"components.Input.error.validation.required": "Ce champ est obligatoire.",
|
||||
"components.ListRow.empty": "Il n'y a pas de données à afficher.",
|
||||
@ -118,7 +118,7 @@
|
||||
"components.ProductionBlocker.description": "Pour des raisons de sécurité il est désactivé dans les autres environnements.",
|
||||
"components.ProductionBlocker.header": "Ce plugin est disponible uniquement en développement.",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "Retour au markdown",
|
||||
"components.Wysiwyg.ToggleMode.preview": "Voir la preview",
|
||||
"components.Wysiwyg.ToggleMode.preview": "Voir une prévisualisation",
|
||||
"components.Wysiwyg.collapse": "Fermer",
|
||||
"components.Wysiwyg.selectOptions.H1": "Titre H1",
|
||||
"components.Wysiwyg.selectOptions.H2": "Titre H2",
|
||||
@ -127,16 +127,16 @@
|
||||
"components.Wysiwyg.selectOptions.H5": "Titre H5",
|
||||
"components.Wysiwyg.selectOptions.H6": "Titre H6",
|
||||
"components.Wysiwyg.selectOptions.title": "Ajouter un titre",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "charactères",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "caractères",
|
||||
"components.WysiwygBottomControls.fullscreen": "Plein écran",
|
||||
"components.WysiwygBottomControls.uploadFiles": "Ajouter des fichiers en les 'droppant', {browse}, ou en les collant depuis le presse-papier",
|
||||
"components.WysiwygBottomControls.uploadFiles": "Ajouter des fichiers en les 'glissant-déposant', {browse}, ou en les collant depuis le presse-papier",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "en les selectionnant",
|
||||
"components.popUpWarning.button.cancel": "Annuler",
|
||||
"components.popUpWarning.button.confirm": "Confirmer",
|
||||
"components.popUpWarning.message": "Etes-vous sure de vouloir le supprimer?",
|
||||
"components.popUpWarning.message": "Etes-vous sure de vouloir le supprimer ?",
|
||||
"components.popUpWarning.title": "Merci de confirmer",
|
||||
"notification.error": "Une erreur est survenue",
|
||||
"notification.error.layout": "Impossible de récupérer le layout de l'admin",
|
||||
"request.error.model.unknown": "Le model n'existe pas",
|
||||
"app.utils.delete": "Supprimer"
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,8 +28,7 @@ module.exports = {
|
||||
|
||||
getGaConfig: async ctx => {
|
||||
try {
|
||||
const allowGa = _.get(strapi.config, 'info.customs.allowGa', true);
|
||||
ctx.send({ allowGa });
|
||||
ctx.send({ uuid: _.get(strapi.config, 'uuid', false) });
|
||||
} catch(err) {
|
||||
ctx.badRequest(null, [{ messages: [{ id: 'An error occurred' }] }]);
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ If you don't want to share your data with us, you can simply modify the `strapi`
|
||||
```json
|
||||
{
|
||||
"strapi": {
|
||||
"allowGa": false
|
||||
"uuid": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-admin",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Strapi Admin",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -31,8 +31,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"sanitize.css": "^4.1.0",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.14.4.0",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.15",
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi",
|
||||
@ -47,8 +47,8 @@
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -1,13 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
@ -18,7 +12,6 @@ const fs = require('fs-extra');
|
||||
* @param {Object} scope
|
||||
* @param {Function} cb
|
||||
*/
|
||||
|
||||
module.exports = function (scope, cb) {
|
||||
if (scope.developerMode) {
|
||||
fs.mkdirsSync(path.resolve(scope.rootPath));
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-admin",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate the default admin panel for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -15,8 +15,8 @@
|
||||
"dependencies": {
|
||||
"fs-extra": "^4.0.1",
|
||||
"lodash": "^4.17.5",
|
||||
"strapi-admin": "3.0.0-alpha.14.4.0",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-admin": "3.0.0-alpha.15",
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
@ -38,8 +38,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-api",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate an API for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
/* global <%= globalID %> */
|
||||
|
||||
/**
|
||||
* <%= filename %> service
|
||||
@ -9,9 +10,6 @@
|
||||
// Public dependencies.
|
||||
const _ = require('lodash');
|
||||
|
||||
// Strapi utilities.
|
||||
const utils = require('strapi-hook-bookshelf/lib/utils/');
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
@ -21,6 +19,8 @@ module.exports = {
|
||||
*/
|
||||
|
||||
fetchAll: (params) => {
|
||||
// Get model hook
|
||||
const hook = strapi.hook[<%= globalID %>.orm];
|
||||
// Convert `params` object to filters compatible with Bookshelf.
|
||||
const filters = strapi.utils.models.convertParams('<%= globalID.toLowerCase() %>', params);
|
||||
// Select field to populate.
|
||||
@ -29,22 +29,18 @@ module.exports = {
|
||||
.map(ast => ast.alias);
|
||||
|
||||
return <%= globalID %>.query(function(qb) {
|
||||
_.forEach(filters.where, (where, key) => {
|
||||
if (_.isArray(where.value) && where.symbol !== 'IN') {
|
||||
for (const value in where.value) {
|
||||
qb[value ? 'where' : 'orWhere'](key, where.symbol, where.value[value])
|
||||
}
|
||||
// Generate match stage.
|
||||
hook.load().generateMatchStage(qb)(<%= globalID %>, filters);
|
||||
|
||||
if (_.has(filters, 'start')) qb.offset(filters.start);
|
||||
if (_.has(filters, 'limit')) qb.limit(filters.limit);
|
||||
if (!_.isEmpty(filters.sort)) {
|
||||
if (filters.sort.key) {
|
||||
qb.orderBy(filters.sort.key, filters.sort.order);
|
||||
} else {
|
||||
qb.where(key, where.symbol, where.value);
|
||||
qb.orderBy(filters.sort);
|
||||
}
|
||||
});
|
||||
|
||||
if (filters.sort) {
|
||||
qb.orderBy(filters.sort.key, filters.sort.order);
|
||||
}
|
||||
|
||||
qb.offset(filters.start);
|
||||
qb.limit(filters.limit);
|
||||
}).fetchAll({
|
||||
withRelated: populate
|
||||
});
|
||||
@ -81,7 +77,7 @@ module.exports = {
|
||||
_.forEach(filters.where, (where, key) => {
|
||||
if (_.isArray(where.value)) {
|
||||
for (const value in where.value) {
|
||||
qb[value ? 'where' : 'orWhere'](key, where.symbol, where.value[value])
|
||||
qb[value ? 'where' : 'orWhere'](key, where.symbol, where.value[value]);
|
||||
}
|
||||
} else {
|
||||
qb.where(key, where.symbol, where.value);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
/* global <%= globalID %> */
|
||||
|
||||
/**
|
||||
* <%= filename %> service
|
||||
@ -9,6 +10,8 @@
|
||||
// Public dependencies.
|
||||
const _ = require('lodash');
|
||||
|
||||
const { models: { mergeStages } } = require('strapi-utils');
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
@ -17,22 +20,24 @@ module.exports = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
fetchAll: (params) => {
|
||||
fetchAll: (params, next, { populate } = {}) => {
|
||||
// Convert `params` object to filters compatible with Mongo.
|
||||
const filters = strapi.utils.models.convertParams('<%= globalID.toLowerCase() %>', params);
|
||||
// Select field to populate.
|
||||
const populate = <%= globalID %>.associations
|
||||
.filter(ast => ast.autoPopulate !== false)
|
||||
.map(ast => ast.alias)
|
||||
.join(' ');
|
||||
const hook = strapi.hook[<%= globalID %>.orm];
|
||||
// Generate stages.
|
||||
const populateStage = hook.load().generateLookupStage(<%= globalID %>, { whitelistedPopulate: populate }); // Nested-Population
|
||||
const matchStage = hook.load().generateMatchStage(<%= globalID %>, filters); // Nested relation filter
|
||||
const aggregateStages = mergeStages(populateStage, matchStage);
|
||||
|
||||
return <%= globalID %>
|
||||
.find()
|
||||
.where(filters.where)
|
||||
.sort(filters.sort)
|
||||
const result = <%= globalID %>.aggregate(aggregateStages)
|
||||
.skip(filters.start)
|
||||
.limit(filters.limit)
|
||||
.populate(populate);
|
||||
.limit(filters.limit);
|
||||
|
||||
if (_.has(filters, 'start')) result.skip(filters.start);
|
||||
if (_.has(filters, 'limit')) result.limit(filters.limit);
|
||||
if (!_.isEmpty(filters.sort)) result.sort(filters.sort);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-controller",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate a controller for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-model",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate a model for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,15 @@ module.exports = {
|
||||
// After saving a value.
|
||||
// Fired after an `insert` or `update` query.
|
||||
// afterSave: async (model, response, options) => {},
|
||||
|
||||
// Before fetching all values.
|
||||
// Fired before a `fetchAll` operation.
|
||||
// beforeFetchCollection: async (model, columns, options) => {},
|
||||
|
||||
// After fetching all values.
|
||||
// Fired after a `fetchAll` operation.
|
||||
// afterFetchCollection: async (model, columns, options) => {},
|
||||
|
||||
// Before fetching a value.
|
||||
// Fired before a `fetch` operation.
|
||||
// beforeFetch: async (model, columns, options) => {},
|
||||
|
||||
3
packages/strapi-generate-new/files/config/.init.json
Normal file
3
packages/strapi-generate-new/files/config/.init.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"init": true
|
||||
}
|
||||
@ -11,6 +11,6 @@
|
||||
"enabled": false
|
||||
},
|
||||
"admin": {
|
||||
"autoOpen": true
|
||||
"autoOpen": false
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,14 +48,15 @@ module.exports = scope => {
|
||||
},
|
||||
'devDependencies': {
|
||||
'babel-eslint': '^7.1.1',
|
||||
'eslint': '^3.12.2',
|
||||
'eslint': '^4.19.1',
|
||||
'eslint-config-airbnb': '^13.0.0',
|
||||
'eslint-plugin-import': '^2.2.0',
|
||||
'eslint-plugin-react': '^6.8.0'
|
||||
'eslint-plugin-import': '^2.11.0',
|
||||
'eslint-plugin-react': '^7.7.0'
|
||||
},
|
||||
'dependencies': Object.assign({}, {
|
||||
'lodash': '^4.17.5',
|
||||
'strapi': getDependencyVersion(cliPkg, 'strapi'),
|
||||
'strapi-utils': getDependencyVersion(cliPkg, 'strapi'),
|
||||
[scope.client.connector]: getDependencyVersion(cliPkg, 'strapi'),
|
||||
}, additionalsDependencies, {
|
||||
[scope.client.module]: scope.client.version
|
||||
@ -75,8 +76,8 @@ module.exports = scope => {
|
||||
'uuid': uuid()
|
||||
},
|
||||
'engines': {
|
||||
'node': '>= 9.0.0',
|
||||
'npm': '>= 5.0.0'
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
'license': scope.license || 'MIT'
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-new",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -19,7 +19,7 @@
|
||||
"listr": "^0.14.1",
|
||||
"lodash": "^4.17.5",
|
||||
"ora": "^2.1.0",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0",
|
||||
"strapi-utils": "3.0.0-alpha.15",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
@ -45,8 +45,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,8 +55,8 @@ module.exports = scope => {
|
||||
'url': scope.website || ''
|
||||
}],
|
||||
'engines': {
|
||||
'node': '>= 9.0.0',
|
||||
'npm': '>= 5.3.0'
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
'license': scope.license || 'MIT'
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-plugin",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate an plugin for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -40,8 +40,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-policy",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate a policy for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-service",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Generate a service for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Master of ceremonies for the Strapi generators.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -17,7 +17,7 @@
|
||||
"fs-extra": "^4.0.0",
|
||||
"lodash": "^4.17.5",
|
||||
"reportback": "^2.0.1",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,9 +3,8 @@ const shell = require('shelljs');
|
||||
|
||||
const pwd = shell.pwd();
|
||||
const isDevelopmentMode = path.resolve(pwd.stdout).indexOf('strapi-admin') !== -1;
|
||||
const isSetup = process.env.IS_MONOREPO || false;
|
||||
const appPath = isDevelopmentMode ? path.resolve(process.env.PWD, '..') : path.resolve(pwd.stdout, '..');
|
||||
// const isSetup = path.resolve(process.env.PWD, '..', '..') === path.resolve(process.env.INIT_CWD);
|
||||
const isSetup = process.env.IS_MONOREPO;
|
||||
|
||||
// Load the app configurations only when :
|
||||
// - starting the app in dev mode
|
||||
|
||||
@ -14,15 +14,8 @@ const isAdmin = process.env.IS_ADMIN === 'true';
|
||||
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
const appPath = (() => {
|
||||
if (process.env.APP_PATH) {
|
||||
return process.env.APP_PATH;
|
||||
}
|
||||
|
||||
return isAdmin ? path.resolve(process.env.PWD, '..') : path.resolve(process.env.PWD, '..', '..');
|
||||
})();
|
||||
// const isSetup = path.resolve(process.env.PWD, '..', '..') === path.resolve(process.env.INIT_CWD);
|
||||
const isSetup = process.env.IS_MONOREPO;
|
||||
const isSetup = process.env.IS_MONOREPO || false;
|
||||
const appPath = process.env.APP_PATH || path.resolve(process.env.PWD, '..', ( isAdmin ? '' : '..' ));
|
||||
|
||||
const adminPath = (() => {
|
||||
if (isAdmin && isSetup) {
|
||||
|
||||
@ -16,19 +16,11 @@ const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
|
||||
|
||||
const isAdmin = process.env.IS_ADMIN === 'true';
|
||||
const isSetup = path.resolve(process.env.PWD, '..', '..') === path.resolve(process.env.INIT_CWD);
|
||||
const appPath = (() => {
|
||||
if (process.env.APP_PATH) {
|
||||
return process.env.APP_PATH;
|
||||
}
|
||||
|
||||
return isAdmin ? path.resolve(process.env.PWD, '..') : path.resolve(process.env.PWD, '..', '..');
|
||||
})();
|
||||
const appPath = process.env.APP_PATH || path.resolve(process.env.PWD, '..', ( isAdmin ? '' : '..' ));
|
||||
|
||||
const rootAdminpath = (() => {
|
||||
if (isSetup) {
|
||||
return isAdmin
|
||||
? path.resolve(appPath, 'strapi-admin')
|
||||
: path.resolve(appPath, 'packages', 'strapi-admin');
|
||||
return isAdmin ? path.resolve(appPath, 'strapi-admin') : path.resolve(appPath, 'packages', 'strapi-admin');
|
||||
}
|
||||
return path.resolve(appPath, 'admin');
|
||||
})();
|
||||
|
||||
@ -9,8 +9,7 @@ const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const isAdmin = process.env.IS_ADMIN === 'true';
|
||||
|
||||
// const isSetup = path.resolve(process.env.PWD, '..', '..') === path.resolve(process.env.INIT_CWD);
|
||||
const isSetup = process.env.IS_MONOREPO;
|
||||
const isSetup = process.env.IS_MONOREPO || false;
|
||||
const appPath = process.env.APP_PATH || path.resolve(process.env.PWD, '..', ( isAdmin ? '' : '..' ));
|
||||
|
||||
const rootAdminpath = (() => {
|
||||
|
||||
@ -15,14 +15,8 @@ const base = require('./webpack.base.babel');
|
||||
|
||||
const isAdmin = process.env.IS_ADMIN === 'true';
|
||||
// const isSetup = path.resolve(process.env.PWD, '..', '..') === path.resolve(process.env.INIT_CWD);
|
||||
const isSetup = process.env.IS_MONOREPO;
|
||||
const appPath = (() => {
|
||||
if (process.env.APP_PATH) {
|
||||
return process.env.APP_PATH;
|
||||
}
|
||||
|
||||
return isAdmin ? path.resolve(process.env.PWD, '..') : path.resolve(process.env.PWD, '..', '..');
|
||||
})();
|
||||
const isSetup = process.env.IS_MONOREPO || false;
|
||||
const appPath = process.env.APP_PATH || path.resolve(process.env.PWD, '..', ( isAdmin ? '' : '..' ));
|
||||
const adminPath = (() => {
|
||||
if (isSetup) {
|
||||
return isAdmin ? path.resolve(appPath, 'strapi-admin') : path.resolve(process.env.PWD, '..');
|
||||
@ -33,9 +27,7 @@ const adminPath = (() => {
|
||||
|
||||
const rootAdminpath = (() => {
|
||||
if (isSetup) {
|
||||
return isAdmin
|
||||
? path.resolve(appPath, 'strapi-admin')
|
||||
: path.resolve(appPath, 'packages', 'strapi-admin');
|
||||
return isAdmin ? path.resolve(appPath, 'strapi-admin') : path.resolve(appPath, 'packages', 'strapi-admin');
|
||||
}
|
||||
return path.resolve(appPath, 'admin');
|
||||
})();
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "strapi-helper-plugin",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Helper for Strapi plugins development",
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
@ -28,22 +28,22 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"add-asset-html-webpack-plugin": "^2.1.2",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-istanbul": "^4.1.5",
|
||||
"babel-plugin-styled-components": "^1.5.1",
|
||||
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
|
||||
"babel-plugin-transform-es2015-parameters": "^6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-react-constant-elements": "^6.23.0",
|
||||
"babel-plugin-transform-react-inline-elements": "^6.22.0",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.18",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-preset-react-hmre": "^1.1.1",
|
||||
"babel-preset-stage-0": "^6.24.1",
|
||||
"babel-cli": "6.26.0",
|
||||
"babel-core": "6.26.0",
|
||||
"babel-loader": "7.1.1",
|
||||
"babel-plugin-istanbul": "4.1.5",
|
||||
"babel-plugin-styled-components": "1.5.1",
|
||||
"babel-plugin-transform-es2015-destructuring": "6.23.0",
|
||||
"babel-plugin-transform-es2015-parameters": "6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "6.26.0",
|
||||
"babel-plugin-transform-react-constant-elements": "6.23.0",
|
||||
"babel-plugin-transform-react-inline-elements": "6.22.0",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.18",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"babel-preset-env": "1.6.1",
|
||||
"babel-preset-react": "6.24.1",
|
||||
"babel-preset-react-hmre": "1.1.1",
|
||||
"babel-preset-stage-0": "6.24.1",
|
||||
"bootstrap": "^4.0.0-alpha.6",
|
||||
"chalk": "^2.1.0",
|
||||
"classnames": "^2.2.5",
|
||||
|
||||
@ -502,7 +502,7 @@ module.exports = function(strapi) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
strapi.log.warn(`The SQL database indexes haven't been generated successfully. Please enable the debug mode for more details.`);
|
||||
strapi.log.warn('The SQL database indexes haven\'t been generated successfully. Please enable the debug mode for more details.');
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -677,24 +677,11 @@ module.exports = function(strapi) {
|
||||
}
|
||||
};
|
||||
|
||||
const table = _.get(manyRelations, 'collectionName') ||
|
||||
_.map(
|
||||
_.sortBy(
|
||||
[
|
||||
collection.attributes[
|
||||
manyRelations.via
|
||||
],
|
||||
manyRelations
|
||||
],
|
||||
'collection'
|
||||
),
|
||||
table => {
|
||||
return _.snakeCase(
|
||||
// eslint-disable-next-line prefer-template
|
||||
pluralize.plural(table.collection) + ' ' + pluralize.plural(table.via)
|
||||
);
|
||||
}
|
||||
).join('__');
|
||||
const table = _.get(manyRelations, 'collectionName')
|
||||
|| utilsModels.getCollectionName(
|
||||
collection.attributes[manyRelations.via],
|
||||
manyRelations
|
||||
);
|
||||
|
||||
await handler(table, attributes);
|
||||
}
|
||||
@ -813,24 +800,11 @@ module.exports = function(strapi) {
|
||||
strapi.plugins[details.plugin].models[details.collection]:
|
||||
strapi.models[details.collection];
|
||||
|
||||
const collectionName = _.get(details, 'collectionName') ||
|
||||
_.map(
|
||||
_.sortBy(
|
||||
[
|
||||
collection.attributes[
|
||||
details.via
|
||||
],
|
||||
details
|
||||
],
|
||||
'collection'
|
||||
),
|
||||
table => {
|
||||
return _.snakeCase(
|
||||
// eslint-disable-next-line prefer-template
|
||||
pluralize.plural(table.collection) + ' ' + pluralize.plural(table.via)
|
||||
);
|
||||
}
|
||||
).join('__');
|
||||
const collectionName = _.get(details, 'collectionName')
|
||||
|| utilsModels.getCollectionName(
|
||||
collection.attributes[details.via],
|
||||
details,
|
||||
);
|
||||
|
||||
const relationship = _.clone(
|
||||
collection.attributes[details.via]
|
||||
|
||||
@ -35,6 +35,89 @@ module.exports = {
|
||||
return _.get(strapi.plugins, [plugin, 'models', model]) || _.get(strapi, ['models', model]) || undefined;
|
||||
},
|
||||
|
||||
generateMatchStage: function (qb) {
|
||||
return (strapiModel, filters) => {
|
||||
if (!filters) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// 1st level deep filter
|
||||
if (filters.where) {
|
||||
this.generateMatchStage(qb)(strapiModel, { relations: filters.where });
|
||||
}
|
||||
|
||||
// 2nd+ level deep filter
|
||||
_.forEach(filters.relations, (value, key) => {
|
||||
if (key !== 'relations') {
|
||||
const association = strapiModel.associations.find(a => a.alias === key);
|
||||
if (!association) {
|
||||
const fieldKey = `${strapiModel.collectionName}.${key}`;
|
||||
if (_.isArray(value.value) && value.symbol !== 'IN') {
|
||||
for (let value in value.value) {
|
||||
if (typeof value === 'string') {
|
||||
value = {
|
||||
value,
|
||||
symbol: '='
|
||||
};
|
||||
}
|
||||
qb[value ? 'where' : 'orWhere'](fieldKey, value.symbol, value.value[value]);
|
||||
}
|
||||
} else {
|
||||
if (typeof value === 'string') {
|
||||
value = {
|
||||
value,
|
||||
symbol: '='
|
||||
};
|
||||
}
|
||||
qb.where(fieldKey, value.symbol, value.value);
|
||||
}
|
||||
} else {
|
||||
const model = association.plugin ?
|
||||
strapi.plugins[association.plugin].models[association.model || association.collection] :
|
||||
strapi.models[association.model || association.collection];
|
||||
const relationTable = model.collectionName;
|
||||
|
||||
qb.distinct();
|
||||
|
||||
if (association.nature === 'manyToMany') {
|
||||
// Join on both ends
|
||||
qb.innerJoin(
|
||||
association.tableCollectionName,
|
||||
`${association.tableCollectionName}.${strapiModel.info.name}_${strapiModel.primaryKey}`,
|
||||
`${strapiModel.collectionName}.${strapiModel.primaryKey}`,
|
||||
);
|
||||
|
||||
qb.innerJoin(
|
||||
relationTable,
|
||||
`${association.tableCollectionName}.${strapiModel.attributes[key].attribute}_${strapiModel.attributes[key].column}`,
|
||||
`${relationTable}.${model.primaryKey}`,
|
||||
);
|
||||
} else {
|
||||
const externalKey = association.type === 'collection'
|
||||
? `${relationTable}.${association.via}`
|
||||
: `${relationTable}.${model.primaryKey}`;
|
||||
|
||||
const internalKey = association.type === 'collection'
|
||||
? `${strapiModel.collectionName}.${strapiModel.primaryKey}`
|
||||
: `${strapiModel.collectionName}.${association.alias}`;
|
||||
|
||||
qb.innerJoin(relationTable, externalKey, internalKey);
|
||||
}
|
||||
|
||||
if (_.isPlainObject(value)) {
|
||||
this.generateMatchStage(qb)(
|
||||
model,
|
||||
{ relations: value.value }
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.generateMatchStage(qb)(strapiModel, { relations: value });
|
||||
}
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
findOne: async function (params, populate) {
|
||||
const record = await this
|
||||
.forge({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-bookshelf",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Bookshelf hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -21,8 +21,8 @@
|
||||
"lodash": "^4.17.5",
|
||||
"pluralize": "^6.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"strapi-hook-knex": "3.0.0-alpha.14.4.0",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-hook-knex": "3.0.0-alpha.15",
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"strapi": {
|
||||
"dependencies": [
|
||||
@ -52,8 +52,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-ejs",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "EJS hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-knex",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Knex hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@ const { models: utilsModels } = require('strapi-utils');
|
||||
|
||||
// Local helpers.
|
||||
const utils = require('./utils/');
|
||||
const _utils = utils();
|
||||
|
||||
const relations = require('./relations');
|
||||
|
||||
/**
|
||||
@ -488,16 +490,16 @@ module.exports = function (strapi) {
|
||||
result.value = value;
|
||||
break;
|
||||
case '_sort':
|
||||
result.key = `sort`;
|
||||
result.key = 'sort';
|
||||
result.value = (_.toLower(value) === 'desc') ? '-' : '';
|
||||
result.value += key;
|
||||
break;
|
||||
case '_start':
|
||||
result.key = `start`;
|
||||
result.key = 'start';
|
||||
result.value = parseFloat(value);
|
||||
break;
|
||||
case '_limit':
|
||||
result.key = `limit`;
|
||||
result.key = 'limit';
|
||||
result.value = parseFloat(value);
|
||||
break;
|
||||
case '_contains':
|
||||
@ -520,6 +522,13 @@ module.exports = function (strapi) {
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
postProcessValue: (value) => {
|
||||
if (_.isArray(value)) {
|
||||
return value.map(_utils.valueToId);
|
||||
}
|
||||
return _utils.valueToId(value);
|
||||
}
|
||||
}, relations);
|
||||
|
||||
|
||||
@ -10,11 +10,156 @@ const _ = require('lodash');
|
||||
// Utils
|
||||
const { models: { getValuePrimaryKey } } = require('strapi-utils');
|
||||
|
||||
|
||||
const buildTempFieldPath = field => {
|
||||
return `__${field}`;
|
||||
};
|
||||
|
||||
const restoreRealFieldPath = (field, prefix) => {
|
||||
return `${prefix}${field}`;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getModel: function (model, plugin) {
|
||||
return _.get(strapi.plugins, [plugin, 'models', model]) || _.get(strapi, ['models', model]) || undefined;
|
||||
},
|
||||
|
||||
generateLookupStage: function (strapiModel, { whitelistedPopulate = null, prefixPath = '' } = {}) {
|
||||
return strapiModel.associations
|
||||
.filter(ast => {
|
||||
if (whitelistedPopulate) {
|
||||
return _.includes(whitelistedPopulate, ast.alias);
|
||||
}
|
||||
return ast.autoPopulate;
|
||||
})
|
||||
.reduce((acc, ast) => {
|
||||
const model = ast.plugin
|
||||
? strapi.plugins[ast.plugin].models[ast.collection || ast.model]
|
||||
: strapi.models[ast.collection || ast.model];
|
||||
|
||||
const from = model.collectionName;
|
||||
const isDominantAssociation =
|
||||
(ast.dominant && ast.nature === 'manyToMany') || !!ast.model;
|
||||
|
||||
const _localField =
|
||||
!isDominantAssociation || ast.via === 'related' ? '_id' : ast.alias;
|
||||
|
||||
const localField = `${prefixPath}${_localField}`;
|
||||
|
||||
const foreignField = ast.filter
|
||||
? `${ast.via}.ref`
|
||||
: isDominantAssociation
|
||||
? '_id'
|
||||
: ast.via;
|
||||
|
||||
// Add the juncture like the `.populate()` function
|
||||
const asTempPath = buildTempFieldPath(ast.alias, prefixPath);
|
||||
const asRealPath = restoreRealFieldPath(ast.alias, prefixPath);
|
||||
acc.push({
|
||||
$lookup: {
|
||||
from,
|
||||
localField,
|
||||
foreignField,
|
||||
as: asTempPath,
|
||||
},
|
||||
});
|
||||
|
||||
// Unwind the relation's result if only one is expected
|
||||
if (ast.type === 'model') {
|
||||
acc.push({
|
||||
$unwind: {
|
||||
path: `$${asTempPath}`,
|
||||
preserveNullAndEmptyArrays: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Preserve relation field if it is empty
|
||||
acc.push({
|
||||
$addFields: {
|
||||
[asRealPath]: {
|
||||
$ifNull: [`$${asTempPath}`, null],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Remove temp field
|
||||
acc.push({
|
||||
$project: {
|
||||
[asTempPath]: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
},
|
||||
|
||||
generateMatchStage: function (strapiModel, filters, { prefixPath = '' } = {}) {
|
||||
if (!filters) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let acc = [];
|
||||
|
||||
// 1st level deep filter
|
||||
if (filters.where) {
|
||||
acc.push(
|
||||
...this.generateMatchStage(
|
||||
strapiModel,
|
||||
{ relations: filters.where },
|
||||
{ prefixPath }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// 2nd+ level deep filter
|
||||
_.forEach(filters.relations, (value, key) => {
|
||||
if (key !== 'relations') {
|
||||
const nextPrefixedPath = `${prefixPath}${key}.`;
|
||||
const association = strapiModel.associations.find(a => a.alias === key);
|
||||
|
||||
if (!association) {
|
||||
acc.push({
|
||||
$match: { [`${prefixPath}${key}`]: value },
|
||||
});
|
||||
} else {
|
||||
const model = association.plugin
|
||||
? strapi.plugins[association.plugin].models[
|
||||
association.collection || association.model
|
||||
]
|
||||
: strapi.models[association.collection || association.model];
|
||||
|
||||
// Generate lookup for this relation
|
||||
acc.push(
|
||||
...this.generateLookupStage(strapiModel, {
|
||||
whitelistedPopulate: [key],
|
||||
prefixPath,
|
||||
})
|
||||
);
|
||||
|
||||
// If it's an object re-run the same function with this new value until having either a primitive value or an array.
|
||||
if (_.isPlainObject(value)) {
|
||||
acc.push(
|
||||
...this.generateMatchStage(
|
||||
model,
|
||||
{ relations: value },
|
||||
{
|
||||
prefixPath: nextPrefixedPath,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
acc.push(
|
||||
...this.generateMatchStage(strapiModel, { relations: value }, { prefixPath })
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
||||
update: async function (params) {
|
||||
const virtualFields = [];
|
||||
const response = await this
|
||||
@ -97,13 +242,13 @@ module.exports = {
|
||||
acc[current] = params.values[current];
|
||||
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
|
||||
// Records to add in the relation.
|
||||
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
|
||||
a[this.primaryKey].toString() === b[this.primaryKey].toString()
|
||||
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
|
||||
(a[this.primaryKey] || a).toString() === (b[this.primaryKey] || b).toString()
|
||||
);
|
||||
|
||||
// Records to remove in the relation.
|
||||
const toRemove = _.differenceWith(response[current], params.values[current], (a, b) =>
|
||||
a[this.primaryKey].toString() === b[this.primaryKey].toString()
|
||||
(a[this.primaryKey] || a).toString() === (b[this.primaryKey] || b).toString()
|
||||
)
|
||||
.filter(x => toAdd.find(y => x.id === y.id) === undefined);
|
||||
|
||||
@ -124,22 +269,11 @@ module.exports = {
|
||||
}
|
||||
|
||||
virtualFields.push(
|
||||
model.findOne({
|
||||
[model.primaryKey]: getValuePrimaryKey(value, model.primaryKey)
|
||||
module.exports.addRelation.call(model, {
|
||||
id: getValuePrimaryKey(value, this.primaryKey),
|
||||
values: _.pick(value, [this.primaryKey, details.via]),
|
||||
foreignKey: current
|
||||
})
|
||||
.populate([details.via])
|
||||
.lean()
|
||||
.then(entry => {
|
||||
if (_.isArray(entry[details.via])) {
|
||||
value[details.via] = entry[details.via].map(entry => _.get(entry, '_id', entry)).concat(value[details.via]);
|
||||
}
|
||||
|
||||
return module.exports.addRelation.call(model, {
|
||||
id: getValuePrimaryKey(value, this.primaryKey),
|
||||
values: _.pick(value, [this.primaryKey, details.via]),
|
||||
foreignKey: current
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -4,9 +4,23 @@
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
module.exports = mongoose => {
|
||||
var Decimal = require('mongoose-float').loadType(mongoose, 2);
|
||||
var Float = require('mongoose-float').loadType(mongoose, 20);
|
||||
// Public node modules.
|
||||
const mongoose = require('mongoose');
|
||||
const Mongoose = mongoose.Mongoose;
|
||||
|
||||
/**
|
||||
* Convert MongoDB ID to the stringify version as GraphQL throws an error if not.
|
||||
*
|
||||
* Refer to: https://github.com/graphql/graphql-js/commit/3521e1429eec7eabeee4da65c93306b51308727b#diff-87c5e74dd1f7d923143e0eee611f598eR183
|
||||
*/
|
||||
mongoose.Types.ObjectId.prototype.valueOf = function () {
|
||||
return this.toString();
|
||||
};
|
||||
|
||||
module.exports = (mongoose = new Mongoose()) => {
|
||||
|
||||
const Decimal = require('mongoose-float').loadType(mongoose, 2);
|
||||
const Float = require('mongoose-float').loadType(mongoose, 20);
|
||||
|
||||
return {
|
||||
convertType: mongooseType => {
|
||||
@ -42,5 +56,16 @@ module.exports = mongoose => {
|
||||
default:
|
||||
}
|
||||
},
|
||||
valueToId: function (value) {
|
||||
return this.isMongoId(value)
|
||||
? mongoose.Types.ObjectId(value)
|
||||
: value;
|
||||
},
|
||||
isMongoId: function (value) {
|
||||
// Here we don't use mongoose.Types.ObjectId.isValid method because it's a weird check,
|
||||
// it returns for instance true for any integer value ¯\_(ツ)_/¯
|
||||
const hexadecimal = /^[0-9A-F]+$/i;
|
||||
return hexadecimal.test(value) && value.length === 24;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-mongoose",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Mongoose hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -20,7 +20,7 @@
|
||||
"mongoose-float": "^1.0.2",
|
||||
"pluralize": "^6.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
@ -42,8 +42,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-redis",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Redis hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -19,7 +19,7 @@
|
||||
"lodash": "^4.17.5",
|
||||
"rimraf": "^2.6.2",
|
||||
"stack-trace": "0.0.10",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
@ -41,8 +41,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +1,13 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"prettier",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"extends": ["airbnb", "prettier", "eslint:recommended"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"es6": true
|
||||
},
|
||||
"plugins": [
|
||||
"redux-saga",
|
||||
"react",
|
||||
"jsx-a11y"
|
||||
],
|
||||
"plugins": ["redux-saga", "react", "jsx-a11y"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 7,
|
||||
"sourceType": "module",
|
||||
@ -25,10 +17,7 @@
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"comma-dangle": [
|
||||
2,
|
||||
"always-multiline"
|
||||
],
|
||||
"comma-dangle": [2, "always-multiline"],
|
||||
"import/newline-after-import": 0,
|
||||
"import/no-dynamic-require": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
@ -38,14 +27,7 @@
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"groups": [
|
||||
"builtin",
|
||||
"external",
|
||||
"internal",
|
||||
"parent",
|
||||
"sibling",
|
||||
"index"
|
||||
]
|
||||
"groups": ["builtin", "external", "internal", "parent", "sibling", "index"]
|
||||
}
|
||||
],
|
||||
"import/imports-first": 2,
|
||||
@ -53,7 +35,8 @@
|
||||
2,
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1
|
||||
"SwitchCase": 1,
|
||||
"ignoredNodes": ["ConditionalExpression"]
|
||||
}
|
||||
],
|
||||
"jsx-a11y/aria-props": 2,
|
||||
@ -76,10 +59,7 @@
|
||||
"class-methods-use-this": 0,
|
||||
"react/forbid-prop-types": 0,
|
||||
"react/react-in-jsx-scope": 0,
|
||||
"react/jsx-first-prop-new-line": [
|
||||
2,
|
||||
"multiline"
|
||||
],
|
||||
"react/jsx-first-prop-new-line": [2, "multiline"],
|
||||
"react/jsx-filename-extension": 0,
|
||||
"react/jsx-no-target-blank": 0,
|
||||
"react/no-did-mount-set-state": 0,
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
|
||||
module.exports = {
|
||||
printWidth: 110,
|
||||
parser: 'flow',
|
||||
useTabs: false,
|
||||
singleQuote: true,
|
||||
bracketSpacing: true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-lint",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Strapi eslint and prettier configurations",
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
@ -14,8 +14,8 @@
|
||||
"url": "http://strapi.io"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
@ -41,4 +41,4 @@
|
||||
"babel-eslint": "^8.2.3",
|
||||
"prettier": "^1.12.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-middleware-views",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Views middleware to enable server-side rendering for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -39,8 +39,8 @@
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import { cloneDeep, isArray, isNull, isUndefined, get, findIndex, isEmpty } from 'lodash';
|
||||
import { cloneDeep, includes, isArray, isNull, isUndefined, get, findIndex, isEmpty } from 'lodash';
|
||||
|
||||
// Utils.
|
||||
import request from 'utils/request';
|
||||
@ -103,6 +103,15 @@ class SelectMany extends React.PureComponent {
|
||||
});
|
||||
};
|
||||
|
||||
handleInputChange = (value) => {
|
||||
const clonedOptions = this.state.options;
|
||||
const filteredValues = clonedOptions.filter(data => includes(data.label, value));
|
||||
|
||||
if (filteredValues.length === 0) {
|
||||
return this.getOptions(value);
|
||||
}
|
||||
}
|
||||
|
||||
handleChange = value => {
|
||||
// Remove new added value from available option;
|
||||
this.state.options = this.state.options.filter(el =>
|
||||
@ -169,6 +178,7 @@ class SelectMany extends React.PureComponent {
|
||||
id={this.props.relation.alias}
|
||||
isLoading={this.state.isLoading}
|
||||
onChange={this.handleChange}
|
||||
onInputChange={this.handleInputChange}
|
||||
onMenuScrollToBottom={this.handleBottomScroll}
|
||||
options={this.state.options}
|
||||
placeholder={<FormattedMessage id='content-manager.containers.Edit.addAnItem' />}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { isEmpty, isNull, isObject, toString } from 'lodash';
|
||||
import { isEmpty, isNull, isObject, toLower, toString } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
|
||||
import CustomInputCheckbox from 'components/CustomInputCheckbox';
|
||||
@ -31,17 +31,17 @@ class TableRow extends React.Component {
|
||||
* @returns {*}
|
||||
*/
|
||||
getDisplayedValue(type, value, name) {
|
||||
switch (type.toLowerCase()) {
|
||||
switch (toLower(type)) {
|
||||
case 'string':
|
||||
case 'text':
|
||||
case 'email':
|
||||
case 'enumeration':
|
||||
return (value && !isEmpty(value.toString())) || name === 'id' ? value.toString() : '-';
|
||||
return (value && !isEmpty(toString(value))) || name === 'id' ? toString(value) : '-';
|
||||
case 'float':
|
||||
case 'integer':
|
||||
case 'biginteger':
|
||||
case 'decimal':
|
||||
return !isNull(value) ? value.toString() : '-';
|
||||
return !isNull(value) ? toString(value) : '-';
|
||||
case 'boolean':
|
||||
return value !== null ? toString(value) : '-';
|
||||
case 'date':
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { fork, put, call, takeLatest, take, cancel, select } from 'redux-saga/effects';
|
||||
import request from 'utils/request';
|
||||
|
||||
|
||||
import { getModelEntriesSucceeded, loadedModels, submitSucceeded } from './actions';
|
||||
import { GET_MODEL_ENTRIES, LOAD_MODELS, ON_SUBMIT } from './constants';
|
||||
import { makeSelectModifiedSchema } from './selectors';
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { findIndex, get, isArray, isEmpty, includes, isNumber, isString, map } from 'lodash';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
cancel,
|
||||
fork,
|
||||
@ -34,9 +35,9 @@ function* dataGet(action) {
|
||||
try {
|
||||
const modelName = yield select(makeSelectModelName());
|
||||
const params = { source: action.source };
|
||||
const [response] = yield [
|
||||
const [response] = yield all([
|
||||
call(request, `/content-manager/explorer/${modelName}/${action.id}`, { method: 'GET', params }),
|
||||
];
|
||||
]);
|
||||
const pluginHeaderTitle = yield call(templateObject, { mainField: action.mainField }, response);
|
||||
|
||||
yield put(getDataSucceeded(action.id, response, pluginHeaderTitle.mainField));
|
||||
@ -74,6 +75,7 @@ export function* submit() {
|
||||
const source = yield select(makeSelectSource());
|
||||
const schema = yield select(makeSelectSchema());
|
||||
let shouldAddTranslationSuffix = false;
|
||||
|
||||
// Remove the updated_at & created_at fields so it is updated correctly when using Postgres or MySQL db
|
||||
if (record.updated_at) {
|
||||
delete record.created_at;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// Dependencies.
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
cancel,
|
||||
fork,
|
||||
@ -9,10 +10,8 @@ import {
|
||||
take,
|
||||
takeLatest,
|
||||
} from 'redux-saga/effects';
|
||||
|
||||
// Utils.
|
||||
import request from 'utils/request';
|
||||
|
||||
// Actions
|
||||
import {
|
||||
deleteDataSuccess,
|
||||
@ -63,10 +62,10 @@ export function* dataGet(action) {
|
||||
params._q = _q;
|
||||
}
|
||||
|
||||
const response = yield [
|
||||
const response = yield all([
|
||||
call(request, countURL, { method: 'GET', params }),
|
||||
call(request, recordsURL, { method: 'GET', params }),
|
||||
];
|
||||
]);
|
||||
|
||||
yield put(getDataSucceeded(response));
|
||||
} catch(err) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.containerFluid {
|
||||
padding: 18px 30px;
|
||||
> div:first-child {
|
||||
max-height: 33px;
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,4 +192,4 @@
|
||||
|
||||
.padded {
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SettingsPage
|
||||
*/
|
||||
|
||||
@ -36,23 +36,23 @@ class SettingsPage extends React.PureComponent {
|
||||
componentWillUnmount() {
|
||||
this.props.onReset();
|
||||
}
|
||||
|
||||
|
||||
getModels = (data = this.props.schema.models, destination = '/') => {
|
||||
const models = Object.keys(data).reduce((acc, curr) => {
|
||||
if (curr !== 'plugins') {
|
||||
|
||||
|
||||
if (!data[curr].fields && _.isObject(data[curr])) {
|
||||
return this.getModels(data[curr], `${destination}${curr}/`);
|
||||
return acc.concat(this.getModels(data[curr], `${destination}${curr}/`));
|
||||
}
|
||||
|
||||
|
||||
return acc.concat([{ name: curr, destination: `${destination}${curr}` }]);
|
||||
}
|
||||
|
||||
return this.getModels(data[curr], `${destination}${curr}/`);
|
||||
}
|
||||
|
||||
return acc.concat(this.getModels(data[curr], `${destination}${curr}/`));
|
||||
}, []);
|
||||
|
||||
return sortBy(
|
||||
models.filter(obj => obj.name !== 'permission' && obj.name !== 'role'),
|
||||
models.filter(obj => !!this.props.schema.layout[obj.name]),
|
||||
['name'],
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.containerFluid {
|
||||
padding: 18px 30px;
|
||||
> div:first-child {
|
||||
max-height: 33px;
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,4 +35,4 @@
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"EditRelations.title": "Données associées",
|
||||
"components.AddFilterCTA.add": "Filtres",
|
||||
"components.AddFilterCTA.hide": "Filtres",
|
||||
"components.DraggableAttr.edit": "Clicquez pour modifier",
|
||||
"components.DraggableAttr.edit": "Cliquez pour modifier",
|
||||
"components.EmptyAttributesBlock.button": "Voir la page des configurations",
|
||||
"components.EmptyAttributesBlock.description": "Vous pouvez modifiez vos paramètres",
|
||||
"components.FilterOptions.FILTER_TYPES.=": "est",
|
||||
@ -46,16 +46,16 @@
|
||||
"containers.SettingPage.addField": "Ajouter un nouveau champs",
|
||||
"containers.SettingPage.addRelationalField": "Ajouter un nouveau champs relationnel",
|
||||
"containers.SettingPage.attributes": "Attributs",
|
||||
"containers.SettingPage.attributes.description": "Organiser les attributs du modèle",
|
||||
"containers.SettingPage.attributes.description": "Organisez les attributs du modèle",
|
||||
"containers.SettingPage.editSettings.description": "Glissez & déposez les champs pour construire le layout",
|
||||
"containers.SettingPage.editSettings.title": "Edit — Paramètres",
|
||||
"containers.SettingPage.listSettings.description": "Configurez les options de ce modèle",
|
||||
"containers.SettingPage.listSettings.title": "Liste — Paramètres",
|
||||
"containers.SettingPage.pluginHeaderDescription": "Configurez les paramètres de ce modèle",
|
||||
"containers.SettingPage.relations": "Champs relationnels",
|
||||
"containers.SettingsPage.Block.contentType.description": "Configurer les paramètres spécifiques",
|
||||
"containers.SettingsPage.Block.contentType.description": "Configurez les paramètres spécifiques",
|
||||
"containers.SettingsPage.Block.contentType.title": "Types de contenu",
|
||||
"containers.SettingsPage.Block.generalSettings.description": "Configurez les options par défault de vos modèles",
|
||||
"containers.SettingsPage.Block.generalSettings.description": "Configurez les options par défault de vos modèles",
|
||||
"containers.SettingsPage.Block.generalSettings.title": "Général",
|
||||
"containers.SettingsPage.pluginHeaderDescription": "Configurez les paramètres par défaut de vos modèles",
|
||||
"emptyAttributes.button": "Ouvrir le Content Type Builder",
|
||||
@ -84,17 +84,17 @@
|
||||
"form.Input.bulkActions": "Autoriser les actions groupées",
|
||||
"form.Input.defaultSort": "Attribut de tri par défault",
|
||||
"form.Input.description": "Description",
|
||||
"form.Input.description.placeholder": "Afficher le nom dans le profile",
|
||||
"form.Input.description.placeholder": "Afficher le nom dans le profil",
|
||||
"form.Input.disabled": "Champ editable",
|
||||
"form.Input.filters": "Autoriser les filtres",
|
||||
"form.Input.label": "Label",
|
||||
"form.Input.label.inputDescription": "Cette valeur modifie celle du champs de la table",
|
||||
"form.Input.pageEntries": "Nombre d'entrées par page",
|
||||
"form.Input.pageEntries.inputDescription": "Note: Vous pouvez modifier ces valeurs par modèle",
|
||||
"form.Input.pageEntries.inputDescription": "Note : Vous pouvez modifier ces valeurs par modèle",
|
||||
"form.Input.placeholder": "Placeholder",
|
||||
"form.Input.placeholder.placeholder": "Mon super placeholder",
|
||||
"form.Input.search": "Autoriser la search",
|
||||
"form.Input.search.field": "Autoriser la search sur ce champs",
|
||||
"form.Input.search": "Autoriser la recherche",
|
||||
"form.Input.search.field": "Autoriser la recherche sur ce champs",
|
||||
"form.Input.sort.field": "Autoriser le tri sur ce champs",
|
||||
"notification.error.displayedFields": "Vous devez avoir au moins un champ d'affiché",
|
||||
"notification.error.relationship.fetch": "Une erreur est survenue en récupérant les relations.",
|
||||
@ -107,8 +107,9 @@
|
||||
"popUpWarning.button.cancel": "Annuler",
|
||||
"popUpWarning.button.confirm": "Confirmer",
|
||||
"popUpWarning.title": "Confirmation requise",
|
||||
"popUpWarning.warning.cancelAllSettings": "Êtes-vous sûr de vouloir vos modifications?",
|
||||
"popUpWarning.warning.cancelAllSettings": "Êtes-vous sûr de vouloir abandonner vos modifications ?",
|
||||
"popUpWarning.warning.updateAllSettings": "Cela modifiera tous vos précédents paramètres.",
|
||||
"success.record.delete": "Supprimé",
|
||||
"success.record.save": "Sauvegardé"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -51,6 +51,12 @@ module.exports = async cb => {
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
// Reference all current models
|
||||
const appModels = Object.keys(pluginsModel).reduce((acc, curr) => {
|
||||
const models = Object.keys(_.get(pluginsModel, [curr, 'models'], {}));
|
||||
|
||||
return acc.concat(models);
|
||||
}, Object.keys(strapi.models).filter(m => m !== 'core_store'));
|
||||
// Init schema
|
||||
const schema = {
|
||||
generalSettings: {
|
||||
@ -102,9 +108,11 @@ module.exports = async cb => {
|
||||
disabled: false,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
// Don't display fields that are hidden by default like the resetPasswordToken for the model user
|
||||
_.unset(fields, fieldsToRemove);
|
||||
fieldsToRemove.forEach(field => {
|
||||
_.unset(fields, field);
|
||||
});
|
||||
schemaModel.attributes = _.omit(schemaModel.attributes, fieldsToRemove);
|
||||
|
||||
schemaModel.fields = fields;
|
||||
@ -233,6 +241,16 @@ module.exports = async cb => {
|
||||
pluginStore.set({ key: 'schema', value: schema });
|
||||
|
||||
return cb();
|
||||
} else {
|
||||
const modelsLayout = Object.keys(_.get(prevSchema, 'layout', {}));
|
||||
|
||||
// Remove previous model from the schema.layout
|
||||
// Usually needed when renaming a model
|
||||
modelsLayout.forEach(model => {
|
||||
if (!appModels.includes(model)) {
|
||||
_.unset(prevSchema, ['layout', model]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Here we do the difference between the previous schema from the database and the new one
|
||||
@ -291,6 +309,15 @@ module.exports = async cb => {
|
||||
// Update the displayed fields
|
||||
const updatedListDisplay = prevListDisplay.filter(obj => obj.name !== currentAttr.join());
|
||||
|
||||
// Retrieve the model's displayed fields for the `EditPage`
|
||||
const fieldsPath = getEditDisplayFieldsPath(attrPath);
|
||||
// Retrieve the previous settings
|
||||
const prevEditDisplayFields = _.get(prevSchema.models, fieldsPath);
|
||||
// Update the fields
|
||||
const updatedEditDisplayFields = prevEditDisplayFields.filter(field => field !== currentAttr.join());
|
||||
// Set the new layout
|
||||
_.set(prevSchema.models, fieldsPath, updatedEditDisplayFields);
|
||||
|
||||
if (updatedListDisplay.length === 0) {
|
||||
// Update it with the one from the generated schema
|
||||
_.set(prevSchema.models, listDisplayPath, _.get(schema.models, listDisplayPath, []));
|
||||
@ -330,16 +357,16 @@ module.exports = async cb => {
|
||||
});
|
||||
|
||||
// Update other keys
|
||||
sameApis.map(apiPath => {
|
||||
sameApis.forEach(apiPath => {
|
||||
// This doesn't keep the prevSettings for the relations, the user will have to reset it.
|
||||
// We might have to improve this if we want the order of the relations to be kept
|
||||
const keysToUpdate = ['relations', 'loadedModel', 'associations', 'attributes', ['editDisplay', 'relations']].map(key => apiPath.concat(key));
|
||||
['relations', 'loadedModel', 'associations', 'attributes', ['editDisplay', 'relations']]
|
||||
.map(key => apiPath.concat(key))
|
||||
.forEach(keyPath => {
|
||||
const newValue = _.get(schema.models, keyPath);
|
||||
|
||||
keysToUpdate.map(keyPath => {
|
||||
const newValue = _.get(schema.models, keyPath);
|
||||
|
||||
_.set(prevSchema.models, keyPath, newValue);
|
||||
});
|
||||
_.set(prevSchema.models, keyPath, newValue);
|
||||
});
|
||||
});
|
||||
|
||||
// Special handler for the upload relations
|
||||
@ -354,6 +381,7 @@ module.exports = async cb => {
|
||||
});
|
||||
|
||||
await pluginStore.set({ key: 'schema', value: prevSchema });
|
||||
|
||||
} catch(err) {
|
||||
console.log('error', err);
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
/**
|
||||
* Retrieve the path of each API
|
||||
* @param {Object}} data
|
||||
* @param {Object}} data
|
||||
* @returns {Array} Array of API path ['plugins.upload.file', 'plugins.users-permissions.user', ...]
|
||||
*/
|
||||
const getApis = (data) => Object.keys(data).reduce((acc, curr) => {
|
||||
@ -10,8 +11,8 @@ const getApis = (data) => Object.keys(data).reduce((acc, curr) => {
|
||||
}
|
||||
|
||||
if (curr === 'plugins') {
|
||||
Object.keys(data[curr]).map(plugin => {
|
||||
Object.keys(data[curr][plugin]).map(api => {
|
||||
Object.keys(data[curr]).forEach(plugin => {
|
||||
Object.keys(data[curr][plugin]).forEach(api => {
|
||||
acc = acc.concat([`${curr}.${plugin}.${api}`]);
|
||||
});
|
||||
});
|
||||
@ -23,8 +24,8 @@ const getApis = (data) => Object.keys(data).reduce((acc, curr) => {
|
||||
|
||||
/**
|
||||
* Retrieve all the fields from an api
|
||||
* @param {Object} data
|
||||
* @param {Array} apis
|
||||
* @param {Object} data
|
||||
* @param {Array} apis
|
||||
* @returns {Array} Array composed of fields path for instance : [['plugins.users-permissions.user.fields.username', 'plugins.users-permissions.user.fields.email', 'plugins.users-permissions.user.fields.password'], [...]]
|
||||
*/
|
||||
const getApisKeys = (data, apis) => apis.map(apiPath => {
|
||||
@ -43,12 +44,12 @@ const getApisUploadRelations = (data, sameArray) => sameArray.map(apiPath => {
|
||||
.filter(relationName => {
|
||||
return _.get(data.models, [...relationPath, relationName, 'plugin' ]) === 'upload';
|
||||
});
|
||||
|
||||
|
||||
return relations.map(relation => `${apiPath.join('.')}.editDisplay.availableFields.${relation}`);
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param {String} attrPath
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
@ -184,7 +184,7 @@ module.exports = {
|
||||
withRelated: populate || this.associations.map(x => x.alias)
|
||||
});
|
||||
|
||||
const data = record.toJSON ? record.toJSON() : record;
|
||||
const data = _.get(record, 'toJSON()', record);
|
||||
|
||||
// Retrieve data manually.
|
||||
if (_.isEmpty(populate)) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-content-manager",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "A powerful UI to easily manage your data.",
|
||||
"strapi": {
|
||||
"name": "Content Manager",
|
||||
@ -26,7 +26,7 @@
|
||||
"draft-js": "^0.10.5",
|
||||
"react-select": "^1.2.1",
|
||||
"showdown": "^1.8.6",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.14.4.0"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"pluralize": "^7.0.0"
|
||||
@ -48,8 +48,8 @@
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -8,7 +8,7 @@ const _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
fetchAll: async (params, query) => {
|
||||
const { limit, skip, sort, query : request, queryAttribute, source, page, populate = [] } = query; // eslint-disable-line no-unused-vars
|
||||
const { limit, skip, sort, query : request, queryAttribute, source, populate = [] } = query;
|
||||
const filters = strapi.utils.models.convertParams(params.model, query);
|
||||
const where = !_.isEmpty(request) ? request : filters.where;
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ import {
|
||||
size,
|
||||
split,
|
||||
take,
|
||||
toLower,
|
||||
toNumber,
|
||||
replace,
|
||||
} from 'lodash';
|
||||
@ -378,7 +379,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
||||
|
||||
handleBlur = ({ target }) => {
|
||||
if (target.name === 'name') {
|
||||
this.props.changeInput(target.name, camelCase(target.value), includes(this.props.hash, 'edit'));
|
||||
this.props.changeInput(target.name, toLower(camelCase(target.value)), includes(this.props.hash, 'edit'));
|
||||
if (!isEmpty(target.value)) {
|
||||
// The input name for content type doesn't have the default handleBlur validation so we need to manually remove the error
|
||||
this.props.removeContentTypeRequiredError();
|
||||
@ -489,7 +490,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
||||
|
||||
return {
|
||||
...model,
|
||||
name: camelCase(model.name),
|
||||
name: toLower(camelCase(model.name)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
"attribute.float": "Número flotante",
|
||||
"attribute.integer": "Número entero",
|
||||
"attribute.json": "JSON",
|
||||
"attribute.media": "Medios",
|
||||
"attribute.media": "Multimedia",
|
||||
"attribute.password": "Contraseña",
|
||||
"attribute.relation": "Relación",
|
||||
"attribute.string": "Cadena de texto",
|
||||
@ -28,7 +28,7 @@
|
||||
"error.validation.minLength": "El valor es demasiado corto.",
|
||||
"error.validation.minSupMax": "No puede ser superior",
|
||||
"error.validation.regex": "El valor no coincide con el valor de regex.",
|
||||
"error.validation.required": "Esta entrada de valor es obligatoria.",
|
||||
"error.validation.required": "Es requerido un valor para este registro.",
|
||||
"form.attribute.item.appearance.description": "Si no, el valor será editable a través de un campo textarea básico",
|
||||
"form.attribute.item.appearance.label": "Mostrar como WYSIWYG",
|
||||
"form.attribute.item.appearance.name": "Apariencia",
|
||||
@ -41,7 +41,7 @@
|
||||
"form.attribute.item.enumeration.graphql.description": "Le permite redefinir el nombre generado por defecto para GraphQL",
|
||||
"form.attribute.item.enumeration.name": "Nombre",
|
||||
"form.attribute.item.enumeration.placeholder": "Ej: mañana, mediodía, noche",
|
||||
"form.attribute.item.enumeration.rules": "Valores (sepárelos con una coma)",
|
||||
"form.attribute.item.enumeration.rules": "Valores (separados con una coma)",
|
||||
"form.attribute.item.json.name": "Nombre",
|
||||
"form.attribute.item.maximum": "Valor máximo",
|
||||
"form.attribute.item.maximumLength": "Longitud máxima",
|
||||
@ -50,17 +50,17 @@
|
||||
"form.attribute.item.minimum": "Valor mínimo",
|
||||
"form.attribute.item.minimumLength": "Longitud mínima",
|
||||
"form.attribute.item.number.name": "Nombre",
|
||||
"form.attribute.item.number.type": "Formato de número",
|
||||
"form.attribute.item.number.type": "Tipo de número",
|
||||
"form.attribute.item.number.type.decimal": "decimal (ex: 2.22)",
|
||||
"form.attribute.item.number.type.float": "flotante (ex: 3.3333333333)",
|
||||
"form.attribute.item.number.type.integer": "entero (ej: 10)",
|
||||
"form.attribute.item.requiredField": "Campo obligatorio",
|
||||
"form.attribute.item.requiredField.description": "No podrá crear una entrada si este campo está vacío",
|
||||
"form.attribute.item.requiredField.description": "No podrá crear un registro si este campo está vacío",
|
||||
"form.attribute.item.settings.name": "Ajustes",
|
||||
"form.attribute.item.string.name": "Nombre",
|
||||
"form.attribute.item.textarea.name": "Nombre",
|
||||
"form.attribute.item.uniqueField": "Campo único",
|
||||
"form.attribute.item.uniqueField.description": "No podrá crear una entrada si hay una entrada existente con contenido idéntico",
|
||||
"form.attribute.item.uniqueField.description": "No podrá crear un registro si ya existe otro registro con el mismo contenido",
|
||||
"form.attribute.settings.default": "Valor por defecto",
|
||||
"form.attribute.settings.default.checkboxLabel": "Ajustar a verdadero",
|
||||
"form.button.cancel": "Cancelar",
|
||||
@ -117,18 +117,18 @@
|
||||
"popUpForm.attributes.json.description": "Datos en formato JSON",
|
||||
"popUpForm.attributes.json.name": "JSON",
|
||||
"popUpForm.attributes.media.description": "Imágenes, vídeos, PDFs y otros archivos",
|
||||
"popUpForm.attributes.media.name": "Medios",
|
||||
"popUpForm.attributes.media.name": "Multimedia",
|
||||
"popUpForm.attributes.number.description": "Todo lo que es número",
|
||||
"popUpForm.attributes.number.name": "Número",
|
||||
"popUpForm.attributes.password.description": "Contraseña de usuario...",
|
||||
"popUpForm.attributes.password.name": "Contraseña",
|
||||
"popUpForm.attributes.relation.description": "Se refiere a un Tipo de Contenido",
|
||||
"popUpForm.attributes.relation.name": "Relación",
|
||||
"popUpForm.attributes.string.description": "Títulos, nombres, párrafos, lista de nombres",
|
||||
"popUpForm.attributes.string.description": "Títulos, nombres, enunciados, lista de nombres",
|
||||
"popUpForm.attributes.string.name": "Cadena de texto",
|
||||
"popUpForm.attributes.text.description": "Descripciones, párrafos de texto, artículos ",
|
||||
"popUpForm.attributes.text.description": "Descripciones, párrafos de texto, artículos",
|
||||
"popUpForm.attributes.text.name": "Texto",
|
||||
"popUpForm.choose.attributes.header.title": "Añadir Nuevo Campo",
|
||||
"popUpForm.choose.attributes.header.title": "Añadir nuevo Campo",
|
||||
"popUpForm.create": "Añadir Nuevo",
|
||||
"popUpForm.create.contentType.header.title": "Añadir nuevo Tipo de Contenido",
|
||||
"popUpForm.edit": "Editar",
|
||||
|
||||
@ -29,18 +29,18 @@
|
||||
"error.validation.minSupMax": "Ne peut pas être plus grand",
|
||||
"error.validation.regex": "La valeur ne correspond pas au format attendu.",
|
||||
"error.validation.required": "Ce champ est obligatoire.",
|
||||
"form.attribute.item.appearance.description": "Sinon, il sera editable à partir d'une simple textarea",
|
||||
"form.attribute.item.appearance.description": "Sinon, il sera editable à partir d'une simple zone de texte",
|
||||
"form.attribute.item.appearance.label": "Editable avec un WYSIWYG",
|
||||
"form.attribute.item.appearance.name": "Apparence",
|
||||
"form.attribute.item.boolean.name": "Nom",
|
||||
"form.attribute.item.customColumnName": "Nom de colonne custom",
|
||||
"form.attribute.item.customColumnName": "Nom de colonne personalisée",
|
||||
"form.attribute.item.customColumnName.description": "Pratique pour renommer la colonne de la db dans un format plus comprehensible pour les responses de l'API",
|
||||
"form.attribute.item.date.name": "Nom",
|
||||
"form.attribute.item.defineRelation.fieldName": "Nom du Champ",
|
||||
"form.attribute.item.enumeration.graphql": "Surchage du nom pour GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Vous permet de remplacer le nom généré par défaut pour GraphQL",
|
||||
"form.attribute.item.enumeration.name": "Nom",
|
||||
"form.attribute.item.enumeration.placeholder": "Ex: matin,midi,soir",
|
||||
"form.attribute.item.enumeration.placeholder": "Ex : matin,midi,soir",
|
||||
"form.attribute.item.enumeration.rules": "Valeurs (les séparer par une virgule)",
|
||||
"form.attribute.item.json.name": "Nom",
|
||||
"form.attribute.item.maximum": "Valeur maximum",
|
||||
@ -64,7 +64,7 @@
|
||||
"form.attribute.settings.default": "Valeur par défault",
|
||||
"form.attribute.settings.default.checkboxLabel": "Définir à true",
|
||||
"form.button.cancel": "Annuler",
|
||||
"form.button.continue": "Continue",
|
||||
"form.button.continue": "Continuer",
|
||||
"form.button.save": "Sauvegarder",
|
||||
"form.contentType.item.collectionName": "Nom de la Collection",
|
||||
"form.contentType.item.collectionName.inputDescription": "Pratique quand le Nom de votre Modèle et de votre table sont différents",
|
||||
@ -111,7 +111,7 @@
|
||||
"popUpForm.attributes.date.description": "Date événements, horaires",
|
||||
"popUpForm.attributes.date.name": "Date",
|
||||
"popUpForm.attributes.email.description": "Email utilisateurs",
|
||||
"popUpForm.attributes.email.name": "Email",
|
||||
"popUpForm.attributes.email.name": "E-mail",
|
||||
"popUpForm.attributes.enumeration": "Énumération",
|
||||
"popUpForm.attributes.enumeration.description": "Liste de choix",
|
||||
"popUpForm.attributes.enumeration.name": "Énumération",
|
||||
@ -144,7 +144,7 @@
|
||||
"popUpWarning.button.cancel": "Annuler",
|
||||
"popUpWarning.button.confirm": "Confirmer",
|
||||
"popUpWarning.title": "Merci de confirmer",
|
||||
"relation.attributeName.placeholder": "Ex: auteur, catégorie, tag",
|
||||
"relation.attributeName.placeholder": "Ex : auteur, catégorie, tag",
|
||||
"relation.manyToMany": "a plusieurs",
|
||||
"relation.manyToOne": "a plusieurs",
|
||||
"relation.oneToMany": "appartient a",
|
||||
@ -155,4 +155,4 @@
|
||||
"table.contentType.head.name": "Nom",
|
||||
"table.contentType.title.plural": "Modèles sont disponibles",
|
||||
"table.contentType.title.singular": "Modèle est disponible"
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ const fs = require('fs');
|
||||
const _ = require('lodash');
|
||||
|
||||
const Service = require('../services/ContentTypeBuilder');
|
||||
const { escapeNewlines } = require('../utils/helpers.js');
|
||||
|
||||
module.exports = {
|
||||
getModels: async ctx => {
|
||||
@ -47,11 +48,13 @@ module.exports = {
|
||||
return ctx.badRequest(null, [{ messages: attributesErrors }]);
|
||||
}
|
||||
|
||||
const _description = escapeNewlines(description, '\\n');
|
||||
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
await Service.appearance(formatedAttributes, name);
|
||||
|
||||
await Service.generateAPI(name, description, connection, collectionName, []);
|
||||
await Service.generateAPI(name, _description, connection, collectionName, []);
|
||||
|
||||
const modelFilePath = await Service.getModelPath(name, plugin);
|
||||
|
||||
@ -103,12 +106,14 @@ module.exports = {
|
||||
return ctx.badRequest(null, [{ messages: attributesErrors }]);
|
||||
}
|
||||
|
||||
const _description = escapeNewlines(description);
|
||||
|
||||
let modelFilePath = Service.getModelPath(model, plugin);
|
||||
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
if (name !== model) {
|
||||
await Service.generateAPI(name, description, connection, collectionName, []);
|
||||
await Service.generateAPI(name, _description, connection, collectionName, []);
|
||||
}
|
||||
|
||||
await Service.appearance(formatedAttributes, name, plugin);
|
||||
@ -120,7 +125,7 @@ module.exports = {
|
||||
modelJSON.collectionName = collectionName;
|
||||
modelJSON.info = {
|
||||
name,
|
||||
description
|
||||
description: _description
|
||||
};
|
||||
modelJSON.attributes = formatedAttributes;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-content-type-builder",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "Strapi plugin to create content type (API).",
|
||||
"strapi": {
|
||||
"name": "Content Type Builder",
|
||||
@ -24,11 +24,11 @@
|
||||
"dependencies": {
|
||||
"immutable": "^3.8.2",
|
||||
"pluralize": "^7.0.0",
|
||||
"strapi-generate": "3.0.0-alpha.14.4.0",
|
||||
"strapi-generate-api": "3.0.0-alpha.14.4.0"
|
||||
"strapi-generate": "3.0.0-alpha.15",
|
||||
"strapi-generate-api": "3.0.0-alpha.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.14.4.0"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
@ -47,8 +47,8 @@
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -21,7 +21,7 @@ module.exports = {
|
||||
});
|
||||
|
||||
const schema = await pluginStore.get({ key: 'schema' });
|
||||
const layout = _.get(schema.layout, model, {});
|
||||
const layout = _.get(schema.layout, model, { attributes: {} });
|
||||
|
||||
// If updating a content-type
|
||||
if (!_.isEmpty(layout)) {
|
||||
@ -105,9 +105,9 @@ module.exports = {
|
||||
_.set(schema, [...schemaPath, 'editDisplay', 'fields'], newList.toJS());
|
||||
}
|
||||
|
||||
Object.keys(attributes).map(attribute => {
|
||||
Object.keys(attributes).forEach(attribute => {
|
||||
const appearances = _.get(attributes, [attribute, 'appearance'], {});
|
||||
Object.keys(appearances).map(appearance => {
|
||||
Object.keys(appearances).forEach(appearance => {
|
||||
_.set(layout, ['attributes', attribute, 'appearance'], appearances[appearance] ? appearance : '' );
|
||||
});
|
||||
|
||||
|
||||
@ -61,10 +61,15 @@ const reorderList = (manager, list) => {
|
||||
return List(flattenDeep(reordered));
|
||||
};
|
||||
|
||||
const escapeNewlines = (content, placeholder = '\n') => {
|
||||
return content.replace(/[\r\n]+/g, placeholder);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createArrayOfLastEls,
|
||||
createManager,
|
||||
getElementsOnALine,
|
||||
removeColsLine,
|
||||
reorderList,
|
||||
escapeNewlines
|
||||
};
|
||||
@ -1,7 +1,6 @@
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { call, fork, put, select, takeLatest } from 'redux-saga/effects';
|
||||
import { all, call, fork, put, select, takeLatest } from 'redux-saga/effects';
|
||||
import request from 'utils/request';
|
||||
|
||||
import {
|
||||
getSettingsSucceeded,
|
||||
submitSucceeded,
|
||||
@ -18,10 +17,10 @@ import {
|
||||
export function* settingsGet(action) {
|
||||
try {
|
||||
const requestURL = `/email/settings/${action.env}`;
|
||||
const response = yield [
|
||||
const response = yield all([
|
||||
call(request, requestURL, { method: 'GET' }),
|
||||
call(request, '/email/environments', { method: 'GET' }),
|
||||
];
|
||||
]);
|
||||
|
||||
yield put(getSettingsSucceeded(response[0], response[1].environments));
|
||||
} catch(err) {
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
"EditForm.Input.number.label": "Taille maximale autorisée (en MB)",
|
||||
"EditForm.Input.select.inputDescription": "Les e-mails peuvent être envoyés avec le fournisseur par défaut (Sendmail) ou un fournisseur externe.",
|
||||
"EditForm.Input.select.label": "Fournisseurs",
|
||||
"EditForm.Input.toggle.label": "Activer l'envoi de e-mails",
|
||||
"EditForm.Input.toggle.label": "Activer l'envoi d'e-mails",
|
||||
"notification.config.success": "Les paramètres ont été mis à jour.",
|
||||
"plugin.description.long": "Envoyez des emails",
|
||||
"plugin.description.short": "Envoyez des emails"
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,8 @@ module.exports = async cb => {
|
||||
fs.readdir(path.join(basePath, 'node_modules'), async (err, node_modules) => {
|
||||
// get all email providers
|
||||
const emails = _.filter(node_modules, (node_module) => {
|
||||
return _.startsWith(node_module, ('strapi-email'));
|
||||
// DEPRECATED strapi-email-* will be remove in next version
|
||||
return _.startsWith(node_module, 'strapi-provider-email') || _.startsWith(node_module, 'strapi-email');
|
||||
});
|
||||
|
||||
// mount all providers to get configs
|
||||
@ -51,7 +52,7 @@ module.exports = async cb => {
|
||||
}
|
||||
} catch (err) {
|
||||
strapi.log.error(`Can't load ${config.provider} email provider.`);
|
||||
strapi.log.warn(`Please install strapi-email-${config.provider} --save in ${path.join(strapi.config.appPath, 'plugins', 'email')} folder.`);
|
||||
strapi.log.warn(`Please install strapi-provider-email-${config.provider} --save in ${path.join(strapi.config.appPath, 'plugins', 'email')} folder.`);
|
||||
strapi.stop();
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-email",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "Email",
|
||||
@ -22,11 +22,11 @@
|
||||
"prepublishOnly": "IS_MONOREPO=true npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"strapi-email-sendmail": "3.0.0-alpha.14.4.0"
|
||||
"strapi-provider-email-sendmail": "3.0.0-alpha.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-copy-to-clipboard": "5.0.1",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.14.4.0"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
@ -45,8 +45,8 @@
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -51,7 +51,7 @@ module.exports = {
|
||||
const provider = _.find(strapi.plugins.email.config.providers, { provider: config.provider });
|
||||
|
||||
if (!provider) {
|
||||
throw new Error(`The provider package isn't installed. Please run \`npm install strapi-email-${config.provider}\``);
|
||||
throw new Error(`The provider package isn't installed. Please run \`npm install strapi-provider-email-${config.provider}\``);
|
||||
}
|
||||
|
||||
const actions = provider.init(config);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-graphql",
|
||||
"version": "3.0.0-alpha.14.4.0",
|
||||
"version": "3.0.0-alpha.15",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "graphql",
|
||||
@ -30,7 +30,7 @@
|
||||
"graphql-type-json": "^0.2.1",
|
||||
"graphql-type-datetime": "^0.2.2",
|
||||
"pluralize": "^7.0.0",
|
||||
"strapi-utils": "3.0.0-alpha.14.4.0"
|
||||
"strapi-utils": "3.0.0-alpha.15"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
@ -45,8 +45,8 @@
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -9,6 +9,7 @@
|
||||
const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const Schema = require('./Schema.js');
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
@ -387,22 +388,6 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of fields that have type included in fieldTypes.
|
||||
*/
|
||||
getFieldsByTypes: (fields, typeCheck, returnType) => {
|
||||
return _.reduce(
|
||||
fields,
|
||||
(acc, fieldType, fieldName) => {
|
||||
if (typeCheck(fieldType)) {
|
||||
acc[fieldName] = returnType(fieldType, fieldName);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate the connection type of each non-array field of the model
|
||||
*
|
||||
|
||||
@ -10,6 +10,7 @@ const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const policyUtils = require('strapi-utils').policy;
|
||||
const Query = require('./Query.js');
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
@ -64,10 +65,7 @@ module.exports = {
|
||||
const [name, action] = handler.split('.');
|
||||
|
||||
const controller = plugin
|
||||
? _.get(
|
||||
strapi.plugins,
|
||||
`${plugin}.controllers.${_.toLower(name)}.${action}`,
|
||||
)
|
||||
? _.get(strapi.plugins, `${plugin}.controllers.${_.toLower(name)}.${action}`)
|
||||
: _.get(strapi.controllers, `${_.toLower(name)}.${action}`);
|
||||
|
||||
if (!controller) {
|
||||
@ -148,10 +146,7 @@ module.exports = {
|
||||
const [name, action] = resolverOf.split('.');
|
||||
|
||||
const controller = plugin
|
||||
? _.get(
|
||||
strapi.plugins,
|
||||
`${plugin}.controllers.${_.toLower(name)}.${action}`,
|
||||
)
|
||||
? _.get(strapi.plugins, `${plugin}.controllers.${_.toLower(name)}.${action}`)
|
||||
: _.get(strapi.controllers, `${_.toLower(name)}.${action}`);
|
||||
|
||||
if (!controller) {
|
||||
|
||||
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