From 25c8aa66de71198f69250175e94935118bc86305 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Thu, 11 Jan 2018 14:23:44 +0100 Subject: [PATCH 01/25] Add helpers in documentation --- docs/3.x.x/en/plugin-development/utils.md | 57 +++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/3.x.x/en/plugin-development/utils.md b/docs/3.x.x/en/plugin-development/utils.md index ed2903421e..3d35014ec2 100644 --- a/docs/3.x.x/en/plugin-development/utils.md +++ b/docs/3.x.x/en/plugin-development/utils.md @@ -2,6 +2,63 @@ Strapi provides helpers so you don't have to develop again and again the same generic functions. +## Auth + +`auth.js` lets you get, set and delete data in either the browser's `localStorage` or `sessionStorage`. + +### Methods + +| Name | Description | +| ---- | ––––––––––– | +| clear(key) | Remove the data in either `localStorage` or `sessionStorage` | +| clearAppStorage() | Remove all data from both storage | +| clearToken() | Remove the user's `jwt Token` in the appropriate browser's storage | +| clearUserInfo() | Remove the user's info from storage | +| get(key) | Get the item in the browser's storage | +| getToken() | Get the user's `jwtToken` | +| getUserInfo() | Get the user's infos | +| set(value, key) | Set an item in the `sessionStorage`. If `true` is passed a 3rd parameter it sets the value in the `localStorage` | +| setToken(value) | Set the user's `jwtToken` in the `sessionStorage`. If `true` is passed a 3rd parameter it sets the value in the `localStorage` | +| setUserInfo(value) | Set the user's info in the `sessionStorage`. If `true` is passed a 3rd parameter it sets the value in the `localStorage` | + + +```js +import auth from 'utils/auth'; + +// ... +// +auth.setToken('12345', true); // This will set 1234 in the browser's localStorage associated with the key: jwtToken +``` + +## Colors + +This function allows to darken a color. + +### Usage + +```js +import { darken } from 'utils/colors'; + +const linkColor = darken('#f5f5f5', 1.5); // Will darken #F5F5F5 by 1.5% which gives #f2f2f2. +``` + +## Get URL Query Parameters + +The helpers allows to retrieve the query parameters in the URL + +### Example + +```js +import getQueryParameters from 'utils/getQueryParameters'; + +const URL = '/create?source=users-permissions'; +const source = getQueryParameters(URL, 'source'); + +console.log(source); // users-permissions + +``` + + ## Request helper A request helper is available to handle all requests inside a plugin. From 4dabad9c658c1ccc3898c4bcc7752c51254a59d3 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 10:56:16 +0100 Subject: [PATCH 02/25] Add server restart watcher to ctb when deleting content type --- .../admin/src/components/TableList/index.js | 8 +++++++- .../admin/src/components/TableListRow/index.js | 9 ++++++++- .../admin/src/containers/App/actions.js | 7 +++++++ .../admin/src/containers/App/constants.js | 1 + .../admin/src/containers/App/reducer.js | 4 ++++ .../admin/src/containers/App/sagas.js | 12 ++++++------ .../admin/src/containers/App/selectors.js | 8 +++++++- .../admin/src/containers/HomePage/index.js | 7 +++++-- 8 files changed, 45 insertions(+), 11 deletions(-) diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js index b72a07c1da..5b69d78509 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js @@ -45,7 +45,12 @@ class TableList extends React.Component { // eslint-disable-line react/prefer-st {map(this.props.rowItems, (rowItem, key) => ( - + ))} @@ -63,6 +68,7 @@ TableList.propTypes = { onHandleDelete: PropTypes.func.isRequired, rowItems: PropTypes.array.isRequired, title: PropTypes.string.isRequired, + toggleDeleteWarning: PropTypes.bool.isRequired, }; export default TableList; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js index 422e59327b..7e8e21bbba 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js @@ -23,6 +23,12 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer }; } + componentWillReceiveProps(nextProps) { + if (nextProps.toggleDeleteWarning !== this.props.toggleDeleteWarning) { + this.setState({ showWarning: false }); + } + } + handleEdit = () => { router.push(`/plugins/content-type-builder/#edit${this.props.rowItem.name}::contentType::baseSettings`); } @@ -31,7 +37,7 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer e.preventDefault(); e.stopPropagation(); this.props.onDelete(this.props.rowItem.name); - this.setState({ showWarning: false }); + // this.setState({ showWarning: false }); } handleGoTo = () => { @@ -73,6 +79,7 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer TableListRow.propTypes = { onDelete: PropTypes.func.isRequired, rowItem: PropTypes.object.isRequired, + toggleDeleteWarning: PropTypes.bool.isRequired, }; export default TableListRow; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js index 2c7c2ccef2..3a5f01f3b1 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js @@ -18,6 +18,7 @@ import { STORE_TEMPORARY_MENU, TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED, TEMPORARY_CONTENT_TYPE_POSTED, + TOGGLE_DELETE_WARNING, } from './constants'; export function deleteContentType(itemToDelete, context) { @@ -119,3 +120,9 @@ export function temporaryContentTypePosted(fieldNumber) { fieldNumber, }; } + +export function toggleDeleteWarning() { + return { + type: TOGGLE_DELETE_WARNING, + }; +} diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js index d521939d38..4119b1d1e8 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js @@ -10,3 +10,4 @@ export const MODELS_FETCH_SUCCEEDED = 'ContentTypeBuilder/App/MODELS_FETCH_SUCCE export const STORE_TEMPORARY_MENU = 'ContentTypeBuilder/App/STORE_TEMPORARY_MENU'; export const TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED = 'ContentTypeBuilder/App/TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED'; export const TEMPORARY_CONTENT_TYPE_POSTED = 'ContentTypeBuilder/App/TEMPORARY_CONTENT_TYPE_POSTED'; +export const TOGGLE_DELETE_WARNING = 'ContentTypeBuilder/App/TOGGLE_DELETE_WARNING'; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js index 59e2d6c303..d0842ca2cc 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js @@ -13,6 +13,7 @@ import { STORE_TEMPORARY_MENU, TEMPORARY_CONTENT_TYPE_POSTED, TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED, + TOGGLE_DELETE_WARNING, } from './constants'; /* eslint-disable new-cap */ @@ -20,6 +21,7 @@ const initialState = fromJS({ loading: true, menu: List(), models: List(), + toggleDeleteWarning: false, }); function appReducer(state = initialState, action) { @@ -58,6 +60,8 @@ function appReducer(state = initialState, action) { .updateIn(['menu', '0', 'items', size(state.getIn(['menu', '0', 'items']).toJS()) -2], () => newData) .updateIn(['models', size(state.get('models').toJS()) - 1], () => newModel); } + case TOGGLE_DELETE_WARNING: + return state.update('toggleDeleteWarning', (v) => !v); default: return state; } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js index 1bbc9a890e..da1d24b88b 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js @@ -1,22 +1,22 @@ import { takeLatest, call, put, fork } from 'redux-saga/effects'; import request from 'utils/request'; import { DELETE_CONTENT_TYPE, MODELS_FETCH } from './constants'; -import { modelsFetchSucceeded } from './actions'; +import { modelsFetchSucceeded, toggleDeleteWarning } from './actions'; export function* deleteContentType(action) { try { if (action.sendRequest) { const requestUrl = `/content-type-builder/models/${action.itemToDelete}`; + const response = yield call(request, requestUrl, { method: 'DELETE' }, true); - yield call(request, requestUrl, { method: 'DELETE' }); - - if (action.updateLeftMenu) { + if (response.ok && action.updateLeftMenu) { action.updatePlugin('content-manager', 'leftMenuSections', action.leftMenuContentTypes); + yield put(toggleDeleteWarning()); + strapi.notification.success('content-type-builder.notification.success.contentTypeDeleted'); } - strapi.notification.success('content-type-builder.notification.success.contentTypeDeleted'); } - } catch(error) { + yield put(toggleDeleteWarning()); strapi.notification.error('content-type-builder.notification.error.message'); } } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js index e8b3ce3ce9..6cc443b364 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js @@ -21,6 +21,11 @@ const makeSelectMenu = () => createSelector( (globalSate) => globalSate.get('menu').toJS(), ); +const makeSelectToggleDeleteWarning = () => createSelector( + selectGlobalDomain(), + (globalSate) => globalSate.get('toggleDeleteWarning'), +); + const selectLocationState = () => { let prevRoutingState; let prevRoutingStateJS; @@ -41,6 +46,7 @@ const selectLocationState = () => { export { selectLocationState, makeSelectLoading, - makeSelectModels, makeSelectMenu, + makeSelectModels, + makeSelectToggleDeleteWarning, }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js index 2e494b9a6b..dbf046e5b7 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js @@ -13,7 +13,7 @@ import Helmet from 'react-helmet'; import PropTypes from 'prop-types'; import { router } from 'app'; -import { makeSelectLoading, makeSelectMenu, makeSelectModels } from 'containers/App/selectors'; +import { makeSelectLoading, makeSelectMenu, makeSelectModels, makeSelectToggleDeleteWarning } from 'containers/App/selectors'; import { deleteContentType } from 'containers/App/actions'; import Form from 'containers/Form'; @@ -69,8 +69,9 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre title={title} buttonLabel={'content-type-builder.button.contentType.add'} onButtonClick={this.handleButtonClick} - rowItems={this.props.models} onHandleDelete={this.handleDelete} + rowItems={this.props.models} + toggleDeleteWarning={this.props.toggleDeleteWarning} /> ); } @@ -121,6 +122,7 @@ HomePage.propTypes = { PropTypes.object, PropTypes.array, ]).isRequired, + toggleDeleteWarning: PropTypes.bool.isRequired, }; const mapStateToProps = createStructuredSelector({ @@ -128,6 +130,7 @@ const mapStateToProps = createStructuredSelector({ modelsLoading: makeSelectLoading(), models: makeSelectModels(), menu: makeSelectMenu(), + toggleDeleteWarning: makeSelectToggleDeleteWarning(), }); function mapDispatchToProps(dispatch) { From 5b7c65e3ea8b4b990d7bd2c9a59a1d21c8999a9b Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 12:51:39 +0100 Subject: [PATCH 03/25] Redo OverlayBlocker design --- .../admin/src/containers/PluginPage/index.js | 2 +- .../admin/src/translations/en.json | 3 + .../admin/src/translations/fr.json | 3 + .../src/components/OverlayBlocker/index.js | 25 +++- .../src/components/OverlayBlocker/styles.scss | 112 +++++++++++++++++- .../admin/src/containers/App/index.js | 4 + .../admin/src/requirements.js | 3 +- 7 files changed, 146 insertions(+), 6 deletions(-) diff --git a/packages/strapi-admin/admin/src/containers/PluginPage/index.js b/packages/strapi-admin/admin/src/containers/PluginPage/index.js index 21f1ac44b9..8ef6a1d2a2 100755 --- a/packages/strapi-admin/admin/src/containers/PluginPage/index.js +++ b/packages/strapi-admin/admin/src/containers/PluginPage/index.js @@ -37,7 +37,7 @@ export class PluginPage extends React.Component { // eslint-disable-line react/p } return ( - + ); diff --git a/packages/strapi-admin/admin/src/translations/en.json b/packages/strapi-admin/admin/src/translations/en.json index 4182b2a794..ec0b96bff7 100755 --- a/packages/strapi-admin/admin/src/translations/en.json +++ b/packages/strapi-admin/admin/src/translations/en.json @@ -60,6 +60,9 @@ "components.ErrorBoundary.title": "Something wen't wrong...", + "components.OverlayBlocker.title": "Waiting for restart...", + "components.OverlayBlocker.description": "You're using a feature that needs the server to restart. Please wait until the server is up.", + "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 6d7fa2c743..6525f81a14 100755 --- a/packages/strapi-admin/admin/src/translations/fr.json +++ b/packages/strapi-admin/admin/src/translations/fr.json @@ -58,6 +58,9 @@ "components.AutoReloadBlocker.header": "L'autoReload doit être activé pour ce plugin.", "components.AutoReloadBlocker.description": "Ouvrez le fichier suivant pour activer cette fonctionnalité.", + "components.OverlayBlocker.title": "Le serveur est en train de redémarrer", + "components.OverlayBlocker.description": "Vous utilisez une fonctionnalité qui nécessite le redémarrage du server. Merci d'attendre que celui redémarré.", + "components.ErrorBoundary.title": "Une erreur est survenue...", "components.ProductionBlocker.header": "Ce plugin est disponible uniquement en développement.", diff --git a/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js b/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js index 6fa4f0d5d0..2db16a4575 100644 --- a/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js +++ b/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js @@ -7,6 +7,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; +import cn from 'classnames'; import styles from './styles.scss'; @@ -22,11 +24,32 @@ class OverlayBlocker extends React.Component { } render() { + const content = this.props.children ? ( + this.props.children + ) : ( +
+
+ +
+
+

+ +

+

+ +

