Add eslint to strapi-helper-plugin!

This commit is contained in:
cyril lopez 2018-03-14 09:59:42 +01:00
parent bf9451d720
commit ac3ea588fa
42 changed files with 341 additions and 298 deletions

View File

@ -66,10 +66,10 @@ module.exports = require('./webpack.base.babel')({
path.join(appPath, 'admin', 'admin', 'src', 'app.js'),
],
}, plugins.src.reduce((acc, current) => {
acc[current] = path.resolve(plugins.folders[current], 'app.js');
acc[current] = path.resolve(plugins.folders[current], 'app.js');
return acc;
}, {})
return acc;
}, {})
),
// Don't use hashes in dev mode for better performance

View File

@ -7,6 +7,8 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import cn from 'classnames';
import PropTypes from 'prop-types';
import styles from './styles.scss';
/* eslint-disable react/require-default-props */
@ -85,4 +87,11 @@ const renderButton = () => (
</div>
);
BlockerComponent.propTypes = {
blockerComponentContent: PropTypes.string.isRequired,
blockerComponentDescription: PropTypes.string.isRequired,
blockerComponentIcon: PropTypes.string.isRequired,
blockerComponentTitle: PropTypes.string.isRequired,
};
export default BlockerComponent;

View File

@ -7,7 +7,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import styles from './styles.scss';
class ErrorBoundary extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {

View File

@ -40,12 +40,12 @@ ExtendComponent.contextTypes = {
plugins: PropTypes.object,
router: PropTypes.object,
updatePlugin: PropTypes.func,
}
};
ExtendComponent.propTypes = {
area: PropTypes.string.isRequired,
container: PropTypes.string.isRequired,
children: PropTypes.node,
container: PropTypes.string.isRequired,
plugin: PropTypes.string.isRequired,
};

View File

