Rename lifecycle hooks

This commit is contained in:
soupette 2019-08-13 11:31:10 +02:00
parent d52d4f603f
commit 857ec1ca70
36 changed files with 524 additions and 328 deletions

View File

@ -15,10 +15,9 @@ The `ExtendComponent` allows you to inject design from one plugin into another.
Let's say that you want to enable another plugin to inject a component into the top area of your plugin's container called `FooPage`;
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/actions.js`.
```js
import {
ON_TOGGLE_SHOW_LOREM,
} from './constants';
import { ON_TOGGLE_SHOW_LOREM } from './constants';
export function onToggleShowLorem() {
return {
@ -28,6 +27,7 @@ export function onToggleShowLorem() {
```
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/index.js`.
```js
import React from 'react';
import { connect } from 'react-redux';
@ -42,7 +42,7 @@ import ExtendComponent from 'components/ExtendComponent';
import injectReducer from 'utils/injectReducer';
// Actions
import { onToggleShowLorem } from './action'
import { onToggleShowLorem } from './action';
import reducer from './reducer';
@ -51,7 +51,11 @@ import { makeSelectShowLorem } from './selectors';
class FooPage extends React.Component {
render() {
const lorem = this.props.showLorem ? <p>Lorem ipsum dolor sit amet, consectetur adipiscing</p> : '';
const lorem = this.props.showLorem ? (
<p>Lorem ipsum dolor sit amet, consectetur adipiscing</p>
) : (
''
);
return (
<div>
<h1>This is FooPage container</h1>
@ -77,7 +81,7 @@ function mapDispatchToProps(dispatch) {
{
onToggleShowLorem,
},
dispatch,
dispatch
);
}
@ -85,16 +89,20 @@ const mapStateToProps = createStructuredSelector({
showLorem: makeSelectShowLorem(),
});
const withConnect = connect(mapDispatchToProps, mapDispatchToProps);
const withConnect = connect(
mapDispatchToProps,
mapDispatchToProps
);
const withReducer = injectReducer({ key: 'fooPage', reducer });
export default compose(
withReducer,
withConnect,
withConnect
)(FooPage);
```
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/reducer.js`.
```js
import { fromJS } from 'immutable';
import { ON_TOGGLE_SHOW_LOREM } from './constants';
@ -103,7 +111,7 @@ const initialState = fromJS({
showLorem: false,
});
function fooPageReducer(state= initialState, action) {
function fooPageReducer(state = initialState, action) {
switch (action.type) {
case ON_TOGGLE_SHOW_LOREM:
return state.set('showLorem', !state.get('showLorem'));
@ -116,23 +124,25 @@ export default fooPageReducer;
```
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/selectors.js`.
```js
import { createSelector } from 'reselect';
import { createSelector } from 'reselect';
/**
* Direct selector to the fooPage state domain
*/
* Direct selector to the fooPage state domain
*/
const selectFooPageDomain = () => state => state.get('fooPage');
/**
* Other specific selectors
*/
* Other specific selectors
*/
const makeSelectShowLorem = () => createSelector(
selectFooPageDomain(),
(substate) => substate.get('showLorem'),
);
const makeSelectShowLorem = () =>
createSelector(
selectFooPageDomain(),
substate => substate.get('showLorem')
);
export { makeSelectShowLorem };
```
@ -141,9 +151,10 @@ That's all now your plugin's container is injectable!
Let's see how to inject a React Component from a plugin into another.
### Create your injectedComponent
**Path -** `./plugins/another-plugin/admin/src/extendables/BarContainer/index.js`;
```js
import React from 'react';
import PropTypes from 'prop-types';
@ -181,6 +192,7 @@ export default BarContainer;
You have to create a file called `injectedComponents.js` at the root of your `another-plugin` src folder.
**Path —** `./plugins/another-plugin/admin/src/injectedComponents.js`.
```js
import BarContainer from 'extendables/BarContainer';
@ -194,15 +206,17 @@ export default [
},
];
```
Just by doing so, the `another-plugin` will add a `Button` which toggles the `lorem` paragraph in the `FooPage` view.
***
---
## Routeless container store injection
If you have a container which can be a child of several other containers (i.e. it doesn't have a route); you'll have to inject it directly in the `./plugins/my-plugin/admin/src/containers/App/index.js` file as follows :
**Path —** `./plugins/my-plugin/admin/src/containers/App/index.js`.
```js
// ...
import fooReducer from 'containers/Foo/reducer';
@ -258,7 +272,7 @@ export default compose(
)(App);
```
***
---
## Execute logic before mounting the plugin
@ -274,24 +288,26 @@ This file must contains a default functions that returns a `Promise`.
In this example, we want to populate the left menu with links that will refer to our Content Types.
**Path —** `./app/plugins/content-manager/admin/src/bootstrap.js`.
```js
import { generateMenu } from 'containers/App/sagas';
// This method is executed before the load of the plugin
const bootstrap = (plugin) => new Promise((resolve, reject) => {
generateMenu()
.then(menu => {
plugin.leftMenuSections = menu;
const bootstrap = plugin =>
new Promise((resolve, reject) => {
generateMenu()
.then(menu => {
plugin.leftMenuSections = menu;
resolve(plugin);
})
.catch(e => reject(e));
});
resolve(plugin);
})
.catch(e => reject(e));
});
export default bootstrap;
```
***
---
## Prevent plugin rendering
@ -307,6 +323,7 @@ This file must contain a default function that returns a `Promise`.
Let's say that you want to disable your plugin if the server autoReload config is disabled in development mode.
**Path —** `./app/config/environments/development/server.json`.
```
{
"host": "localhost",
@ -323,6 +340,7 @@ Let's say that you want to disable your plugin if the server autoReload config i
You'll first create a request to check if the `autoReload` config is enabled.
**Path —** `./app/plugins/my-plugin/config/routes.json`.
```json
{
"routes": [
@ -337,18 +355,24 @@ You'll first create a request to check if the `autoReload` config is enabled.
]
}
```
Then the associated handler:
**Path —** `./app/plugins/my-plugin/controllers/MyPlugin.js`.
```js
const _ = require('lodash');
const send = require('koa-send');
module.exports = {
autoReload: async ctx => {
ctx.send({ autoReload: _.get(strapi.config.currentEnvironment, 'server.autoReload', { enabled: false }) });
}
}
ctx.send({
autoReload: _.get(strapi.config.currentEnvironment, 'server.autoReload', {
enabled: false,
}),
});
},
};
```
Finally, you'll create a file called `requirements.js`at the root of your plugin's src folder.
@ -356,6 +380,7 @@ Finally, you'll create a file called `requirements.js`at the root of your plugin
The default function exported must return a `Promise`.
If you wan't to prevent the plugin from being rendered you'll have to set `plugin.preventComponentRendering = true;`.
In this case, you'll have to set:
```js
plugin.blockerComponentProps = {
blockerComponentTitle: 'my-plugin.blocker.title',
@ -367,27 +392,29 @@ plugin.blockerComponentProps = {
To follow the example above:
**Path —** `./app/plugins/my-plugin/admin/src/requirements.js`.
```js
// Use our request helper
import request from 'utils/request';
const shouldRenderCompo = (plugin) => new Promise((resolve, request) => {
request('/my-plugin/autoReload')
.then(response => {
// If autoReload is enabled the response is `{ autoReload: { enabled: true } }`
plugin.preventComponentRendering = !response.autoReload.enabled;
// Set the BlockerComponent props
plugin.blockerComponentProps = {
blockerComponentTitle: 'my-plugin.blocker.title',
blockerComponentDescription: 'my-plugin.blocker.description',
blockerComponentIcon: 'fa-refresh',
blockerComponentContent: 'renderIde', // renderIde will add an ide section that shows the development environment server.json config
};
const shouldRenderCompo = plugin =>
new Promise((resolve, request) => {
request('/my-plugin/autoReload')
.then(response => {
// If autoReload is enabled the response is `{ autoReload: { enabled: true } }`
plugin.preventComponentRendering = !response.autoReload.enabled;
// Set the BlockerComponent props
plugin.blockerComponentProps = {
blockerComponentTitle: 'my-plugin.blocker.title',
blockerComponentDescription: 'my-plugin.blocker.description',
blockerComponentIcon: 'fa-refresh',
blockerComponentContent: 'renderIde', // renderIde will add an ide section that shows the development environment server.json config
};
return resolve(plugin);
})
.catch(err => reject(err));
});
return resolve(plugin);
})
.catch(err => reject(err));
});
export default shouldRenderCompo;
```
@ -397,6 +424,7 @@ export default shouldRenderCompo;
You can render your own custom blocker by doing as follows:
**Path —** `./app/plugins/my-plugin/admin/src/requirements.js`.
```js
// Use our request helper
import request from 'utils/request';
@ -404,24 +432,25 @@ import request from 'utils/request';
// Your custom blockerComponentProps
import MyCustomBlockerComponent from 'components/MyCustomBlockerComponent';
const shouldRenderCompo = (plugin) => new Promise((resolve, request) => {
request('/my-plugin/autoReload')
.then(response => {
// If autoReload is enabled the response is `{ autoReload: { enabled: true } }`
plugin.preventComponentRendering = !response.autoReload.enabled;
const shouldRenderCompo = plugin =>
new Promise((resolve, request) => {
request('/my-plugin/autoReload')
.then(response => {
// If autoReload is enabled the response is `{ autoReload: { enabled: true } }`
plugin.preventComponentRendering = !response.autoReload.enabled;
// Tell which component to be rendered instead
plugin.blockerComponent = MyCustomBlockerComponent;
// Tell which component to be rendered instead
plugin.blockerComponent = MyCustomBlockerComponent;
return resolve(plugin);
})
.catch(err => reject(err));
});
return resolve(plugin);
})
.catch(err => reject(err));
});
export default shouldRenderCompo;
```
***
---
## Using React/Redux and sagas
@ -431,6 +460,7 @@ This short tutorial will show how to fetch data using actions/reducer/sagas.
### Constants declaration
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/constants.js`
```js
export const DATA_FETCH = 'MyPlugin/FooPage/DATA_FETCH';
export const DATA_FETCH_ERROR = 'MyPlugin/FooPage/DATA_FETCH_ERROR';
@ -440,6 +470,7 @@ export const DATA_FETCH_SUCCEEDED = 'MyPlugin/FooPage/DATA_FETCH_SUCCEEDED';
### Actions declaration
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/actions.js`
```js
import {
DATA_FETCH,
@ -474,12 +505,10 @@ export function dataFetchSucceeded(data) {
We strongly recommend to use [Immutable.js](https://facebook.github.io/immutable-js/) to structure your data.
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/reducer.js`
```js
import { fromJS, Map } from 'immutable';
import {
DATA_FETCH_ERROR,
DATA_FETCH_SUCCEEDED,
} from './constants';
import { DATA_FETCH_ERROR, DATA_FETCH_SUCCEEDED } from './constants';
const initialState = fromJS({
data: Map({}),
@ -512,6 +541,7 @@ export default fooPageReducer;
### Sagas
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/sagas.js`
```js
import { LOCATION_CHANGE } from 'react-router-redux';
import { takeLatest, put, fork, call, take, cancel } from 'redux-saga/effects';
@ -535,8 +565,7 @@ export function* fetchData(action) {
// Pass the response to the reducer
yield put(dataFetchSucceeded(response));
} catch(error) {
} catch (error) {
yield put(dataFetchError(error));
}
}
@ -566,7 +595,7 @@ export function* foo() {
const userName = yield select(makeSelectUserName());
// ...
} catch(error) {
} catch (error) {
// ...
}
}
@ -578,53 +607,54 @@ function defaultSaga() {
export default defaultSaga;
```
### Selectors
[Reselect](https://github.com/reactjs/reselect) is a library used for slicing your redux state and providing only the relevant sub-tree to a react component. It has three key features:
1. Computational power
2. Memoization
3. Composability
1. Computational power
2. Memoization
3. Composability
Creating a selector:
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/selectors.js`
```js
import { createSelector } from 'reselect';
/**
* Direct selector to the fooPage state domain
*/
* Direct selector to the fooPage state domain
*/
const selectFooPageDomain = () => state => state.get('fooPage');
/**
* Other specific selectors
*/
const makeSelectLoading = () => createSelector(
selectFooPageDomain(),
(substate) => substate.get('loading'),
);
const makeSelectLoading = () =>
createSelector(
selectFooPageDomain(),
substate => substate.get('loading')
);
/**
* Default selector used by FooPage
*/
const selectFooPage = () => createSelector(
selectFooDomain(),
(substate) => substate.toJS()
);
const selectFooPage = () =>
createSelector(
selectFooDomain(),
substate => substate.toJS()
);
export default selectFooPage;
export { makeSelectLoading };
```
#### Example
**Path —** `./plugins/my-plugin/admin/src/containers/FooPage/index.js`
```js
import React from 'react';
import { bindActionCreators } from 'redux';
@ -648,7 +678,7 @@ import selectFooPage from './selectors';
import reducer from './reducer';
export class FooPage extends React.Component {
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.error !== nextProps.error && nextProps.error) {
strapi.notification.error(nextProps.errorMessage);
}

View File

@ -330,7 +330,7 @@ export class ContentTypePage extends React.Component {
this.props.dataFetch(this.props.match.params.contentTypeName);
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (
nextProps.match.params.contentTypeName !==
this.props.match.params.contentTypeName

View File

@ -2,6 +2,9 @@
"private": true,
"dependencies": {},
"devDependencies": {
"@testing-library/jest-dom": "^4.0.0",
"@testing-library/react": "^9.1.1",
"@testing-library/react-hooks": "^2.0.1",
"babel-eslint": "^10.0.1",
"cross-env": "^5.2.0",
"cypress": "3.1.2",
@ -21,6 +24,7 @@
"lint-staged": "^9.1.0",
"npm-run-all": "^4.1.5",
"prettier": "^1.18.2",
"react-test-renderer": "^16.9.0",
"request": "^2.87.0",
"request-promise-native": "^1.0.7",
"snyk": "^1.99.0",

View File

@ -21,7 +21,7 @@ const PLUGINS_WITH_CONFIG = ['content-manager', 'email', 'upload'];
class Row extends React.Component {
state = { showModal: false };
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.pluginActionSucceeded !== this.props.pluginActionSucceeded) {
this.setState({ showModal: false });
}

View File

@ -31,16 +31,22 @@ class ImgPreview extends React.Component {
componentDidMount() {
// We don't need the generateImgURL function here since the compo will
// always have an init value here
const file = this.props.multiple ? get(this.props.files, ['0', 'name'], '') : get(this.props.files, 'name');
const file = this.props.multiple
? get(this.props.files, ['0', 'name'], '')
: get(this.props.files, 'name');
this.setState({
imgURL: get(this.props.files, ['0', 'url'], '') || get(this.props.files, 'url', ''),
imgURL:
get(this.props.files, ['0', 'url'], '') ||
get(this.props.files, 'url', ''),
isImg: this.isPictureType(file),
});
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.isUploading !== this.props.isUploading) {
const lastFile = this.props.multiple ? nextProps.files.slice(-1)[0] : nextProps.files[0] || nextProps.files;
const lastFile = this.props.multiple
? nextProps.files.slice(-1)[0]
: nextProps.files[0] || nextProps.files;
this.generateImgURL(lastFile);
if (this.props.multiple) {
@ -48,7 +54,12 @@ class ImgPreview extends React.Component {
}
}
// Update the preview or slide pictures or init the component
if (nextProps.didDeleteFile !== this.props.didDeleteFile || nextProps.position !== this.props.position || size(nextProps.files) !== size(this.props.files) && !this.state.isInitValue) {
if (
nextProps.didDeleteFile !== this.props.didDeleteFile ||
nextProps.position !== this.props.position ||
(size(nextProps.files) !== size(this.props.files) &&
!this.state.isInitValue)
) {
const file = nextProps.files[nextProps.position] || nextProps.files || '';
this.generateImgURL(file);
@ -66,14 +77,14 @@ class ImgPreview extends React.Component {
console.log('An error occured in ImgPreview', info);
}
getFileType = (fileName) => fileName.split('.').slice(-1)[0];
getFileType = fileName => fileName.split('.').slice(-1)[0];
/**
* [generateImgURL description]
* @param {FileList} files
* @return {URL}
*/
generateImgURL = (file) => {
generateImgURL = file => {
if (this.isPictureType(file.name) && !has(file, 'url')) {
const reader = new FileReader();
reader.onloadend = () => {
@ -86,15 +97,16 @@ class ImgPreview extends React.Component {
reader.readAsDataURL(file);
} else if (has(file, 'url')) {
const isImg = this.isPictureType(file.name);
const imgURL = file.url[0] === '/' ?`${strapi.backendURL}${file.url}` :file.url;
const imgURL =
file.url[0] === '/' ? `${strapi.backendURL}${file.url}` : file.url;
this.setState({ isImg, imgURL });
} else {
this.setState({ isImg: false, imgURL: file.name });
}
}
};
handleClick = (type) => {
handleClick = type => {
const { files, position } = this.props;
let file; // eslint-disable-line no-unused-vars
let nextPosition;
@ -109,51 +121,51 @@ class ImgPreview extends React.Component {
nextPosition = files[position - 1] ? position - 1 : files.length - 1;
break;
default:
// Do nothing
// Do nothing
}
// Update the parent position
this.updateFilePosition(nextPosition);
}
};
handleDragEnter = (e) => {
handleDragEnter = e => {
e.preventDefault();
e.stopPropagation();
this.setState({ isDraging: true });
}
};
handleDragLeave = (e) => {
handleDragLeave = e => {
e.preventDefault();
e.stopPropagation();
this.setState({ isDraging: false });
}
};
handleDragOver = (e) => {
handleDragOver = e => {
e.preventDefault();
e.stopPropagation();
}
};
handleDrop = (e) => {
handleDrop = e => {
this.setState({ isDraging: false });
this.props.onDrop(e);
}
};
// TODO change logic to depend on the type
isPictureType = (fileName) => /\.(jpe?g|png|gif)$/i.test(fileName);
isPictureType = fileName => /\.(jpe?g|png|gif)$/i.test(fileName);
updateFilePosition = (newPosition) => {
updateFilePosition = newPosition => {
this.props.updateFilePosition(newPosition);
}
};
renderContent = () => {
const fileType = this.getFileType(this.state.imgURL);
if (this.state.isImg) {
const imgURL = startsWith(this.state.imgURL, '/') ? `${strapi.backendURL}${this.state.imgURL}` : this.state.imgURL;
return (
<img src={imgURL} alt="" />
);
if (this.state.isImg) {
const imgURL = startsWith(this.state.imgURL, '/')
? `${strapi.backendURL}${this.state.imgURL}`
: this.state.imgURL;
return <img src={imgURL} alt="" />;
}
return (
@ -161,25 +173,24 @@ class ImgPreview extends React.Component {
<i className={`fa fa-file-${fileType}-o`} />
</div>
);
}
};
render() {
const { files, onBrowseClick } = this.props;
const { imgURL } = this.state;
const containerStyle = isEmpty(imgURL) ?
{
backgroundImage: `url(${BkgImg})`,
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
zIndex: 9999,
} : {};
const containerStyle = isEmpty(imgURL)
? {
backgroundImage: `url(${BkgImg})`,
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
zIndex: 9999,
}
: {};
return (
<div
className={cn(
styles.imgPreviewContainer,
)}
className={cn(styles.imgPreviewContainer)}
onDragOver={this.handleDragOver}
onDragEnter={this.handleDragEnter}
style={containerStyle}
@ -196,7 +207,7 @@ class ImgPreview extends React.Component {
onDrop={this.handleDrop}
showWhiteHint={this.state.isDraging || isEmpty(files)}
/>
{ !isEmpty(imgURL) && this.renderContent() }
{!isEmpty(imgURL) && this.renderContent()}
<ImgPreviewArrow
enable={isArray(files) && size(files) > 1}
onClick={this.handleClick}
@ -230,10 +241,7 @@ ImgPreview.defaultProps = {
ImgPreview.propTypes = {
didDeleteFile: PropTypes.bool,
files: PropTypes.oneOfType([
PropTypes.object,
PropTypes.array,
]),
files: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
isUploading: PropTypes.bool,
multiple: PropTypes.bool,
onBrowseClick: PropTypes.func,

View File

@ -21,7 +21,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputAddonWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputAddonWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -38,7 +39,7 @@ class InputAddonWithErrors extends React.Component { // eslint-disable-line reac
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -62,7 +63,7 @@ class InputAddonWithErrors extends React.Component { // eslint-disable-line reac
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -105,7 +106,7 @@ class InputAddonWithErrors extends React.Component { // eslint-disable-line reac
className={cn(
styles.containerAddon,
customBootstrapClass,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -138,7 +139,7 @@ class InputAddonWithErrors extends React.Component { // eslint-disable-line reac
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -211,10 +212,7 @@ InputAddonWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,

View File

@ -29,7 +29,7 @@ class InputCheckboxWithErrors extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Check if errors have been updated during validations
if (nextProps.didCheckErrors !== this.props.didCheckErrors) {
// Remove from the state the errors that have already been set
@ -38,7 +38,7 @@ class InputCheckboxWithErrors extends React.Component {
}
}
render () {
render() {
const {
autoFocus,
className,
@ -76,7 +76,11 @@ class InputCheckboxWithErrors extends React.Component {
if (isObject(title) && title.id) {
inputTitle = (
<div className={styles.inputTitle}>
<FormattedMessage id={title.id} defaultMessage={title.id} values={title.params} />
<FormattedMessage
id={title.id}
defaultMessage={title.id}
values={title.params}
/>
</div>
);
}
@ -90,7 +94,7 @@ class InputCheckboxWithErrors extends React.Component {
className={cn(
styles.container,
customBootstrapClass,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -110,7 +114,10 @@ class InputCheckboxWithErrors extends React.Component {
value={value}
/>
<InputDescription
className={cn(styles.inputCheckboxDescriptionContainer, inputDescriptionClassName)}
className={cn(
styles.inputCheckboxDescriptionContainer,
inputDescriptionClassName
)}
message={this.props.inputDescription}
style={inputDescriptionStyle}
/>
@ -181,10 +188,7 @@ InputCheckboxWithErrors.propTypes = {
]),
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,
@ -198,10 +202,7 @@ InputCheckboxWithErrors.propTypes = {
params: PropTypes.object,
}),
]),
value: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.string,
]),
value: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
};
export default InputCheckboxWithErrors;

View File

@ -21,7 +21,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputDateWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputDateWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -38,7 +39,7 @@ class InputDateWithErrors extends React.Component { // eslint-disable-line react
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -53,16 +54,16 @@ class InputDateWithErrors extends React.Component { // eslint-disable-line react
}
/**
* Set the errors depending on the validations given to the input
* @param {Object} target
*/
* Set the errors depending on the validations given to the input
* @param {Object} target
*/
handleBlur = ({ target }) => {
// Prevent from displaying error if the input is initially isEmpty
if (!isEmpty(get(target, 'value')) || this.state.hasInitialValue) {
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -102,9 +103,10 @@ class InputDateWithErrors extends React.Component { // eslint-disable-line react
return (
<div
className={cn(
!isEmpty(customBootstrapClass) && customBootstrapClass || 'col-md-4',
(!isEmpty(customBootstrapClass) && customBootstrapClass) ||
'col-md-4',
styles.containerDate,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -136,7 +138,7 @@ class InputDateWithErrors extends React.Component { // eslint-disable-line react
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -208,20 +210,14 @@ InputDateWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,
validations: PropTypes.object,
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object,
]),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
};
export default InputDateWithErrors;

View File

@ -21,7 +21,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputEmailWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputEmailWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -38,7 +39,7 @@ class InputEmailWithErrors extends React.Component { // eslint-disable-line reac
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -59,10 +60,14 @@ class InputEmailWithErrors extends React.Component { // eslint-disable-line reac
handleBlur = ({ target }) => {
// Prevent from displaying error if the input is initially isEmpty
if (!isEmpty(target.value) || this.state.hasInitialValue) {
const errors = validateInput(target.value, this.props.validations, 'email');
const errors = validateInput(
target.value,
this.props.validations,
'email'
);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -102,7 +107,7 @@ class InputEmailWithErrors extends React.Component { // eslint-disable-line reac
className={cn(
styles.containerEmail,
this.props.customBootstrapClass,
!isEmpty(this.props.className) && this.props.className,
!isEmpty(this.props.className) && this.props.className
)}
style={style}
>
@ -134,7 +139,7 @@ class InputEmailWithErrors extends React.Component { // eslint-disable-line reac
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -205,10 +210,7 @@ InputEmailWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,

View File

@ -15,7 +15,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputNumberWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputNumberWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -32,7 +33,7 @@ class InputNumberWithErrors extends React.Component { // eslint-disable-line rea
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -56,7 +57,7 @@ class InputNumberWithErrors extends React.Component { // eslint-disable-line rea
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -99,7 +100,7 @@ class InputNumberWithErrors extends React.Component { // eslint-disable-line rea
className={cn(
styles.containerInputNumber,
customBootstrapClass,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -132,7 +133,7 @@ class InputNumberWithErrors extends React.Component { // eslint-disable-line rea
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -205,10 +206,7 @@ InputNumberWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,
@ -216,10 +214,7 @@ InputNumberWithErrors.propTypes = {
style: PropTypes.object,
tabIndex: PropTypes.string,
validations: PropTypes.object,
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
export default InputNumberWithErrors;

View File

@ -38,7 +38,7 @@ class InputPasswordWithErrors extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -62,7 +62,7 @@ class InputPasswordWithErrors extends React.Component {
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -87,7 +87,9 @@ class InputPasswordWithErrors extends React.Component {
tabIndex,
value,
} = this.props;
const handleBlur = isFunction(this.props.onBlur) ? this.props.onBlur : this.handleBlur;
const handleBlur = isFunction(this.props.onBlur)
? this.props.onBlur
: this.handleBlur;
let spacer = !isEmpty(inputDescription) ? <InputSpacer /> : <div />;
@ -100,7 +102,7 @@ class InputPasswordWithErrors extends React.Component {
className={cn(
styles.containerInputPassword,
this.props.customBootstrapClass,
!isEmpty(this.props.className) && this.props.className,
!isEmpty(this.props.className) && this.props.className
)}
style={style}
>
@ -132,7 +134,7 @@ class InputPasswordWithErrors extends React.Component {
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -169,7 +171,6 @@ InputPasswordWithErrors.defaultProps = {
validations: {},
};
InputPasswordWithErrors.propTypes = {
autoFocus: PropTypes.bool,
className: PropTypes.string,
@ -204,10 +205,7 @@ InputPasswordWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,

View File

@ -21,7 +21,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputSearchWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputSearchWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -38,7 +39,7 @@ class InputSearchWithErrors extends React.Component { // eslint-disable-line rea
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -62,7 +63,7 @@ class InputSearchWithErrors extends React.Component { // eslint-disable-line rea
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -102,7 +103,7 @@ class InputSearchWithErrors extends React.Component { // eslint-disable-line rea
className={cn(
styles.containerSearch,
this.props.customBootstrapClass,
!isEmpty(this.props.className) && this.props.className,
!isEmpty(this.props.className) && this.props.className
)}
style={style}
>
@ -134,7 +135,7 @@ class InputSearchWithErrors extends React.Component { // eslint-disable-line rea
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -205,10 +206,7 @@ InputSearchWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,

View File

@ -39,7 +39,7 @@ class InputSelectWithErrors extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Check if errors have been updated during validations
if (nextProps.didCheckErrors !== this.props.didCheckErrors) {
// Remove from the state the errors that have already been set

View File

@ -15,7 +15,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputTextAreaWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputTextAreaWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -32,7 +33,7 @@ class InputTextAreaWithErrors extends React.Component { // eslint-disable-line r
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -56,7 +57,7 @@ class InputTextAreaWithErrors extends React.Component { // eslint-disable-line r
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -98,7 +99,7 @@ class InputTextAreaWithErrors extends React.Component { // eslint-disable-line r
className={cn(
styles.containerTextArea,
customBootstrapClass,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -130,7 +131,7 @@ class InputTextAreaWithErrors extends React.Component { // eslint-disable-line r
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -201,10 +202,7 @@ InputTextAreaWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,

View File

@ -16,7 +16,8 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputTextWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputTextWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
@ -33,7 +34,7 @@ class InputTextWithErrors extends React.Component { // eslint-disable-line react
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });
@ -57,7 +58,7 @@ class InputTextWithErrors extends React.Component { // eslint-disable-line react
const errors = validateInput(target.value, this.props.validations);
this.setState({ errors, hasInitialValue: true });
}
}
};
render() {
const {
@ -99,7 +100,7 @@ class InputTextWithErrors extends React.Component { // eslint-disable-line react
className={cn(
styles.containerText,
customBootstrapClass,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -131,7 +132,7 @@ class InputTextWithErrors extends React.Component { // eslint-disable-line react
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
@ -202,10 +203,7 @@ InputTextWithErrors.propTypes = {
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,

View File

@ -18,7 +18,7 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
class InputToggleWithErrors extends React.Component {
state = { errors: [] }
state = { errors: [] };
componentDidMount() {
const { errors } = this.props;
@ -28,7 +28,7 @@ class InputToggleWithErrors extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Check if errors have been updated during validations
if (nextProps.didCheckErrors !== this.props.didCheckErrors) {
// Remove from the state the errors that have already been set
@ -73,7 +73,7 @@ class InputToggleWithErrors extends React.Component {
className={cn(
styles.containerToggleErrors,
customBootstrapClass,
!isEmpty(className) && className,
!isEmpty(className) && className
)}
style={style}
>
@ -104,7 +104,7 @@ class InputToggleWithErrors extends React.Component {
/>
<InputErrors
className={errorsClassName}
errors={!noErrorsDescription && this.state.errors || []}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>

View File

@ -153,7 +153,7 @@ class PreviewWysiwyg extends React.PureComponent {
// NOTE: This is not optimal and this lifecycle should be removed
// I couldn't find a better way to decrease the fullscreen preview's data conversion time
// Trying with componentDidUpdate didn't work
UNSAFE_componentWillUpdate(nextProps, nextState) {
UNSAFE_UNSAFE_componentWillUpdate(nextProps, nextState) {
if (nextProps.data !== this.props.data) {
new Promise(resolve => {
setTimeout(() => {

View File

@ -38,7 +38,7 @@ class WysiwygWithErrors extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(nextProps.value) && !this.state.hasInitialValue) {
this.setState({ hasInitialValue: true });

View File

@ -31,7 +31,7 @@ class EditFormSectionNested extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.values) {
this.checkForNestedForm(nextProps);
}
@ -62,9 +62,7 @@ class EditFormSectionNested extends React.Component {
render() {
return (
<div
className={`${this.props.styles.stmpadded} ${
this.props.styles.stmnesTedFormContainer
}`}
className={`${this.props.styles.stmpadded} ${this.props.styles.stmnesTedFormContainer}`}
>
<div className="row">
{map(this.props.section, (item, key) => {

View File

@ -59,7 +59,7 @@ class InputNumber extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.errors !== nextProps.errors) {
this.setState({
errors: uniqBy(union(this.state.errors, nextProps.errors), 'id'),

View File

@ -37,7 +37,7 @@ class InputPassword extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (!this.isSame(nextProps)) {
this.setState({ errors: nextProps.errors });
}
@ -57,7 +57,7 @@ class InputPassword extends React.Component {
return (
size(this.props.errors) === size(nextProps.errors) &&
this.props.errors.every(
(error, index) => error.id === nextProps.errors[index].id,
(error, index) => error.id === nextProps.errors[index].id
)
);
};
@ -152,9 +152,7 @@ class InputPassword extends React.Component {
return (
<div className={`${bootStrapClass}`}>
<div
className={`${
this.props.styles.stminputText
} ${bootStrapClassDanger}`}
className={`${this.props.styles.stminputText} ${bootStrapClassDanger}`}
>
<label htmlFor={this.props.name}>
<FormattedMessage id={`settings-manager.${this.props.name}`} />

View File

@ -61,7 +61,7 @@ class InputText extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (!this.isSame(nextProps)) {
const errors = isEmpty(nextProps.errors)
? []

View File

@ -31,7 +31,7 @@ class InputToggle extends React.Component {
this.setState({ isChecked });
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.isChecked !== this.props.isChecked) {
this.setState({ isChecked: nextProps.isChecked });
}

View File

@ -27,7 +27,7 @@ class PluginLeftMenuLink extends React.Component {
this.setState({ environmentIndex });
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.state.environmentIndex === -1 && nextProps.envParams) {
this.setState({
environmentIndex: findIndex(nextProps.environments, [
@ -52,9 +52,9 @@ class PluginLeftMenuLink extends React.Component {
if (!isEmpty(this.props.environments)) {
url = this.props.environmentsRequired
? `${this.props.link.slug}/${get(this.props.environments, [
this.state.environmentIndex,
'name',
])}`
this.state.environmentIndex,
'name',
])}`
: `${this.props.link.slug}`;
}

View File

@ -66,7 +66,7 @@ const WithFormSection = InnerComponent =>
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (
nextProps.section !== this.props.section ||
nextProps.cancelAction !== this.props.cancelAction

View File

@ -31,7 +31,7 @@ class App extends React.Component {
this.props.environmentsFetch();
}
componentWillUpdate(nextProps) {
UNSAFE_componentWillUpdate(nextProps) {
if (
!isEmpty(nextProps.sections) &&
nextProps.location.pathname !== '/plugins/settings-manager'

View File

@ -109,7 +109,7 @@ export class HomePage extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// check if params slug updated
if (
this.props.match.params.slug !== nextProps.match.params.slug &&

View File

@ -27,7 +27,7 @@ class ConfigPage extends React.Component {
this.getSettings(this.props);
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Get new settings on navigation change
if (nextProps.match.params.env !== this.props.match.params.env) {
this.getSettings(nextProps);
@ -79,8 +79,8 @@ class ConfigPage extends React.Component {
get(
this.props.settings,
['providers', this.getSelectedProviderIndex(), 'auth'],
{},
),
{}
)
).reduce((acc, current) => {
if (isEmpty(get(this.props.modifiedData, current, ''))) {
acc.push({
@ -174,7 +174,7 @@ function mapDispatchToProps(dispatch) {
setErrors,
submit,
},
dispatch,
dispatch
);
}
@ -182,7 +182,7 @@ const mapStateToProps = selectConfigPage();
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
mapDispatchToProps
);
const withReducer = strapi.injectReducer({
@ -195,5 +195,5 @@ const withSaga = strapi.injectSaga({ key: 'configPage', saga, pluginId });
export default compose(
withReducer,
withSaga,
withConnect,
withConnect
)(ConfigPage);

View File

@ -51,7 +51,7 @@ export class HomePage extends React.Component {
deleteData: this.props.deleteData,
});
componentWillMount() {
UNSAFE_componentWillMount() {
if (!isEmpty(this.props.location.search)) {
const _page = parseInt(this.getURLParams('_page'), 10);
const _limit = parseInt(this.getURLParams('_limit'), 10);
@ -64,7 +64,7 @@ export class HomePage extends React.Component {
this.props.getData();
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.deleteSuccess !== this.props.deleteSuccess) {
this.props.getData();
}

View File

@ -1,8 +1,8 @@
/**
*
* InputCheckboxPlugin
*
*/
*
* InputCheckboxPlugin
*
*/
import React from 'react';
import PropTypes from 'prop-types';
@ -10,12 +10,16 @@ import cn from 'classnames';
import styles from './styles.scss';
class InputCheckboxPlugin extends React.Component { // eslint-disable-line react/prefer-stateless-function
class InputCheckboxPlugin extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { showBackground: false, showCog: false };
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Remove background if another input is selected
if (nextProps.inputSelected !== this.props.inputSelected && nextProps.inputSelected !== this.props.name) {
if (
nextProps.inputSelected !== this.props.inputSelected &&
nextProps.inputSelected !== this.props.name
) {
this.setState({ showBackground: false });
}
@ -45,7 +49,7 @@ class InputCheckboxPlugin extends React.Component { // eslint-disable-line react
}
this.context.onChange({ target });
}
};
handleClick = () => {
this.setState({ showBackground: !this.state.showBackground });
@ -57,7 +61,7 @@ class InputCheckboxPlugin extends React.Component { // eslint-disable-line react
} else {
this.context.setShouldDisplayPolicieshint();
}
}
};
render() {
return (
@ -70,8 +74,20 @@ class InputCheckboxPlugin extends React.Component { // eslint-disable-line react
}}
onMouseLeave={() => this.setState({ showCog: false })}
>
<div className={cn('form-check', this.state.showBackground ? styles.highlighted : '')}>
<label className={cn('form-check-label', styles.label, this.props.value ? styles.checked : '')} htmlFor={this.props.name}>
<div
className={cn(
'form-check',
this.state.showBackground ? styles.highlighted : ''
)}
>
<label
className={cn(
'form-check-label',
styles.label,
this.props.value ? styles.checked : ''
)}
htmlFor={this.props.name}
>
<input
className="form-check-input"
defaultChecked={this.props.value}
@ -84,7 +100,9 @@ class InputCheckboxPlugin extends React.Component { // eslint-disable-line react
</label>
{this.state.showCog || this.state.showBackground ? (
<i className="fa fa-cog" onClick={this.handleClick} />
) : ''}
) : (
''
)}
</div>
</div>
);

View File

@ -26,7 +26,7 @@ class InputSearchContainer extends React.Component {
value: '',
};
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.didDeleteUser !== this.props.didDeleteUser) {
this.setState({
users: nextProps.values,
@ -52,8 +52,8 @@ class InputSearchContainer extends React.Component {
const filteredUsers = isEmpty(target.value)
? this.state.users
: this.state.users.filter(user =>
includes(toLower(user.name), toLower(target.value)),
);
includes(toLower(user.name), toLower(target.value))
);
if (isEmpty(filteredUsers) && !isEmpty(target.value)) {
this.props.getUser(target.value);
@ -106,7 +106,7 @@ class InputSearchContainer extends React.Component {
className={cn(
'input-group-addon',
styles.addon,
this.state.isFocused && styles.addonFocus,
this.state.isFocused && styles.addonFocus
)}
/>
<FormattedMessage id="users-permissions.InputSearch.placeholder">
@ -114,7 +114,7 @@ class InputSearchContainer extends React.Component {
<input
className={cn(
'form-control',
!isEmpty(this.state.errors) ? 'is-invalid' : '',
!isEmpty(this.state.errors) ? 'is-invalid' : ''
)}
id={this.props.name}
name={this.props.name}
@ -134,7 +134,7 @@ class InputSearchContainer extends React.Component {
<div
className={cn(
styles.ulContainer,
this.state.isFocused && styles.ulFocused,
this.state.isFocused && styles.ulFocused
)}
>
<ul>

View File

@ -1,8 +1,8 @@
/**
*
* Plugin
*
*/
*
* Plugin
*
*/
import React from 'react';
import PropTypes from 'prop-types';
@ -14,19 +14,26 @@ import Controller from '../Controller';
import styles from './styles.scss';
class Plugin extends React.Component { // eslint-disable-line react/prefer-stateless-function
class Plugin extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { collapse: false };
componentDidMount() {
// Open the application's permissions section if there are APIs
if (this.props.name === 'application' && !isEmpty(get(this.props.plugin, 'controllers'))) {
if (
this.props.name === 'application' &&
!isEmpty(get(this.props.plugin, 'controllers'))
) {
this.props.changePluginSelected('application');
this.setState({ collapse: !this.state.collapse });
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.pluginSelected !== this.props.pluginSelected && nextProps.pluginSelected !== this.props.name) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (
nextProps.pluginSelected !== this.props.pluginSelected &&
nextProps.pluginSelected !== this.props.name
) {
this.context.resetShouldDisplayPoliciesHint();
this.setState({ collapse: false });
}
@ -42,7 +49,7 @@ class Plugin extends React.Component { // eslint-disable-line react/prefer-state
if (this.state.collapse) {
this.context.resetShouldDisplayPoliciesHint();
}
}
};
render() {
const divStyle = this.state.collapse ? { marginBottom: '.4rem' } : {};
@ -59,16 +66,14 @@ class Plugin extends React.Component { // eslint-disable-line react/prefer-state
<div>
{this.props.name !== 'application' && (
<div className={styles.iconContainer}>
{icon && <img src={icon} alt="icon" />}
{icon && <img src={icon} alt="icon" />}
</div>
)}
<div className={styles.name}>{this.props.name}</div>
&nbsp;&nbsp;
<div className={styles.description}>
{this.props.name === 'application' ? (
<FormattedMessage
id="users-permissions.Plugin.permissions.application.description"
/>
<FormattedMessage id="users-permissions.Plugin.permissions.application.description" />
) : (
<FormattedMessage
id="users-permissions.Plugin.permissions.plugins.description"
@ -77,21 +82,30 @@ class Plugin extends React.Component { // eslint-disable-line react/prefer-state
)}
</div>
</div>
{ emptyApplication && <div className={this.state.collapse ? styles.chevronUp : styles.chevronDown}></div> }
{emptyApplication && (
<div
className={
this.state.collapse ? styles.chevronUp : styles.chevronDown
}
></div>
)}
</div>
<Collapse isOpen={this.state.collapse}>
<div />
<div className={styles.controllerContainer}>
{map(get(this.props.plugin, 'controllers'), (controllerActions, key) => (
<Controller
inputNamePath={`permissions.${this.props.name}`}
isOpen={this.state.collapse}
key={key}
name={key}
actions={controllerActions}
resetInputBackground={this.state.resetInputBackground}
/>
))}
{map(
get(this.props.plugin, 'controllers'),
(controllerActions, key) => (
<Controller
inputNamePath={`permissions.${this.props.name}`}
isOpen={this.state.collapse}
key={key}
name={key}
actions={controllerActions}
resetInputBackground={this.state.resetInputBackground}
/>
)
)}
</div>
</Collapse>
</div>

View File

@ -34,7 +34,7 @@ class PopUpForm extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { enabled: false, isEditing: false };
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
const { values } = nextProps;
if (

View File

@ -83,7 +83,7 @@ export class EditPage extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
// Redirect user to HomePage if submit ok
if (nextProps.editPage.didSubmit !== this.props.editPage.didSubmit) {
this.props.history.push('/plugins/users-permissions/roles');
@ -218,7 +218,7 @@ export class EditPage extends React.Component {
type: 'submit',
disabled: isEqual(
this.props.editPage.modifiedData,
this.props.editPage.initialData,
this.props.editPage.initialData
),
},
];
@ -364,13 +364,13 @@ function mapDispatchToProps(dispatch) {
resetProps,
resetShouldDisplayPoliciesHint,
},
dispatch,
dispatch
);
}
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
mapDispatchToProps
);
const withReducer = strapi.injectReducer({
key: 'editPage',
@ -382,5 +382,5 @@ const withSaga = strapi.injectSaga({ key: 'editPage', saga, pluginId });
export default compose(
withReducer,
withSaga,
withConnect,
withConnect
)(EditPage);

View File

@ -64,13 +64,13 @@ export class HomePage extends React.Component {
document.addEventListener('keyup', this.handleKeyBoardShortCut);
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.dataToEdit !== this.props.dataToEdit) {
this.setState({ showModalEdit: !isEmpty(nextProps.dataToEdit) });
}
}
componentWillUpdate(nextProps) {
UNSAFE_componentWillUpdate(nextProps) {
const allowedPaths = ['roles', 'providers', 'email-templates', 'advanced'];
const shouldRedirect =
allowedPaths.filter(el => el === nextProps.match.params.settingType)
@ -122,9 +122,7 @@ export class HomePage extends React.Component {
this.props.history.push(`${this.props.location.pathname}/create`);
} else if (this.props.match.params.settingType === 'providers') {
this.props.history.push(
`${this.props.location.pathname}#add::${
this.props.match.params.settingType
}`,
`${this.props.location.pathname}#add::${this.props.match.params.settingType}`
);
}
};
@ -142,7 +140,7 @@ export class HomePage extends React.Component {
const formErrors = checkFormValidity(
this.props.match.params.settingType,
modifiedObject,
this.props.dataToEdit,
this.props.dataToEdit
);
if (isEqual(initObject, modifiedObject)) {
@ -322,7 +320,7 @@ function mapDispatchToProps(dispatch) {
submit,
unsetDataToEdit,
},
dispatch,
dispatch
);
}
@ -330,7 +328,7 @@ const mapStateToProps = selectHomePage();
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
mapDispatchToProps
);
const withReducer = strapi.injectReducer({
key: 'homePage',
@ -342,5 +340,5 @@ const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
export default compose(
withReducer,
withSaga,
withConnect,
withConnect
)(injectIntl(HomePage));

156
yarn.lock
View File

@ -713,7 +713,7 @@
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.3", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.3", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
@ -2044,6 +2044,11 @@
"@sendgrid/client" "^6.4.0"
"@sendgrid/helpers" "^6.4.0"
"@sheerun/mutationobserver-shim@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b"
integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==
"@sindresorhus/is@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
@ -2081,6 +2086,50 @@
resolved "https://registry.yarnpkg.com/@snyk/gemfile/-/gemfile-1.2.0.tgz#919857944973cce74c650e5428aaf11bcd5c0457"
integrity sha512-nI7ELxukf7pT4/VraL4iabtNNMz8mUo7EXlqCFld8O5z6mIMLX9llps24iPpaIZOwArkY3FWA+4t+ixyvtTSIA==
"@testing-library/dom@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.0.0.tgz#34e28e69e49bd6347fc64a5dde4c4f9aabbd17d3"
integrity sha512-B5XTz3uMsbqbdR9CZlnwpZjTE3fCWuqRkz/zvDc2Ej/vuHmTM0Ur2v0XPwr7usWfGIBsahEK5HL1E91+4IFiBg==
dependencies:
"@babel/runtime" "^7.5.5"
"@sheerun/mutationobserver-shim" "^0.3.2"
aria-query "3.0.0"
pretty-format "^24.8.0"
wait-for-expect "^1.3.0"
"@testing-library/jest-dom@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-4.0.0.tgz#56eee8dd183fe14a682fda7aca6413ec4e5303d2"
integrity sha512-YQA/LnRRfqHV5YRauawOGgMDgq43XfyqCz3whmxIPyrfvTdjLCNyY/BseGaa48y54yb3oiRo/NZT0oXNMQdkTA==
dependencies:
"@babel/runtime" "^7.5.1"
chalk "^2.4.1"
css "^2.2.3"
css.escape "^1.5.1"
jest-diff "^24.0.0"
jest-matcher-utils "^24.0.0"
lodash "^4.17.11"
pretty-format "^24.0.0"
redent "^3.0.0"
"@testing-library/react-hooks@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-2.0.1.tgz#1c3ec40882d0830df3078ddae0056fdf7366c81d"
integrity sha512-MLTvWX7/csq/uQzP4WJntGz0QJDq6H4EzjV0VTL5YJE7KBZbaQ9DGT0IbtjuB33L4R4YKZ55rGZQ5eL+WiZtQA==
dependencies:
"@babel/runtime" "^7.5.4"
"@types/react" ">=16.9.0"
"@types/react-test-renderer" ">=16.9.0"
"@testing-library/react@^9.1.1":
version "9.1.1"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.1.1.tgz#ee5b15c02b64cfbd14cdcad87fee2ed5f28fc2d1"
integrity sha512-mjX9l/onA5eVe8/4/obe7ZAw05U8s+kinXVglySVOMJo/oCSam9D9Dcg+aYVGsuBEuYV2W9m2LTP4KbNZh8BOw==
dependencies:
"@babel/runtime" "^7.5.5"
"@testing-library/dom" "^6.0.0"
"@types/react-dom" "^16.8.5"
"@types/accepts@*", "@types/accepts@^1.3.5":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575"
@ -2401,6 +2450,20 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/react-dom@^16.8.5":
version "16.8.5"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.5.tgz#3e3f4d99199391a7fb40aa3a155c8dd99b899cbd"
integrity sha512-idCEjROZ2cqh29+trmTmZhsBAUNQuYrF92JHKzZ5+aiFM1mlSk3bb23CK7HhYuOY75Apgap5y2jTyHzaM2AJGA==
dependencies:
"@types/react" "*"
"@types/react-test-renderer@>=16.9.0":
version "16.9.0"
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.0.tgz#d60f530ecf4c906721511603cca711b4fa830d41"
integrity sha512-bN5EyjtuTY35xX7N5j0KP1vg5MpUXHpFTX6tGsqkNOthjNvet4VQOYRxFh+NT5cDSJrATmAFK9NLeYZ4mp/o0Q==
dependencies:
"@types/react" "*"
"@types/react@*":
version "16.8.23"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.23.tgz#ec6be3ceed6353a20948169b6cb4c97b65b97ad2"
@ -2409,6 +2472,14 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/react@>=16.9.0":
version "16.9.1"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.1.tgz#862c83b4c9d5cd116e42fd9a4f3694843cd2c051"
integrity sha512-jGM2x8F7m7/r+81N/BOaUKVwbC5Cdw6ExlWEUpr77XPwVeNvAppnPEnMMLMfxRDYL8FPEX8MHjwtD2NQMJ0yyQ==
dependencies:
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/request@^2.0.3", "@types/request@^2.48.1":
version "2.48.2"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.2.tgz#936374cbe1179d7ed529fc02543deb4597450fed"
@ -3129,6 +3200,14 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
aria-query@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=
dependencies:
ast-types-flow "0.0.7"
commander "^2.11.0"
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@ -3322,6 +3401,11 @@ assign-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
ast-types-flow@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
ast-types@0.9.6:
version "0.9.6"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
@ -4746,7 +4830,7 @@ commander@2.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873"
integrity sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=
commander@^2.19.0, commander@^2.20.0, commander@^2.8.1, commander@~2.20.0:
commander@^2.11.0, commander@^2.19.0, commander@^2.20.0, commander@^2.8.1, commander@~2.20.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
@ -5415,6 +5499,21 @@ css-what@2.1, css-what@^2.1.2:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
css.escape@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=
css@^2.2.3:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
dependencies:
inherits "^2.0.3"
source-map "^0.6.1"
source-map-resolve "^0.5.2"
urix "^0.1.0"
cssdb@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0"
@ -8925,6 +9024,11 @@ indent-string@^3.0.0:
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
indent-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
@ -9819,7 +9923,7 @@ jest-config@^24.8.0:
pretty-format "^24.8.0"
realpath-native "^1.1.0"
jest-diff@^24.8.0:
jest-diff@^24.0.0, jest-diff@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172"
integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==
@ -9923,7 +10027,7 @@ jest-leak-detector@^24.8.0:
dependencies:
pretty-format "^24.8.0"
jest-matcher-utils@^24.8.0:
jest-matcher-utils@^24.0.0, jest-matcher-utils@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495"
integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw==
@ -11687,6 +11791,11 @@ mimic-response@^1.0.0:
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
min-indent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256"
integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=
mini-create-react-context@^0.3.0:
version "0.3.2"
resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189"
@ -14419,7 +14528,7 @@ pretty-error@^2.0.2:
renderkid "^2.0.1"
utila "~0.4"
pretty-format@^24.8.0:
pretty-format@^24.0.0, pretty-format@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==
@ -14977,6 +15086,11 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
react-is@^16.9.0:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@ -15126,6 +15240,16 @@ react-test-renderer@^16.0.0-0:
react-is "^16.8.6"
scheduler "^0.13.6"
react-test-renderer@^16.9.0:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.9.0.tgz#7ed657a374af47af88f66f33a3ef99c9610c8ae9"
integrity sha512-R62stB73qZyhrJo7wmCW9jgl/07ai+YzvouvCXIJLBkRlRqLx4j9RqcLEAfNfU3OxTGucqR2Whmn3/Aad6L3hQ==
dependencies:
object-assign "^4.1.1"
prop-types "^15.6.2"
react-is "^16.9.0"
scheduler "^0.15.0"
react-transition-group@^2.2.1, react-transition-group@^2.3.1, react-transition-group@^2.5.0, react-transition-group@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
@ -15412,6 +15536,14 @@ redent@^2.0.0:
indent-string "^3.0.0"
strip-indent "^2.0.0"
redent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
dependencies:
indent-string "^4.0.0"
strip-indent "^3.0.0"
redis-commands@*, redis-commands@1.5.0, redis-commands@^1.2.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785"
@ -16947,7 +17079,7 @@ source-list-map@^2.0.0:
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
source-map-resolve@^0.5.0:
source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==
@ -17428,6 +17560,13 @@ strip-indent@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
strip-indent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
dependencies:
min-indent "^1.0.0"
strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
@ -18555,6 +18694,11 @@ w3c-hr-time@^1.0.1:
dependencies:
browser-process-hrtime "^0.1.2"
wait-for-expect@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.3.0.tgz#65241ce355425f907f5d127bdb5e72c412ff830c"
integrity sha512-8fJU7jiA96HfGPt+P/UilelSAZfhMBJ52YhKzlmZQvKEZU2EcD1GQ0yqGB6liLdHjYtYAoGVigYwdxr5rktvzA==
wait-on@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-3.3.0.tgz#9940981d047a72a9544a97b8b5fca45b2170a082"