diff --git a/README.md b/README.md index 4b81eb2223..3b59930005 100755 --- a/README.md +++ b/README.md @@ -1,11 +1,23 @@ -![Logo](https://cldup.com/7umchwdUBh.png) +

+

API creation made simple, secure and fast.

+

The most advanced open-source Content Management Framework to build powerful API with no effort.

+
+

+ + Dependency Status + + + Dependency Status + + + Dependency Status + + + Dependency Status + +

-[![npm version](https://img.shields.io/npm/v/strapi.svg)](https://www.npmjs.org/package/strapi) -[![npm downloads](https://img.shields.io/npm/dm/strapi.svg)](https://www.npmjs.org/package/strapi) -[![Build status](https://travis-ci.org/strapi/strapi.svg?branch=master)](https://travis-ci.org/strapi/strapi) -[![Slack status](http://strapi-slack.herokuapp.com/badge.svg)](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. +
## 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. diff --git a/packages/strapi-admin/admin/src/app.js b/packages/strapi-admin/admin/src/app.js index 063f1a174f..68aed0cfe2 100755 --- a/packages/strapi-admin/admin/src/app.js +++ b/packages/strapi-admin/admin/src/app.js @@ -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)); } }; diff --git a/packages/strapi-admin/admin/src/containers/PluginPage/index.js b/packages/strapi-admin/admin/src/containers/PluginPage/index.js index 793596c0cc..a3e6aed737 100755 --- a/packages/strapi-admin/admin/src/containers/PluginPage/index.js +++ b/packages/strapi-admin/admin/src/containers/PluginPage/index.js @@ -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 ; } }); diff --git a/packages/strapi-admin/admin/src/translations/en.json b/packages/strapi-admin/admin/src/translations/en.json index 725671d08b..a83776608a 100755 --- a/packages/strapi-admin/admin/src/translations/en.json +++ b/packages/strapi-admin/admin/src/translations/en.json @@ -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." + } diff --git a/packages/strapi-admin/admin/src/translations/fr.json b/packages/strapi-admin/admin/src/translations/fr.json index c5bf22d06e..015d6b0f99 100755 --- a/packages/strapi-admin/admin/src/translations/fr.json +++ b/packages/strapi-admin/admin/src/translations/fr.json @@ -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." } diff --git a/packages/strapi-admin/config/admin.json b/packages/strapi-admin/config/admin.json index 2d2d20d05a..e55c6baf82 100644 --- a/packages/strapi-admin/config/admin.json +++ b/packages/strapi-admin/config/admin.json @@ -1,6 +1,3 @@ { - "languages": ["en", "fr"], - "plugins": { - "ports": [3000] - } + "languages": ["en", "fr"] } diff --git a/packages/strapi-admin/package.json b/packages/strapi-admin/package.json index c5b7fa75ca..c985dbbdef 100755 --- a/packages/strapi-admin/package.json +++ b/packages/strapi-admin/package.json @@ -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" @@ -66,4 +66,4 @@ "npm": ">= 3.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-helper-plugin/lib/src/app.js b/packages/strapi-helper-plugin/lib/src/app.js index 0c3a32336a..b77085f170 100755 --- a/packages/strapi-helper-plugin/lib/src/app.js +++ b/packages/strapi-helper-plugin/lib/src/app.js @@ -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 diff --git a/packages/strapi-helper-plugin/lib/src/components/AutoReloadBlocker/index.js b/packages/strapi-helper-plugin/lib/src/components/AutoReloadBlocker/index.js new file mode 100644 index 0000000000..b911a29b70 --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/components/AutoReloadBlocker/index.js @@ -0,0 +1,61 @@ +/** +* +* AutoReloadBlocker +* +*/ + +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import styles from './styles.scss'; + +function AutoReloadBlocker() { + return ( +
+
+
+ +

+ +

+

+ +

+
+

./config/environments/development/server.json

+
+
+                
+                  {
+                  
+  "host": "localhost", +
+  "port": 1337, +
+ +  "autoReload": true, + +
+  "proxi": { +
+   "enabled": true +
+  }, +
+  "cron": { +
+   "enabled": false +
+  } +
+ } +
+
+
+
+
+
+
+ ); +} + +export default AutoReloadBlocker; diff --git a/packages/strapi-helper-plugin/lib/src/components/AutoReloadBlocker/styles.scss b/packages/strapi-helper-plugin/lib/src/components/AutoReloadBlocker/styles.scss new file mode 100644 index 0000000000..d990cd9915 --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/components/AutoReloadBlocker/styles.scss @@ -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; + } + } + } +} diff --git a/packages/strapi-helper-plugin/lib/src/components/ProductionBlocker/index.js b/packages/strapi-helper-plugin/lib/src/components/ProductionBlocker/index.js new file mode 100644 index 0000000000..12743eaa3b --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/components/ProductionBlocker/index.js @@ -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 ( +
+
+
+

+ +

+

+ +

+
+ Read the documentation +
+
+
+
+ ); +} + +export default ProductionBlocker; diff --git a/packages/strapi-helper-plugin/lib/src/components/ProductionBlocker/styles.scss b/packages/strapi-helper-plugin/lib/src/components/ProductionBlocker/styles.scss new file mode 100644 index 0000000000..1d0b0d079e --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/components/ProductionBlocker/styles.scss @@ -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; + } +} +} diff --git a/packages/strapi-plugin-content-manager/admin/src/bootstrap.js b/packages/strapi-plugin-content-manager/admin/src/bootstrap.js new file mode 100644 index 0000000000..acc622fcb2 --- /dev/null +++ b/packages/strapi-plugin-content-manager/admin/src/bootstrap.js @@ -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; diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js index eda1f45056..c7dd29bd6f 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js @@ -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'); diff --git a/packages/strapi-plugin-content-manager/admin/src/requirements.js b/packages/strapi-plugin-content-manager/admin/src/requirements.js new file mode 100644 index 0000000000..fcf49dd7d8 --- /dev/null +++ b/packages/strapi-plugin-content-manager/admin/src/requirements.js @@ -0,0 +1,3 @@ +const shouldRenderCompo = (plugin) => Promise.resolve(plugin); + +export default shouldRenderCompo; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ContentHeader/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ContentHeader/index.js index 299c0843a7..a6d4887297 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/ContentHeader/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ContentHeader/index.js @@ -23,7 +23,7 @@ class ContentHeader extends React.Component { // eslint-disable-line react/prefe if (this.props.isLoading) { return (
-
); } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/requirements.js b/packages/strapi-plugin-content-type-builder/admin/src/requirements.js new file mode 100644 index 0000000000..0070ba9ceb --- /dev/null +++ b/packages/strapi-plugin-content-type-builder/admin/src/requirements.js @@ -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; diff --git a/packages/strapi-plugin-content-type-builder/config/routes.json b/packages/strapi-plugin-content-type-builder/config/routes.json index 9f2dca1ce1..857022ccf0 100755 --- a/packages/strapi-plugin-content-type-builder/config/routes.json +++ b/packages/strapi-plugin-content-type-builder/config/routes.json @@ -55,6 +55,14 @@ "config": { "policies": [] } + }, + { + "method": "GET", + "path": "/autoReload", + "handler": "ContentTypeBuilder.autoReload", + "config": { + "policies": [] + } } ] } diff --git a/packages/strapi-plugin-content-type-builder/controllers/ContentTypeBuilder.js b/packages/strapi-plugin-content-type-builder/controllers/ContentTypeBuilder.js index 299d4aa5d2..593b7c3c65 100755 --- a/packages/strapi-plugin-content-type-builder/controllers/ContentTypeBuilder.js +++ b/packages/strapi-plugin-content-type-builder/controllers/ContentTypeBuilder.js @@ -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), + }); } }; diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/index.js b/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/index.js index b2e2ea5a5c..f550cb653b 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/index.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/index.js @@ -322,7 +322,7 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre renderPopUpFormLanguage = (section) => ( map(section.items, (item) => { const value = this.props.home.modifiedData[item.target] || this.props.home.selectOptions.options[0].value; - + return (
diff --git a/packages/strapi-plugin-settings-manager/admin/src/requirements.js b/packages/strapi-plugin-settings-manager/admin/src/requirements.js new file mode 100644 index 0000000000..d6a78a0601 --- /dev/null +++ b/packages/strapi-plugin-settings-manager/admin/src/requirements.js @@ -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; diff --git a/packages/strapi-plugin-settings-manager/config/routes.json b/packages/strapi-plugin-settings-manager/config/routes.json index 6144471b58..8cc8f2451d 100755 --- a/packages/strapi-plugin-settings-manager/config/routes.json +++ b/packages/strapi-plugin-settings-manager/config/routes.json @@ -111,6 +111,14 @@ "config": { "policies": [] } + }, + { + "method": "GET", + "path": "/autoReload", + "handler": "SettingsManager.autoReload", + "config": { + "policies": [] + } } ] } diff --git a/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js b/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js index 12e1d74f1e..89ba85fa90 100755 --- a/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js +++ b/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js @@ -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, + }); } };