@ -10,6 +10,7 @@ import PropTypes from 'prop-types';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/anchor-is-valid */
class GlobalPagination extends React.Component {
getLastPageNumber = () => Math.ceil(this.props.count / this.props.params.limit);
@ -163,6 +164,7 @@ class GlobalPagination extends React.Component {
}
GlobalPagination.defaultProps = {
count: 0,
onChangeParams: () => {},
params: {
page: 1,

View File

@ -23,11 +23,13 @@ const handleClick = (e, onClick) => {
Ico.propTypes = {
icoType: PropTypes.string,
id: PropTypes.string,
onClick: PropTypes.func,
};
Ico.defaultProps = {
icoType: 'trash',
id: '',
onClick: () => {},
};

View File

@ -30,8 +30,8 @@ class ImgPreview extends React.Component {
// We don't need the generateImgURL function here since the compo will
// always have an init value here
this.setState({
imgURL: get(this.props.files, ['0', 'url'], '') || get(this.props.files, 'url', ''),
isImg: this.isPictureType(get(this.props.files, ['0', 'name'], '')),
imgURL: get(this.props.files, ['0', 'url'], '') || get(this.props.files, 'url', ''),
isImg: this.isPictureType(get(this.props.files, ['0', 'name'], '')),
});
}
@ -47,7 +47,7 @@ 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) {
const file = nextProps.files[nextProps.position] || nextProps.files || '';
this.generateImgURL(file)
this.generateImgURL(file);
if (!this.state.isInitValue) {
this.setState({ isInitValue: true });
@ -74,7 +74,7 @@ class ImgPreview extends React.Component {
imgURL: reader.result,
isImg: true,
});
}
};
reader.readAsDataURL(file);
} else if (has(file, 'url')) {
@ -89,7 +89,7 @@ class ImgPreview extends React.Component {
handleClick = (type) => {
const { files, position } = this.props;
let file;
let file; // eslint-disable-line no-unused-vars
let nextPosition;
switch (type) {
@ -134,12 +134,17 @@ class ImgPreview extends React.Component {
// TODO change logic to depend on the type
isPictureType = (fileName) => /\.(jpe?g|png|gif)$/i.test(fileName);
updateFilePosition = (newPosition) => {
// this.setState({ position: newPosition });
this.props.updateFilePosition(newPosition);
}
renderContent = () => {
const fileType = this.getFileType(this.state.imgURL);
if (this.state.isImg) {
return (
<img src={this.state.imgURL} />
<img src={this.state.imgURL} alt="" />
);
}
@ -150,13 +155,8 @@ class ImgPreview extends React.Component {
);
}
updateFilePosition = (newPosition) => {
// this.setState({ position: newPosition });
this.props.updateFilePosition(newPosition);
}
render() {
const { files, multiple, onBrowseClick } = this.props;
const { files, onBrowseClick } = this.props;
const { imgURL } = this.state;
const containerStyle = isEmpty(imgURL) ?
{
@ -167,44 +167,43 @@ class ImgPreview extends React.Component {
} : {};
return (
<div
className={cn(
styles.imgPreviewContainer,
)}
onDragOver={this.handleDragOver}
onDragEnter={this.handleDragEnter}
style={containerStyle}
>
<div
className={cn(
styles.imgPreviewContainer,
)}
className={cn(this.state.isDraging && styles.overlay)}
onDragLeave={this.handleDragLeave}
onDragOver={this.handleDragOver}
onDragEnter={this.handleDragEnter}
style={containerStyle}
>
<div
className={cn(this.state.isDraging && styles.overlay)}
onDragLeave={this.handleDragLeave}
onDragOver={this.handleDragOver}
onDrop={this.handleDrop}
/>
<ImgPreviewHint
displayHint={isEmpty(files)}
onClick={onBrowseClick}
onDrop={this.handleDrop}
showWhiteHint={this.state.isDraging || isEmpty(files)}
/>
{ !isEmpty(imgURL) && this.renderContent() }
<ImgPreviewArrow
enable={isArray(files) && size(files) > 1}
onClick={this.handleClick}
onMouseEnter={(e) => this.setState({ isOverArrow: true })}
onMouseLeave={(e) => this.setState({ isOverArrow: false })}
show={isArray(files) && size(files) > 1}
type="right"
/>
<ImgPreviewArrow
enable={isArray(files) && size(files) > 1}
onClick={this.handleClick}
onMouseEnter={(e) => this.setState({ isOverArrow: true })}
onMouseLeave={(e) => this.setState({ isOverArrow: false })}
show={isArray(files) && size(files) > 1}
/>
</div>
onDrop={this.handleDrop}
/>
<ImgPreviewHint
displayHint={isEmpty(files)}
onClick={onBrowseClick}
onDrop={this.handleDrop}
showWhiteHint={this.state.isDraging || isEmpty(files)}
/>
{ !isEmpty(imgURL) && this.renderContent() }
<ImgPreviewArrow
enable={isArray(files) && size(files) > 1}
onClick={this.handleClick}
onMouseEnter={() => this.setState({ isOverArrow: true })}
onMouseLeave={() => this.setState({ isOverArrow: false })}
show={isArray(files) && size(files) > 1}
type="right"
/>
<ImgPreviewArrow
enable={isArray(files) && size(files) > 1}
onClick={this.handleClick}
onMouseEnter={() => this.setState({ isOverArrow: true })}
onMouseLeave={() => this.setState({ isOverArrow: false })}
show={isArray(files) && size(files) > 1}
/>
</div>
);
}
}
@ -214,9 +213,7 @@ ImgPreview.defaultProps = {
files: [],
isUploading: false,
multiple: false,
name: '',
onBrowseClick: () => {},
onChange: () => {},
onDrop: () => {},
position: 0,
updateFilePosition: () => {},
@ -230,9 +227,7 @@ ImgPreview.propTypes = {
]),
isUploading: PropTypes.bool,
multiple: PropTypes.bool,
name: PropTypes.string,
onBrowseClick: PropTypes.func,
onChange: PropTypes.func,
onDrop: PropTypes.func,
position: PropTypes.number,
updateFilePosition: PropTypes.func,

View File

@ -11,6 +11,7 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputAddon extends React.Component {
state = { isFocused: false };
@ -47,7 +48,8 @@ class InputAddon extends React.Component {
<div className={cn(styles.inputAddon, 'input-group', !isEmpty(className) && className)} style={style}>
<FormattedMessage id={addon} defaultMessage={upperFirst(addon)}>
{(message) => (
<span className={cn(
<span
className={cn(
'input-group-addon',
styles.addon,
this.state.isFocused && styles.addonFocus,
@ -106,13 +108,13 @@ InputAddon.propTypes = {
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.oneOfType([
PropTypes.func,
PropTypes.bool,
]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,

View File

@ -101,7 +101,8 @@ class InputAddonWithErrors extends React.Component { // eslint-disable-line reac
}
return (
<div className={cn(
<div
className={cn(
styles.containerAddon,
customBootstrapClass,
!isEmpty(className) && className,

View File

@ -12,6 +12,8 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
/* eslint-disable jsx-a11y/label-has-for */
class InputCheckbox extends React.Component {
handleChange = () => {
const target = {
@ -84,7 +86,8 @@ class InputCheckbox extends React.Component {
);
}
return (
<div className={cn(
<div
className={cn(
'form-check',
styles.inputCheckbox,
!isEmpty(className) && className,

View File

@ -11,7 +11,6 @@ import { isEmpty, isObject, isFunction } from 'lodash';
import cn from 'classnames';
// Design
import Label from 'components/Label';
import InputDescription from 'components/InputDescription';
import InputErrors from 'components/InputErrors';
import InputCheckbox from 'components/InputCheckbox';
@ -44,7 +43,6 @@ class InputCheckboxWithErrors extends React.Component {
autoFocus,
className,
customBootstrapClass,
deactivateErrorHighlight,
disabled,
errorsClassName,
errorsStyle,
@ -54,8 +52,6 @@ class InputCheckboxWithErrors extends React.Component {
inputDescriptionStyle,
inputStyle,
label,
labelClassName,
labelStyle,
name,
noErrorsDescription,
onBlur,
@ -90,7 +86,8 @@ class InputCheckboxWithErrors extends React.Component {
}
return (
<div className={cn(
<div
className={cn(
styles.container,
customBootstrapClass,
!isEmpty(className) && className,
@ -122,7 +119,7 @@ class InputCheckboxWithErrors extends React.Component {
errors={this.state.errors}
style={errorsStyle}
/>
{spacer}
{spacer}
</div>
);
}
@ -132,7 +129,6 @@ InputCheckboxWithErrors.defaultProps = {
autoFocus: false,
className: '',
customBootstrapClass: 'col-md-3',
deactivateErrorHighlight: false,
didCheckErrors: false,
disabled: false,
onBlur: () => {},
@ -146,21 +142,17 @@ InputCheckboxWithErrors.defaultProps = {
inputDescriptionStyle: {},
inputStyle: {},
label: '',
labelClassName: '',
labelStyle: {},
noErrorsDescription: false,
placeholder: 'app.utils.placeholder.defaultMessage',
style: {},
tabIndex: '0',
title: '',
validations: {},
value: false,
};
InputCheckboxWithErrors.propTypes = {
autoFocus: PropTypes.bool,
className: PropTypes.string,
customBootstrapClass: PropTypes.string,
deactivateErrorHighlight: PropTypes.bool,
didCheckErrors: PropTypes.bool,
disabled: PropTypes.bool,
errors: PropTypes.array,
@ -186,8 +178,6 @@ InputCheckboxWithErrors.propTypes = {
params: PropTypes.object,
}),
]),
labelClassName: PropTypes.string,
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([
@ -207,7 +197,6 @@ InputCheckboxWithErrors.propTypes = {
params: PropTypes.object,
}),
]),
validations: PropTypes.object,
value: PropTypes.bool,
};

View File

@ -7,7 +7,7 @@
import React from 'react';
import moment from 'moment';
import PropTypes from 'prop-types';
import DateTimeStyle from 'react-datetime/css/react-datetime.css';
// import DateTimeStyle from 'react-datetime/css/react-datetime.css';
import DateTime from 'react-datetime';
import { FormattedMessage } from 'react-intl';
import { isEmpty, isObject } from 'lodash';
@ -15,6 +15,7 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable react/jsx-boolean-value */
function InputDate(props) {
const value = isObject(props.value) && props.value._isAMomentObject === true ? props.value : moment(props.value);
@ -76,10 +77,10 @@ InputDate.propTypes = {
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,

View File

@ -100,7 +100,8 @@ class InputDateWithErrors extends React.Component { // eslint-disable-line react
}
return (
<div className={cn(
<div
className={cn(
!isEmpty(customBootstrapClass) && customBootstrapClass || 'col-md-4',
styles.containerDate,
!isEmpty(className) && className,
@ -145,77 +146,77 @@ class InputDateWithErrors extends React.Component { // eslint-disable-line react
}
InputDateWithErrors.defaultProps = {
autoFocus: false,
className: '',
customBootstrapClass: 'col-md-4',
deactivateErrorHighlight: false,
didCheckErrors: false,
disabled: false,
onBlur: false,
onFocus: () => {},
errors: [],
errorsClassName: '',
errorsStyle: {},
inputClassName: '',
inputDescription: '',
inputDescriptionClassName: '',
inputDescriptionStyle: {},
inputStyle: {},
label: '',
labelClassName: '',
labelStyle: {},
noErrorsDescription: false,
placeholder: 'app.utils.placeholder.defaultMessage',
style: {},
tabIndex: '0',
validations: {},
autoFocus: false,
className: '',
customBootstrapClass: 'col-md-4',
deactivateErrorHighlight: false,
didCheckErrors: false,
disabled: false,
onBlur: false,
onFocus: () => {},
errors: [],
errorsClassName: '',
errorsStyle: {},
inputClassName: '',
inputDescription: '',
inputDescriptionClassName: '',
inputDescriptionStyle: {},
inputStyle: {},
label: '',
labelClassName: '',
labelStyle: {},
noErrorsDescription: false,
placeholder: 'app.utils.placeholder.defaultMessage',
style: {},
tabIndex: '0',
validations: {},
};
InputDateWithErrors.propTypes = {
autoFocus: PropTypes.bool,
className: PropTypes.string,
customBootstrapClass: PropTypes.string,
deactivateErrorHighlight: PropTypes.bool,
didCheckErrors: PropTypes.bool,
disabled: PropTypes.bool,
errors: PropTypes.array,
errorsClassName: PropTypes.string,
errorsStyle: PropTypes.object,
inputClassName: PropTypes.string,
inputDescription: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}),
]),
inputDescriptionClassName: PropTypes.string,
inputDescriptionStyle: PropTypes.object,
inputStyle: PropTypes.object,
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}),
]),
labelClassName: PropTypes.string,
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
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.string.isRequired,
autoFocus: PropTypes.bool,
className: PropTypes.string,
customBootstrapClass: PropTypes.string,
deactivateErrorHighlight: PropTypes.bool,
didCheckErrors: PropTypes.bool,
disabled: PropTypes.bool,
errors: PropTypes.array,
errorsClassName: PropTypes.string,
errorsStyle: PropTypes.object,
inputClassName: PropTypes.string,
inputDescription: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}),
]),
inputDescriptionClassName: PropTypes.string,
inputDescriptionStyle: PropTypes.object,
inputStyle: PropTypes.object,
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}),
]),
labelClassName: PropTypes.string,
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
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.string.isRequired,
};
export default InputDateWithErrors;

View File

@ -21,7 +21,8 @@ function InputDescription(props) {
content = props.message();
}
return (
<div className={cn(
<div
className={cn(
styles.inputDescriptionContainer,
!isEmpty(props.className) && props.className
)}

View File

@ -11,6 +11,7 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputEmail extends React.Component {
state = { isFocused: false };
@ -41,7 +42,8 @@ class InputEmail extends React.Component {
return (
<div className={cn(styles.inputEmail, 'input-group', !isEmpty(className) && className)} style={style}>
<span className={cn(
<span
className={cn(
'input-group-addon',
styles.addonEmail,
this.state.isFocused && styles.addonFocus,
@ -94,10 +96,10 @@ InputEmail.propTypes = {
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,

View File

@ -98,7 +98,8 @@ class InputEmailWithErrors extends React.Component { // eslint-disable-line reac
}
return (
<div className={cn(
<div
className={cn(
styles.containerEmail,
this.props.customBootstrapClass,
!isEmpty(this.props.className) && this.props.className,

View File

@ -16,7 +16,8 @@ function InputErrors(props) {
<FormattedMessage {...error} values={{ errorMessage: error.errorMessage }} /> : error;
return (
<div className={cn(
<div
className={cn(
'form-control-feedback',
'invalid-feedback',
styles.errorContainer,
@ -24,10 +25,10 @@ function InputErrors(props) {
)}
key={key}
style={divStyle}
>
>
{displayError}
</div>
)
);
})}
</div>
);

View File

@ -8,14 +8,15 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { cloneDeep, isArray, isObject, isEmpty, last } from 'lodash';
import cn from 'classnames';
import { cloneDeep } from 'lodash';
import ImgPreview from 'components/ImgPreview';
import InputFileDetails from 'components/InputFileDetails';
import styles from './styles.scss';
/* eslint-disable react/jsx-handler-names */
/* eslint-disable jsx-a11y/label-has-for */
class InputFile extends React.Component {
state = {
didDeleteFile: false,
@ -23,6 +24,19 @@ class InputFile extends React.Component {
position: 0,
};
onDrop = (e) => {
e.preventDefault();
this.addFilesToProps(e.dataTransfer.files);
}
handleClick = (e) => {
e.preventDefault();
e.stopPropagation();
this.inputFile.click();
}
handleChange = ({ target }) => this.addFilesToProps(target.files);
addFilesToProps = (files) => {
const initAcc = this.props.multiple ? cloneDeep(this.props.value) : {};
const value = Object.keys(files).reduce((acc, current) => {
@ -34,7 +48,7 @@ class InputFile extends React.Component {
}
return acc;
}, initAcc)
}, initAcc);
const target = {
name: this.props.name,
@ -46,19 +60,6 @@ class InputFile extends React.Component {
this.props.onChange({ target });
}
handleChange = ({ target }) => this.addFilesToProps(target.files);
handleClick = (e) => {
e.preventDefault();
e.stopPropagation();
this.inputFile.click();
}
onDrop = (e) => {
e.preventDefault();
this.addFilesToProps(e.dataTransfer.files);
}
handleFileDelete = (e) => {
e.preventDefault();
e.stopPropagation();

View File

@ -8,7 +8,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { get, startsWith } from 'lodash';
import cn from 'classnames';
import styles from './styles.scss';
@ -19,7 +18,7 @@ function InputFileDetails(props) {
// TODO improve logic
if (!get(props.file, 'name') && !props.multiple) {
return <div />
return <div />;
}
const url = startsWith(props.file.url, '/') ? `${strapi.backendURL}${props.file.url}` : props.file.url;

View File

@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { differenceBy, isEmpty, isObject } from 'lodash';
import { differenceBy, isEmpty } from 'lodash';
// Design
import Label from 'components/Label';

View File

@ -6,6 +6,7 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
function InputNumber(props) {
return (
<FormattedMessage id={props.placeholder} defaultMessage={props.placeholder}>
@ -32,7 +33,7 @@ function InputNumber(props) {
/>
)}
</FormattedMessage>
)
);
}
InputNumber.defaultProps = {
@ -54,10 +55,10 @@ InputNumber.propTypes = {
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,

View File

@ -94,7 +94,8 @@ class InputNumberWithErrors extends React.Component { // eslint-disable-line rea
}
return (
<div className={cn(
<div
className={cn(
styles.containerInputNumber,
customBootstrapClass,
!isEmpty(className) && className,
@ -163,6 +164,7 @@ InputNumberWithErrors.defaultProps = {
style: {},
tabIndex: '0',
validations: {},
value: 0,
};
InputNumberWithErrors.propTypes = {

View File

@ -12,6 +12,7 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputPassword extends React.Component {
state = { showPassword: false };

View File

@ -96,7 +96,8 @@ class InputPasswordWithErrors extends React.Component {
}
return (
<div className={cn(
<div
className={cn(
styles.containerInputPassword,
this.props.customBootstrapClass,
!isEmpty(this.props.className) && this.props.className,

View File

@ -12,6 +12,7 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputSearch extends React.Component {
state = { isFocused: false };
@ -42,7 +43,8 @@ class InputSearch extends React.Component {
return (
<div className={cn(styles.inputSearch, 'input-group', !isEmpty(className) && className)} style={style}>
<span className={cn(
<span
className={cn(
'input-group-addon',
styles.addonSearch,
this.state.isFocused && styles.addonFocus,
@ -77,32 +79,32 @@ class InputSearch extends React.Component {
}
InputSearch.defaultProps = {
autoFocus: false,
className: '',
deactivateErrorHighlight: false,
disabled: false,
error: false,
onBlur: () => {},
onFocus: () => {},
placeholder: 'app.utils.placeholder.defaultMessage',
style: {},
tabIndex: '0',
autoFocus: false,
className: '',
deactivateErrorHighlight: false,
disabled: false,
error: false,
onBlur: () => {},
onFocus: () => {},
placeholder: 'app.utils.placeholder.defaultMessage',
style: {},
tabIndex: '0',
};
InputSearch.propTypes = {
autoFocus: PropTypes.bool,
className: PropTypes.string,
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,
value: PropTypes.string.isRequired,
autoFocus: PropTypes.bool,
className: PropTypes.string,
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,
value: PropTypes.string.isRequired,
};
export default InputSearch;

View File

@ -98,7 +98,8 @@ class InputSearchWithErrors extends React.Component { // eslint-disable-line rea
}
return (
<div className={cn(
<div
className={cn(
styles.containerSearch,
this.props.customBootstrapClass,
!isEmpty(this.props.className) && this.props.className,

View File

@ -14,6 +14,7 @@ import SelectOption from 'components/SelectOption';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
function InputSelect(props) {
return (
<select
@ -39,7 +40,7 @@ function InputSelect(props) {
return <SelectOption key={key} {...option} />;
}
return <option key={key} value={option}>{option}</option>
return <option key={key} value={option}>{option}</option>;
})}
</select>
);

View File

@ -13,7 +13,7 @@ import cn from 'classnames';
import Label from 'components/Label';
import InputDescription from 'components/InputDescription';
import InputErrors from 'components/InputErrors';
import InputSelect from 'components/InputSelect'
import InputSelect from 'components/InputSelect';
import styles from './styles.scss';
@ -59,7 +59,6 @@ class InputSelectWithErrors extends React.Component {
customBootstrapClass,
deactivateErrorHighlight,
disabled,
errors,
errorsClassName,
errorsStyle,
inputClassName,
@ -81,7 +80,8 @@ class InputSelectWithErrors extends React.Component {
} = this.props;
return (
<div className={cn(
<div
className={cn(
styles.containerSelect,
customBootstrapClass,
!isEmpty(className) && className,
@ -202,7 +202,7 @@ InputSelectWithErrors.propTypes = {
).isRequired,
style: PropTypes.object,
tabIndex: PropTypes.string,
validation: PropTypes.object,
validations: PropTypes.object,
value: PropTypes.string.isRequired,
};

View File

@ -4,11 +4,12 @@ import { isEmpty } from 'lodash';
import { FormattedMessage } from 'react-intl';
import cn from 'classnames';
/* eslint-disable jsx-a11y/no-autofocus */
import styles from './styles.scss';
function InputText(props) {
const placeholder = isEmpty(props.placeholder) ? 'app.utils.placeholder.defaultMessage' : props.placeholder;
return (
<FormattedMessage id={placeholder} defaultMessage={placeholder}>
{(message) => (
@ -56,10 +57,10 @@ InputText.propTypes = {
deactivateErrorHighlight: PropTypes.bool,
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,

View File

@ -4,6 +4,7 @@
*
*/
/* eslint-disable jsx-a11y/no-autofocus */
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { isEmpty } from 'lodash';
@ -60,7 +61,9 @@ InputTextArea.propTypes = {
disabled: PropTypes.bool,
error: PropTypes.bool,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
placeholder: PropTypes.string,
style: PropTypes.object,
tabIndex: PropTypes.string,

View File

@ -94,7 +94,8 @@ class InputTextAreaWithErrors extends React.Component { // eslint-disable-line r
}
return (
<div className={cn(
<div
className={cn(
styles.containerTextArea,
customBootstrapClass,
!isEmpty(className) && className,

View File

@ -15,6 +15,7 @@ import validateInput from 'utils/inputsValidations';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputTextWithErrors extends React.Component { // eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
@ -94,7 +95,8 @@ class InputTextWithErrors extends React.Component { // eslint-disable-line react
}
return (
<div className={cn(
<div
className={cn(
styles.containerText,
customBootstrapClass,
!isEmpty(className) && className,

View File

@ -9,6 +9,7 @@ import { isEmpty } from 'lodash';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputToggle extends React.Component {
handleClick = (e) => {
const target = {
@ -33,7 +34,8 @@ class InputToggle extends React.Component {
} = this.props;
return (
<div className={cn(
<div
className={cn(
'btn-group',
styles.inputToggleContainer,
!isEmpty(className) && className,

View File

@ -24,7 +24,7 @@ class InputToggleWithErrors extends React.Component {
// Display input error if it already has some
if (!isEmpty(errors)) {
this.setState({ errors })
this.setState({ errors });
}
}
@ -69,7 +69,8 @@ class InputToggleWithErrors extends React.Component {
}
return (
<div className={cn(
<div
className={cn(
styles.containerToggleErrors,
customBootstrapClass,
!isEmpty(className) && className,
@ -82,7 +83,7 @@ class InputToggleWithErrors extends React.Component {
htmlFor={name}
message={label}
style={labelStyle}
/>
/>
</div>
<InputToggle
autoFocus={autoFocus}

View File

@ -3,6 +3,7 @@
* InputsIndex references all the input with errors available
*/
/* eslint-disable react/require-default-props */
import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';
@ -22,7 +23,7 @@ import InputTextWithErrors from 'components/InputTextWithErrors';
import InputToggleWithErrors from 'components/InputToggleWithErrors';
import WysiwygWithErrors from 'components/WysiwygWithErrors';
const DefaultInputError = ({ type }) => <div>Your input type: <b>{type}</b> does not exist</div>
const DefaultInputError = ({ type }) => <div>Your input type: <b>{type}</b> does not exist</div>;
const inputs = {
addon: InputAddonWithErrors,
@ -50,7 +51,7 @@ function InputsIndex(props) {
inputValue = props.value || false;
break;
case 'number':
inputValue = props.value === 0 ? props.values : props.value || '';
inputValue = props.value === 0 ? props.value : props.value || '';
break;
case 'file':
inputValue = props.value || [];
@ -58,15 +59,19 @@ function InputsIndex(props) {
default:
inputValue = props.value || '';
}
const Input = inputs[type] ? inputs[type] : DefaultInputError;
return <Input {...props} value={inputValue} />;
}
DefaultInputError.propTypes = {
type: PropTypes.string.isRequired,
};
InputsIndex.defaultProps = {
addon: false,
}
};
InputsIndex.propTypes = {
addon: PropTypes.oneOfType([
@ -74,6 +79,7 @@ InputsIndex.propTypes = {
PropTypes.string,
]),
type: PropTypes.string.isRequired,
value: PropTypes.any,
};
export default InputsIndex;

View File

@ -1,11 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { isFunction, isObject, upperFirst } from 'lodash';
import { isFunction, isObject } from 'lodash';
import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/label-has-for */
function Label(props) {
let content = props.children;

View File

@ -8,14 +8,13 @@ import React from 'react';
import {
ContentState,
convertFromHTML,
Editor,
EditorState,
getDefaultKeyBinding,
Modifier,
RichUtils,
} from 'draft-js';
import PropTypes from 'prop-types';
import { cloneDeep, isEmpty, replace, trimStart, trimEnd } from 'lodash';
import { isEmpty, replace, trimStart, trimEnd } from 'lodash';
import cn from 'classnames';
import { FormattedMessage } from 'react-intl';
import Controls from 'components/WysiwygInlineControls';
@ -77,52 +76,6 @@ class Wysiwyg extends React.Component {
}
}
addEntity = (text, style) => {
const editorState = this.state.editorState;
const currentContent = editorState.getCurrentContent();
// Get the selected text
const selection = editorState.getSelection();
const anchorKey = selection.getAnchorKey();
const currentContentBlock = currentContent.getBlockForKey(anchorKey);
// Range of the text we want to replace
const { start, end } = getOffSets(selection);
// Retrieve the selected text
const selectedText = currentContentBlock.getText().slice(start, end);
const innerText = selectedText === '' ? getInnerText(style) : replace(text, 'innerText', selectedText);
const trimedStart = trimStart(innerText, START_REPLACER).length;
const trimedEnd = trimEnd(innerText, END_REPLACER).length;
// Set the correct offset
const focusOffset = start === end ? trimedEnd : start + trimedEnd;
const anchorOffset = start + innerText.length - trimedStart;
// Merge the old selection with the new one so the editorState is updated
const updateSelection = selection.merge({
anchorOffset,
focusOffset,
});
// Dynamically add some content to the one selected
const textWithEntity = Modifier.replaceText(currentContent, selection, innerText);
// Push the new content to the editorState
const newEditorState = EditorState.push(editorState, textWithEntity, 'insert-characters');
// SetState and force focus
this.setState({
editorState: EditorState.forceSelection(newEditorState, updateSelection),
headerValue: '',
}, () => {
this.focus();
});
}
handleChangeSelect = ({ target }) => {
this.setState({ headerValue: target.value });
const splitData = target.value.split('.');
this.addEntity(splitData[0], splitData[1]);
}
onChange = (editorState) => {
this.setState({ editorState });
this.props.onChange({ target: {
@ -132,22 +85,6 @@ class Wysiwyg extends React.Component {
}});
}
mapKeyToEditorCommand = (e) => {
if (e.keyCode === 9 /* TAB */) {
const newEditorState = RichUtils.onTab(
e,
this.state.editorState,
4, /* maxDepth */
);
if (newEditorState !== this.state.editorState) {
this.onChange(newEditorState);
}
return;
}
return getDefaultKeyBinding(e);
}
// NOTE: leave these function if we change to HTML instead of markdown
// toggleBlockType = (blockType) => {
// this.onChange(
@ -167,15 +104,6 @@ class Wysiwyg extends React.Component {
// );
// }
toggleFullScreen = (e) => {
e.preventDefault();
this.setState({
toggleFullScreen: !this.state.toggleFullScreen,
}, () => {
this.focus();
});
}
/**
* Init the editor with data from
* @param {[type]} props [description]
@ -190,6 +118,76 @@ class Wysiwyg extends React.Component {
this.setState({ editorState, hasInitialValue: true, initialValue: props.value });
}
handleChangeSelect = ({ target }) => {
this.setState({ headerValue: target.value });
const splitData = target.value.split('.');
this.addEntity(splitData[0], splitData[1]);
}
mapKeyToEditorCommand = (e) => {
if (e.keyCode === 9 /* TAB */) {
const newEditorState = RichUtils.onTab(
e,
this.state.editorState,
4, /* maxDepth */
);
if (newEditorState !== this.state.editorState) {
this.onChange(newEditorState);
}
return;
}
return getDefaultKeyBinding(e);
}
addEntity = (text, style) => {
const editorState = this.state.editorState;
const currentContent = editorState.getCurrentContent();
// Get the selected text
const selection = editorState.getSelection();
const anchorKey = selection.getAnchorKey();
const currentContentBlock = currentContent.getBlockForKey(anchorKey);
// Range of the text we want to replace
const { start, end } = getOffSets(selection);
// Retrieve the selected text
const selectedText = currentContentBlock.getText().slice(start, end);
const innerText = selectedText === '' ? getInnerText(style) : replace(text, 'innerText', selectedText);
const trimedStart = trimStart(innerText, START_REPLACER).length;
const trimedEnd = trimEnd(innerText, END_REPLACER).length;
// Set the correct offset
const focusOffset = start === end ? trimedEnd : start + trimedEnd;
const anchorOffset = start + innerText.length - trimedStart;
// Merge the old selection with the new one so the editorState is updated
const updateSelection = selection.merge({
anchorOffset,
focusOffset,
});
// Dynamically add some content to the one selected
const textWithEntity = Modifier.replaceText(currentContent, selection, innerText);
// Push the new content to the editorState
const newEditorState = EditorState.push(editorState, textWithEntity, 'insert-characters');
// SetState and force focus
this.setState({
editorState: EditorState.forceSelection(newEditorState, updateSelection),
headerValue: '',
}, () => {
this.focus();
});
}
toggleFullScreen = (e) => {
e.preventDefault();
this.setState({
toggleFullScreen: !this.state.toggleFullScreen,
}, () => {
this.focus();
});
}
handleKeyCommand(command, editorState) {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {

View File

@ -6,7 +6,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { FormattedMessage } from 'react-intl';
import styles from './styles.scss';
@ -20,7 +19,7 @@ const WysiwygBottomControls = ({ charactersNumber, onClick }) => {
</div>
</div>
);
}
};
WysiwygBottomControls.defaultProps = {
charactersNumber: 0,

View File

@ -6,13 +6,22 @@
import React from 'react';
import { Editor } from 'draft-js';
import PropTypes from 'prop-types';
class WysiwygEditor extends React.Component {
render() {
return (
<Editor {...this.props} ref={this.props.setRef}/>
<Editor {...this.props} ref={this.props.setRef} />
);
}
}
WysiwygEditor.defaultProps = {
setRef: () => {},
};
WysiwygEditor.propTypes = {
setRef: PropTypes.func,
};
export default WysiwygEditor;

View File

@ -70,6 +70,7 @@ StyleButton.defaultProps = {
onToggle: () => {},
onToggleBlock: () => {},
style: '',
text: '',
};
StyleButton.propTypes = {
@ -82,6 +83,7 @@ StyleButton.propTypes = {
// onToggle: PropTypes.func,
// onToggleBlock: PropTypes.func,
style: PropTypes.string,
text: PropTypes.string,
};
WysiwygInlineControls.defaultProps = {

View File

@ -32,5 +32,5 @@ cd ../strapi-plugin-upload
npm run test
# Test `strapi-helper-plugin`
# cd ../strapi-helper-plugin/lib
# npm run test
cd ../strapi-helper-plugin/lib
npm run test