Merge branch 'master' into patch-1

This commit is contained in:
Jim LAURIE 2020-02-10 17:25:53 +01:00 committed by GitHub
commit acfcd68e2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 83 deletions

View File

@ -97,7 +97,7 @@ module.exports = strapi => {
And here it is.
You can now use `strapi.github` everywhere in your code to use the GitHub client.
You can now use `strapi.services.github` everywhere in your code to use the GitHub client.
To simply test if it works, lets update the `bootstrap.js` function to log your GitHub profile.
@ -133,7 +133,7 @@ And in your GitHub hook, you will have to replace `strapi.config.hook.github` by
}
```
**Path —** `./hooks/github/inde.js`
**Path —** `./hooks/github/index.js`
```js
const GitHubAPI = require('@octokit/rest');

View File

@ -1,24 +1,19 @@
# Front-end Development
::: danger
This feature is currently not available (coming soon).
:::
<!--
## Admin panel
Strapi's admin panel and plugins system aim to be an easy and powerful way to create new features.
The admin panel is a [React](https://facebook.github.io/react/) application which can embed other React applications. These other React applications are the `admin` parts of each Strapi's plugins.
### Admin Lifecycle
## Environment setup
The admin package has the following lifecycle.
To enable local plugin development, you need to start your application with the front-end development mode activated:
1. Retrieve all the installed plugin and and store them into the main redux store
2. Load until all the plugin emit the event `isReady`
3. Runtime
```bash
$ cd my-app
$ yarn develop --watch-admin
```
## API
### Strapi global variable
@ -44,52 +39,6 @@ Display a loader that will prevent the user from interacting with the applicatio
Remove the loader so the user can interact with the application
#### `strapi.injectSaga`
Dynamically inject a plugin's saga.
**Path —** `plugins/my-plugin/admin/src/containers/App/index.js`.
```js
import React from 'react';
import { compose } from 'redux';
import pluginId from '../../pluginId';
import saga from './saga';
class App extends React.Component {
render() {
return null;
}
}
const withSaga = strapi.injectSaga({ key: 'app', saga, pluginId });
export default compose(withSaga)(App);
```
#### `strapi.injectReducer`
Dynamically inject a plugin's reducer.
**Path —** `plugins/my-plugin/admin/src/containers/App/index.js`.
```js
import React from 'react';
import { compose } from 'redux';
import pluginId from '../../pluginId';
import reducer from './reducer';
class App extends React.Component {
render() {
return null;
}
}
const withReducer = strapi.injectReducer({ key: 'app', reducer, pluginId });
export default compose(withReducer)(App);
```
#### `strapi.notification`
Display a notification (works with i18n message id). Use this command anywhere in your code.
@ -105,16 +54,6 @@ strapi.notification.warning('app.notification.warning');
The administration url (e.g. `http://localhost:4000/admin`).
### Available hooks
The Admin container exposes hooks in which a plugin can run custom code.
(Documentation coming soon).
## Plugin development
(Coming soon).
### Main plugin object
Each plugin exports all its configurations in a object. This object is located in `my-plugin/admin/src/index.js`
@ -190,12 +129,12 @@ class Initializer extends React.PureComponent {
this.props.updatePlugin(
pluginId,
'preventComponentRendering',
preventComponentRendering,
preventComponentRendering
);
this.props.updatePlugin(
pluginId,
'blockerComponentProps',
blockerComponentProps,
blockerComponentProps
);
// Emit the event plugin ready
this.props.updatePlugin(pluginId, 'isReady', true);
@ -214,17 +153,13 @@ Initializer.propTypes = {
export default Initializer;
```
### Lifecycle
(Coming soon)
### Injected Components
(Coming soon)
### Routing
The routing is based on the [React Router V4](https://reacttraining.com/react-router/web/guides/philosophy), due to it's implementation each route is declared in the `containers/App/index.js` file.
The routing is based on the [React Router V5](https://reacttraining.com/react-router/web/guides/philosophy), due to it's implementation each route is declared in the `containers/App/index.js` file.
::: tip
Each route defined in a plugin must be prefixed by the plugin's id.
@ -251,7 +186,7 @@ class App extends React.Component {
render() {
return (
<div className={styles.myPlugin}>
<div>
<Switch>
<Route
exact
@ -267,6 +202,10 @@ class App extends React.Component {
// ...
```
### Styling
The administration panel uses [styled-components](https://styled-components.com/) for writing css.
### i18n
[React Intl](https://github.com/yahoo/react-intl) provides React components and an API to format dates, numbers, and strings, including pluralization and handling translations.
@ -314,4 +253,41 @@ export default Foo;
```
See [the documentation](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) for more extensive usage.
-->
### Global context
All plugins are wrapped inside the `GlobalContextProvider`, in this object you will have access to all plugins object as well as other utilities.
Usage:
**Inside a functional component:**
```js
import React from 'react';
import { useGlobalContext } from 'strapi-helper-plugin';
const Foo = () => {
const globalContext = useGlobalContext();
console.log(globalContext);
return <div>Foo</div>;
};
```
**Inside a class component:**
```js
import React from 'react';
import { GlobalContext } from 'strapi-helper-plugin';
class Foo extends React.Component {
static contextType = GlobalContext;
render() {
console.log(this.context);
return <div>Foo</div>;
}
}
```

View File

@ -448,11 +448,19 @@ module.exports = async ({
const defAttr = definition.attributes[alias];
const targetCol = `${targetAttr.attribute}_${targetAttr.column}`;
let rootCol = `${defAttr.attribute}_${defAttr.column}`;
// manyWay with same CT
if (rootCol === targetCol) {
rootCol = `related_${rootCol}`;
}
const attributes = {
[`${targetAttr.attribute}_${targetAttr.column}`]: {
[targetCol]: {
type: targetCollection.primaryKeyType,
},
[`${defAttr.attribute}_${defAttr.column}`]: {
[rootCol]: {
type: definition.primaryKeyType,
},
};

View File

@ -259,7 +259,11 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
definition.primaryKey
}`;
const otherKey = `${details.attribute}_${details.column}`;
let otherKey = `${details.attribute}_${details.column}`;
if (otherKey === foreignKey) {
otherKey = `related_${otherKey}`;
}
loadedModel[name] = function() {
const targetBookshelfModel = GLOBALS[globalId];

View File

@ -125,6 +125,8 @@ module.exports = function(strapi) {
connection,
};
_.set(strapi, `connections.${connectionName}`, instance);
return Promise.all([
mountComponents(connectionName, ctx),
mountApis(connectionName, ctx),