+ +
+
+ ); + if (this.props.isOpen) { return ReactDOM.createPortal(
- {this.props.children} + {content}
, this.overlayContainer diff --git a/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/styles.scss b/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/styles.scss index 7db766be8d..e365f100cf 100644 --- a/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/styles.scss +++ b/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/styles.scss @@ -1,3 +1,35 @@ +.container { + display: flex; + justify-content: center; + > 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; + } + } +} + +.icoContainer { + padding-top: 0 !important; + font-size: 4.2rem; + color: #323740; + margin-right: 20px; + line-height: 9.3rem; + > i { + -webkit-animation:spin 4s linear infinite; + -moz-animation:spin 4s linear infinite; + animation:spin 4s linear infinite; + } +} + .overlay { position: fixed; top: 0; @@ -5,12 +37,86 @@ bottom: 0; left: 0; z-index: 1040; - background-color: rgba(0, 0, 0, 0.5); + &:before { + position: fixed; + content: ''; + top: 6rem; + right: 0; + bottom: 0; + left: 0; + background: linear-gradient(rgba(0,0,0, 15) 0%, rgba(0,0,0,0) 100%); + opacity: 0.5; + } + + &:after { + content:''; + position: fixed; + top: 6rem; + right: 0; + bottom: 0; + left: 24rem; + background: linear-gradient(#FBFBFB 20%, rgba(0, 0, 100, 0) 100%); + box-shadow: inset 0px 2px 4px rgba(0,0,0,0.1); + box-shadow: inset 0 1px 2px 0 rgba(40, 42, 49, 0.16); + } > div { position: fixed; - top: 17.5rem; + top: 11.5rem; left: 50%; - margin-left: -24rem; + margin-left: -17.5rem; + z-index: 1100; } } + +.buttonContainer { + padding-top: 3.9rem; + > a { + height: 30px; + font-size: 13px; + } +} + +.primary { + min-width: 15rem; + padding-top: 4px; + padding-left: 1.6rem; + padding-right: 1.6rem; + border-radius: 0.3rem; + border: none; + background: linear-gradient(315deg, #0097F6 0%, #005EEA 100%); + color: white; + font-family: Lato; + font-weight: 600; + -webkit-font-smoothing: antialiased; + cursor: pointer; + + > i { + margin-right: 1.3rem; + font-weight: 600; + padding-top: 1px; + } + &:before { + content: '\f02d'; + font-family: 'FontAwesome'; + font-weight: 600; + font-size: 1.3rem; + margin-right: 13px; + } + + &:active { + box-shadow: inset 1px 1px 3px rgba(0,0,0,.15); + } + + &:focus { + outline: 0; + } + + &:hover { + color: white; + } +} + +@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } } +@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } } +@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js index 042511b6e7..3bbba394f8 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js @@ -20,6 +20,9 @@ import NotFoundPage from 'containers/NotFoundPage'; import formSaga from 'containers/Form/sagas'; import formReducer from 'containers/Form/reducer'; +// Design +import OverlayBlocker from 'components/OverlayBlocker'; + import { makeSelectShouldRefetchContentType } from 'containers/Form/selectors'; // Utils @@ -52,6 +55,7 @@ class App extends React.Component { render() { 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 index c4078c45d0..a15db35433 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/requirements.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/requirements.js @@ -3,7 +3,8 @@ import request from 'utils/request'; const shouldRenderCompo = (plugin) => new Promise((resolve, reject) => { request(`${strapi.backendURL}/content-type-builder/autoReload`) .then(response => { - plugin.preventComponentRendering = !response.autoReload; + console.log(response.autoReload.enabled); + plugin.preventComponentRendering = !response.autoReload.enabled; plugin.blockerComponentProps = { blockerComponentTitle: 'components.AutoReloadBlocker.header', blockerComponentDescription: 'components.AutoReloadBlocker.description', From 696fe5b836351fe99039f1951e77d2af41ef073c Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 14:17:29 +0100 Subject: [PATCH 04/25] Add OverlayBlocker to ctb when deleting a model --- .../admin/src/components/TableList/index.js | 2 -- .../admin/src/components/TableListRow/index.js | 9 +-------- .../admin/src/containers/App/actions.js | 13 ++++++++++--- .../admin/src/containers/App/constants.js | 3 ++- .../admin/src/containers/App/index.js | 6 +++++- .../admin/src/containers/App/reducer.js | 11 +++++++---- .../admin/src/containers/App/sagas.js | 8 +++++--- .../admin/src/containers/App/selectors.js | 12 ++++++------ .../admin/src/containers/HomePage/index.js | 5 +---- .../admin/src/requirements.js | 1 - 10 files changed, 37 insertions(+), 33 deletions(-) diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js index 5b69d78509..3c33b1227f 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/TableList/index.js @@ -49,7 +49,6 @@ class TableList extends React.Component { // eslint-disable-line react/prefer-st key={key} onDelete={this.props.onHandleDelete} rowItem={rowItem} - toggleDeleteWarning={this.props.toggleDeleteWarning} /> ))} @@ -68,7 +67,6 @@ TableList.propTypes = { onHandleDelete: PropTypes.func.isRequired, rowItems: PropTypes.array.isRequired, title: PropTypes.string.isRequired, - toggleDeleteWarning: PropTypes.bool.isRequired, }; export default TableList; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js index 7e8e21bbba..422e59327b 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/index.js @@ -23,12 +23,6 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer }; } - componentWillReceiveProps(nextProps) { - if (nextProps.toggleDeleteWarning !== this.props.toggleDeleteWarning) { - this.setState({ showWarning: false }); - } - } - handleEdit = () => { router.push(`/plugins/content-type-builder/#edit${this.props.rowItem.name}::contentType::baseSettings`); } @@ -37,7 +31,7 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer e.preventDefault(); e.stopPropagation(); this.props.onDelete(this.props.rowItem.name); - // this.setState({ showWarning: false }); + this.setState({ showWarning: false }); } handleGoTo = () => { @@ -79,7 +73,6 @@ class TableListRow extends React.Component { // eslint-disable-line react/prefer TableListRow.propTypes = { onDelete: PropTypes.func.isRequired, rowItem: PropTypes.object.isRequired, - toggleDeleteWarning: PropTypes.bool.isRequired, }; export default TableListRow; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js index 3a5f01f3b1..01d9e4eab1 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js @@ -13,12 +13,13 @@ import { storeData } from '../../utils/storeData'; import { DELETE_CONTENT_TYPE, + FREEZE_APP, MODELS_FETCH, MODELS_FETCH_SUCCEEDED, STORE_TEMPORARY_MENU, TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED, TEMPORARY_CONTENT_TYPE_POSTED, - TOGGLE_DELETE_WARNING, + UNFREEZE_APP, } from './constants'; export function deleteContentType(itemToDelete, context) { @@ -57,6 +58,12 @@ export function deleteContentType(itemToDelete, context) { }; } +export function freezeApp() { + return { + type: FREEZE_APP, + }; +} + export function modelsFetch() { return { type: MODELS_FETCH, @@ -121,8 +128,8 @@ export function temporaryContentTypePosted(fieldNumber) { }; } -export function toggleDeleteWarning() { +export function unfreezeApp() { return { - type: TOGGLE_DELETE_WARNING, + type: UNFREEZE_APP, }; } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js index 4119b1d1e8..f7186b06b0 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js @@ -5,9 +5,10 @@ */ export const DELETE_CONTENT_TYPE = 'ContentTypeBuilder/App/DELETE_CONTENT_TYPE'; +export const FREEZE_APP = 'ContentTypeBuilder/App/FREEZE_APP'; export const MODELS_FETCH = 'ContentTypeBuilder/App/MODELS_FETCH'; export const MODELS_FETCH_SUCCEEDED = 'ContentTypeBuilder/App/MODELS_FETCH_SUCCEEDED'; export const STORE_TEMPORARY_MENU = 'ContentTypeBuilder/App/STORE_TEMPORARY_MENU'; export const TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED = 'ContentTypeBuilder/App/TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED'; export const TEMPORARY_CONTENT_TYPE_POSTED = 'ContentTypeBuilder/App/TEMPORARY_CONTENT_TYPE_POSTED'; -export const TOGGLE_DELETE_WARNING = 'ContentTypeBuilder/App/TOGGLE_DELETE_WARNING'; +export const UNFREEZE_APP = 'ContentTypeBuilder/App/UNFREEZE_APP'; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js index 3bbba394f8..0ae4243262 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js @@ -23,6 +23,7 @@ import formReducer from 'containers/Form/reducer'; // Design import OverlayBlocker from 'components/OverlayBlocker'; +// Other containers actions import { makeSelectShouldRefetchContentType } from 'containers/Form/selectors'; // Utils @@ -32,6 +33,7 @@ import { storeData } from '../../utils/storeData'; import styles from './styles.scss'; import { modelsFetch } from './actions'; +import { makeSelectBlockApp } from './selectors'; import saga from './sagas'; /* eslint-disable consistent-return */ @@ -55,7 +57,7 @@ class App extends React.Component { render() { return (
- + @@ -73,6 +75,7 @@ App.contextTypes = { }; App.propTypes = { + blockApp: PropTypes.bool.isRequired, modelsFetch: PropTypes.func.isRequired, shouldRefetchContentType: PropTypes.bool, }; @@ -91,6 +94,7 @@ export function mapDispatchToProps(dispatch) { } const mapStateToProps = createStructuredSelector({ + blockApp: makeSelectBlockApp(), shouldRefetchContentType: makeSelectShouldRefetchContentType(), }); diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js index d0842ca2cc..1e021d8d63 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js @@ -8,20 +8,21 @@ import { fromJS, List } from 'immutable'; import { findIndex, size } from 'lodash'; import { DELETE_CONTENT_TYPE, + FREEZE_APP, MODELS_FETCH, MODELS_FETCH_SUCCEEDED, STORE_TEMPORARY_MENU, TEMPORARY_CONTENT_TYPE_POSTED, TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED, - TOGGLE_DELETE_WARNING, + UNFREEZE_APP, } from './constants'; /* eslint-disable new-cap */ const initialState = fromJS({ + blockApp: false, loading: true, menu: List(), models: List(), - toggleDeleteWarning: false, }); function appReducer(state = initialState, action) { @@ -30,6 +31,8 @@ function appReducer(state = initialState, action) { return state .updateIn(['menu', '0', 'items'], (list) => list.splice(findIndex(state.getIn(['menu', '0', 'items']).toJS(), ['name', action.itemToDelete]), 1)) .update('models', (array) => array.splice(findIndex(state.get('models').toJS(), ['name', action.itemToDelete]), 1)); + case FREEZE_APP: + return state.set('blockApp', true); case MODELS_FETCH: return state.set('loading', true); case MODELS_FETCH_SUCCEEDED: @@ -60,8 +63,8 @@ function appReducer(state = initialState, action) { .updateIn(['menu', '0', 'items', size(state.getIn(['menu', '0', 'items']).toJS()) -2], () => newData) .updateIn(['models', size(state.get('models').toJS()) - 1], () => newModel); } - case TOGGLE_DELETE_WARNING: - return state.update('toggleDeleteWarning', (v) => !v); + case UNFREEZE_APP: + return state.set('blockApp', false); default: return state; } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js index da1d24b88b..9f150899e9 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js @@ -1,22 +1,24 @@ import { takeLatest, call, put, fork } from 'redux-saga/effects'; import request from 'utils/request'; import { DELETE_CONTENT_TYPE, MODELS_FETCH } from './constants'; -import { modelsFetchSucceeded, toggleDeleteWarning } from './actions'; +import { freezeApp, modelsFetchSucceeded, unfreezeApp } from './actions'; export function* deleteContentType(action) { try { if (action.sendRequest) { + // Display the OverlayBlocker + yield put(freezeApp()); const requestUrl = `/content-type-builder/models/${action.itemToDelete}`; const response = yield call(request, requestUrl, { method: 'DELETE' }, true); if (response.ok && action.updateLeftMenu) { action.updatePlugin('content-manager', 'leftMenuSections', action.leftMenuContentTypes); - yield put(toggleDeleteWarning()); + yield put(unfreezeApp()); strapi.notification.success('content-type-builder.notification.success.contentTypeDeleted'); } } } catch(error) { - yield put(toggleDeleteWarning()); + yield put(unfreezeApp()); strapi.notification.error('content-type-builder.notification.error.message'); } } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js index 6cc443b364..d3533a3693 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js @@ -6,6 +6,11 @@ import { createSelector } from 'reselect'; const selectGlobalDomain = () => state => state.get('global'); +const makeSelectBlockApp = () => createSelector( + selectGlobalDomain(), + (globalSate) => globalSate.get('blockApp'), +); + const makeSelectLoading = () => createSelector( selectGlobalDomain(), (globalSate) => globalSate.get('loading'), @@ -21,11 +26,6 @@ const makeSelectMenu = () => createSelector( (globalSate) => globalSate.get('menu').toJS(), ); -const makeSelectToggleDeleteWarning = () => createSelector( - selectGlobalDomain(), - (globalSate) => globalSate.get('toggleDeleteWarning'), -); - const selectLocationState = () => { let prevRoutingState; let prevRoutingStateJS; @@ -45,8 +45,8 @@ const selectLocationState = () => { export { selectLocationState, + makeSelectBlockApp, makeSelectLoading, makeSelectMenu, makeSelectModels, - makeSelectToggleDeleteWarning, }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js index dbf046e5b7..24f8de6ed1 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/HomePage/index.js @@ -13,7 +13,7 @@ import Helmet from 'react-helmet'; import PropTypes from 'prop-types'; import { router } from 'app'; -import { makeSelectLoading, makeSelectMenu, makeSelectModels, makeSelectToggleDeleteWarning } from 'containers/App/selectors'; +import { makeSelectLoading, makeSelectMenu, makeSelectModels } from 'containers/App/selectors'; import { deleteContentType } from 'containers/App/actions'; import Form from 'containers/Form'; @@ -71,7 +71,6 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre onButtonClick={this.handleButtonClick} onHandleDelete={this.handleDelete} rowItems={this.props.models} - toggleDeleteWarning={this.props.toggleDeleteWarning} /> ); } @@ -122,7 +121,6 @@ HomePage.propTypes = { PropTypes.object, PropTypes.array, ]).isRequired, - toggleDeleteWarning: PropTypes.bool.isRequired, }; const mapStateToProps = createStructuredSelector({ @@ -130,7 +128,6 @@ const mapStateToProps = createStructuredSelector({ modelsLoading: makeSelectLoading(), models: makeSelectModels(), menu: makeSelectMenu(), - toggleDeleteWarning: makeSelectToggleDeleteWarning(), }); function mapDispatchToProps(dispatch) { diff --git a/packages/strapi-plugin-content-type-builder/admin/src/requirements.js b/packages/strapi-plugin-content-type-builder/admin/src/requirements.js index a15db35433..4959964937 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/requirements.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/requirements.js @@ -3,7 +3,6 @@ import request from 'utils/request'; const shouldRenderCompo = (plugin) => new Promise((resolve, reject) => { request(`${strapi.backendURL}/content-type-builder/autoReload`) .then(response => { - console.log(response.autoReload.enabled); plugin.preventComponentRendering = !response.autoReload.enabled; plugin.blockerComponentProps = { blockerComponentTitle: 'components.AutoReloadBlocker.header', From 7ae1cc944e211735556ded42c6d6b8e6545ae2a7 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 14:42:47 +0100 Subject: [PATCH 05/25] Freeze app when add/modifying a field in ctb --- .../admin/src/containers/ModelPage/sagas.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js index a6c4d9bc81..daceb084c7 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js @@ -18,7 +18,7 @@ import { takeLatest, call, take, put, fork, cancel, select } from 'redux-saga/ef import request from 'utils/request'; -import { temporaryContentTypePosted } from 'containers/App/actions'; +import { freezeApp, temporaryContentTypePosted, unfreezeApp } from 'containers/App/actions'; import { storeData } from '../../utils/storeData'; @@ -74,6 +74,7 @@ export function* submitChanges(action) { try { // Show button loader yield put(setButtonLoader()); + yield put(freezeApp()); const modelName = get(storeData.getContentType(), 'name'); const data = yield select(makeSelectModel()); @@ -140,10 +141,11 @@ export function* submitChanges(action) { } yield put(submitActionSucceeded()); - yield put(resetShowButtonsProps()); // Remove loader yield put(unsetButtonLoader()); + // Unfreeze app + yield put(unfreezeApp()); } } catch(error) { From 967f3e672508827e316ca92c246a7bb470e3f16a Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 17:20:19 +0100 Subject: [PATCH 06/25] Add OverlayBlocker in all actions that require restart server in ctb, comment ModelPage willUpdate lifecycle that redirects the user to /404 when updating a content type name --- .../admin/src/containers/Form/index.js | 1 + .../admin/src/containers/Form/sagas.js | 5 +++ .../admin/src/containers/ModelPage/index.js | 40 +++++++++---------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js index 9b5f5e8348..d1bb3174fe 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js @@ -254,6 +254,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer- this.props.contentTypeCreate(contentType); } + this.setState({ showModal: false }); return this.props.contentTypeEdit(this.context); } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js index 4870e3655e..8053ba1425 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js @@ -3,6 +3,8 @@ import { capitalize, findIndex, get, isEmpty, sortBy } from 'lodash'; import { takeLatest, call, put, fork, select } from 'redux-saga/effects'; import request from 'utils/request'; +import { freezeApp, unfreezeApp } from 'containers/App/actions'; + import { connectionsFetchSucceeded, contentTypeActionSucceeded, @@ -25,6 +27,7 @@ import { export function* editContentType(action) { try { const initialContentType = yield select(makeSelectInitialDataEdit()); + yield put(freezeApp()); const requestUrl = `/content-type-builder/models/${initialContentType.name}`; const body = yield select(makeSelectModifiedDataEdit()); const opts = { @@ -55,8 +58,10 @@ export function* editContentType(action) { action.context.updatePlugin('content-manager', 'leftMenuSections', leftMenuContentTypes); } strapi.notification.success('content-type-builder.notification.success.message.contentType.edit'); + yield put(unfreezeApp()); } } catch(error) { + yield put(unfreezeApp()); strapi.notification.error(get(error, ['response', 'payload', 'message'], 'notification.error')); } } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/index.js index f6fba9d323..ae493b014c 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/index.js @@ -76,8 +76,6 @@ export class ModelPage extends React.Component { // eslint-disable-line react/pr if (this.props.updatedContentType !== nextProps.updatedContentType) { if (this.state.contentTypeTemporary && storeData.getContentType()) { this.props.modelFetchSucceeded({ model: storeData.getContentType() }); - } else { - this.fetchModel(nextProps); } } @@ -86,24 +84,24 @@ export class ModelPage extends React.Component { // eslint-disable-line react/pr } } - componentWillUpdate(nextProps) { - if (!isEmpty(nextProps.menu)) { - const allowedPaths = nextProps.menu.reduce((acc, current) => { - const models = current.items.reduce((acc, current) => { - acc.push(current.name); - - return acc; - }, []); - return acc.concat(models); - }, []); - - const shouldRedirect = allowedPaths.filter(el => el === this.props.match.params.modelName.split('&')[0]).length === 0; - - if (shouldRedirect) { - this.props.history.push('/404'); - } - } - } + // componentWillUpdate(nextProps) { + // if (!isEmpty(nextProps.menu)) { + // const allowedPaths = nextProps.menu.reduce((acc, current) => { + // const models = current.items.reduce((acc, current) => { + // acc.push(current.name); + // + // return acc; + // }, []); + // return acc.concat(models); + // }, []); + // + // const shouldRedirect = allowedPaths.filter(el => el === this.props.match.params.modelName.split('&')[0]).length === 0; + // + // if (shouldRedirect) { + // this.props.history.push('/404'); + // } + // } + // } componentDidUpdate(prevProps) { if (prevProps.match.params.modelName !== this.props.match.params.modelName) { @@ -347,7 +345,7 @@ ModelPage.propTypes = { cancelChanges: PropTypes.func.isRequired, checkIfTableExists: PropTypes.func.isRequired, deleteAttribute: PropTypes.func.isRequired, - history: PropTypes.object.isRequired, + // history: PropTypes.object.isRequired, location: PropTypes.object.isRequired, match: PropTypes.object.isRequired, menu: PropTypes.array.isRequired, From e49ae84b97505b310106818db22c68a2b1ec0fa5 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 17:35:00 +0100 Subject: [PATCH 07/25] Add OverlayBlocker to stm --- .../admin/src/containers/App/actions.js | 45 ++++++++++++------- .../admin/src/containers/App/constants.js | 6 ++- .../admin/src/containers/App/index.js | 6 ++- .../admin/src/containers/App/reducer.js | 13 ++++-- .../admin/src/containers/App/selectors.js | 13 +++++- .../admin/src/containers/HomePage/sagas.js | 28 ++++++++++-- 6 files changed, 85 insertions(+), 26 deletions(-) diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js index 192122218e..8eb247cb3f 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js @@ -5,26 +5,14 @@ */ import { - MENU_FETCH, ENVIRONMENTS_FETCH, - MENU_FETCH_SUCCEEDED, ENVIRONMENTS_FETCH_SUCCEEDED, + FREEZE_APP, + MENU_FETCH_SUCCEEDED, + MENU_FETCH, + UNFREEZE_APP, } from './constants'; - -export function menuFetch() { - return { - type: MENU_FETCH, - }; -} - -export function fetchMenuSucceeded(menu) { - return { - type: MENU_FETCH_SUCCEEDED, - menu, - }; -} - export function environmentsFetch() { return { type: ENVIRONMENTS_FETCH, @@ -37,3 +25,28 @@ export function environmentsFetchSucceeded(environments) { environments, }; } + +export function freezeApp() { + return { + type: FREEZE_APP, + }; +} + +export function fetchMenuSucceeded(menu) { + return { + type: MENU_FETCH_SUCCEEDED, + menu, + }; +} + +export function menuFetch() { + return { + type: MENU_FETCH, + }; +} + +export function unfreezeApp() { + return { + type: UNFREEZE_APP, + }; +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js index 9af5e8ea19..94e5bbabf6 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js @@ -4,7 +4,9 @@ * */ -export const MENU_FETCH = 'SettingsManager/App/MENU_FETCH'; export const ENVIRONMENTS_FETCH = 'SettingsManager/App/ENVIRONMENTS_FETCH'; -export const MENU_FETCH_SUCCEEDED = 'SettingsManager/App/MENU_FETCH_SUCCEEDED'; export const ENVIRONMENTS_FETCH_SUCCEEDED = 'SettingsManager/App/ENVIRONMENTS_FETCH_SUCCEEDED'; +export const FREEZE_APP = 'SettingsManager/App/FREEZE_APP'; +export const MENU_FETCH = 'SettingsManager/App/MENU_FETCH'; +export const MENU_FETCH_SUCCEEDED = 'SettingsManager/App/MENU_FETCH_SUCCEEDED'; +export const UNFREEZE_APP = 'SettingsManager/App/UNFREEZE_APP'; diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js index 4df01e3935..26c30a5e22 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js @@ -19,9 +19,10 @@ import { pluginId } from 'app'; import injectSaga from 'utils/injectSaga'; import HomePage from 'containers/HomePage'; +import OverlayBlocker from 'components/OverlayBlocker'; import { menuFetch, environmentsFetch } from './actions'; -import { makeSelectLoading, makeSelectSections } from './selectors'; +import { makeSelectBlockApp, makeSelectLoading, makeSelectSections } from './selectors'; import styles from './styles.scss'; import saga from './sagas'; @@ -56,6 +57,7 @@ class App extends React.Component { render() { return (
+ @@ -71,6 +73,7 @@ App.contextTypes = { }; App.propTypes = { + blockApp: PropTypes.bool.isRequired, environmentsFetch: PropTypes.func.isRequired, history: PropTypes.object.isRequired, menuFetch: PropTypes.func.isRequired, @@ -88,6 +91,7 @@ export function mapDispatchToProps(dispatch) { } const mapStateToProps = createStructuredSelector({ + blockApp: makeSelectBlockApp(), loading: makeSelectLoading(), sections: makeSelectSections(), }); diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js index 7a2e4b4eed..8f42bd3954 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js @@ -6,12 +6,15 @@ import { fromJS, List } from 'immutable'; import { - MENU_FETCH_SUCCEEDED, ENVIRONMENTS_FETCH_SUCCEEDED, + FREEZE_APP, + MENU_FETCH_SUCCEEDED, + UNFREEZE_APP, } from './constants'; /* eslint-disable new-cap */ const initialState = fromJS({ + blockApp: false, sections: List(), // eslint-disable-line new-cap environments: List(), loading: true, @@ -19,11 +22,15 @@ const initialState = fromJS({ function appReducer(state = initialState, action) { switch (action.type) { - case MENU_FETCH_SUCCEEDED: - return state.set('sections', List(action.menu.sections)).set('loading', false); case ENVIRONMENTS_FETCH_SUCCEEDED: return state .set('environments', List(action.environments.environments)); + case FREEZE_APP: + return state.set('blockApp', true); + case MENU_FETCH_SUCCEEDED: + return state.set('sections', List(action.menu.sections)).set('loading', false); + case UNFREEZE_APP: + return state.set('blockApp', false); default: return state; } diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js index 832273de5c..5690c7d9b4 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js @@ -22,6 +22,11 @@ const selectLocationState = () => { }; }; +const makeSelectBlockApp = () => createSelector( + selectGlobalDomain(), + (globalSate) => globalSate.get('blockApp'), +); + const makeSelectSections = () => createSelector( selectGlobalDomain(), (globalSate) => globalSate.get('sections').toJS(), @@ -37,5 +42,11 @@ const makeSelectLoading = () => createSelector( (globalSate) => globalSate.get('loading'), ); -export { selectLocationState, makeSelectSections, makeSelectEnvironments, makeSelectLoading }; +export { + makeSelectBlockApp, + makeSelectEnvironments, + makeSelectLoading, + makeSelectSections, + selectLocationState, +}; export default selectGlobalDomain; diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js b/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js index 6c2155133d..2a32a1b5f0 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js @@ -2,6 +2,8 @@ import { LOCATION_CHANGE } from 'react-router-redux'; import { forEach, set, map, replace } from 'lodash'; import { call, take, put, fork, cancel, select, takeLatest } from 'redux-saga/effects'; + +import { freezeApp, unfreezeApp } from 'containers/App/actions'; import request from 'utils/request'; // selectors @@ -38,6 +40,8 @@ import { export function* editDatabase(action) { try { + yield put(freezeApp()); + const body = {}; forEach(action.data, (value, key) => { @@ -54,11 +58,13 @@ export function* editDatabase(action) { if (resp.ok) { strapi.notification.success('settings-manager.strapi.notification.success.databaseEdit'); + yield put(unfreezeApp()); yield put(databaseActionSucceeded()); } } catch(error) { const formErrors = map(error.response.payload.message, err => ({ target: err.target, errors: map(err.messages, mess => ({ id: `settings-manager.${mess.id}`})) })); + yield put(unfreezeApp()); yield put(databaseActionError(formErrors)); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -66,15 +72,18 @@ export function* editDatabase(action) { export function* deleteDatabase(action) { try { + yield put(freezeApp()); const opts = { method: 'DELETE' }; const requestUrl = `/settings-manager/configurations/databases/${action.databaseToDelete}/${action.endPoint}`; const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { + yield put(unfreezeApp()); strapi.notification.success('settings-manager.strapi.notification.success.databaseDeleted'); } } catch(error) { + yield put(unfreezeApp()); yield put(databaseActionError([])); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -82,6 +91,7 @@ export function* deleteDatabase(action) { export function* deleteLanguage(action) { try { + yield put(freezeApp()); const opts = { method: 'DELETE', }; @@ -90,9 +100,11 @@ export function* deleteLanguage(action) { const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { + yield put(unfreezeApp()); strapi.notification.success('settings-manager.strapi.notification.success.languageDelete'); } } catch(error) { + yield put(unfreezeApp()); yield put(languageActionError()); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -151,6 +163,8 @@ export function* fetchLanguages() { export function* postLanguage() { try { + yield put(freezeApp()); + const newLanguage = yield select(makeSelectModifiedData()); const body = { @@ -165,10 +179,12 @@ export function* postLanguage() { const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { - strapi.notification.success('settings-manager.strapi.notification.success.languageAdd'); yield put(languageActionSucceeded()); + yield put(unfreezeApp()); + strapi.notification.success('settings-manager.strapi.notification.success.languageAdd'); } } catch(error) { + yield put(unfreezeApp()); yield put(languageActionError()); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -176,6 +192,7 @@ export function* postLanguage() { export function* postDatabase(action) { try { + yield put(freezeApp()); const body = {}; forEach(action.data, (value, key) => { @@ -191,6 +208,7 @@ export function* postDatabase(action) { const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { + yield put(unfreezeApp()); yield put(databaseActionSucceeded()); strapi.notification.success('settings-manager.strapi.notification.success.databaseAdd'); } @@ -210,6 +228,7 @@ export function* postDatabase(action) { export function* settingsEdit(action) { try { + yield put(freezeApp()); // Show button loader yield put(setLoader()); @@ -221,13 +240,16 @@ export function* settingsEdit(action) { const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { - strapi.notification.success('settings-manager.strapi.notification.success.settingsEdit'); yield put(editSettingsSucceeded()); yield put(unsetLoader()); + yield put(unfreezeApp()); + + strapi.notification.success('settings-manager.strapi.notification.success.settingsEdit'); } } catch(error) { - strapi.notification.error('settings-manager.strapi.notification.error'); yield put(unsetLoader()); + yield put(unfreezeApp()); + strapi.notification.error('settings-manager.strapi.notification.error'); } } From 977a79eaff7049491a7028fefb63889f9ba89a20 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 17:50:18 +0100 Subject: [PATCH 08/25] Fix up plugin required props error --- .../admin/src/components/Plugin/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi-plugin-users-permissions/admin/src/components/Plugin/index.js b/packages/strapi-plugin-users-permissions/admin/src/components/Plugin/index.js index 5d67e2e0e5..946e1e048d 100644 --- a/packages/strapi-plugin-users-permissions/admin/src/components/Plugin/index.js +++ b/packages/strapi-plugin-users-permissions/admin/src/components/Plugin/index.js @@ -117,7 +117,7 @@ Plugin.propTypes = { plugin: PropTypes.shape({ description: PropTypes.string, information: PropTypes.shape({ - logo: PropTypes.string.isRequired, + logo: PropTypes.string, }), }), pluginSelected: PropTypes.string.isRequired, From 100c70a2acf6b8201ac1270b53956a1e50f6a0fb Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Fri, 12 Jan 2018 17:53:48 +0100 Subject: [PATCH 09/25] Change OverlayBlocker doc url --- .../lib/src/components/OverlayBlocker/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js b/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js index 2db16a4575..ea507dad36 100644 --- a/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js +++ b/packages/strapi-helper-plugin/lib/src/components/OverlayBlocker/index.js @@ -39,7 +39,7 @@ class OverlayBlocker extends React.Component {

From c838b90e2123617248434a5c86f17b4e87f771b1 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Mon, 15 Jan 2018 11:07:40 +0100 Subject: [PATCH 10/25] Add serverRestart to users-permissions --- .../admin/src/containers/EditPage/saga.js | 2 +- .../admin/src/containers/HomePage/saga.js | 2 +- .../controllers/UsersPermissions.js | 17 ++++++++++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js index b3f8289b26..2a4dd646dd 100644 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js @@ -98,7 +98,7 @@ export function* submit() { }; const requestURL = actionType === 'POST' ? '/users-permissions/roles' : `/users-permissions/roles/${roleId}`; - const response = yield call(request, requestURL, opts); + const response = yield call(request, requestURL, opts, true); if (response.ok) { yield put(submitSucceeded()); diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js index 63f0bf88c1..525318b740 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js @@ -33,7 +33,7 @@ export function* dataDelete() { const id = dataToDelete.id; const requestURL = `/users-permissions/${endPointAPI}/${id}`; // TODO watchServerRestart - const response = yield call(request, requestURL, { method: 'DELETE' }); + const response = yield call(request, requestURL, { method: 'DELETE' }, true); if (response.ok) { yield put(deleteDataSucceeded(indexDataToDelete)); diff --git a/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js b/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js index da6c037a06..2480d3ed98 100644 --- a/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js +++ b/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js @@ -20,9 +20,14 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } + strapi.reload.isWatching = false; + try { await strapi.plugins['users-permissions'].services.userspermissions.createRole(ctx.request.body); + ctx.send({ ok: true }); + + strapi.reload(); } catch(err) { ctx.badRequest(null, [{ messages: [{ id: 'An error occured' }] }]); } @@ -50,9 +55,14 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Unauthorized' }] }]); } + strapi.reload.isWatching = false; + try { await strapi.plugins['users-permissions'].services.userspermissions.deleteRole(role); - return ctx.send({ ok: true }); + + ctx.send({ ok: true }); + + strapi.reload(); } catch(err) { return ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]); } @@ -139,9 +149,14 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]); } + strapi.reload.isWatching = false; + try { await strapi.plugins['users-permissions'].services.userspermissions.updateRole(roleId, ctx.request.body); + ctx.send({ ok: true }); + + strapi.reload(); } catch(error) { ctx.badRequest(null, [{ messages: [{ id: 'An error occurred' }] }]); } From 17fd135ac1047e8c15c46edb4404fe93551a0745 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Mon, 15 Jan 2018 11:28:43 +0100 Subject: [PATCH 11/25] Add overlayBlocker when deleting a role in users plugin --- .../admin/src/components/List/index.js | 4 +--- .../admin/src/components/ListRow/index.js | 12 ++++-------- .../admin/src/containers/App/actions.js | 17 +++++++++++++++++ .../admin/src/containers/App/constants.js | 3 +++ .../admin/src/containers/App/index.js | 9 ++++++++- .../admin/src/containers/App/reducer.js | 12 +++++++++++- .../admin/src/containers/App/selectors.js | 13 ++++++++++--- .../admin/src/containers/HomePage/index.js | 2 -- .../admin/src/containers/HomePage/reducer.js | 4 +--- .../admin/src/containers/HomePage/saga.js | 8 +++++++- 10 files changed, 62 insertions(+), 22 deletions(-) diff --git a/packages/strapi-plugin-users-permissions/admin/src/components/List/index.js b/packages/strapi-plugin-users-permissions/admin/src/components/List/index.js index 948e1d35b9..fb7191e4b4 100644 --- a/packages/strapi-plugin-users-permissions/admin/src/components/List/index.js +++ b/packages/strapi-plugin-users-permissions/admin/src/components/List/index.js @@ -48,7 +48,7 @@ const generateListTitle = (data, settingType) => { } }; -function List({ data, deleteActionSucceeded, deleteData, noButton, onButtonClick, settingType }) { +function List({ data, deleteData, noButton, onButtonClick, settingType }) { return (
@@ -69,7 +69,6 @@ function List({ data, deleteActionSucceeded, deleteData, noButton, onButtonClick
    {map(data, item => ( this.props.deleteData(this.props.item, this.props.settingType); + handleDelete = () => { + this.props.deleteData(this.props.item, this.props.settingType); + this.setState({ showModalDelete: false }); + } render() { return ( @@ -176,7 +173,6 @@ ListRow.defaultProps = { }; ListRow.propTypes = { - deleteActionSucceeded: PropTypes.bool.isRequired, deleteData: PropTypes.func.isRequired, item: PropTypes.object, settingType: PropTypes.string, diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js index a5002ad023..8d6fdc3171 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js @@ -3,3 +3,20 @@ * App actions * */ + +import { + FREEZE_APP, + UNFREEZE_APP, +} from './constants'; + +export function freezeApp() { + return { + type: FREEZE_APP, + }; +} + +export function unfreezeApp() { + return { + type: UNFREEZE_APP, + }; +} diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js index f62c609507..8181110dba 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js @@ -3,3 +3,6 @@ * App constants * */ + +export const FREEZE_APP = 'UsersPermissions/App/FREEZE_APP'; +export const UNFREEZE_APP = 'UsersPermissions/App/UNFREEZE_APP'; diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js index 16efbef769..d3ede1b929 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js @@ -20,6 +20,9 @@ import AuthPage from 'containers/AuthPage'; import EditPage from 'containers/EditPage'; import HomePage from 'containers/HomePage'; import NotFoundPage from 'containers/NotFoundPage'; +import OverlayBlocker from 'components/OverlayBlocker'; + +import { makeSelectBlockApp } from './selectors'; class App extends React.Component { componentDidMount() { @@ -37,6 +40,7 @@ class App extends React.Component { render() { return (
    + @@ -55,6 +59,7 @@ App.contextTypes = { }; App.propTypes = { + blockApp: PropTypes.bool.isRequired, history: PropTypes.object.isRequired, location: PropTypes.object.isRequired, }; @@ -66,7 +71,9 @@ export function mapDispatchToProps(dispatch) { ); } -const mapStateToProps = createStructuredSelector({}); +const mapStateToProps = createStructuredSelector({ + blockApp: makeSelectBlockApp(), +}); // Wrap the component to inject dispatch and state into it const withConnect = connect(mapStateToProps, mapDispatchToProps); diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js index 38026c39cd..ab8fc9825b 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js @@ -5,11 +5,21 @@ */ import { fromJS } from 'immutable'; +import { + FREEZE_APP, + UNFREEZE_APP, +} from './constants'; -const initialState = fromJS({}); +const initialState = fromJS({ + blockApp: false, +}); function appReducer(state = initialState, action) { switch (action.type) { + case FREEZE_APP: + return state.set('blockApp', true); + case UNFREEZE_APP: + return state.set('blockApp', false); default: return state; } diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js index 2393a073cd..b74dd3ebf5 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js @@ -1,9 +1,16 @@ -// import { createSelector } from 'reselect'; +import { createSelector } from 'reselect'; /** * Direct selector to the list state domain */ -// const selectGlobalDomain = () => state => state.get('global'); +const selectGlobalDomain = () => state => state.get('global'); -export {}; +const makeSelectBlockApp = () => createSelector( + selectGlobalDomain(), + (globalState) => globalState.get('blockApp'), +); + +export { + makeSelectBlockApp, +}; diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/index.js b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/index.js index 1f579509be..10ee81114f 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/index.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/index.js @@ -116,7 +116,6 @@ export class HomePage extends React.Component { : ( list.splice(action.indexDataToDelete, 1)) .set('deleteEndPoint', '') - .set('dataToDelete', Map({})) - .set('deleteActionSucceeded', !state.get('deleteActionSucceeded')); + .set('dataToDelete', Map({})); case FETCH_DATA_SUCCEEDED: return state.set('data', List(action.data)); case ON_CHANGE: diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js index 525318b740..a844897dec 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js @@ -1,6 +1,9 @@ import { LOCATION_CHANGE } from 'react-router-redux'; import { findIndex } from 'lodash'; import { takeLatest, put, fork, take, cancel, select, call } from 'redux-saga/effects'; + +import { freezeApp, unfreezeApp } from 'containers/App/actions'; + import request from 'utils/request'; import { @@ -8,6 +11,7 @@ import { fetchDataSucceeded, setForm, } from './actions'; + import { DELETE_DATA, FETCH_DATA, @@ -30,17 +34,19 @@ export function* dataDelete() { const endPointAPI = yield select(makeSelectDeleteEndPoint()); if (indexDataToDelete !== -1) { + yield put(freezeApp()); const id = dataToDelete.id; const requestURL = `/users-permissions/${endPointAPI}/${id}`; - // TODO watchServerRestart const response = yield call(request, requestURL, { method: 'DELETE' }, true); if (response.ok) { yield put(deleteDataSucceeded(indexDataToDelete)); + yield put(unfreezeApp()); strapi.notification.success('users-permissions.notification.success.delete'); } } } catch(err) { + yield put(unfreezeApp()); strapi.notification.error('users-permissions.notification.error.delete'); } } From 950d0200821f8a8217ebce57617d34ddbff61f15 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Mon, 15 Jan 2018 11:36:48 +0100 Subject: [PATCH 12/25] Add overlay blocker to user plugin when creating/updating a role --- .../admin/src/containers/EditPage/saga.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js index 2a4dd646dd..114998894c 100644 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js @@ -8,6 +8,9 @@ import { take, takeLatest, } from 'redux-saga/effects'; + +import { freezeApp, unfreezeApp } from 'containers/App/actions'; + import request from 'utils/request'; import { @@ -89,6 +92,8 @@ export function* roleGet(action) { export function* submit() { try { + yield put(freezeApp()); + const actionType = yield select(makeSelectActionType()); const body = yield select(makeSelectModifiedData()); const roleId = yield select(makeSelectRoleId()); @@ -101,10 +106,12 @@ export function* submit() { const response = yield call(request, requestURL, opts, true); if (response.ok) { + yield put(unfreezeApp()); yield put(submitSucceeded()); } } catch(error) { console.log(error); + yield put(unfreezeApp()); } } From 8222a30d98a30a218a0861ba12f0ff08a16621b9 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 10:46:29 +0100 Subject: [PATCH 13/25] Fix doc typos --- docs/3.x.x/en/plugin-development/utils.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/3.x.x/en/plugin-development/utils.md b/docs/3.x.x/en/plugin-development/utils.md index 3d35014ec2..23bc3ab99c 100644 --- a/docs/3.x.x/en/plugin-development/utils.md +++ b/docs/3.x.x/en/plugin-development/utils.md @@ -9,7 +9,7 @@ Strapi provides helpers so you don't have to develop again and again the same ge ### Methods | Name | Description | -| ---- | ––––––––––– | +| ---- | ----------- | | clear(key) | Remove the data in either `localStorage` or `sessionStorage` | | clearAppStorage() | Remove all data from both storage | | clearToken() | Remove the user's `jwt Token` in the appropriate browser's storage | @@ -17,9 +17,9 @@ Strapi provides helpers so you don't have to develop again and again the same ge | get(key) | Get the item in the browser's storage | | getToken() | Get the user's `jwtToken` | | getUserInfo() | Get the user's infos | -| set(value, key) | Set an item in the `sessionStorage`. If `true` is passed a 3rd parameter it sets the value in the `localStorage` | -| setToken(value) | Set the user's `jwtToken` in the `sessionStorage`. If `true` is passed a 3rd parameter it sets the value in the `localStorage` | -| setUserInfo(value) | Set the user's info in the `sessionStorage`. If `true` is passed a 3rd parameter it sets the value in the `localStorage` | +| set(value, key, isLocalStorage) | Set an item in the `sessionStorage`. If `true` is passed as the 3rd parameter it sets the value in the `localStorage` | +| setToken(value, isLocalStorage) | Set the user's `jwtToken` in the `sessionStorage`. If `true` is passed as the 2nd parameter it sets the value in the `localStorage` | +| setUserInfo(value, isLocalStorage) | Set the user's info in the `sessionStorage`. If `true` is passed as the 2nd parameter it sets the value in the `localStorage` | ```js @@ -44,7 +44,7 @@ const linkColor = darken('#f5f5f5', 1.5); // Will darken #F5F5F5 by 1.5% which g ## Get URL Query Parameters -The helpers allows to retrieve the query parameters in the URL +The helpers allows to retrieve the query parameters in the URL. ### Example @@ -425,7 +425,6 @@ function* defaultSaga() { export default defaultSaga; ``` -*** *** ### Example with server autoReload watcher From b13960de3c7338144dd770ebc60753d4356c95ee Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 12:08:48 +0100 Subject: [PATCH 14/25] Created Global constants and actions to display the OverlayBlocker directly from the request helper when the server is restarting --- .../admin/src/containers/AdminPage/index.js | 7 +++- .../admin/src/containers/App/reducer.js | 12 ++++++ .../admin/src/containers/App/selectors.js | 6 +++ .../src/containers/InstallPluginPage/index.js | 17 +++++++++ .../lib/src/actions/overlayBlocker.js | 37 +++++++++++++++++++ .../lib/src/constants/overlayBlocker.js | 10 +++++ .../lib/src/utils/request.js | 3 ++ 7 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js create mode 100644 packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/index.js b/packages/strapi-admin/admin/src/containers/AdminPage/index.js index d49065e07d..7a904d24fb 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/index.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/index.js @@ -17,7 +17,7 @@ import { Switch, Route } from 'react-router-dom'; import { get, includes, isFunction, map, omit } from 'lodash'; import { pluginLoaded, updatePlugin } from 'containers/App/actions'; -import { selectHasUserPlugin, selectPlugins } from 'containers/App/selectors'; +import { selectHasUserPlugin, selectPlugins, makeSelectShowGlobalAppBlocker } from 'containers/App/selectors'; import { hideNotification } from 'containers/NotificationProvider/actions'; // Design @@ -108,7 +108,8 @@ export class AdminPage extends React.Component { // eslint-disable-line react/pr const leftMenu = this.showLeftMenu() ? : ''; const header = this.showLeftMenu() ?
    : ''; const style = this.showLeftMenu() ? {} : { width: '100%' }; - + console.log('showGlobalAppBlocker', this.props.showGlobalAppBlocker); + return (
    {leftMenu} @@ -154,12 +155,14 @@ AdminPage.propTypes = { location: PropTypes.object.isRequired, pluginLoaded: PropTypes.func.isRequired, plugins: PropTypes.object.isRequired, + showGlobalAppBlocker: PropTypes.bool.isRequired, updatePlugin: PropTypes.func.isRequired, }; const mapStateToProps = createStructuredSelector({ hasUserPlugin: selectHasUserPlugin(), plugins: selectPlugins(), + showGlobalAppBlocker: makeSelectShowGlobalAppBlocker(), }); function mapDispatchToProps(dispatch) { diff --git a/packages/strapi-admin/admin/src/containers/App/reducer.js b/packages/strapi-admin/admin/src/containers/App/reducer.js index 39c19a9391..4d03aeb14b 100755 --- a/packages/strapi-admin/admin/src/containers/App/reducer.js +++ b/packages/strapi-admin/admin/src/containers/App/reducer.js @@ -1,4 +1,11 @@ +// Shared constants +import { + DISABLE_GLOBAL_OVERLAY_BLOCKER, + ENABLE_GLOBAL_OVERLAY_BLOCKER, +} from 'constants/overlayBlocker'; + import { fromJS } from 'immutable'; + import { UPDATE_PLUGIN, PLUGIN_DELETED, @@ -7,12 +14,17 @@ import { } from './constants'; const initialState = fromJS({ + showGlobalAppBlocker: true, plugins: {}, hasUserPlugin: true, }); function appReducer(state = initialState, action) { switch (action.type) { + case DISABLE_GLOBAL_OVERLAY_BLOCKER: + return state.set('showGlobalAppBlocker', false); + case ENABLE_GLOBAL_OVERLAY_BLOCKER: + return state.set('showGlobalAppBlocker', true); case PLUGIN_LOADED: return state.setIn(['plugins', action.plugin.id], fromJS(action.plugin)); case UPDATE_PLUGIN: diff --git a/packages/strapi-admin/admin/src/containers/App/selectors.js b/packages/strapi-admin/admin/src/containers/App/selectors.js index cd4ac3c647..195f616553 100644 --- a/packages/strapi-admin/admin/src/containers/App/selectors.js +++ b/packages/strapi-admin/admin/src/containers/App/selectors.js @@ -19,8 +19,14 @@ const selectHasUserPlugin = () => createSelector( (appState) => appState.get('hasUserPlugin'), ); +const makeSelectShowGlobalAppBlocker = () => createSelector( + selectApp(), + (appState) => appState.get('showGlobalAppBlocker'), +); + export { selectApp, selectHasUserPlugin, selectPlugins, + makeSelectShowGlobalAppBlocker, }; diff --git a/packages/strapi-admin/admin/src/containers/InstallPluginPage/index.js b/packages/strapi-admin/admin/src/containers/InstallPluginPage/index.js index cfb7895c3c..58209024e4 100644 --- a/packages/strapi-admin/admin/src/containers/InstallPluginPage/index.js +++ b/packages/strapi-admin/admin/src/containers/InstallPluginPage/index.js @@ -13,6 +13,11 @@ import { bindActionCreators, compose } from 'redux'; import cn from 'classnames'; import { get, isUndefined, map } from 'lodash'; +import { + disableGlobalOverlayBlocker, + enableGlobalOverlayBlocker, +} from 'actions/overlayBlocker'; + // Design // import Input from 'components/Input'; import DownloadInfo from 'components/DownloadInfo'; @@ -43,12 +48,20 @@ export class InstallPluginPage extends React.Component { // eslint-disable-line ); componentDidMount() { + // Disable the AdminPage OverlayBlocker in order to give it a custom design (children) + this.props.disableGlobalOverlayBlocker(); + // Don't fetch the available plugins if it has already been done if (!this.props.didFetchPlugins) { this.props.getPlugins(); } } + componentWillUnmount() { + // Enable the AdminPage OverlayBlocker so it is displayed when the server is restarting + this.props.enableGlobalOverlayBlocker(); + } + render() { return (
    @@ -118,7 +131,9 @@ InstallPluginPage.propTypes = { availablePlugins: PropTypes.array.isRequired, blockApp: PropTypes.bool.isRequired, didFetchPlugins: PropTypes.bool.isRequired, + disableGlobalOverlayBlocker: PropTypes.func.isRequired, downloadPlugin: PropTypes.func.isRequired, + enableGlobalOverlayBlocker: PropTypes.func.isRequired, getPlugins: PropTypes.func.isRequired, history: PropTypes.object.isRequired, // onChange: PropTypes.func.isRequired, @@ -130,7 +145,9 @@ const mapStateToProps = makeSelectInstallPluginPage(); function mapDispatchToProps(dispatch) { return bindActionCreators( { + disableGlobalOverlayBlocker, downloadPlugin, + enableGlobalOverlayBlocker, getPlugins, onChange, }, diff --git a/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js b/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js new file mode 100644 index 0000000000..07d6a29968 --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js @@ -0,0 +1,37 @@ +/* +* +* Shared OverlayBlocker actions +* + */ + + +import { + DISABLE_GLOBAL_OVERLAY_BLOCKER, + ENABLE_GLOBAL_OVERLAY_BLOCKER, + FREEZE_APP, + UNFREEZE_APP, +} from '../constants/overlayBlocker'; + +export function disableGlobalOverlayBlocker() { + return { + type: DISABLE_GLOBAL_OVERLAY_BLOCKER, + }; +} + +export function enableGlobalOverlayBlocker() { + return { + type: ENABLE_GLOBAL_OVERLAY_BLOCKER, + }; +} + +export function freezeApp() { + return { + type: FREEZE_APP, + }; +} + +export function unfreezeApp() { + return { + type: UNFREEZE_APP, + }; +} diff --git a/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js b/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js new file mode 100644 index 0000000000..44ed36a8ae --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js @@ -0,0 +1,10 @@ +/* +* +* Shared OverlayBlocker constants +* + */ + +export const DISABLE_GLOBAL_OVERLAY_BLOCKER = 'strapiHelperPlugin/OverlayBlocker/DISABLE_GLOBAL_OVERLAY_BLOCKER'; +export const ENABLE_GLOBAL_OVERLAY_BLOCKER = 'strapiHelperPlugin/OverlayBlocker/ENABLE_GLOBAL_OVERLAY_BLOCKER'; +export const FREEZE_APP = 'strapiHelperPlugin/OverlayBlocker/FREEZE_APP'; +export const UNFREEZE_APP = 'strapiHelperPlugin/OverlayBlocker/UNFREEZE_APP'; diff --git a/packages/strapi-helper-plugin/lib/src/utils/request.js b/packages/strapi-helper-plugin/lib/src/utils/request.js index b055ebbafd..ea90fb607f 100755 --- a/packages/strapi-helper-plugin/lib/src/utils/request.js +++ b/packages/strapi-helper-plugin/lib/src/utils/request.js @@ -1,5 +1,6 @@ import 'whatwg-fetch'; import auth from 'utils/auth'; +import { freezeApp, unfreezeApp } from 'actions/overlayBlocker'; /** * Parses the JSON returned by a network request * @@ -86,6 +87,7 @@ function serverRestartWatcher(response) { } }) .then(() => { + unfreezeApp(); resolve(response); }) .catch(err => { @@ -141,6 +143,7 @@ export default function request(url, options = {}, shouldWatchServerRestart = fa .then(parseJSON) .then((response) => { if (shouldWatchServerRestart) { + freezeApp(); return serverRestartWatcher(response); } From d9895fc4319ce190519c48d3cea08548504f51e3 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 12:58:14 +0100 Subject: [PATCH 15/25] Remove the OverlayBlocker from users plugin pass set lockApp in the strapi object --- packages/strapi-admin/admin/src/app.js | 18 ++++++- .../admin/src/containers/AdminPage/index.js | 15 ++++-- .../admin/src/containers/App/actions.js | 50 ++++++++++++------- .../admin/src/containers/App/constants.js | 6 ++- .../admin/src/containers/App/reducer.js | 13 +++-- .../admin/src/containers/App/selectors.js | 6 +++ packages/strapi-admin/package.json | 2 +- .../lib/src/actions/overlayBlocker.js | 14 ------ .../lib/src/constants/overlayBlocker.js | 2 - .../lib/src/utils/request.js | 8 +-- .../admin/src/containers/App/actions.js | 17 ------- .../admin/src/containers/App/constants.js | 3 -- .../admin/src/containers/App/index.js | 9 +--- .../admin/src/containers/App/reducer.js | 12 +---- .../admin/src/containers/App/selectors.js | 13 +---- .../admin/src/containers/EditPage/saga.js | 6 --- .../admin/src/containers/HomePage/saga.js | 5 -- 17 files changed, 91 insertions(+), 108 deletions(-) diff --git a/packages/strapi-admin/admin/src/app.js b/packages/strapi-admin/admin/src/app.js index 8be1784c5d..e7731ac01b 100755 --- a/packages/strapi-admin/admin/src/app.js +++ b/packages/strapi-admin/admin/src/app.js @@ -23,7 +23,14 @@ import LanguageProvider from 'containers/LanguageProvider'; import App from 'containers/App'; import { showNotification } from 'containers/NotificationProvider/actions'; -import { pluginLoaded, updatePlugin, unsetHasUserPlugin } from 'containers/App/actions'; +import { + freezeApp, + pluginLoaded, + unfreezeApp, + unsetHasUserPlugin, + updatePlugin, +} from 'containers/App/actions'; + import auth from 'utils/auth'; import configureStore from './store'; import { translationMessages, languages } from './i18n'; @@ -175,6 +182,13 @@ const displayNotification = (message, status) => { store.dispatch(showNotification(message, status)); }; +const lockApp = () => { + store.dispatch(freezeApp()); +}; + +const unlockApp = () => { + store.dispatch(unfreezeApp()); +}; /** * Public Strapi object exposed to the `window` object @@ -208,6 +222,8 @@ window.strapi = Object.assign(window.strapi || {}, { router: history, languages, currentLanguage: window.localStorage.getItem('strapi-admin-language') || window.navigator.language || window.navigator.userLanguage || 'en', + lockApp, + unlockApp, }); const dispatch = store.dispatch; diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/index.js b/packages/strapi-admin/admin/src/containers/AdminPage/index.js index 7a904d24fb..849f118814 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/index.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/index.js @@ -17,7 +17,13 @@ import { Switch, Route } from 'react-router-dom'; import { get, includes, isFunction, map, omit } from 'lodash'; import { pluginLoaded, updatePlugin } from 'containers/App/actions'; -import { selectHasUserPlugin, selectPlugins, makeSelectShowGlobalAppBlocker } from 'containers/App/selectors'; +import { + makeSelectBlockApp, + makeSelectShowGlobalAppBlocker, + selectHasUserPlugin, + selectPlugins, +} from 'containers/App/selectors'; + import { hideNotification } from 'containers/NotificationProvider/actions'; // Design @@ -30,6 +36,7 @@ import LeftMenu from 'containers/LeftMenu'; import ListPluginsPage from 'containers/ListPluginsPage'; import Logout from 'components/Logout'; import NotFoundPage from 'containers/NotFoundPage'; +import OverlayBlocker from 'components/OverlayBlocker'; import PluginPage from 'containers/PluginPage'; import auth from 'utils/auth'; @@ -108,8 +115,7 @@ export class AdminPage extends React.Component { // eslint-disable-line react/pr const leftMenu = this.showLeftMenu() ? : ''; const header = this.showLeftMenu() ?
    : ''; const style = this.showLeftMenu() ? {} : { width: '100%' }; - console.log('showGlobalAppBlocker', this.props.showGlobalAppBlocker); - + return (
    {leftMenu} @@ -131,6 +137,7 @@ export class AdminPage extends React.Component { // eslint-disable-line react/pr
    +
    ); } @@ -150,6 +157,7 @@ AdminPage.defaultProps = { }; AdminPage.propTypes = { + blockApp: PropTypes.bool.isRequired, hasUserPlugin: PropTypes.bool, history: PropTypes.object.isRequired, location: PropTypes.object.isRequired, @@ -160,6 +168,7 @@ AdminPage.propTypes = { }; const mapStateToProps = createStructuredSelector({ + blockApp: makeSelectBlockApp(), hasUserPlugin: selectHasUserPlugin(), plugins: selectPlugins(), showGlobalAppBlocker: makeSelectShowGlobalAppBlocker(), diff --git a/packages/strapi-admin/admin/src/containers/App/actions.js b/packages/strapi-admin/admin/src/containers/App/actions.js index 6b35df17c8..ebb9411621 100755 --- a/packages/strapi-admin/admin/src/containers/App/actions.js +++ b/packages/strapi-admin/admin/src/containers/App/actions.js @@ -5,13 +5,21 @@ */ import { + FREEZE_APP, LOAD_PLUGIN, - UPDATE_PLUGIN, - PLUGIN_LOADED, PLUGIN_DELETED, + PLUGIN_LOADED, + UNFREEZE_APP, UNSET_HAS_USERS_PLUGIN, + UPDATE_PLUGIN, } from './constants'; +export function freezeApp() { + return { + type: FREEZE_APP, + }; +} + export function loadPlugin(newPlugin) { return { type: LOAD_PLUGIN, @@ -19,22 +27,6 @@ export function loadPlugin(newPlugin) { }; } -export function updatePlugin(pluginId, updatedKey, updatedValue) { - return { - type: UPDATE_PLUGIN, - pluginId, - updatedKey, - updatedValue, - }; -} - -export function pluginLoaded(newPlugin) { - return { - type: PLUGIN_LOADED, - plugin: newPlugin, - }; -} - export function pluginDeleted(plugin) { return { type: PLUGIN_DELETED, @@ -42,8 +34,30 @@ export function pluginDeleted(plugin) { }; } +export function pluginLoaded(newPlugin) { + return { + type: PLUGIN_LOADED, + plugin: newPlugin, + }; +} + +export function unfreezeApp() { + return { + type: UNFREEZE_APP, + }; +} + export function unsetHasUserPlugin() { return { type: UNSET_HAS_USERS_PLUGIN, }; } + +export function updatePlugin(pluginId, updatedKey, updatedValue) { + return { + type: UPDATE_PLUGIN, + pluginId, + updatedKey, + updatedValue, + }; +} diff --git a/packages/strapi-admin/admin/src/containers/App/constants.js b/packages/strapi-admin/admin/src/containers/App/constants.js index ca9553e768..80c3ddfd2f 100755 --- a/packages/strapi-admin/admin/src/containers/App/constants.js +++ b/packages/strapi-admin/admin/src/containers/App/constants.js @@ -4,8 +4,10 @@ * */ -export const UNSET_HAS_USERS_PLUGIN = 'app/App/UNSET_HAS_USERS_PLUGIN'; +export const FREEZE_APP = 'app/App/FREEZE_APP'; export const LOAD_PLUGIN = 'app/App/LOAD_PLUGIN'; -export const UPDATE_PLUGIN = 'app/App/UPDATE_PLUGIN'; export const PLUGIN_LOADED = 'app/App/PLUGIN_LOADED'; export const PLUGIN_DELETED = 'app/App/PLUGIN_DELETED'; +export const UNFREEZE_APP = 'app/App/UNFREEZE_APP'; +export const UNSET_HAS_USERS_PLUGIN = 'app/App/UNSET_HAS_USERS_PLUGIN'; +export const UPDATE_PLUGIN = 'app/App/UPDATE_PLUGIN'; diff --git a/packages/strapi-admin/admin/src/containers/App/reducer.js b/packages/strapi-admin/admin/src/containers/App/reducer.js index 4d03aeb14b..43358c898f 100755 --- a/packages/strapi-admin/admin/src/containers/App/reducer.js +++ b/packages/strapi-admin/admin/src/containers/App/reducer.js @@ -7,16 +7,19 @@ import { import { fromJS } from 'immutable'; import { - UPDATE_PLUGIN, + FREEZE_APP, PLUGIN_DELETED, PLUGIN_LOADED, + UNFREEZE_APP, UNSET_HAS_USERS_PLUGIN, + UPDATE_PLUGIN, } from './constants'; const initialState = fromJS({ - showGlobalAppBlocker: true, - plugins: {}, + blockApp: false, hasUserPlugin: true, + plugins: {}, + showGlobalAppBlocker: true, }); function appReducer(state = initialState, action) { @@ -25,12 +28,16 @@ function appReducer(state = initialState, action) { return state.set('showGlobalAppBlocker', false); case ENABLE_GLOBAL_OVERLAY_BLOCKER: return state.set('showGlobalAppBlocker', true); + case FREEZE_APP: + return state.set('blockApp', true); case PLUGIN_LOADED: return state.setIn(['plugins', action.plugin.id], fromJS(action.plugin)); case UPDATE_PLUGIN: return state.setIn(['plugins', action.pluginId, action.updatedKey], fromJS(action.updatedValue)); case PLUGIN_DELETED: return state.deleteIn(['plugins', action.plugin]); + case UNFREEZE_APP: + return state.set('blockApp', false); case UNSET_HAS_USERS_PLUGIN: return state.set('hasUserPlugin', false); default: diff --git a/packages/strapi-admin/admin/src/containers/App/selectors.js b/packages/strapi-admin/admin/src/containers/App/selectors.js index 195f616553..db4e8913e4 100644 --- a/packages/strapi-admin/admin/src/containers/App/selectors.js +++ b/packages/strapi-admin/admin/src/containers/App/selectors.js @@ -24,9 +24,15 @@ const makeSelectShowGlobalAppBlocker = () => createSelector( (appState) => appState.get('showGlobalAppBlocker'), ); +const makeSelectBlockApp = () => createSelector( + selectApp(), + (appState) => appState.get('blockApp'), +); + export { selectApp, selectHasUserPlugin, selectPlugins, + makeSelectBlockApp, makeSelectShowGlobalAppBlocker, }; diff --git a/packages/strapi-admin/package.json b/packages/strapi-admin/package.json index 2b61981250..04ce12d68a 100755 --- a/packages/strapi-admin/package.json +++ b/packages/strapi-admin/package.json @@ -48,4 +48,4 @@ "npm": ">= 3.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js b/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js index 07d6a29968..f9b22fe71f 100644 --- a/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js +++ b/packages/strapi-helper-plugin/lib/src/actions/overlayBlocker.js @@ -8,8 +8,6 @@ import { DISABLE_GLOBAL_OVERLAY_BLOCKER, ENABLE_GLOBAL_OVERLAY_BLOCKER, - FREEZE_APP, - UNFREEZE_APP, } from '../constants/overlayBlocker'; export function disableGlobalOverlayBlocker() { @@ -23,15 +21,3 @@ export function enableGlobalOverlayBlocker() { type: ENABLE_GLOBAL_OVERLAY_BLOCKER, }; } - -export function freezeApp() { - return { - type: FREEZE_APP, - }; -} - -export function unfreezeApp() { - return { - type: UNFREEZE_APP, - }; -} diff --git a/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js b/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js index 44ed36a8ae..044e5ae4e6 100644 --- a/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js +++ b/packages/strapi-helper-plugin/lib/src/constants/overlayBlocker.js @@ -6,5 +6,3 @@ export const DISABLE_GLOBAL_OVERLAY_BLOCKER = 'strapiHelperPlugin/OverlayBlocker/DISABLE_GLOBAL_OVERLAY_BLOCKER'; export const ENABLE_GLOBAL_OVERLAY_BLOCKER = 'strapiHelperPlugin/OverlayBlocker/ENABLE_GLOBAL_OVERLAY_BLOCKER'; -export const FREEZE_APP = 'strapiHelperPlugin/OverlayBlocker/FREEZE_APP'; -export const UNFREEZE_APP = 'strapiHelperPlugin/OverlayBlocker/UNFREEZE_APP'; diff --git a/packages/strapi-helper-plugin/lib/src/utils/request.js b/packages/strapi-helper-plugin/lib/src/utils/request.js index ea90fb607f..2e8354092d 100755 --- a/packages/strapi-helper-plugin/lib/src/utils/request.js +++ b/packages/strapi-helper-plugin/lib/src/utils/request.js @@ -1,6 +1,6 @@ import 'whatwg-fetch'; import auth from 'utils/auth'; -import { freezeApp, unfreezeApp } from 'actions/overlayBlocker'; + /** * Parses the JSON returned by a network request * @@ -87,7 +87,8 @@ function serverRestartWatcher(response) { } }) .then(() => { - unfreezeApp(); + // Hide the global OverlayBlocker + strapi.unlockApp(); resolve(response); }) .catch(err => { @@ -143,7 +144,8 @@ export default function request(url, options = {}, shouldWatchServerRestart = fa .then(parseJSON) .then((response) => { if (shouldWatchServerRestart) { - freezeApp(); + // Display the global OverlayBlocker + strapi.lockApp(); return serverRestartWatcher(response); } diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js index 8d6fdc3171..a5002ad023 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/actions.js @@ -3,20 +3,3 @@ * App actions * */ - -import { - FREEZE_APP, - UNFREEZE_APP, -} from './constants'; - -export function freezeApp() { - return { - type: FREEZE_APP, - }; -} - -export function unfreezeApp() { - return { - type: UNFREEZE_APP, - }; -} diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js index 8181110dba..f62c609507 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/constants.js @@ -3,6 +3,3 @@ * App constants * */ - -export const FREEZE_APP = 'UsersPermissions/App/FREEZE_APP'; -export const UNFREEZE_APP = 'UsersPermissions/App/UNFREEZE_APP'; diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js index d3ede1b929..16efbef769 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/index.js @@ -20,9 +20,6 @@ import AuthPage from 'containers/AuthPage'; import EditPage from 'containers/EditPage'; import HomePage from 'containers/HomePage'; import NotFoundPage from 'containers/NotFoundPage'; -import OverlayBlocker from 'components/OverlayBlocker'; - -import { makeSelectBlockApp } from './selectors'; class App extends React.Component { componentDidMount() { @@ -40,7 +37,6 @@ class App extends React.Component { render() { return (
    - @@ -59,7 +55,6 @@ App.contextTypes = { }; App.propTypes = { - blockApp: PropTypes.bool.isRequired, history: PropTypes.object.isRequired, location: PropTypes.object.isRequired, }; @@ -71,9 +66,7 @@ export function mapDispatchToProps(dispatch) { ); } -const mapStateToProps = createStructuredSelector({ - blockApp: makeSelectBlockApp(), -}); +const mapStateToProps = createStructuredSelector({}); // Wrap the component to inject dispatch and state into it const withConnect = connect(mapStateToProps, mapDispatchToProps); diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js index ab8fc9825b..38026c39cd 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/reducer.js @@ -5,21 +5,11 @@ */ import { fromJS } from 'immutable'; -import { - FREEZE_APP, - UNFREEZE_APP, -} from './constants'; -const initialState = fromJS({ - blockApp: false, -}); +const initialState = fromJS({}); function appReducer(state = initialState, action) { switch (action.type) { - case FREEZE_APP: - return state.set('blockApp', true); - case UNFREEZE_APP: - return state.set('blockApp', false); default: return state; } diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js b/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js index b74dd3ebf5..59c3cfbba0 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/App/selectors.js @@ -1,16 +1,7 @@ -import { createSelector } from 'reselect'; +// import { createSelector } from 'reselect'; /** * Direct selector to the list state domain */ -const selectGlobalDomain = () => state => state.get('global'); - -const makeSelectBlockApp = () => createSelector( - selectGlobalDomain(), - (globalState) => globalState.get('blockApp'), -); - -export { - makeSelectBlockApp, -}; +// const selectGlobalDomain = () => state => state.get('global'); diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js index 114998894c..4fb5774655 100644 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/EditPage/saga.js @@ -9,8 +9,6 @@ import { takeLatest, } from 'redux-saga/effects'; -import { freezeApp, unfreezeApp } from 'containers/App/actions'; - import request from 'utils/request'; import { @@ -92,8 +90,6 @@ export function* roleGet(action) { export function* submit() { try { - yield put(freezeApp()); - const actionType = yield select(makeSelectActionType()); const body = yield select(makeSelectModifiedData()); const roleId = yield select(makeSelectRoleId()); @@ -106,12 +102,10 @@ export function* submit() { const response = yield call(request, requestURL, opts, true); if (response.ok) { - yield put(unfreezeApp()); yield put(submitSucceeded()); } } catch(error) { console.log(error); - yield put(unfreezeApp()); } } diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js index a844897dec..cd109009e8 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js @@ -2,8 +2,6 @@ import { LOCATION_CHANGE } from 'react-router-redux'; import { findIndex } from 'lodash'; import { takeLatest, put, fork, take, cancel, select, call } from 'redux-saga/effects'; -import { freezeApp, unfreezeApp } from 'containers/App/actions'; - import request from 'utils/request'; import { @@ -34,19 +32,16 @@ export function* dataDelete() { const endPointAPI = yield select(makeSelectDeleteEndPoint()); if (indexDataToDelete !== -1) { - yield put(freezeApp()); const id = dataToDelete.id; const requestURL = `/users-permissions/${endPointAPI}/${id}`; const response = yield call(request, requestURL, { method: 'DELETE' }, true); if (response.ok) { yield put(deleteDataSucceeded(indexDataToDelete)); - yield put(unfreezeApp()); strapi.notification.success('users-permissions.notification.success.delete'); } } } catch(err) { - yield put(unfreezeApp()); strapi.notification.error('users-permissions.notification.error.delete'); } } From d3f81bc2b1fd222a9688b68cf90c7b30d81bd6a4 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 14:19:02 +0100 Subject: [PATCH 16/25] Remove stm request helper and remove stm OverlayBlocker related constants and action --- .../internals/webpack/webpack.base.babel.js | 4 + .../admin/src/containers/App/actions.js | 14 -- .../admin/src/containers/App/constants.js | 2 - .../admin/src/containers/App/index.js | 6 +- .../admin/src/containers/App/reducer.js | 12 +- .../admin/src/containers/App/selectors.js | 6 - .../admin/src/containers/HomePage/sagas.js | 29 ---- .../admin/src/utils/request.js | 126 ------------------ 8 files changed, 7 insertions(+), 192 deletions(-) delete mode 100755 packages/strapi-plugin-settings-manager/admin/src/utils/request.js diff --git a/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js b/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js index 55d867bb97..f93d17a415 100755 --- a/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js +++ b/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js @@ -74,6 +74,10 @@ if (isAdmin && !isSetup) { if (_.get(server, 'admin.build.plugins.source') === 'backend') { URLs.mode = 'backend'; } + + if (process.env.npm_lifecycle_event === 'start') { + URLs.backend = `http://${_.get(server, 'host', 'localhost')}:${_.get(server, 'port', 1337)}`; + } } } catch (e) { throw new Error(`Impossible to access to ${serverConfig}`) diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js index 8eb247cb3f..bd7cdc3d89 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/actions.js @@ -7,10 +7,8 @@ import { ENVIRONMENTS_FETCH, ENVIRONMENTS_FETCH_SUCCEEDED, - FREEZE_APP, MENU_FETCH_SUCCEEDED, MENU_FETCH, - UNFREEZE_APP, } from './constants'; export function environmentsFetch() { @@ -26,12 +24,6 @@ export function environmentsFetchSucceeded(environments) { }; } -export function freezeApp() { - return { - type: FREEZE_APP, - }; -} - export function fetchMenuSucceeded(menu) { return { type: MENU_FETCH_SUCCEEDED, @@ -44,9 +36,3 @@ export function menuFetch() { type: MENU_FETCH, }; } - -export function unfreezeApp() { - return { - type: UNFREEZE_APP, - }; -} diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js index 94e5bbabf6..38c18f4b7e 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/constants.js @@ -6,7 +6,5 @@ export const ENVIRONMENTS_FETCH = 'SettingsManager/App/ENVIRONMENTS_FETCH'; export const ENVIRONMENTS_FETCH_SUCCEEDED = 'SettingsManager/App/ENVIRONMENTS_FETCH_SUCCEEDED'; -export const FREEZE_APP = 'SettingsManager/App/FREEZE_APP'; export const MENU_FETCH = 'SettingsManager/App/MENU_FETCH'; export const MENU_FETCH_SUCCEEDED = 'SettingsManager/App/MENU_FETCH_SUCCEEDED'; -export const UNFREEZE_APP = 'SettingsManager/App/UNFREEZE_APP'; diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js index 26c30a5e22..4df01e3935 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/index.js @@ -19,10 +19,9 @@ import { pluginId } from 'app'; import injectSaga from 'utils/injectSaga'; import HomePage from 'containers/HomePage'; -import OverlayBlocker from 'components/OverlayBlocker'; import { menuFetch, environmentsFetch } from './actions'; -import { makeSelectBlockApp, makeSelectLoading, makeSelectSections } from './selectors'; +import { makeSelectLoading, makeSelectSections } from './selectors'; import styles from './styles.scss'; import saga from './sagas'; @@ -57,7 +56,6 @@ class App extends React.Component { render() { return (
    - @@ -73,7 +71,6 @@ App.contextTypes = { }; App.propTypes = { - blockApp: PropTypes.bool.isRequired, environmentsFetch: PropTypes.func.isRequired, history: PropTypes.object.isRequired, menuFetch: PropTypes.func.isRequired, @@ -91,7 +88,6 @@ export function mapDispatchToProps(dispatch) { } const mapStateToProps = createStructuredSelector({ - blockApp: makeSelectBlockApp(), loading: makeSelectLoading(), sections: makeSelectSections(), }); diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js index 8f42bd3954..c37e943f3f 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/reducer.js @@ -7,16 +7,12 @@ import { fromJS, List } from 'immutable'; import { ENVIRONMENTS_FETCH_SUCCEEDED, - FREEZE_APP, MENU_FETCH_SUCCEEDED, - UNFREEZE_APP, } from './constants'; -/* eslint-disable new-cap */ const initialState = fromJS({ - blockApp: false, - sections: List(), // eslint-disable-line new-cap - environments: List(), + sections: List([]), + environments: List([]), loading: true, }); @@ -25,12 +21,8 @@ function appReducer(state = initialState, action) { case ENVIRONMENTS_FETCH_SUCCEEDED: return state .set('environments', List(action.environments.environments)); - case FREEZE_APP: - return state.set('blockApp', true); case MENU_FETCH_SUCCEEDED: return state.set('sections', List(action.menu.sections)).set('loading', false); - case UNFREEZE_APP: - return state.set('blockApp', false); default: return state; } diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js b/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js index 5690c7d9b4..d254d456c6 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/App/selectors.js @@ -22,11 +22,6 @@ const selectLocationState = () => { }; }; -const makeSelectBlockApp = () => createSelector( - selectGlobalDomain(), - (globalSate) => globalSate.get('blockApp'), -); - const makeSelectSections = () => createSelector( selectGlobalDomain(), (globalSate) => globalSate.get('sections').toJS(), @@ -43,7 +38,6 @@ const makeSelectLoading = () => createSelector( ); export { - makeSelectBlockApp, makeSelectEnvironments, makeSelectLoading, makeSelectSections, diff --git a/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js b/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js index 2a32a1b5f0..f43cec42df 100755 --- a/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js +++ b/packages/strapi-plugin-settings-manager/admin/src/containers/HomePage/sagas.js @@ -1,9 +1,6 @@ import { LOCATION_CHANGE } from 'react-router-redux'; - import { forEach, set, map, replace } from 'lodash'; import { call, take, put, fork, cancel, select, takeLatest } from 'redux-saga/effects'; - -import { freezeApp, unfreezeApp } from 'containers/App/actions'; import request from 'utils/request'; // selectors @@ -40,8 +37,6 @@ import { export function* editDatabase(action) { try { - yield put(freezeApp()); - const body = {}; forEach(action.data, (value, key) => { @@ -58,13 +53,11 @@ export function* editDatabase(action) { if (resp.ok) { strapi.notification.success('settings-manager.strapi.notification.success.databaseEdit'); - yield put(unfreezeApp()); yield put(databaseActionSucceeded()); } } catch(error) { const formErrors = map(error.response.payload.message, err => ({ target: err.target, errors: map(err.messages, mess => ({ id: `settings-manager.${mess.id}`})) })); - yield put(unfreezeApp()); yield put(databaseActionError(formErrors)); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -72,18 +65,15 @@ export function* editDatabase(action) { export function* deleteDatabase(action) { try { - yield put(freezeApp()); const opts = { method: 'DELETE' }; const requestUrl = `/settings-manager/configurations/databases/${action.databaseToDelete}/${action.endPoint}`; const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { - yield put(unfreezeApp()); strapi.notification.success('settings-manager.strapi.notification.success.databaseDeleted'); } } catch(error) { - yield put(unfreezeApp()); yield put(databaseActionError([])); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -91,20 +81,16 @@ export function* deleteDatabase(action) { export function* deleteLanguage(action) { try { - yield put(freezeApp()); const opts = { method: 'DELETE', }; const requestUrl = `/settings-manager/configurations/languages/${action.languageToDelete}`; - const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { - yield put(unfreezeApp()); strapi.notification.success('settings-manager.strapi.notification.success.languageDelete'); } } catch(error) { - yield put(unfreezeApp()); yield put(languageActionError()); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -163,10 +149,7 @@ export function* fetchLanguages() { export function* postLanguage() { try { - yield put(freezeApp()); - const newLanguage = yield select(makeSelectModifiedData()); - const body = { name: newLanguage['language.defaultLocale'], }; @@ -175,16 +158,13 @@ export function* postLanguage() { method: 'POST', }; const requestUrl = '/settings-manager/configurations/languages'; - const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { yield put(languageActionSucceeded()); - yield put(unfreezeApp()); strapi.notification.success('settings-manager.strapi.notification.success.languageAdd'); } } catch(error) { - yield put(unfreezeApp()); yield put(languageActionError()); strapi.notification.error('settings-manager.strapi.notification.error'); } @@ -192,7 +172,6 @@ export function* postLanguage() { export function* postDatabase(action) { try { - yield put(freezeApp()); const body = {}; forEach(action.data, (value, key) => { @@ -204,11 +183,9 @@ export function* postDatabase(action) { body, }; const requestUrl = `/settings-manager/configurations/databases/${action.endPoint}`; - const resp = yield call(request, requestUrl, opts, true); if (resp.ok) { - yield put(unfreezeApp()); yield put(databaseActionSucceeded()); strapi.notification.success('settings-manager.strapi.notification.success.databaseAdd'); } @@ -221,14 +198,12 @@ export function* postDatabase(action) { }); yield put(databaseActionError(formErrors)); - strapi.notification.error('settings-manager.strapi.notification.error'); } } export function* settingsEdit(action) { try { - yield put(freezeApp()); // Show button loader yield put(setLoader()); @@ -242,13 +217,10 @@ export function* settingsEdit(action) { if (resp.ok) { yield put(editSettingsSucceeded()); yield put(unsetLoader()); - yield put(unfreezeApp()); - strapi.notification.success('settings-manager.strapi.notification.success.settingsEdit'); } } catch(error) { yield put(unsetLoader()); - yield put(unfreezeApp()); strapi.notification.error('settings-manager.strapi.notification.error'); } } @@ -259,7 +231,6 @@ export function* fetchSpecificDatabase(action) { method: 'GET', }; const requestUrl = `/settings-manager/configurations/databases/${action.databaseName}/${action.endPoint}`; - const data = yield call(request, requestUrl, opts); yield put(specificDatabaseFetchSucceeded(data)); diff --git a/packages/strapi-plugin-settings-manager/admin/src/utils/request.js b/packages/strapi-plugin-settings-manager/admin/src/utils/request.js deleted file mode 100755 index f539e1b20f..0000000000 --- a/packages/strapi-plugin-settings-manager/admin/src/utils/request.js +++ /dev/null @@ -1,126 +0,0 @@ -import 'whatwg-fetch'; -import { startsWith } from 'lodash'; -import auth from 'utils/auth'; - -/** - * Parses the JSON returned by a network request - * - * @param {object} response A response from a network request - * - * @return {object} The parsed JSON from the request - */ -function parseJSON(response) { - return response.json(); -} - -/** - * Checks if a network request came back fine, and throws an error if not - * - * @param {object} response A response from a network request - * - * @return {object|undefined} Returns either the response, or throws an error - */ -function checkStatus(response) { - - if (response.status >= 200 && response.status < 300) { - return response; - } - - return parseJSON(response).then(responseFormatted => { - const error = new Error(response.statusText); - error.response = response; - error.response.payload = responseFormatted; - throw error; - }); -} - -/** - * Format query params - * - * @param params - * @returns {string} - */ -function formatQueryParams(params) { - return Object.keys(params) - .map(k => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`) - .join('&'); -} - -/** -* Server restart watcher -* @param response -* @returns {object} the response data -*/ -function serverRestartWatcher(response) { - return new Promise((resolve) => { - fetch(`${strapi.backendURL}/_health`, { - method: 'HEAD', - mode: 'no-cors', - headers: { - 'Content-Type': 'application/json', - 'Keep-Alive': false, - }, - }) - .then(() => { - resolve(response); - }) - .catch(() => { - setTimeout(() => { - return serverRestartWatcher(response) - .then(resolve); - }, 100); - }); - }); -} - -/** - * Requests a URL, returning a promise - * - * @param {string} url The URL we want to request - * @param {object} [options] The options we want to pass to "fetch" - * - * @return {object} The response data - */ -export default function request(url, options, shouldWatchServerRestart = false) { - const optionsObj = options || {}; - - // Set headers - optionsObj.headers = { - 'Content-Type': 'application/json', - 'X-Forwarded-Host': 'strapi', - }; - - const token = auth.getToken(); - - if (token) { - optionsObj.headers = Object.assign({ - 'Authorization': `Bearer ${token}`, - }, optionsObj.headers); - } - - // Add parameters to url - let urlFormatted = startsWith(url, '/') - ? `${strapi.backendURL}${url}` - : url; - - if (optionsObj && optionsObj.params) { - const params = formatQueryParams(optionsObj.params); - urlFormatted = `${url}?${params}`; - } - - // Stringify body object - if (optionsObj && optionsObj.body) { - optionsObj.body = JSON.stringify(optionsObj.body); - } - - return fetch(urlFormatted, optionsObj) - .then(checkStatus) - .then(parseJSON) - .then((response) => { - if (shouldWatchServerRestart) { - return serverRestartWatcher(response); - } - - return response; - }); -} From 5d92accfabd551aeeeb92bc9672769364f748a7d Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 14:28:41 +0100 Subject: [PATCH 17/25] Remove OverlayBlocker from ctb --- .../admin/src/containers/App/actions.js | 14 -------------- .../admin/src/containers/App/constants.js | 2 -- .../admin/src/containers/App/index.js | 7 ------- .../admin/src/containers/App/reducer.js | 7 ------- .../admin/src/containers/App/sagas.js | 6 +----- .../admin/src/containers/App/selectors.js | 6 ------ .../admin/src/containers/Form/sagas.js | 5 ----- .../admin/src/containers/ModelPage/sagas.js | 5 +---- 8 files changed, 2 insertions(+), 50 deletions(-) diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js index 01d9e4eab1..2c7c2ccef2 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js @@ -13,13 +13,11 @@ import { storeData } from '../../utils/storeData'; import { DELETE_CONTENT_TYPE, - FREEZE_APP, MODELS_FETCH, MODELS_FETCH_SUCCEEDED, STORE_TEMPORARY_MENU, TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED, TEMPORARY_CONTENT_TYPE_POSTED, - UNFREEZE_APP, } from './constants'; export function deleteContentType(itemToDelete, context) { @@ -58,12 +56,6 @@ export function deleteContentType(itemToDelete, context) { }; } -export function freezeApp() { - return { - type: FREEZE_APP, - }; -} - export function modelsFetch() { return { type: MODELS_FETCH, @@ -127,9 +119,3 @@ export function temporaryContentTypePosted(fieldNumber) { fieldNumber, }; } - -export function unfreezeApp() { - return { - type: UNFREEZE_APP, - }; -} diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js index f7186b06b0..d521939d38 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js @@ -5,10 +5,8 @@ */ export const DELETE_CONTENT_TYPE = 'ContentTypeBuilder/App/DELETE_CONTENT_TYPE'; -export const FREEZE_APP = 'ContentTypeBuilder/App/FREEZE_APP'; export const MODELS_FETCH = 'ContentTypeBuilder/App/MODELS_FETCH'; export const MODELS_FETCH_SUCCEEDED = 'ContentTypeBuilder/App/MODELS_FETCH_SUCCEEDED'; export const STORE_TEMPORARY_MENU = 'ContentTypeBuilder/App/STORE_TEMPORARY_MENU'; export const TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED = 'ContentTypeBuilder/App/TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED'; export const TEMPORARY_CONTENT_TYPE_POSTED = 'ContentTypeBuilder/App/TEMPORARY_CONTENT_TYPE_POSTED'; -export const UNFREEZE_APP = 'ContentTypeBuilder/App/UNFREEZE_APP'; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js index 0ae4243262..af53dc9825 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js @@ -20,9 +20,6 @@ import NotFoundPage from 'containers/NotFoundPage'; import formSaga from 'containers/Form/sagas'; import formReducer from 'containers/Form/reducer'; -// Design -import OverlayBlocker from 'components/OverlayBlocker'; - // Other containers actions import { makeSelectShouldRefetchContentType } from 'containers/Form/selectors'; @@ -33,7 +30,6 @@ import { storeData } from '../../utils/storeData'; import styles from './styles.scss'; import { modelsFetch } from './actions'; -import { makeSelectBlockApp } from './selectors'; import saga from './sagas'; /* eslint-disable consistent-return */ @@ -57,7 +53,6 @@ class App extends React.Component { render() { return (
    - @@ -75,7 +70,6 @@ App.contextTypes = { }; App.propTypes = { - blockApp: PropTypes.bool.isRequired, modelsFetch: PropTypes.func.isRequired, shouldRefetchContentType: PropTypes.bool, }; @@ -94,7 +88,6 @@ export function mapDispatchToProps(dispatch) { } const mapStateToProps = createStructuredSelector({ - blockApp: makeSelectBlockApp(), shouldRefetchContentType: makeSelectShouldRefetchContentType(), }); diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js index 1e021d8d63..59e2d6c303 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js @@ -8,18 +8,15 @@ import { fromJS, List } from 'immutable'; import { findIndex, size } from 'lodash'; import { DELETE_CONTENT_TYPE, - FREEZE_APP, MODELS_FETCH, MODELS_FETCH_SUCCEEDED, STORE_TEMPORARY_MENU, TEMPORARY_CONTENT_TYPE_POSTED, TEMPORARY_CONTENT_TYPE_FIELDS_UPDATED, - UNFREEZE_APP, } from './constants'; /* eslint-disable new-cap */ const initialState = fromJS({ - blockApp: false, loading: true, menu: List(), models: List(), @@ -31,8 +28,6 @@ function appReducer(state = initialState, action) { return state .updateIn(['menu', '0', 'items'], (list) => list.splice(findIndex(state.getIn(['menu', '0', 'items']).toJS(), ['name', action.itemToDelete]), 1)) .update('models', (array) => array.splice(findIndex(state.get('models').toJS(), ['name', action.itemToDelete]), 1)); - case FREEZE_APP: - return state.set('blockApp', true); case MODELS_FETCH: return state.set('loading', true); case MODELS_FETCH_SUCCEEDED: @@ -63,8 +58,6 @@ function appReducer(state = initialState, action) { .updateIn(['menu', '0', 'items', size(state.getIn(['menu', '0', 'items']).toJS()) -2], () => newData) .updateIn(['models', size(state.get('models').toJS()) - 1], () => newModel); } - case UNFREEZE_APP: - return state.set('blockApp', false); default: return state; } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js index 9f150899e9..150fff761a 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/sagas.js @@ -1,24 +1,20 @@ import { takeLatest, call, put, fork } from 'redux-saga/effects'; import request from 'utils/request'; import { DELETE_CONTENT_TYPE, MODELS_FETCH } from './constants'; -import { freezeApp, modelsFetchSucceeded, unfreezeApp } from './actions'; +import { modelsFetchSucceeded } from './actions'; export function* deleteContentType(action) { try { if (action.sendRequest) { - // Display the OverlayBlocker - yield put(freezeApp()); const requestUrl = `/content-type-builder/models/${action.itemToDelete}`; const response = yield call(request, requestUrl, { method: 'DELETE' }, true); if (response.ok && action.updateLeftMenu) { action.updatePlugin('content-manager', 'leftMenuSections', action.leftMenuContentTypes); - yield put(unfreezeApp()); strapi.notification.success('content-type-builder.notification.success.contentTypeDeleted'); } } } catch(error) { - yield put(unfreezeApp()); strapi.notification.error('content-type-builder.notification.error.message'); } } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js index d3533a3693..f9b6cb77a8 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/selectors.js @@ -6,11 +6,6 @@ import { createSelector } from 'reselect'; const selectGlobalDomain = () => state => state.get('global'); -const makeSelectBlockApp = () => createSelector( - selectGlobalDomain(), - (globalSate) => globalSate.get('blockApp'), -); - const makeSelectLoading = () => createSelector( selectGlobalDomain(), (globalSate) => globalSate.get('loading'), @@ -45,7 +40,6 @@ const selectLocationState = () => { export { selectLocationState, - makeSelectBlockApp, makeSelectLoading, makeSelectMenu, makeSelectModels, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js index 8053ba1425..4870e3655e 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/sagas.js @@ -3,8 +3,6 @@ import { capitalize, findIndex, get, isEmpty, sortBy } from 'lodash'; import { takeLatest, call, put, fork, select } from 'redux-saga/effects'; import request from 'utils/request'; -import { freezeApp, unfreezeApp } from 'containers/App/actions'; - import { connectionsFetchSucceeded, contentTypeActionSucceeded, @@ -27,7 +25,6 @@ import { export function* editContentType(action) { try { const initialContentType = yield select(makeSelectInitialDataEdit()); - yield put(freezeApp()); const requestUrl = `/content-type-builder/models/${initialContentType.name}`; const body = yield select(makeSelectModifiedDataEdit()); const opts = { @@ -58,10 +55,8 @@ export function* editContentType(action) { action.context.updatePlugin('content-manager', 'leftMenuSections', leftMenuContentTypes); } strapi.notification.success('content-type-builder.notification.success.message.contentType.edit'); - yield put(unfreezeApp()); } } catch(error) { - yield put(unfreezeApp()); strapi.notification.error(get(error, ['response', 'payload', 'message'], 'notification.error')); } } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js index daceb084c7..ad405597f7 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelPage/sagas.js @@ -18,7 +18,7 @@ import { takeLatest, call, take, put, fork, cancel, select } from 'redux-saga/ef import request from 'utils/request'; -import { freezeApp, temporaryContentTypePosted, unfreezeApp } from 'containers/App/actions'; +import { temporaryContentTypePosted } from 'containers/App/actions'; import { storeData } from '../../utils/storeData'; @@ -74,7 +74,6 @@ export function* submitChanges(action) { try { // Show button loader yield put(setButtonLoader()); - yield put(freezeApp()); const modelName = get(storeData.getContentType(), 'name'); const data = yield select(makeSelectModel()); @@ -144,8 +143,6 @@ export function* submitChanges(action) { yield put(resetShowButtonsProps()); // Remove loader yield put(unsetButtonLoader()); - // Unfreeze app - yield put(unfreezeApp()); } } catch(error) { From e7fcb3cd8cf675d6586f625ac3a7b53f250850e8 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 14:30:37 +0100 Subject: [PATCH 18/25] Fix typo --- packages/strapi-admin/admin/src/translations/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi-admin/admin/src/translations/fr.json b/packages/strapi-admin/admin/src/translations/fr.json index 6525f81a14..c3566bd48c 100755 --- a/packages/strapi-admin/admin/src/translations/fr.json +++ b/packages/strapi-admin/admin/src/translations/fr.json @@ -59,7 +59,7 @@ "components.AutoReloadBlocker.description": "Ouvrez le fichier suivant pour activer cette fonctionnalité.", "components.OverlayBlocker.title": "Le serveur est en train de redémarrer", - "components.OverlayBlocker.description": "Vous utilisez une fonctionnalité qui nécessite le redémarrage du server. Merci d'attendre que celui redémarré.", + "components.OverlayBlocker.description": "Vous utilisez une fonctionnalité qui nécessite le redémarrage du server. Merci d'attendre que celui-ci ait redémarré.", "components.ErrorBoundary.title": "Une erreur est survenue...", From f6715c0ccbf7c5320523361bc1d8b04feb3ce6b5 Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Wed, 17 Jan 2018 14:36:26 +0100 Subject: [PATCH 19/25] Update OverlayBlocker doc --- .../en/plugin-development/ui-components.md | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/3.x.x/en/plugin-development/ui-components.md b/docs/3.x.x/en/plugin-development/ui-components.md index 85a904a897..0242d7a07f 100644 --- a/docs/3.x.x/en/plugin-development/ui-components.md +++ b/docs/3.x.x/en/plugin-development/ui-components.md @@ -330,7 +330,7 @@ export default FooPage; ## OverlayBlocker -The OverlayBlocker is a React component that is very useful to block user interactions when the strapi server is restarting in order to avoid front-end errors. +The OverlayBlocker is a React component that is very useful to block user interactions when the strapi server is restarting in order to avoid front-end errors. This component is automatically displayed when the server needs to restart. You need to disable in order to override the current design. ### Usage @@ -373,6 +373,12 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; +// Actions required for disabling and enabling the OverlayBlocker +import { + disableGlobalOverlayBlocker, + enableGlobalOverlayBlocker, +} from 'actions/overlayBlocker'; + // Design import Button from 'components/Button'; import OverlayBlocker from 'components/OverlayBlocker'; @@ -395,6 +401,16 @@ import makeSelectFooPage from './selectors'; export class FooPage extends React.Component { + componentDidMount() { + // Disable the AdminPage OverlayBlocker in order to give it a custom design (children) + this.props.disableGlobalOverlayBlocker(); + } + + componentWillUnmount() { + // Enable the AdminPage OverlayBlocker so it is displayed when the server is restarting in the other plugins + this.props.enableGlobalOverlayBlocker(); + } + render() { return (
    @@ -410,6 +426,8 @@ export class FooPage extends React.Component { } FooPage.propTypes = { + disableGlobalOverlayBlocker: PropTypes.func.isRequired, + enableGlobalOverlayBlocker: PropTypes.func.isRequired, onButtonClick: PropTypes.func.isRequired, showOverlayBlocker: PropTypes.bool.isRequired, }; @@ -419,6 +437,8 @@ const mapStateToProps = makeSelectFooPage(); function mapDispatchToProps(dispatch) { return bindActionCreators( { + disableGlobalOverlayBlocker, + enableGlobalOverlayBlocker, onButtonClick, }, dispatch, From b53b074b3f1606265436c11d25b5bc658f86d778 Mon Sep 17 00:00:00 2001 From: Jim LAURIE Date: Thu, 18 Jan 2018 09:40:48 +0100 Subject: [PATCH 20/25] Update overlay blocker documentation --- docs/3.x.x/en/plugin-development/ui-components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/3.x.x/en/plugin-development/ui-components.md b/docs/3.x.x/en/plugin-development/ui-components.md index 0242d7a07f..605f9fa1eb 100644 --- a/docs/3.x.x/en/plugin-development/ui-components.md +++ b/docs/3.x.x/en/plugin-development/ui-components.md @@ -330,7 +330,7 @@ export default FooPage; ## OverlayBlocker -The OverlayBlocker is a React component that is very useful to block user interactions when the strapi server is restarting in order to avoid front-end errors. This component is automatically displayed when the server needs to restart. You need to disable in order to override the current design. +The OverlayBlocker is a React component that is very useful to block user interactions when the strapi server is restarting in order to avoid front-end errors. This component is automatically displayed when the server needs to restart. You need to disable it in order to override the current design (once disabled it won't show on the other plugins so it's really important to enable it back when the component is unmounting). ### Usage @@ -341,7 +341,7 @@ The OverlayBlocker is a React component that is very useful to block user intera ### Example -In this example we'll have a button that when clicked it will display the OverlayBlocker for 5 seconds thus 'freezes' the admin so the user can't navigate (it simulates a very long server restart). +In this example we'll have a button that when clicked will display the OverlayBlocker for 5 seconds thus 'freezes' the admin so the user can't navigate (it simulates a very long server restart). **Path -** `./plugins/my-plugin/admin/src/containers/FooPage/constants.js`. ```js From 87d01af7a7e432b5599e68950aa6659ad4c0b8cc Mon Sep 17 00:00:00 2001 From: cyril lopez Date: Thu, 18 Jan 2018 10:56:31 +0100 Subject: [PATCH 21/25] Decrease BackHeader z-index --- .../lib/src/components/BackHeader/styles.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi-helper-plugin/lib/src/components/BackHeader/styles.scss b/packages/strapi-helper-plugin/lib/src/components/BackHeader/styles.scss index 787be8cfea..d045a43b46 100644 --- a/packages/strapi-helper-plugin/lib/src/components/BackHeader/styles.scss +++ b/packages/strapi-helper-plugin/lib/src/components/BackHeader/styles.scss @@ -4,7 +4,7 @@ height: 6rem; width: 6.5rem; line-height: 6rem; - z-index: 999999; + z-index: 999; text-align: center; background-color: #FFFFFF; color: #81848A; From 5adff6248194a8d52418869a72dd59346123db76 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Thu, 18 Jan 2018 11:18:48 +0100 Subject: [PATCH 22/25] Update strapi version in documentation --- docs/3.x.x/en/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/3.x.x/en/README.md b/docs/3.x.x/en/README.md index 8b17e2ae75..47f4f89e13 100644 --- a/docs/3.x.x/en/README.md +++ b/docs/3.x.x/en/README.md @@ -12,10 +12,10 @@ The most advanced open-source Content Management Framework to build powerful API {% endcenter %} -## v3@alpha.7 is available! +## v3@alpha.8 is available! We've been working on a major update for Strapi during the past months, rewriting the core framework and the dashboard. -This documentation is only related to Strapi v3@alpha.7 ([v1 documentation is still available](http://strapi.io/documentation/1.x.x)). +This documentation is only related to Strapi v3@alpha.8 ([v1 documentation is still available](http://strapi.io/documentation/1.x.x)). **[Get Started](getting-started/installation.md)**
    Learn how to install Strapi and start developing your API. @@ -36,4 +36,4 @@ Understand how to develop your own plugin. Learn about Strapi's API, the `strapi` object that is available in your backend. **[Migration guide](migration/migration-guide.md)**
    -Migrate from v1 to v3@alpha.7. +Migrate from v1 to v3@alpha.8. From f129a249206185f71fea9e0d3be39878baad581e Mon Sep 17 00:00:00 2001 From: Jim LAURIE Date: Thu, 18 Jan 2018 11:47:12 +0100 Subject: [PATCH 23/25] Delete text migration guide link --- docs/3.x.x/en/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/3.x.x/en/README.md b/docs/3.x.x/en/README.md index 47f4f89e13..dab7d7d2ed 100644 --- a/docs/3.x.x/en/README.md +++ b/docs/3.x.x/en/README.md @@ -36,4 +36,3 @@ Understand how to develop your own plugin. Learn about Strapi's API, the `strapi` object that is available in your backend. **[Migration guide](migration/migration-guide.md)**
    -Migrate from v1 to v3@alpha.8. From 801a47994a9c78379c963fb331119d62507a211c Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Thu, 18 Jan 2018 12:28:59 +0100 Subject: [PATCH 24/25] Add migration from alpha.7.4 to alpha.8 --- README.md | 12 ++-- docs/3.x.x/en/SUMMARY.md | 1 + .../migration-guide-alpha-7-4-to-alpha-8.md | 57 +++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 docs/3.x.x/en/migration/migration-guide-alpha-7-4-to-alpha-8.md diff --git a/README.md b/README.md index 12d7164b79..1978de0c51 100755 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ This is the production-ready version of Strapi (v1). You should also consider th npm install strapi -g ``` -Read the [Getting started](http://strapi.io/documentation/getting-started/quick-start.html) page to create your first project using Strapi. +Read the [Getting started](https://strapi.io/documentation/getting-started/quick-start.html) page to create your first project using Strapi. ## Features @@ -56,7 +56,7 @@ Read the [Getting started](http://strapi.io/documentation/getting-started/quick- ## Philosophy ? -> At [Strapi](http://strapi.io), everything we do we believe in changing the status quo of web development. Our products are simple to use, user friendly and production-ready. +> At [Strapi](https://strapi.io), everything we do we believe in changing the status quo of web development. Our products are simple to use, user friendly and production-ready. Web and mobile applications needed a powerful, simple to use and production-ready API-driven solution. That's why we created Strapi, an open-source Content Management Framework (CMF) for exposing your content (data, media) accross multi-devices. @@ -78,8 +78,12 @@ For general help using Strapi, please refer to [the official Strapi documentatio ### Professional support -[Strapi Solutions](http://strapi.io), the company behind Strapi, provides a full range of solutions to get better results, faster. We're always looking for the next challenge: coaching, consulting, training, customization, etc. [Drop us an email](mailto:support@strapi.io) to see how we can help you. +[Strapi Solutions](https://strapi.io), the company behind Strapi, provides a full range of solutions to get better results, faster. We're always looking for the next challenge: coaching, consulting, training, customization, etc. [Drop us an email](mailto:support@strapi.io) to see how we can help you. + +### Migration + +Follow our [migration guides](https://strapi.io/documentation/migration/migration-guide.html) on the website to keep your Strapi projects updated. ## License -[MIT License](LICENSE.md) Copyright (c) 2015-2018 [Strapi Solutions](http://strapi.io/). +[MIT License](LICENSE.md) Copyright (c) 2015-2018 [Strapi Solutions](https://strapi.io/). diff --git a/docs/3.x.x/en/SUMMARY.md b/docs/3.x.x/en/SUMMARY.md index 240c6098dc..07b1c3d99a 100644 --- a/docs/3.x.x/en/SUMMARY.md +++ b/docs/3.x.x/en/SUMMARY.md @@ -53,3 +53,4 @@ ### Migration * [Migrating from v1 to v3](migration/migration-guide.md) +* [Migrating from 3.0.0-alpha.7.4 to 3.0.0-alpha.8](migration/migration-guide-alpha-7-4-to-alpha-8.md) diff --git a/docs/3.x.x/en/migration/migration-guide-alpha-7-4-to-alpha-8.md b/docs/3.x.x/en/migration/migration-guide-alpha-7-4-to-alpha-8.md new file mode 100644 index 0000000000..a228c0573d --- /dev/null +++ b/docs/3.x.x/en/migration/migration-guide-alpha-7-4-to-alpha-8.md @@ -0,0 +1,57 @@ +# Migrating from 3.0.0-alpha.7.3 to 3.0.0-alpha.8 + +**Here are the major changes:** + +- Fix deployment process +- Setup database connection on project creation +- Helper for table creation for SQL database + +> Feel free to [join us on Slack](http://slack.strapi.io) and ask questions about the migration process. + +## Getting started + +Install Strapi `alpha.8` globally on your computer. To do so run `npm install strapi@3.0.0-alpha.8 -g`. + +When it's done, generate a new empty project `strapi new myNewProject` (don't pay attention to the database configuration). + +## Configurations + +You will have to update just 1 file: `package.json` + +- Edit the scripts section: (only the `setup` line has changed) + +```json +{ + "scripts": { + "setup": "cd admin && npm run setup", + "start": "node server.js", + "strapi": "node_modules/strapi/bin/strapi.js", + "lint": "node_modules/.bin/eslint api/**/*.js config/**/*.js plugins/**/*.js", + "postinstall": "node node_modules/strapi/lib/utils/post-install.js" + } +} +``` + +- Edit the Strapi's dependencies version: (move Strapi's dependencies to `3.0.0-alpha.8` version) + +```json +{ + "dependencies": { + "lodash": "4.x.x", + "strapi": "3.0.0-alpha.8", + "strapi-mongoose": "3.0.0-alpha.8" + } +} +``` + +## Update the Admin + +Delete your old admin folder and replace by the new one. + +## Update the Plugins + +Copy these 3 files `/plugins/users-permissions/config/jwt.json`, `/plugins/users-permissions/config/roles.json` and `/plugins/users-permissions/models/User.settings.json` **from your old project** and paste them in the corresponding ones in your new project. It is important to save these files. + +Then, delete your old `plugins` folder and replace it by the new one. + +That's all, you have now upgraded to Strapi `alpha.8`. From 1c555293b194bfe09415569c6e57c85b158df529 Mon Sep 17 00:00:00 2001 From: Pierre BURGY Date: Thu, 18 Jan 2018 15:10:55 +0100 Subject: [PATCH 25/25] Update README.md Change Getting Started link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1978de0c51..25f2ce20f3 100755 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ This is the production-ready version of Strapi (v1). You should also consider th npm install strapi -g ``` -Read the [Getting started](https://strapi.io/documentation/getting-started/quick-start.html) page to create your first project using Strapi. +Read the [Getting started](https://strapi.io/getting-started) page to create your first project using Strapi. ## Features