Merge branch 'webhooks/tests' of github.com:strapi/strapi into webhooks/tests

Signed-off-by: Virginie Ky <virginie.ky@gmail.com>
This commit is contained in:
Virginie Ky 2020-01-22 18:11:12 +01:00
commit ab85b7642e
199 changed files with 5740 additions and 843 deletions

View File

@ -2,4 +2,7 @@
**/build/** **/build/**
**/dist/** **/dist/**
testApp/** testApp/**
packages/strapi-plugin-users-permissions/admin/**
packages/strapi-plugin-upload/admin/**
packages/strapi-generate-plugin/files/admin/src/**
.eslintrc.js .eslintrc.js

View File

@ -4,10 +4,9 @@ module.exports = {
'eslint:recommended', 'eslint:recommended',
'plugin:react/recommended', 'plugin:react/recommended',
'plugin:redux-saga/recommended', 'plugin:redux-saga/recommended',
'prettier', 'prettier',
], ],
plugins: ['react', 'redux-saga', 'react-hooks', 'import'], plugins: ['react', 'redux-saga', 'react-hooks', 'import', 'jsx-a11y'],
env: { env: {
browser: true, browser: true,
commonjs: true, commonjs: true,
@ -54,9 +53,87 @@ module.exports = {
overrides: [ overrides: [
{ {
files: ['packages/**/admin/src/**/**/*.js'], files: ['packages/**/admin/src/**/**/*.js'],
extends: ['airbnb'],
rules: { rules: {
'no-nested-ternary': ['error'], 'arrow-body-style': 0,
'arrow-parens': 0,
camelcase: 0,
'comma-dangle': 0,
'consistent-return': [
2,
{
treatUndefinedAsUnspecified: true,
},
],
indent: [
2,
2,
{
flatTernaryExpressions: false,
SwitchCase: 1,
ignoredNodes: [
'ConditionalExpression',
"VariableDeclarator[kind='const']",
],
},
],
'func-names': ['error', 'never'],
'function-paren-newline': 0,
'implicit-arrow-linebreak': 0,
'import/no-extraneous-dependencies': 0,
'import/no-named-as-default': 0,
'import/order': 2, 'import/order': 2,
'jsx-a11y/click-events-have-key-events': 1,
'max-len': [
2,
{
code: 120,
ignoreComments: true,
ignoreUrls: true,
ignoreTrailingComments: true,
ignoreStrings: true,
ignoreTemplateLiterals: true,
},
],
'newline-before-return': 2,
'no-confusing-arrow': 0,
'no-else-return': 1,
'no-nested-ternary': ['error'],
'no-return-assign': 0,
'no-param-reassign': 0,
'no-shadow': 0,
'no-underscore-dangle': 0,
'no-use-before-define': [
'error',
{ functions: false, classes: false, variables: false },
],
'object-curly-newline': [2, { multiline: true, consistent: true }],
'operator-linebreak': 0,
'padding-line-between-statements': [
'error',
{ blankLine: 'always', prev: '*', next: 'if' },
{ blankLine: 'any', prev: 'block-like', next: 'if' },
],
'prefer-arrow-callback': 0,
'prefer-const': 0,
'prefer-destructuring': 0,
'prefer-object-spread': 0,
'prefer-spread': 0,
'space-before-function-paren': [
'error',
{
anonymous: 'never',
named: 'never',
asyncArrow: 'always',
},
],
'react/destructuring-assignment': 0,
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
'react/forbid-prop-types': 0,
'react/jsx-props-no-spreading': 0,
'react/jsx-one-expression-per-line': 0,
'react/state-in-constructor': 0,
'react/static-property-placement': 0,
}, },
}, },
], ],

View File

@ -1,2 +1,4 @@
comment: comment:
branch: master branches:
- master
- develop

View File

@ -81,10 +81,10 @@
"dz": { "dz": {
"type": "dynamiczone", "type": "dynamiczone",
"components": [ "components": [
"default.closingperiod",
"default.dish",
"default.openingtimes", "default.openingtimes",
"default.restaurantservice" "default.restaurantservice",
"default.closingperiod",
"default.dish"
] ]
} }
} }

View File

@ -11,8 +11,11 @@
"enzyme": "^3.9.0", "enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1", "enzyme-adapter-react-16": "^1.12.1",
"eslint": "^6.3.0", "eslint": "^6.3.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-config-prettier": "^6.2.0", "eslint-config-prettier": "^6.2.0",
"eslint-plugin-import": "^2.19.1", "eslint-plugin-import": "^2.19.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.14.0", "eslint-plugin-react": "^7.14.0",
"eslint-plugin-react-hooks": "^2.0.0", "eslint-plugin-react-hooks": "^2.0.0",
"eslint-plugin-redux-saga": "^1.1.0", "eslint-plugin-redux-saga": "^1.1.0",
@ -38,6 +41,7 @@
"build": "lerna run --stream build --no-private", "build": "lerna run --stream build --no-private",
"lint": "npm-run-all -p lint:code", "lint": "npm-run-all -p lint:code",
"lint:code": "eslint .", "lint:code": "eslint .",
"lint:fix": "eslint --fix .",
"lint:other": "npm run prettier:other -- --check", "lint:other": "npm run prettier:other -- --check",
"format": "npm-run-all -p format:*", "format": "npm-run-all -p format:*",
"format:code": "npm run prettier:code -- --write", "format:code": "npm run prettier:code -- --write",

View File

@ -5,6 +5,8 @@
// * Entry point of the application // * Entry point of the application
// */ // */
/* eslint-disable */
import '@babel/polyfill'; import '@babel/polyfill';
import 'sanitize.css/sanitize.css'; import 'sanitize.css/sanitize.css';

View File

