mirror of
https://github.com/strapi/strapi.git
synced 2025-09-21 06:22:30 +00:00
Merge branch 'alpha.6' of https://github.com/strapi/strapi into improvements/filters
This commit is contained in:
commit
c97893a700
26
README.md
26
README.md
@ -1,11 +1,23 @@
|
||||

|
||||
<p align="center"><img src="https://cldup.com/7umchwdUBh.png" /></p>
|
||||
<h3 align="center">API creation made simple, secure and fast.</h3>
|
||||
<p align="center">The most advanced open-source Content Management Framework to build powerful API with no effort.</p>
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.org/package/strapi">
|
||||
<img src="https://img.shields.io/npm/v/strapi.svg" alt="Dependency Status" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.org/package/strapi">
|
||||
<img src="https://img.shields.io/npm/dm/strapi.svg" alt="Dependency Status" />
|
||||
</a>
|
||||
<a href="https://travis-ci.org/strapi/strapi">
|
||||
<img src="https://travis-ci.org/strapi/strapi.svg?branch=master" alt="Dependency Status" />
|
||||
</a>
|
||||
<a href="http://slack.strapi.io">
|
||||
<img src="http://strapi-slack.herokuapp.com/badge.svg" alt="Dependency Status" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[](https://www.npmjs.org/package/strapi)
|
||||
[](https://www.npmjs.org/package/strapi)
|
||||
[](https://travis-ci.org/strapi/strapi)
|
||||
[](http://slack.strapi.io)
|
||||
|
||||
[Strapi](http://strapi.io) is an open source solution to create, deploy and manage your own API. It provides a powerful dashboard and features to make your life easier.
|
||||
<br>
|
||||
|
||||
## v3.0.0 coming soon...
|
||||
We've been working on a major update to Strapi for several months now, rewriting the core framework and the dashboard. Some parts of this work have been merged into our master branch. Currently, this is not stable and ready.
|
||||
|
@ -83,13 +83,31 @@ const registerPlugin = (plugin) => {
|
||||
|
||||
plugin.leftMenuSections = plugin.leftMenuSections || [];
|
||||
|
||||
// Execute bootstrap function.
|
||||
if (isFunction(plugin.bootstrap)) {
|
||||
plugin.bootstrap(plugin).then(plugin => {
|
||||
switch (true) {
|
||||
// Execute bootstrap function and check if plugin can be rendered
|
||||
case isFunction(plugin.bootstrap) && isFunction(plugin.pluginRequirements):
|
||||
plugin.pluginRequirements(plugin)
|
||||
.then(plugin => {
|
||||
return plugin.bootstrap(plugin);
|
||||
})
|
||||
.then(plugin => {
|
||||
store.dispatch(pluginLoaded(plugin));
|
||||
});
|
||||
break;
|
||||
// Check if plugin can be rendered
|
||||
case isFunction(plugin.pluginRequirements):
|
||||
plugin.pluginRequirements(plugin).then(plugin => {
|
||||
store.dispatch(pluginLoaded(plugin));
|
||||
})
|
||||
break;
|
||||
// Execute bootstrap function
|
||||
case isFunction(plugin.bootstrap):
|
||||
plugin.bootstrap(plugin).then(plugin => {
|
||||
store.dispatch(pluginLoaded(plugin));
|
||||
});
|
||||
break;
|
||||
default:
|
||||
store.dispatch(pluginLoaded(plugin));
|
||||
});
|
||||
} else {
|
||||
store.dispatch(pluginLoaded(plugin));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,8 @@ export class PluginPage extends React.Component { // eslint-disable-line react/p
|
||||
if (plugin.id === pluginId) {
|
||||
pluginName = plugin.name;
|
||||
|
||||
const Elem = plugin.mainComponent;
|
||||
const Elem = plugin.preventComponentRendering ? plugin.blockerComponent : plugin.mainComponent;
|
||||
|
||||
return <Elem key={plugin.id} {...this.props} />;
|
||||
}
|
||||
});
|
||||
|
@ -10,5 +10,10 @@
|
||||
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "No plugins installed yet",
|
||||
"app.components.LeftMenuLinkContainer.plugins": "Plugins",
|
||||
"app.components.NotFoundPage.description": "Not Found",
|
||||
"app.components.NotFoundPage.back": "Back to homepage"
|
||||
"app.components.NotFoundPage.back": "Back to homepage",
|
||||
"components.AutoReloadBlocker.header": "Reload feature is required for this plugin.",
|
||||
"components.AutoReloadBlocker.description": "Open the following file and enable the feature.",
|
||||
"components.ProductionBlocker.header": "This plugin is only available in development.",
|
||||
"components.ProductionBlocker.description": "For safety we have to disable this plugin in other environments."
|
||||
|
||||
}
|
||||
|
@ -10,5 +10,9 @@
|
||||
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "Aucun plugin installé",
|
||||
"app.components.LeftMenuLinkContainer.plugins": "Plugins",
|
||||
"app.components.NotFoundPage.description": "Page introuvable",
|
||||
"app.components.NotFoundPage.back": "Retourner à la page d'accueil"
|
||||
"app.components.NotFoundPage.back": "Retourner à la page d'accueil",
|
||||
"components.AutoReloadBlocker.header": "L'autoReload doit être activé pour ce plugin.",
|
||||
"components.AutoReloadBlocker.description": "Ouvrez le fichier suivant pour activer cette fonctionnalité.",
|
||||
"components.ProductionBlocker.header": "Ce plugin est disponible uniquement en développement.",
|
||||
"components.ProductionBlocker.description": "Pour des raisons de sécurité il est désactivé dans les autres environnements."
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
{
|
||||
"languages": ["en", "fr"],
|
||||
"plugins": {
|
||||
"ports": [3000]
|
||||
}
|
||||
"languages": ["en", "fr"]
|
||||
}
|
||||
|
@ -44,7 +44,7 @@
|
||||
"html-loader": "^0.4.3",
|
||||
"html-webpack-plugin": "^2.22.0",
|
||||
"plop": "^1.8.1",
|
||||
"prettier": "^1.7.0",
|
||||
"prettier": "^1.7.2",
|
||||
"rimraf": "^2.6.2",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.5.5",
|
||||
"webpack": "^3.6.0"
|
||||
|
@ -8,11 +8,24 @@
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import App, { bootstrap } from 'containers/App'; // eslint-disable-line
|
||||
import App from 'containers/App'; // eslint-disable-line
|
||||
|
||||
import configureStore from './store';
|
||||
import { translationMessages } from './i18n';
|
||||
|
||||
const tryRequire = (bootstrap = false) => {
|
||||
try {
|
||||
const config = bootstrap ? require('bootstrap').default : require('requirements').default;
|
||||
return config;
|
||||
} catch(err) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const bootstrap = tryRequire(true);
|
||||
const pluginRequirements = tryRequire();
|
||||
|
||||
|
||||
// Plugin identifier based on the package.json `name` value
|
||||
const pluginPkg = require('../../../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
@ -61,6 +74,9 @@ window.Strapi.registerPlugin({
|
||||
mainComponent: Comp,
|
||||
translationMessages,
|
||||
bootstrap,
|
||||
pluginRequirements,
|
||||
preventComponentRendering: false,
|
||||
blockerComponent: null,
|
||||
});
|
||||
|
||||
// Export store
|
||||
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
*
|
||||
* AutoReloadBlocker
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import styles from './styles.scss';
|
||||
|
||||
function AutoReloadBlocker() {
|
||||
return (
|
||||
<div className={styles.autoReloadBlocker}>
|
||||
<div className={styles.header}>
|
||||
<div>
|
||||
|
||||
<h4>
|
||||
<FormattedMessage id="components.AutoReloadBlocker.header" />
|
||||
</h4>
|
||||
<p>
|
||||
<FormattedMessage id="components.AutoReloadBlocker.description" />
|
||||
</p>
|
||||
<div className={styles.ide}>
|
||||
<p>./config/environments/development/server.json</p>
|
||||
<div>
|
||||
<pre style={{ whiteSpace: 'pre-wrap'}}>
|
||||
<code>
|
||||
{
|
||||
<br />
|
||||
"host": "localhost",
|
||||
<br />
|
||||
"port": 1337,
|
||||
<br />
|
||||
<span style={{ color: '#006EE7'}}>
|
||||
"autoReload": true,
|
||||
</span>
|
||||
<br />
|
||||
"proxi": {
|
||||
<br />
|
||||
"enabled": true
|
||||
<br />
|
||||
},
|
||||
<br />
|
||||
"cron": {
|
||||
<br />
|
||||
"enabled": false
|
||||
<br />
|
||||
}
|
||||
<br />
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AutoReloadBlocker;
|
@ -0,0 +1,53 @@
|
||||
.autoReloadBlocker {
|
||||
padding-top: 5.5rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-family: Lato;
|
||||
> div {
|
||||
padding-top: 2.5rem;
|
||||
> h4 {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
> p {
|
||||
margin-top: -1px;
|
||||
font-size: 14px;
|
||||
color: #919BAE;
|
||||
}
|
||||
}
|
||||
&:before{
|
||||
content: '\f021';
|
||||
font-family: 'FontAwesome';
|
||||
font-size: 4.2rem;
|
||||
color: #323740;
|
||||
margin-right: 20px;
|
||||
line-height: 9.3rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.ide {
|
||||
padding-top: 2.3rem;
|
||||
> p {
|
||||
color: #006EE7;
|
||||
font-size: 14px;
|
||||
}
|
||||
> div {
|
||||
width: 455px;
|
||||
background: #FFFFFF;
|
||||
color: #787E8F;
|
||||
font-size: 12px;
|
||||
> ul {
|
||||
padding-left: 20px;
|
||||
list-style: none;
|
||||
> li {
|
||||
list-style: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
*
|
||||
* ProductionBlocker
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import styles from './styles.scss';
|
||||
|
||||
function ProductionBlocker() {
|
||||
return (
|
||||
<div className={styles.productionBlocker}>
|
||||
<div className={styles.header}>
|
||||
<div>
|
||||
<h4>
|
||||
<FormattedMessage id="components.ProductionBlocker.header" />
|
||||
</h4>
|
||||
<p>
|
||||
<FormattedMessage id="components.ProductionBlocker.description" />
|
||||
</p>
|
||||
<div className={styles.buttonContainer}>
|
||||
<a className={cn(styles.primary, 'btn')} href="http://strapi.io" target="_blank">Read the documentation</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductionBlocker;
|
@ -0,0 +1,84 @@
|
||||
.productionBlocker {
|
||||
padding-top: 5.5rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-family: Lato;
|
||||
> div {
|
||||
padding-top: 2.5rem;
|
||||
> h4 {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
> p {
|
||||
margin-top: -1px;
|
||||
font-size: 14px;
|
||||
color: #919BAE;
|
||||
}
|
||||
}
|
||||
&:before{
|
||||
content: '\f05e';
|
||||
font-family: 'FontAwesome';
|
||||
font-size: 4.2rem;
|
||||
color: #323740;
|
||||
margin-right: 20px;
|
||||
line-height: 9.3rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
.primary {
|
||||
border-radius: 0.3rem;
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
min-width: 15rem;
|
||||
background: linear-gradient(315deg, #0097F6 0%, #005EEA 100%);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: white;
|
||||
&:active {
|
||||
box-shadow: inset 1px 1px 3px rgba(0,0,0,.15);
|
||||
}
|
||||
padding-top: 4px;
|
||||
padding-left: 1.6rem;
|
||||
padding-right: 1.6rem;
|
||||
&:before {
|
||||
content: '\f02d';
|
||||
font-family: 'FontAwesome';
|
||||
font-weight: 600;
|
||||
font-size: 1.3rem;
|
||||
margin-right: 13px;
|
||||
}
|
||||
cursor: pointer;
|
||||
font-family: Lato;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
> i {
|
||||
margin-right: 1.3rem;
|
||||
font-weight: 600;
|
||||
padding-top: 1px;
|
||||
}
|
||||
&:hover {
|
||||
color: white;
|
||||
&::after {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-radius: 0.3rem;
|
||||
content: '';
|
||||
opacity: 0.1;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
14
packages/strapi-plugin-content-manager/admin/src/bootstrap.js
vendored
Normal file
14
packages/strapi-plugin-content-manager/admin/src/bootstrap.js
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { generateMenu } from 'containers/App/sagas';
|
||||
|
||||
// This method is executed before the load of the plugin
|
||||
const bootstrap = (plugin) => new Promise((resolve, reject) => {
|
||||
generateMenu()
|
||||
.then(menu => {
|
||||
plugin.leftMenuSections = menu;
|
||||
|
||||
resolve(plugin);
|
||||
})
|
||||
.catch(e => reject(e));
|
||||
});
|
||||
|
||||
export default bootstrap;
|
@ -22,7 +22,7 @@ import List from 'containers/List';
|
||||
import { loadModels, updateSchema } from './actions';
|
||||
import { makeSelectLoading } from './selectors';
|
||||
|
||||
import saga, { generateMenu } from './sagas';
|
||||
import saga from './sagas';
|
||||
|
||||
const tryRequire = (path) => {
|
||||
try {
|
||||
@ -32,17 +32,6 @@ const tryRequire = (path) => {
|
||||
}
|
||||
};
|
||||
|
||||
// This method is executed before the load of the plugin.
|
||||
export const bootstrap = (plugin) => new Promise((resolve, reject) => {
|
||||
generateMenu()
|
||||
.then(menu => {
|
||||
plugin.leftMenuSections = menu;
|
||||
|
||||
resolve(plugin);
|
||||
})
|
||||
.catch(e => reject(e));
|
||||
});
|
||||
|
||||
class App extends React.Component {
|
||||
componentDidMount() {
|
||||
const config = tryRequire('../../../../config/admin.json');
|
||||
|
@ -0,0 +1,3 @@
|
||||
const shouldRenderCompo = (plugin) => Promise.resolve(plugin);
|
||||
|
||||
export default shouldRenderCompo;
|
@ -23,7 +23,7 @@ class ContentHeader extends React.Component { // eslint-disable-line react/prefe
|
||||
if (this.props.isLoading) {
|
||||
return (
|
||||
<div className={styles.buttonContainer}>
|
||||
<Button type="submit" lg primary loader />
|
||||
<Button type="submit" primary loader />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
import AutoReloadBlocker from 'components/AutoReloadBlocker';
|
||||
import request from 'utils/request';
|
||||
|
||||
const shouldRenderCompo = (plugin) => new Promise((resolve, reject) => {
|
||||
request('/content-type-builder/autoReload')
|
||||
.then(response => {
|
||||
plugin.preventComponentRendering = !response.autoReload;
|
||||
plugin.blockerComponent = AutoReloadBlocker;
|
||||
|
||||
return resolve(plugin);
|
||||
})
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
|
||||
|
||||
export default shouldRenderCompo;
|
@ -55,6 +55,14 @@
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/autoReload",
|
||||
"handler": "ContentTypeBuilder.autoReload",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -191,5 +191,11 @@ module.exports = {
|
||||
} catch (err) {
|
||||
ctx.body = ctx.notFound();
|
||||
}
|
||||
},
|
||||
|
||||
autoReload: async ctx => {
|
||||
ctx.send({
|
||||
autoReload: _.get(strapi.config.environments, 'development.server.autoReload', false),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,21 @@
|
||||
import AutoReloadBlocker from 'components/AutoReloadBlocker';
|
||||
import ProductionBlocker from 'components/ProductionBlocker';
|
||||
import request from 'utils/request';
|
||||
|
||||
const shouldRenderCompo = (plugin) => new Promise((resolve, reject) => {
|
||||
request('/settings-manager/autoReload')
|
||||
.then(response => {
|
||||
plugin.preventComponentRendering = !response.autoReload;
|
||||
plugin.blockerComponent = AutoReloadBlocker;
|
||||
|
||||
if (response.environment !== 'development') {
|
||||
plugin.preventComponentRendering = true;
|
||||
plugin.blockerComponent = ProductionBlocker;
|
||||
}
|
||||
|
||||
return resolve(plugin);
|
||||
})
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
|
||||
export default shouldRenderCompo;
|
@ -111,6 +111,14 @@
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/autoReload",
|
||||
"handler": "SettingsManager.autoReload",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -336,5 +336,12 @@ module.exports = {
|
||||
} catch (err) {
|
||||
ctx.body = ctx.notFound();
|
||||
}
|
||||
},
|
||||
|
||||
autoReload: async ctx => {
|
||||
ctx.send({
|
||||
autoReload: _.get(strapi.config.environments, 'development.server.autoReload', false),
|
||||
environment: strapi.config.environment,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user