@ -11,16 +11,17 @@ import Wrapper from './Wrapper';
function EmptyList() { function EmptyList() {
const { formatMessage } = useGlobalContext(); const { formatMessage } = useGlobalContext();
return ( return (
<Wrapper> <Wrapper>
<p>{formatMessage({ id: `Settings.webhooks.list.empty.title` })}</p> <p>{formatMessage({ id: 'Settings.webhooks.list.empty.title' })}</p>
<p>{formatMessage({ id: `Settings.webhooks.list.empty.description` })}</p> <p>{formatMessage({ id: 'Settings.webhooks.list.empty.description' })}</p>
<a <a
href="https://strapi.io/documentation/3.0.0-beta.x/guides/webhooks.html" href="https://strapi.io/documentation/3.0.0-beta.x/guides/webhooks.html"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
{formatMessage({ id: `Settings.webhooks.list.empty.link` })} {formatMessage({ id: 'Settings.webhooks.list.empty.link' })}
</a> </a>
</Wrapper> </Wrapper>
); );

View File

@ -7,9 +7,9 @@ import EventRow from './EventRow';
const EventInput = ({ onChange, name: inputName, value: inputValue }) => { const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
const headersName = [ const headersName = [
`Settings.webhooks.events.create`, 'Settings.webhooks.events.create',
`Settings.webhooks.events.edit`, 'Settings.webhooks.events.edit',
`Settings.webhooks.events.delete`, 'Settings.webhooks.events.delete',
]; ];
const events = { const events = {
@ -22,6 +22,7 @@ const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
const formatValue = inputValue.reduce((acc, curr) => { const formatValue = inputValue.reduce((acc, curr) => {
const key = curr.split('.')[0]; const key = curr.split('.')[0];
if (!acc[key]) { if (!acc[key]) {
acc[key] = []; acc[key] = [];
} }
@ -32,6 +33,7 @@ const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
const handleChange = ({ target: { name, value } }) => { const handleChange = ({ target: { name, value } }) => {
let set = new Set(inputValue); let set = new Set(inputValue);
if (value) { if (value) {
set.add(name); set.add(name);
} else { } else {
@ -42,14 +44,15 @@ const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
const handleChangeAll = ({ target: { name, value } }) => { const handleChangeAll = ({ target: { name, value } }) => {
let set = new Set(inputValue); let set = new Set(inputValue);
if (value) { if (value) {
events[name].map(event => { events[name].forEach(event => {
if (!disabledEvents.includes(event)) { if (!disabledEvents.includes(event)) {
set.add(event); set.add(event);
} }
}); });
} else { } else {
events[name].map(event => set.delete(event)); events[name].forEach(event => set.delete(event));
} }
onChange({ target: { name: inputName, value: Array.from(set) } }); onChange({ target: { name: inputName, value: Array.from(set) } });
}; };
@ -59,7 +62,7 @@ const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
<table> <table>
<thead> <thead>
<tr> <tr>
<td></td> <td />
{headersName.map(header => { {headersName.map(header => {
return ( return (
<td key={header}> <td key={header}>
@ -89,15 +92,12 @@ const EventInput = ({ onChange, name: inputName, value: inputValue }) => {
); );
}; };
EventInput.defaultProps = { EventInput.defaultProps = {};
onBlur: () => {},
};
EventInput.propTypes = { EventInput.propTypes = {
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
value: PropTypes.array, value: PropTypes.array.isRequired,
}; };
export default EventInput; export default EventInput;

View File

@ -11,8 +11,10 @@ import getBorderColor from './utils/getBorderColor';
import keys from './keys'; import keys from './keys';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
/* eslint-disable react/no-array-index-key */
const HeadersInput = ({ errors, name, onClick, onChange, onRemove, value }) => { const HeadersInput = ({ errors, name, onClick, onChange, onRemove, value }) => {
const formatOption = value => ({ value: value, label: value }); const formatOption = value => ({ value, label: value });
const options = keys.map(key => formatOption(key)); const options = keys.map(key => formatOption(key));
const handleChangeKey = (selected, name) => { const handleChangeKey = (selected, name) => {

View File

@ -5,6 +5,7 @@ const getBorderColor = ({ isFocused = false, hasError = false }) => {
if (hasError) { if (hasError) {
return '#F64D0A'; return '#F64D0A';
} }
return '#E3E9F3'; return '#E3E9F3';
}; };

View File

@ -7,12 +7,10 @@
import React from 'react'; import React from 'react';
import { defineMessages, FormattedMessage } from 'react-intl'; import { defineMessages, FormattedMessage } from 'react-intl';
import { PropTypes } from 'prop-types'; import { PropTypes } from 'prop-types';
import LeftMenuLink from '../LeftMenuLink'; import LeftMenuLink from '../LeftMenuLink';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
import messages from './messages.json'; import messages from './messages.json';
defineMessages(messages); defineMessages(messages);
function LeftMenuFooter({ version, ...rest }) { function LeftMenuFooter({ version, ...rest }) {

View File

@ -13,6 +13,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import en from '../../translations/en.json'; import en from '../../translations/en.json';
import Li from './Li'; import Li from './Li';
/* eslint-disable */
function LeftMenuLink(props) { function LeftMenuLink(props) {
const isLinkActive = startsWith( const isLinkActive = startsWith(
props.location.pathname.replace('/admin', '').concat('/'), props.location.pathname.replace('/admin', '').concat('/'),

View File

@ -8,11 +8,12 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { get, snakeCase, isEmpty, map, sortBy } from 'lodash'; import { get, snakeCase, isEmpty, map, sortBy } from 'lodash';
import LeftMenuLink from '../LeftMenuLink'; import LeftMenuLink from '../LeftMenuLink';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
import messages from './messages.json'; import messages from './messages.json';
/* eslint-disable */
function LeftMenuLinkContainer({ plugins, ...rest }) { function LeftMenuLinkContainer({ plugins, ...rest }) {
// Generate the list of sections // Generate the list of sections
const pluginsSections = Object.keys(plugins).reduce((acc, current) => { const pluginsSections = Object.keys(plugins).reduce((acc, current) => {

View File

@ -15,6 +15,8 @@ import { Button } from 'strapi-helper-plugin';
import Row from '../Row'; import Row from '../Row';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
/* eslint-disable react/prefer-stateless-function */
class ListPlugins extends React.Component { class ListPlugins extends React.Component {
render() { render() {
const listSize = size(this.props.plugins); const listSize = size(this.props.plugins);

View File

@ -55,12 +55,16 @@ function ListRow({
<p title={url}>{url}</p> <p title={url}>{url}</p>
</td> </td>
<td> <td>
<div onClick={e => e.stopPropagation()}> <div
onClick={e => e.stopPropagation()}
role="button"
aria-hidden="true"
>
<Switch <Switch
name={name} name={name}
value={isEnabled} value={isEnabled}
onChange={({ target: { value } }) => onEnabledChange(value, id)} onChange={({ target: { value } }) => onEnabledChange(value, id)}
></Switch> />
</div> </div>
</td> </td>
<td> <td>

View File

@ -3,7 +3,7 @@
* Notification * Notification
* *
*/ */
/* eslint-disable */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';

View File

@ -11,6 +11,8 @@ import { CSSTransition } from 'react-transition-group';
import Notification from '../Notification'; import Notification from '../Notification';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
/* eslint-disable */
const NotificationsContainer = ({ notifications, onHideNotification }) => { const NotificationsContainer = ({ notifications, onHideNotification }) => {
if (notifications.length === 0) { if (notifications.length === 0) {
return false; return false;

View File

@ -13,6 +13,8 @@ import { Player } from 'video-react';
import 'video-react/dist/video-react.css'; import 'video-react/dist/video-react.css';
import Li from './Li'; import Li from './Li';
/* eslint-disable */
class OnboardingVideo extends React.Component { class OnboardingVideo extends React.Component {
componentDidMount() { componentDidMount() {
this.hiddenPlayer.current.subscribeToStateChange(this.handleChangeState); this.hiddenPlayer.current.subscribeToStateChange(this.handleChangeState);

View File

@ -22,6 +22,8 @@ import Content from './Content';
const PLUGINS_WITH_CONFIG = ['email', 'upload']; const PLUGINS_WITH_CONFIG = ['email', 'upload'];
/* eslint-disable */
class Row extends React.Component { class Row extends React.Component {
static contextType = GlobalContext; static contextType = GlobalContext;
state = { showModal: false }; state = { showModal: false };

View File

@ -20,12 +20,11 @@ function Switch({ name, value, onChange }) {
checked={value} checked={value}
name={name} name={name}
onChange={({ target: { checked } }) => onChange={({ target: { checked } }) =>
onChange({ target: { name, value: checked } }) onChange({ target: { name, value: checked } })}
}
/> />
<div className="button"> <div className="button">
<div className="button-rect"></div> <div className="button-rect" />
<div className="button-circle"></div> <div className="button-circle" />
</div> </div>
<p> <p>
{value {value

View File

@ -52,6 +52,14 @@ import Content from './Content';
export class Admin extends React.Component { export class Admin extends React.Component {
// eslint-disable-line react/prefer-stateless-function // eslint-disable-line react/prefer-stateless-function
helpers = {
updatePlugin: this.props.updatePlugin,
};
componentDidMount() {
this.props.emitEvent('didAccessAuthenticatedAdministration');
}
shouldComponentUpdate(prevProps) { shouldComponentUpdate(prevProps) {
return !isEmpty(difference(prevProps, this.props)); return !isEmpty(difference(prevProps, this.props));
} }
@ -70,10 +78,6 @@ export class Admin extends React.Component {
this.props.setAppError(); this.props.setAppError();
} }
componentDidMount() {
this.props.emitEvent('didAccessAuthenticatedAdministration');
}
hasApluginNotReady = props => { hasApluginNotReady = props => {
const { const {
global: { plugins }, global: { plugins },
@ -84,10 +88,6 @@ export class Admin extends React.Component {
); );
}; };
helpers = {
updatePlugin: this.props.updatePlugin,
};
/** /**
* Display the app loader until the app is ready * Display the app loader until the app is ready
* @returns {Boolean} * @returns {Boolean}
@ -135,10 +135,10 @@ export class Admin extends React.Component {
// We need the admin data in order to make the initializers work // We need the admin data in order to make the initializers work
if (this.showLoader()) { if (this.showLoader()) {
return ( return (
<React.Fragment> <>
{this.renderInitializers()} {this.renderInitializers()}
<LoadingIndicatorPage /> <LoadingIndicatorPage />
</React.Fragment> </>
); );
} }
@ -202,6 +202,12 @@ export class Admin extends React.Component {
} }
} }
Admin.defaultProps = {
intl: {
formatMessage: () => {},
},
};
Admin.propTypes = { Admin.propTypes = {
admin: PropTypes.shape({ admin: PropTypes.shape({
appError: PropTypes.bool, appError: PropTypes.bool,

View File

@ -23,6 +23,7 @@ import GlobalStyle from '../../components/GlobalStyle';
import Admin from '../Admin'; import Admin from '../Admin';
import AuthPage from '../AuthPage'; import AuthPage from '../AuthPage';
import NotFoundPage from '../NotFoundPage'; import NotFoundPage from '../NotFoundPage';
// eslint-disable-next-line import/no-cycle
import NotificationProvider from '../NotificationProvider'; import NotificationProvider from '../NotificationProvider';
import PrivateRoute from '../PrivateRoute'; import PrivateRoute from '../PrivateRoute';
import Theme from '../Theme'; import Theme from '../Theme';

View File

@ -6,6 +6,8 @@ import { get } from 'lodash';
import { InputsIndex as Inputs } from 'strapi-helper-plugin'; import { InputsIndex as Inputs } from 'strapi-helper-plugin';
import CustomLabel from './CustomLabel'; import CustomLabel from './CustomLabel';
/* eslint-disable */
const Input = ({ const Input = ({
autoFocus, autoFocus,
customBootstrapClass, customBootstrapClass,

View File

@ -1,8 +1,7 @@
import React, { memo, useEffect, useReducer, useRef } from 'react'; import React, { memo, useEffect, useReducer, useRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { get, isEmpty, omit, set } from 'lodash'; import { get, isEmpty, omit, set, upperFirst } from 'lodash';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { upperFirst } from 'lodash';
import { Link, Redirect } from 'react-router-dom'; import { Link, Redirect } from 'react-router-dom';
import { import {
auth, auth,
@ -267,12 +266,12 @@ AuthPage.propTypes = {
hasAdminUser: PropTypes.bool.isRequired, hasAdminUser: PropTypes.bool.isRequired,
location: PropTypes.shape({ location: PropTypes.shape({
search: PropTypes.string.isRequired, search: PropTypes.string.isRequired,
}), }).isRequired,
match: PropTypes.shape({ match: PropTypes.shape({
params: PropTypes.shape({ params: PropTypes.shape({
authType: PropTypes.string, authType: PropTypes.string,
}), }).isRequired,
}), }).isRequired,
}; };
export default memo(AuthPage); export default memo(AuthPage);

View File

@ -38,7 +38,7 @@ const SocialLink = ({ link, name }) => {
return ( return (
<SocialLinkWrapper className="col-6"> <SocialLinkWrapper className="col-6">
<a href={link} target="_blank" rel="noopener noreferrer"> <a href={link} target="_blank" rel="noopener noreferrer">
<img src={getSrc(name)} /> <img src={getSrc(name)} alt={name} />
<span>{name}</span> <span>{name}</span>
</a> </a>
</SocialLinkWrapper> </SocialLinkWrapper>

View File

@ -1,3 +1,4 @@
/* eslint-disable */
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
const Block = styled.div` const Block = styled.div`

View File

@ -4,9 +4,9 @@
* *
*/ */
import { /* eslint-disable */
CHANGE_LOCALE,
} from './constants'; import { CHANGE_LOCALE } from './constants';
export function changeLocale(languageLocale) { export function changeLocale(languageLocale) {
return { return {

View File

@ -4,4 +4,5 @@
* *
*/ */
/* eslint-disable */
export const CHANGE_LOCALE = 'app/LanguageToggle/CHANGE_LOCALE'; export const CHANGE_LOCALE = 'app/LanguageToggle/CHANGE_LOCALE';

View File

@ -14,13 +14,14 @@ import { IntlProvider } from 'react-intl';
import { defaultsDeep } from 'lodash'; import { defaultsDeep } from 'lodash';
import { selectLocale } from './selectors'; import { selectLocale } from './selectors';
// eslint-disable-next-line react/prefer-stateless-function
export class LanguageProvider extends React.Component { export class LanguageProvider extends React.Component {
// eslint-disable-line react/prefer-stateless-function
render() { render() {
const messages = defaultsDeep( const messages = defaultsDeep(
this.props.messages[this.props.locale], this.props.messages[this.props.locale],
this.props.messages.en, this.props.messages.en
); );
return ( return (
<IntlProvider <IntlProvider
locale={this.props.locale} locale={this.props.locale}
@ -41,7 +42,7 @@ LanguageProvider.propTypes = {
const mapStateToProps = createSelector( const mapStateToProps = createSelector(
selectLocale(), selectLocale(),
locale => ({ locale }), locale => ({ locale })
); );
function mapDispatchToProps(dispatch) { function mapDispatchToProps(dispatch) {
@ -52,5 +53,5 @@ function mapDispatchToProps(dispatch) {
export default connect( export default connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps, mapDispatchToProps
)(LanguageProvider); )(LanguageProvider);

View File

@ -9,11 +9,10 @@ import { get, includes, split } from 'lodash';
// Import supported languages from the translations folder // Import supported languages from the translations folder
import trads from '../../translations'; import trads from '../../translations';
import { CHANGE_LOCALE } from './constants';
const languages = Object.keys(trads); const languages = Object.keys(trads);
import { CHANGE_LOCALE } from './constants';
// Define a key to store and get user preferences in local storage. // Define a key to store and get user preferences in local storage.
const localStorageKey = 'strapi-admin-language'; const localStorageKey = 'strapi-admin-language';
@ -24,6 +23,7 @@ const userLanguage =
window.navigator.userLanguage; window.navigator.userLanguage;
let foundLanguage = includes(languages, userLanguage) && userLanguage; let foundLanguage = includes(languages, userLanguage) && userLanguage;
if (!foundLanguage) { if (!foundLanguage) {
// Split user language in a correct format. // Split user language in a correct format.
const userLanguageShort = get(split(userLanguage, '-'), '0'); const userLanguageShort = get(split(userLanguage, '-'), '0');

View File

@ -86,7 +86,7 @@ export class ListPluginsPage extends React.Component {
ListPluginsPage.propTypes = { ListPluginsPage.propTypes = {
global: PropTypes.shape({ global: PropTypes.shape({
currentEnvironment: PropTypes.string.isRequired, currentEnvironment: PropTypes.string.isRequired,
}), }).isRequired,
getPlugins: PropTypes.func.isRequired, getPlugins: PropTypes.func.isRequired,
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
intl: PropTypes.shape({ intl: PropTypes.shape({

View File

@ -7,6 +7,8 @@ import { deletePluginSucceeded, getPluginsSucceeded } from './actions';
import { GET_PLUGINS, ON_DELETE_PLUGIN_CONFIRM } from './constants'; import { GET_PLUGINS, ON_DELETE_PLUGIN_CONFIRM } from './constants';
import { makeSelectPluginToDelete } from './selectors'; import { makeSelectPluginToDelete } from './selectors';
/* eslint-disable */
export function* deletePlugin() { export function* deletePlugin() {
try { try {
const plugin = yield select(makeSelectPluginToDelete()); const plugin = yield select(makeSelectPluginToDelete());

View File

@ -1,12 +1,9 @@
/** /**
* *
* LocaleToggle actions * LocaleToggle actions
*/ */
import { import { RESET_DEFAULT_CLASSNAME, SET_CUSTOM_CLASSNAME } from './constants';
RESET_DEFAULT_CLASSNAME,
SET_CUSTOM_CLASSNAME,
} from './constants';
export function resetLocaleDefaultClassName() { export function resetLocaleDefaultClassName() {
return { return {

View File

@ -11,7 +11,7 @@ describe('<LocaleToggle /> selectors', () => {
const mockedState = fromJS({ const mockedState = fromJS({
localeToggle: state, localeToggle: state,
}); });
expect(selectLocaleToggle()(mockedState)).toEqual(state); expect(selectLocaleToggle()(mockedState)).toEqual(state);
}); });
}); });
@ -29,5 +29,3 @@ describe('<LocaleToggle /> selectors', () => {
}); });
}); });
}); });

View File

@ -118,7 +118,7 @@ Marketplace.propTypes = {
global: PropTypes.shape({ global: PropTypes.shape({
autoReload: PropTypes.bool.isRequired, autoReload: PropTypes.bool.isRequired,
currentEnvironment: PropTypes.string.isRequired, currentEnvironment: PropTypes.string.isRequired,
}), }).isRequired,
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
installedPlugins: PropTypes.array.isRequired, installedPlugins: PropTypes.array.isRequired,
intl: PropTypes.shape({ intl: PropTypes.shape({

View File

@ -4,6 +4,7 @@
* *
*/ */
/* eslint-disable import/no-cycle */
import { dispatch } from '../../app'; import { dispatch } from '../../app';
import { SHOW_NOTIFICATION, HIDE_NOTIFICATION } from './constants'; import { SHOW_NOTIFICATION, HIDE_NOTIFICATION } from './constants';

View File

@ -4,16 +4,16 @@
* *
*/ */
/* eslint-disable */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect'; import { createStructuredSelector } from 'reselect';
import NotificationsContainer from '../../components/NotificationsContainer'; import NotificationsContainer from '../../components/NotificationsContainer';
import { selectNotifications } from './selectors'; import { selectNotifications } from './selectors';
import { hideNotification } from './actions'; import { hideNotification } from './actions';
export class NotificationProvider extends React.Component { // eslint-disable-line react/prefer-stateless-function export class NotificationProvider extends React.Component {
render() { render() {
return ( return (
<NotificationsContainer <NotificationsContainer
@ -35,11 +35,14 @@ const mapStateToProps = createStructuredSelector({
function mapDispatchToProps(dispatch) { function mapDispatchToProps(dispatch) {
return { return {
onHideNotification: (id) => { onHideNotification: id => {
dispatch(hideNotification(id)); dispatch(hideNotification(id));
}, },
dispatch, dispatch,
}; };
} }
export default connect(mapStateToProps, mapDispatchToProps)(NotificationProvider); export default connect(
mapStateToProps,
mapDispatchToProps
)(NotificationProvider);

View File

@ -1,5 +1,36 @@
import styled, { keyframes } from 'styled-components'; import styled, { keyframes } from 'styled-components';
const fadeIn = keyframes`
0% {
width: auto;
height: auto;
opacity: 0;
}
5% {
opacity: 0;
}
100% {
opacity: 1;
}
`;
const fadeOut = keyframes`
0% {
opacity: 1;
}
60% {
opacity: 0;
}
100% {
opacity: 0;
width: 0;
height: 0;
}
`;
const Wrapper = styled.div` const Wrapper = styled.div`
position: fixed; position: fixed;
right: 15px; right: 15px;
@ -93,35 +124,4 @@ const Wrapper = styled.div`
} }
`; `;
const fadeIn = keyframes`
0% {
width: auto;
height: auto;
opacity: 0;
}
5% {
opacity: 0;
}
100% {
opacity: 1;
}
`;
const fadeOut = keyframes`
0% {
opacity: 1;
}
60% {
opacity: 0;
}
100% {
opacity: 0;
width: 0;
height: 0;
}
`;
export default Wrapper; export default Wrapper;

View File

@ -27,9 +27,9 @@ import makeSelectOnboarding from './selectors';
import reducer from './reducer'; import reducer from './reducer';
import saga from './saga'; import saga from './saga';
export class Onboarding extends React.Component { /* eslint-disable react/no-array-index-key */
static contextType = GlobalContext;
export class Onboarding extends React.Component {
state = { showVideos: false }; state = { showVideos: false };
componentDidMount() { componentDidMount() {
@ -92,6 +92,8 @@ export class Onboarding extends React.Component {
this.props.setVideoEnd(index, true); this.props.setVideoEnd(index, true);
}; };
static contextType = GlobalContext;
render() { render() {
const { videos, onClick, setVideoDuration } = this.props; const { videos, onClick, setVideoDuration } = this.props;
const { showVideos } = this.state; const { showVideos } = this.state;
@ -144,6 +146,7 @@ export class Onboarding extends React.Component {
<button <button
onClick={this.handleVideosToggle} onClick={this.handleVideosToggle}
className={this.state.showVideos ? 'active' : ''} className={this.state.showVideos ? 'active' : ''}
type="button"
> >
<i className="fa fa-question" /> <i className="fa fa-question" />
<i className="fa fa-times" /> <i className="fa fa-times" />

View File

@ -5,7 +5,15 @@
*/ */
import { fromJS } from 'immutable'; import { fromJS } from 'immutable';
import { GET_VIDEOS_SUCCEEDED, SHOULD_OPEN_MODAL, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME, SET_VIDEO_END, REMOVE_VIDEOS } from './constants'; import {
GET_VIDEOS_SUCCEEDED,
SHOULD_OPEN_MODAL,
ON_CLICK,
SET_VIDEOS_DURATION,
UPDATE_VIDEO_START_TIME,
SET_VIDEO_END,
REMOVE_VIDEOS,
} from './constants';
const initialState = fromJS({ const initialState = fromJS({
videos: fromJS([]), videos: fromJS([]),
@ -20,7 +28,6 @@ function onboardingReducer(state = initialState, action) {
case ON_CLICK: case ON_CLICK:
return state.updateIn(['videos'], list => { return state.updateIn(['videos'], list => {
return list.reduce((acc, current, index) => { return list.reduce((acc, current, index) => {
if (index === action.index) { if (index === action.index) {
return acc.updateIn([index, 'isOpen'], v => !v); return acc.updateIn([index, 'isOpen'], v => !v);
} }
@ -29,15 +36,17 @@ function onboardingReducer(state = initialState, action) {
}, list); }, list);
}); });
case SET_VIDEOS_DURATION: case SET_VIDEOS_DURATION:
return state.updateIn(['videos', action.index, 'duration'], () => action.duration); return state.updateIn(
['videos', action.index, 'duration'],
() => action.duration
);
case UPDATE_VIDEO_START_TIME: { case UPDATE_VIDEO_START_TIME: {
const storedVideos = JSON.parse(localStorage.getItem('videos')); const storedVideos = JSON.parse(localStorage.getItem('videos'));
const videos = state.updateIn(['videos'], list => { const videos = state.updateIn(['videos'], list => {
return list.reduce((acc, current, index) => { return list.reduce((acc, current, index) => {
if (index === action.index) { if (index === action.index) {
storedVideos[index].startTime = action.startTime; storedVideos[index].startTime = action.startTime;
return acc.updateIn([index, 'startTime'], () => action.startTime); return acc.updateIn([index, 'startTime'], () => action.startTime);
} }
@ -52,8 +61,8 @@ function onboardingReducer(state = initialState, action) {
return videos; return videos;
} }
case SET_VIDEO_END: { case SET_VIDEO_END: {
const storedVideos = JSON.parse(localStorage.getItem('videos')); const storedVideos = JSON.parse(localStorage.getItem('videos'));
storedVideos[action.index].end = action.end; storedVideos[action.index].end = action.end;
localStorage.setItem('videos', JSON.stringify(storedVideos)); localStorage.setItem('videos', JSON.stringify(storedVideos));

View File

@ -10,9 +10,10 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import { Redirect, Route } from 'react-router-dom'; import { Redirect, Route } from 'react-router-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { auth } from 'strapi-helper-plugin'; import { auth } from 'strapi-helper-plugin';
/* eslint-disable react/jsx-curly-newline */
const PrivateRoute = ({ component: Component, path, ...rest }) => ( const PrivateRoute = ({ component: Component, path, ...rest }) => (
<Route <Route
path={path} path={path}

View File

@ -18,7 +18,7 @@ function SettingsPage() {
title: { id: 'Settings.global' }, title: { id: 'Settings.global' },
links: [ links: [
{ {
title: formatMessage({ id: `Settings.webhooks.title` }), title: formatMessage({ id: 'Settings.webhooks.title' }),
to: '/settings/webhooks', to: '/settings/webhooks',
name: 'webhooks', name: 'webhooks',
}, },

View File

@ -91,13 +91,14 @@ function EditView() {
.filter(key => key.includes('headers')) .filter(key => key.includes('headers'))
.reduce((obj, key) => { .reduce((obj, key) => {
obj[key] = formErrors[key]; obj[key] = formErrors[key];
return obj; return obj;
}, {}); }, {});
const headerTitle = isCreating const headerTitle = isCreating
? formatMessage({ ? formatMessage({
id: `Settings.webhooks.create`, id: 'Settings.webhooks.create',
}) })
: name; : name;
const headersActions = [ const headersActions = [
@ -105,7 +106,7 @@ function EditView() {
color: 'primary', color: 'primary',
disabled: isTriggerActionDisabled, disabled: isTriggerActionDisabled,
label: formatMessage({ label: formatMessage({
id: `Settings.webhooks.trigger`, id: 'Settings.webhooks.trigger',
}), }),
onClick: () => handleTrigger(), onClick: () => handleTrigger(),
style: { style: {
@ -113,8 +114,8 @@ function EditView() {
}, },
title: isTriggerActionDisabled title: isTriggerActionDisabled
? formatMessage({ ? formatMessage({
id: `Settings.webhooks.trigger.save`, id: 'Settings.webhooks.trigger.save',
}) })
: null, : null,
type: 'button', type: 'button',
icon: ( icon: (
@ -129,7 +130,7 @@ function EditView() {
color: 'cancel', color: 'cancel',
disabled: areActionDisabled, disabled: areActionDisabled,
label: formatMessage({ label: formatMessage({
id: `app.components.Button.reset`, id: 'app.components.Button.reset',
}), }),
onClick: () => handleReset(), onClick: () => handleReset(),
style: { style: {
@ -141,7 +142,7 @@ function EditView() {
color: 'success', color: 'success',
disabled: areActionDisabled, disabled: areActionDisabled,
label: formatMessage({ label: formatMessage({
id: `app.components.Button.save`, id: 'app.components.Button.save',
}), }),
style: { style: {
minWidth: 140, minWidth: 140,
@ -181,7 +182,7 @@ function EditView() {
const createWebhooks = async () => { const createWebhooks = async () => {
try { try {
await request(`/admin/webhooks`, { await request('/admin/webhooks', {
method: 'POST', method: 'POST',
body: cleanData(modifiedData), body: cleanData(modifiedData),
}); });
@ -191,7 +192,7 @@ function EditView() {
type: 'SUBMIT_SUCCEEDED', type: 'SUBMIT_SUCCEEDED',
}); });
strapi.notification.success(`Settings.webhooks.created`); strapi.notification.success('Settings.webhooks.created');
goBack(); goBack();
} }
} catch (err) { } catch (err) {
@ -312,6 +313,7 @@ function EditView() {
.filter(key => !key.includes('headers')) .filter(key => !key.includes('headers'))
.reduce((obj, key) => { .reduce((obj, key) => {
obj[key] = formErrors[key]; obj[key] = formErrors[key];
return obj; return obj;
}, {}); }, {});
@ -321,7 +323,7 @@ function EditView() {
const setErrors = errors => { const setErrors = errors => {
dispatch({ dispatch({
type: 'SET_ERRORS', type: 'SET_ERRORS',
errors: errors, errors,
}); });
}; };

View File

@ -30,7 +30,7 @@ const reducer = (state, action) => {
if (Object.keys(headers).length > 0) { if (Object.keys(headers).length > 0) {
formattedHeaders = Object.keys(headers).map(key => { formattedHeaders = Object.keys(headers).map(key => {
return { key: key, value: headers[key] }; return { key, value: headers[key] };
}); });
} }
@ -52,6 +52,7 @@ const reducer = (state, action) => {
if (headers.size === 1) { if (headers.size === 1) {
return fromJS([header]); return fromJS([header]);
} }
return headers.remove(action.index); return headers.remove(action.index);
}); });
} }

View File

@ -4,12 +4,14 @@ const cleanData = data => {
const webhooks = data; const webhooks = data;
set(webhooks, 'headers', unformatHeaders(data.headers)); set(webhooks, 'headers', unformatHeaders(data.headers));
return webhooks; return webhooks;
}; };
const unformatHeaders = headers => { const unformatHeaders = headers => {
return headers.reduce((acc, current) => { return headers.reduce((acc, current) => {
const { key, value } = current; const { key, value } = current;
if (key !== '') { if (key !== '') {
return { return {
...acc, ...acc,
@ -21,4 +23,4 @@ const unformatHeaders = headers => {
}, {}); }, {});
}; };
export { cleanData }; export { cleanData, unformatHeaders };

View File

@ -46,7 +46,7 @@ function ListView() {
// New button // New button
const addBtnLabel = formatMessage({ const addBtnLabel = formatMessage({
id: `Settings.webhooks.list.button.add`, id: 'Settings.webhooks.list.button.add',
}); });
const newButtonProps = { const newButtonProps = {
@ -71,25 +71,25 @@ function ListView() {
const headerProps = { const headerProps = {
title: { title: {
label: formatMessage({ id: `Settings.webhooks.title` }), label: formatMessage({ id: 'Settings.webhooks.title' }),
}, },
content: formatMessage({ id: `Settings.webhooks.list.description` }), content: formatMessage({ id: 'Settings.webhooks.list.description' }),
actions: actions, actions,
}; };
// List props // List props
const rowsCount = webhooks.length; const rowsCount = webhooks.length;
const titleLabel = `${ const titleLabel = `${
rowsCount > 1 rowsCount > 1
? formatMessage({ id: `Settings.webhooks.title` }) ? formatMessage({ id: 'Settings.webhooks.title' })
: formatMessage({ id: `Settings.webhooks.singular` }) : formatMessage({ id: 'Settings.webhooks.singular' })
}`; }`;
const title = `${rowsCount} ${titleLabel}`; const title = `${rowsCount} ${titleLabel}`;
const buttonProps = { const buttonProps = {
color: 'delete', color: 'delete',
disabled: webhooksToDelete.length > 0 ? false : true, disabled: !(webhooksToDelete.length > 0),
label: formatMessage({ id: `Settings.webhooks.list.button.delete` }), label: formatMessage({ id: 'Settings.webhooks.list.button.delete' }),
onClick: () => setShowModal(true), onClick: () => setShowModal(true),
type: 'button', type: 'button',
}; };
@ -102,7 +102,7 @@ function ListView() {
const fetchData = async () => { const fetchData = async () => {
try { try {
const { data } = await request(`/admin/webhooks`, { const { data } = await request('/admin/webhooks', {
method: 'GET', method: 'GET',
}); });
@ -161,7 +161,7 @@ function ListView() {
}; };
try { try {
await request(`/admin/webhooks/batch-delete`, { await request('/admin/webhooks/batch-delete', {
method: 'POST', method: 'POST',
body, body,
}); });
@ -186,7 +186,7 @@ function ListView() {
dispatch({ dispatch({
type: 'SET_WEBHOOK_TO_DELETE', type: 'SET_WEBHOOK_TO_DELETE',
id: id, id,
}); });
}; };
@ -207,7 +207,7 @@ function ListView() {
dispatch({ dispatch({
type: 'SET_WEBHOOK_ENABLED', type: 'SET_WEBHOOK_ENABLED',
keys, keys,
value: value, value,
}); });
await request(`/admin/webhooks/${id}`, { await request(`/admin/webhooks/${id}`, {

View File

@ -19,6 +19,7 @@ const reducer = (state, action) => {
if (action.value) { if (action.value) {
return list.push(action.id); return list.push(action.id);
} }
return list.filter(data => data !== action.id); return list.filter(data => data !== action.id);
}); });
case 'WEBHOOKS_DELETED': case 'WEBHOOKS_DELETED':

View File

@ -13,8 +13,8 @@ import EditView from './EditView';
function Webhooks() { function Webhooks() {
return ( return (
<Switch> <Switch>
<Route exact path={`/settings/webhooks`} component={ListView} /> <Route exact path="/settings/webhooks" component={ListView} />
<Route exact path={`/settings/webhooks/:id`} component={EditView} /> <Route exact path="/settings/webhooks/:id" component={EditView} />
</Switch> </Switch>
); );
} }

View File

@ -1,3 +1,5 @@
/* eslint-disable */
const injectReducer = require('./utils/injectReducer').default; const injectReducer = require('./utils/injectReducer').default;
const useInjectReducer = require('./utils/injectReducer').useInjectReducer; const useInjectReducer = require('./utils/injectReducer').useInjectReducer;
const injectSaga = require('./utils/injectSaga').default; const injectSaga = require('./utils/injectSaga').default;

View File

@ -1,4 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable */
import React from 'react'; import React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics'; import hoistNonReactStatics from 'hoist-non-react-statics';
import { ReactReduxContext } from 'react-redux'; import { ReactReduxContext } from 'react-redux';

View File

@ -1,4 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable */
import React from 'react'; import React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics'; import hoistNonReactStatics from 'hoist-non-react-statics';
import { ReactReduxContext } from 'react-redux'; import { ReactReduxContext } from 'react-redux';

View File

@ -1,3 +1,5 @@
/* eslint-disable */
import invariant from 'invariant'; import invariant from 'invariant';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import isFunction from 'lodash/isFunction'; import isFunction from 'lodash/isFunction';
@ -12,7 +14,7 @@ export function injectReducerFactory(store, isValid) {
invariant( invariant(
isString(key) && !isEmpty(key) && isFunction(reducer), isString(key) && !isEmpty(key) && isFunction(reducer),
'(app/utils...) injectReducer: Expected `reducer` to be a reducer function', '(app/utils...) injectReducer: Expected `reducer` to be a reducer function'
); );
// Check `store.injectedReducers[key] === reducer` for hot reloading when a key is the same but a reducer is different // Check `store.injectedReducers[key] === reducer` for hot reloading when a key is the same but a reducer is different

View File

@ -1,3 +1,5 @@
/* eslint-disable */
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import isFunction from 'lodash/isFunction'; import isFunction from 'lodash/isFunction';
import isString from 'lodash/isString'; import isString from 'lodash/isString';
@ -5,23 +7,20 @@ import invariant from 'invariant';
import conformsTo from 'lodash/conformsTo'; import conformsTo from 'lodash/conformsTo';
import checkStore from './checkStore'; import checkStore from './checkStore';
import { import { DAEMON, ONCE_TILL_UNMOUNT, RESTART_ON_REMOUNT } from './constants';
DAEMON,
ONCE_TILL_UNMOUNT,
RESTART_ON_REMOUNT,
} from './constants';
const allowedModes = [RESTART_ON_REMOUNT, DAEMON, ONCE_TILL_UNMOUNT]; const allowedModes = [RESTART_ON_REMOUNT, DAEMON, ONCE_TILL_UNMOUNT];
const checkKey = (key) => invariant( const checkKey = key =>
isString(key) && !isEmpty(key), invariant(
'(app/utils...) injectSaga: Expected `key` to be a non empty string' isString(key) && !isEmpty(key),
); '(app/utils...) injectSaga: Expected `key` to be a non empty string'
);
const checkDescriptor = (descriptor) => { const checkDescriptor = descriptor => {
const shape = { const shape = {
saga: isFunction, saga: isFunction,
mode: (mode) => isString(mode) && allowedModes.includes(mode), mode: mode => isString(mode) && allowedModes.includes(mode),
}; };
invariant( invariant(
conformsTo(descriptor, shape), conformsTo(descriptor, shape),
@ -33,7 +32,10 @@ export function injectSagaFactory(store, isValid) {
return function injectSaga(key, descriptor = {}, args) { return function injectSaga(key, descriptor = {}, args) {
if (!isValid) checkStore(store); if (!isValid) checkStore(store);
const newDescriptor = { ...descriptor, mode: descriptor.mode || RESTART_ON_REMOUNT }; const newDescriptor = {
...descriptor,
mode: descriptor.mode || RESTART_ON_REMOUNT,
};
const { saga, mode } = newDescriptor; const { saga, mode } = newDescriptor;
checkKey(key); checkKey(key);
@ -50,8 +52,14 @@ export function injectSagaFactory(store, isValid) {
} }
} }
if (!hasSaga || (hasSaga && mode !== DAEMON && mode !== ONCE_TILL_UNMOUNT)) { if (
store.injectedSagas[key] = { ...newDescriptor, task: store.runSaga(saga, args) }; // eslint-disable-line no-param-reassign !hasSaga ||
(hasSaga && mode !== DAEMON && mode !== ONCE_TILL_UNMOUNT)
) {
store.injectedSagas[key] = {
...newDescriptor,
task: store.runSaga(saga, args),
}; // eslint-disable-line no-param-reassign
} }
}; };
} }

View File

@ -1,4 +1,5 @@
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
/* eslint-disable */
const Wrapper = styled.div` const Wrapper = styled.div`
margin-left: 29px; margin-left: 29px;

View File

@ -1,4 +1,5 @@
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
/* eslint-disable */
const Label = styled.label` const Label = styled.label`
cursor: pointer; cursor: pointer;

View File

@ -2,7 +2,7 @@ const DATE_FORMATS = {
date: 'dddd, MMMM Do YYYY', date: 'dddd, MMMM Do YYYY',
datetime: 'dddd, MMMM Do YYYY HH:mm', datetime: 'dddd, MMMM Do YYYY HH:mm',
time: 'HH:mm A', time: 'HH:mm A',
timestamp: 'dddd, MMMM Do YYYY', timestamp: 'dddd, MMMM Do YYYY HH:mm',
}; };
export default DATE_FORMATS; export default DATE_FORMATS;

View File

@ -10,6 +10,8 @@ import MediaPreviewList from '../MediaPreviewList';
import { ActionContainer, Truncate, Truncated } from './styledComponents'; import { ActionContainer, Truncate, Truncated } from './styledComponents';
import DATE_FORMATS from './DATE_FORMATS'; import DATE_FORMATS from './DATE_FORMATS';
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
const dateToUtcTime = date => moment.parseZone(date).utc(); const dateToUtcTime = date => moment.parseZone(date).utc();
const getDisplayedValue = (type, value, name) => { const getDisplayedValue = (type, value, name) => {
@ -56,6 +58,7 @@ const getDisplayedValue = (type, value, name) => {
second, second,
}; };
const date = moment().set(timeObj); const date = moment().set(timeObj);
return date.format(DATE_FORMATS.time); return date.format(DATE_FORMATS.time);
} }
default: default:
@ -104,9 +107,7 @@ function Row({ goTo, isBulkable, row, headers }) {
<Truncated>{memoizedDisplayedValue(header.name)}</Truncated> <Truncated>{memoizedDisplayedValue(header.name)}</Truncated>
</Truncate> </Truncate>
) : ( ) : (
<MediaPreviewList <MediaPreviewList files={memoizedDisplayedValue(header.name)} />
files={memoizedDisplayedValue(header.name)}
></MediaPreviewList>
)} )}
</td> </td>
); );

View File

@ -5,6 +5,8 @@ import useListView from '../../hooks/useListView';
import CustomInputCheckbox from '../CustomInputCheckbox'; import CustomInputCheckbox from '../CustomInputCheckbox';
import { Arrow, Thead } from './styledComponents'; import { Arrow, Thead } from './styledComponents';
/* eslint-disable jsx-a11y/control-has-associated-label */
function TableHeader({ headers, isBulkable }) { function TableHeader({ headers, isBulkable }) {
const { const {
data, data,
@ -67,7 +69,7 @@ function TableHeader({ headers, isBulkable }) {
</th> </th>
); );
})} })}
<th></th> <th />
</tr> </tr>
</Thead> </Thead>
); );

View File

@ -94,7 +94,6 @@ CustomTable.defaultProps = {
data: [], data: [],
headers: [], headers: [],
isBulkable: true, isBulkable: true,
slug: '',
}; };
CustomTable.propTypes = { CustomTable.propTypes = {
@ -108,7 +107,6 @@ CustomTable.propTypes = {
push: PropTypes.func.isRequired, push: PropTypes.func.isRequired,
}).isRequired, }).isRequired,
isBulkable: PropTypes.bool, isBulkable: PropTypes.bool,
slug: PropTypes.string,
}; };
export default withRouter(memo(CustomTable)); export default withRouter(memo(CustomTable));

View File

@ -1,3 +1,5 @@
/* eslint-disable */
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
const Table = styled.table` const Table = styled.table`

View File

@ -17,6 +17,8 @@ const MenuDropdown = styled(DropdownMenu)`
border-top-right-radius: 0; border-top-right-radius: 0;
`; `;
} }
return '';
}} }}
`; `;

View File

@ -1,3 +1,5 @@
/* eslint-disable */
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import getColor from './utils/getColor'; import getColor from './utils/getColor';

View File

@ -20,6 +20,8 @@ const NameWrapper = styled.div`
color: #007eff; color: #007eff;
`; `;
} }
return '';
}} }}
`; `;

View File

@ -30,6 +30,8 @@ const RemoveWrapper = styled.div`
} }
`; `;
} }
return '';
}} }}
`; `;

View File

@ -1,3 +1,5 @@
/* eslint-disable */
import styled from 'styled-components'; import styled from 'styled-components';
import getColor from './utils/getColor'; import getColor from './utils/getColor';
import getHeight from './utils/getHeight'; import getHeight from './utils/getHeight';

View File

@ -1,3 +1,5 @@
/* eslint-disable */
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import getColor from './utils/getColor'; import getColor from './utils/getColor';

View File

@ -14,6 +14,7 @@ import SubWrapper from './SubWrapper';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
import Close from './Close'; import Close from './Close';
/* eslint-disable */
const DraggedField = forwardRef( const DraggedField = forwardRef(
( (
{ {

View File

@ -1,11 +1,12 @@
const getColor = (isOverRemove, isSelected, isOverEditBlock) => { const getColor = (isOverRemove, isSelected, isOverEditBlock) => {
if (isOverRemove) { if (isOverRemove) {
return '#ffa784'; return '#ffa784';
} else if (isSelected || isOverEditBlock) {
return '#aed4fb';
} else {
return '#e9eaeb';
} }
if (isSelected || isOverEditBlock) {
return '#aed4fb';
}
return '#e9eaeb';
}; };
export default getColor; export default getColor;

View File

@ -8,6 +8,8 @@ import DynamicZoneWrapper from './DynamicZoneWrapper';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
import DynamicComponent from './DynamicComponent'; import DynamicComponent from './DynamicComponent';
/* eslint-disable react/no-array-index-key */
const DraggedFieldWithPreview = forwardRef( const DraggedFieldWithPreview = forwardRef(
( (
{ {
@ -136,7 +138,7 @@ const DraggedFieldWithPreview = forwardRef(
withLongerHeight={higherFields.includes( withLongerHeight={higherFields.includes(
fieldType fieldType
)} )}
></DraggedField> />
</div> </div>
); );
})} })}

View File

@ -19,7 +19,7 @@ const DynamicComponentCard = ({
onClick(componentUid); onClick(componentUid);
}} }}
> >
<button className="component-icon"> <button className="component-icon" type="button">
<FontAwesomeIcon icon={icon} /> <FontAwesomeIcon icon={icon} />
</button> </button>

View File

@ -22,6 +22,8 @@ const Button = styled(PlusButton)`
} }
`; `;
} }
return '';
}} }}
&.isOpen { &.isOpen {
transform: rotate(-45deg); transform: rotate(-45deg);

View File

@ -17,6 +17,8 @@ import Label from './Label';
import RoundCTA from './RoundCTA'; import RoundCTA from './RoundCTA';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
/* eslint-disable react/no-array-index-key */
const DynamicZone = ({ max, min, name }) => { const DynamicZone = ({ max, min, name }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const { const {
@ -117,7 +119,7 @@ const DynamicZone = ({ max, min, name }) => {
<RoundCTA <RoundCTA
onClick={() => removeComponentFromDynamicZone(name, index)} onClick={() => removeComponentFromDynamicZone(name, index)}
> >
<FontAwesomeIcon icon={'trash'} /> <FontAwesomeIcon icon="trash" />
</RoundCTA> </RoundCTA>
<FieldComponent <FieldComponent
componentUid={componentUid} componentUid={componentUid}
@ -127,7 +129,7 @@ const DynamicZone = ({ max, min, name }) => {
icon={getDynamicComponentInfos(componentUid).icon} icon={getDynamicComponentInfos(componentUid).icon}
label="" label=""
name={`${name}.${index}`} name={`${name}.${index}`}
isFromDynamicZone={true} isFromDynamicZone
/> />
</div> </div>
); );

View File

@ -12,6 +12,8 @@ const Wrapper = styled.div`
background-color: #fff; background-color: #fff;
`; `;
} }
return '';
}} }}
`; `;

View File

@ -1,3 +1,4 @@
/* eslint-disable import/no-cycle */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { get, size } from 'lodash'; import { get, size } from 'lodash';

View File

@ -85,8 +85,6 @@ const Item = ({
item.rowIndex = targetRow; item.rowIndex = targetRow;
item.itemIndex = hoverIndex; item.itemIndex = hoverIndex;
return;
}, },
drop(item, monitor) { drop(item, monitor) {
if (!dropRef.current) { if (!dropRef.current) {
@ -122,6 +120,7 @@ const Item = ({
item.itemIndex = hoverIndex + 1; item.itemIndex = hoverIndex + 1;
item.rowIndex = targetRow; item.rowIndex = targetRow;
return; return;
} }
@ -136,8 +135,6 @@ const Item = ({
item.itemIndex = hoverIndex; item.itemIndex = hoverIndex;
item.rowIndex = targetRow; item.rowIndex = targetRow;
return;
}, },
collect: monitor => ({ collect: monitor => ({
canDrop: monitor.canDrop(), canDrop: monitor.canDrop(),

View File

@ -5,4 +5,4 @@ const Wrapper = styled.div`
margin-bottom: 6px; margin-bottom: 6px;
`; `;
export { Wrapper }; export default Wrapper;

View File

@ -6,7 +6,7 @@ import useLayoutDnd from '../../hooks/useLayoutDnd';
import Add from '../AddDropdown'; import Add from '../AddDropdown';
import SortWrapper from '../SortWrapper'; import SortWrapper from '../SortWrapper';
import { Wrapper } from './components'; import Wrapper from './components';
import Item from './Item'; import Item from './Item';
const FieldsReorder = ({ className }) => { const FieldsReorder = ({ className }) => {

View File

@ -48,6 +48,8 @@ const Div = styled.div`
? 'margin-top .3s ease-out, margin-bottom .2s ease-out' ? 'margin-top .3s ease-out, margin-bottom .2s ease-out'
: 'margin .3s ease-in'; : 'margin .3s ease-in';
} }
return '';
}}; }};
`; `;

View File

@ -153,6 +153,7 @@ function FilterPicker({
}} }}
type={get(schema, ['attributes', filter.name, 'type'], '')} type={get(schema, ['attributes', filter.name, 'type'], '')}
showAddButton={key === modifiedData.length - 1} showAddButton={key === modifiedData.length - 1}
// eslint-disable-next-line react/no-array-index-key
key={key} key={key}
/> />
))} ))}
@ -180,8 +181,7 @@ FilterPicker.propTypes = {
isOpen: PropTypes.bool, isOpen: PropTypes.bool,
location: PropTypes.shape({ location: PropTypes.shape({
search: PropTypes.string.isRequired, search: PropTypes.string.isRequired,
}), }).isRequired,
name: PropTypes.string, name: PropTypes.string,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
toggleFilterPickerState: PropTypes.func.isRequired, toggleFilterPickerState: PropTypes.func.isRequired,

View File

@ -21,6 +21,7 @@ function reducer(state, action) {
if (action.value && action.value._isAMomentObject === true) { if (action.value && action.value._isAMomentObject === true) {
return moment(action.value, 'YYYY-MM-DD HH:mm:ss').format(); return moment(action.value, 'YYYY-MM-DD HH:mm:ss').format();
} }
return action.value; return action.value;
}) })
.updateIn(['modifiedData', index, 'value'], value => { .updateIn(['modifiedData', index, 'value'], value => {

View File

@ -48,7 +48,7 @@ function Input({ type, ...rest }) {
const styles = const styles =
type === 'boolean' ? { minWidth: '100px', maxWidth: '200px' } : style; type === 'boolean' ? { minWidth: '100px', maxWidth: '200px' } : style;
const wrapperStyle = const wrapperStyle =
type == 'boolean' || type === 'boolean' ||
['date', 'timestamp', 'time', 'datetime'].includes(type) ['date', 'timestamp', 'time', 'datetime'].includes(type)
? { marginRight: '20px' } ? { marginRight: '20px' }
: { marginRight: '10px' }; : { marginRight: '10px' };

View File

@ -1,5 +1,7 @@
import styled from 'styled-components'; import styled from 'styled-components';
/* eslint-disable */
const Wrapper = styled.div` const Wrapper = styled.div`
min-height: 38px; min-height: 38px;
border-left: ${props => props.borderLeft && '3px solid #007EFF'}; border-left: ${props => props.borderLeft && '3px solid #007EFF'};

View File

@ -3,14 +3,14 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
const FormTitle = ({ description, title }) => ( const FormTitle = ({ description, title }) => (
<React.Fragment> <>
{!!title && <FormattedMessage id={title} />} {!!title && <FormattedMessage id={title} />}
{!!description && ( {!!description && (
<FormattedMessage id={description}> <FormattedMessage id={description}>
{msg => <p>{msg}</p>} {msg => <p>{msg}</p>}
</FormattedMessage> </FormattedMessage>
)} )}
</React.Fragment> </>
); );
FormTitle.propTypes = { FormTitle.propTypes = {

View File

@ -58,6 +58,8 @@ const Label = styled.label`
} }
`; `;
} }
return '';
}} }}
`; `;

View File

@ -24,6 +24,8 @@ const stringify = JSON.stringify;
const DEFAULT_THEME = '3024-night'; const DEFAULT_THEME = '3024-night';
class InputJSON extends React.Component { class InputJSON extends React.Component {
timer = null;
constructor(props) { constructor(props) {
super(props); super(props);
this.editor = React.createRef(); this.editor = React.createRef();
@ -88,7 +90,7 @@ class InputJSON extends React.Component {
let content = this.getContentAtLine(line); let content = this.getContentAtLine(line);
if (content === '{') { if (content === '{') {
line = line + 1; line += 1;
content = this.getContentAtLine(line); content = this.getContentAtLine(line);
} }
const chEnd = content.length; const chEnd = content.length;
@ -101,8 +103,6 @@ class InputJSON extends React.Component {
this.setState({ markedText }); this.setState({ markedText });
}; };
timer = null;
handleBlur = ({ target }) => { handleBlur = ({ target }) => {
const { name, onBlur } = this.props; const { name, onBlur } = this.props;

View File

@ -17,7 +17,6 @@ import Wrapper from './Wrapper';
class InputJSONWithErrors extends React.Component { class InputJSONWithErrors extends React.Component {
handleChange = e => { handleChange = e => {
this.setState({ errors: [] });
this.props.onChange(e); this.props.onChange(e);
}; };

View File

@ -1,3 +1,6 @@
/* eslint-disable react/no-array-index-key */
/* eslint-disable import/no-cycle */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { get } from 'lodash'; import { get } from 'lodash';

View File

@ -33,6 +33,7 @@ const PopupForm = ({
return type; return type;
}; };
return ( return (
<Modal isOpen={isOpen} onClosed={onClosed} onToggle={onToggle}> <Modal isOpen={isOpen} onClosed={onClosed} onToggle={onToggle}>
<HeaderModal> <HeaderModal>

View File

@ -14,6 +14,8 @@ const Wrapper = styled.div`
padding: 0; padding: 0;
`; `;
} }
return '';
}} }}
border-radius: 2px; border-radius: 2px;
> div { > div {

View File

@ -21,6 +21,8 @@ const Button = styled.button`
border-radius: 2px; border-radius: 2px;
`; `;
} }
return '';
}} }}
${({ hasMinError }) => { ${({ hasMinError }) => {
@ -30,6 +32,8 @@ const Button = styled.button`
border-top-color: rgba(227, 233, 243, 0.75); border-top-color: rgba(227, 233, 243, 0.75);
`; `;
} }
return '';
}} }}
color: #007eff; color: #007eff;

View File

@ -8,6 +8,8 @@ import PreviewCarret from '../PreviewCarret';
import BannerWrapper from './BannerWrapper'; import BannerWrapper from './BannerWrapper';
import CarretTop from './CarretTop'; import CarretTop from './CarretTop';
/* eslint-disable jsx-a11y/no-static-element-interactions */
const Banner = forwardRef( const Banner = forwardRef(
( (
{ {

View File

@ -1,5 +1,7 @@
import styled from 'styled-components'; import styled from 'styled-components';
/* eslint-disable */
const BannerWrapper = styled.button` const BannerWrapper = styled.button`
display: flex; display: flex;
height: 36px; height: 36px;

View File

@ -1,3 +1,4 @@
/* eslint-disable import/no-cycle */
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { get } from 'lodash'; import { get } from 'lodash';
@ -12,6 +13,8 @@ import FieldComponent from '../FieldComponent';
import Banner from './Banner'; import Banner from './Banner';
import FormWrapper from './FormWrapper'; import FormWrapper from './FormWrapper';
/* eslint-disable react/no-array-index-key */
// Issues: // Issues:
// https://github.com/react-dnd/react-dnd/issues/1368 // https://github.com/react-dnd/react-dnd/issues/1368
// https://github.com/frontend-collective/react-sortable-tree/issues/490 // https://github.com/frontend-collective/react-sortable-tree/issues/490
@ -89,6 +92,7 @@ const DraggedItem = ({
const clientOffset = monitor.getClientOffset(); const clientOffset = monitor.getClientOffset();
// Get pixels to the top // Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top; const hoverClientY = clientOffset.y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height // Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50% // When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50% // When dragging upwards, only move when the cursor is above 50%
@ -109,8 +113,6 @@ const DraggedItem = ({
// but it's good here for the sake of performance // but it's good here for the sake of performance
// to avoid expensive index searches. // to avoid expensive index searches.
item.originalPath = hoverPath; item.originalPath = hoverPath;
return;
}, },
}); });
const [{ isDragging }, drag, preview] = useDrag({ const [{ isDragging }, drag, preview] = useDrag({

View File

@ -12,8 +12,10 @@ const EmptyComponent = styled.div`
${({ hasMinError }) => { ${({ hasMinError }) => {
if (hasMinError) { if (hasMinError) {
return `border-color: #FAA684`; return 'border-color: #FAA684';
} }
return '';
}} }}
> p { > p {

View File

@ -1,5 +1,7 @@
import styled from 'styled-components'; import styled from 'styled-components';
/* eslint-disable indent */
const FormWrapper = styled.div` const FormWrapper = styled.div`
padding-top: 24px; padding-top: 24px;
padding-left: 20px; padding-left: 20px;
@ -9,11 +11,12 @@ const FormWrapper = styled.div`
${({ hasErrors, isOpen }) => { ${({ hasErrors, isOpen }) => {
if (hasErrors) { if (hasErrors) {
return '#ffa784'; return '#ffa784';
} else if (isOpen) {
return '#AED4FB';
} else {
return 'rgba(227, 233, 243, 0.75)';
} }
if (isOpen) {
return '#AED4FB';
}
return 'rgba(227, 233, 243, 0.75)';
}}; }};
`; `;

View File

@ -1,3 +1,4 @@
/* eslint-disable import/no-cycle */
import React, { useReducer } from 'react'; import React, { useReducer } from 'react';
import { useDrop } from 'react-dnd'; import { useDrop } from 'react-dnd';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';

View File

@ -12,11 +12,14 @@ import Cross from '../../icons/Cross';
import Filter from '../../icons/Filter'; import Filter from '../../icons/Filter';
import SearchIcon from '../../icons/Search'; import SearchIcon from '../../icons/Search';
import { Wrapper, Infos, Clear } from './components'; import { Wrapper, Infos, Clear } from './components';
const WAIT = 400; const WAIT = 400;
class Search extends React.Component { class Search extends React.Component {
state = { value: this.props.initValue }; state = { value: this.props.initValue };
timer = null;
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { model, value } = this.props; const { model, value } = this.props;
@ -28,8 +31,6 @@ class Search extends React.Component {
} }
} }
timer = null;
resetState = () => this.setState({ value: '' }); resetState = () => this.setState({ value: '' });
handleChange = ({ target }) => { handleChange = ({ target }) => {

View File

@ -7,6 +7,8 @@ import { FormattedMessage } from 'react-intl';
import pluginId from '../../pluginId'; import pluginId from '../../pluginId';
import IconRemove from '../../assets/images/icon_remove.svg'; import IconRemove from '../../assets/images/icon_remove.svg';
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
const Relation = ({ data, mainField, onRemove, to }) => { const Relation = ({ data, mainField, onRemove, to }) => {
return ( return (
<> <>

View File

@ -64,6 +64,7 @@ function SelectMany({
if (!isEmpty(value)) { if (!isEmpty(value)) {
const isSelected = const isSelected =
value.findIndex(item => item.id === candidate.value.id) !== -1; value.findIndex(item => item.id === candidate.value.id) !== -1;
if (isSelected) { if (isSelected) {
return false; return false;
} }

View File

@ -59,7 +59,7 @@ function SelectWrapper({
const data = await request(requestUrl, { const data = await request(requestUrl, {
method: 'GET', method: 'GET',
params: params, params,
signal, signal,
}); });
@ -82,6 +82,7 @@ function SelectWrapper({
if (objIndex === -1) { if (objIndex === -1) {
return true; return true;
} }
return ( return (
prevState.findIndex(el => el.value.id === obj.value.id) === index prevState.findIndex(el => el.value.id === obj.value.id) === index
); );
@ -130,6 +131,7 @@ function SelectWrapper({
if (prevState._q === inputValue) { if (prevState._q === inputValue) {
return prevState; return prevState;
} }
return { ...prevState, _q: inputValue }; return { ...prevState, _q: inputValue };
}); });
} }
@ -220,7 +222,6 @@ SelectWrapper.defaultProps = {
editable: true, editable: true,
description: '', description: '',
label: '', label: '',
plugin: '',
placeholder: '', placeholder: '',
}; };
@ -231,7 +232,6 @@ SelectWrapper.propTypes = {
mainField: PropTypes.string.isRequired, mainField: PropTypes.string.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
placeholder: PropTypes.string, placeholder: PropTypes.string,
plugin: PropTypes.string,
relationType: PropTypes.string.isRequired, relationType: PropTypes.string.isRequired,
targetModel: PropTypes.string.isRequired, targetModel: PropTypes.string.isRequired,
}; };

Some files were not shown because too many files have changed in this diff Show More