components refacto ip

This commit is contained in:
Virginie Ky 2019-09-18 17:39:54 +02:00
parent b5a18e27bc
commit c06b0d9031
7 changed files with 299 additions and 203 deletions

View File

@ -4,25 +4,26 @@ const Wrapper = styled.div`
margin-bottom: 0.5rem;
padding-left: 0;
font-size: 13px;
> div {
div {
height: 26px;
padding-left: 15px;
line-height: 26px;
> i {
i {
display: none;
position: absolute;
top: 8px;
right: 10px;
color: #787e8f;
cursor: pointer;
}
}
.highlighted {
border-radius: 3px;
background-color: #e9eaeb;
font-weight: 600;
&.highlighted {
border-radius: 3px;
background-color: #e9eaeb;
font-weight: 600;
> i {
display: block;
}
}
}
`;
@ -33,7 +34,6 @@ const Label = styled.label`
display: none;
margin-right: 9px;
}
&:before {
content: '';
position: absolute;

View File

@ -9,98 +9,63 @@ import PropTypes from 'prop-types';
import { Label, Wrapper } from './Components';
class InputCheckboxPlugin extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { showBackground: false, showCog: false };
function InputCheckboxPlugin(
{ inputSelected, label, name, setNewInputSelected, value },
context
) {
const isSelected = inputSelected === name;
UNSAFE_componentWillReceiveProps(nextProps) {
// Remove background if another input is selected
if (
nextProps.inputSelected !== this.props.inputSelected &&
nextProps.inputSelected !== this.props.name
) {
this.setState({ showBackground: false });
}
if (!nextProps.isOpen) {
this.setState({ showBackground: false, showCog: false });
}
}
handleChange = () => {
const handleChange = () => {
const target = {
type: 'checkbox',
name: this.props.name,
value: !this.props.value,
name: name,
value: !value,
};
// Don't show the label background if the user unselects the input
if (!this.props.value) {
this.setState({ showBackground: true });
// Tell the Parent component that another input has been selected
this.props.setNewInputSelected(this.props.name);
// Tell the policies component to show the associated routes
this.context.setShouldDisplayPolicieshint();
this.context.setInputPoliciesPath(this.props.name);
if (!value) {
setNewInputSelected(name);
context.setShouldDisplayPolicieshint();
context.setInputPoliciesPath(name);
} else {
this.setState({ showBackground: false, showCog: false });
this.props.setNewInputSelected('');
setNewInputSelected('');
}
this.context.onChange({ target });
context.onChange({ target });
};
handleClick = () => {
this.setState({ showBackground: !this.state.showBackground });
this.props.setNewInputSelected(this.props.name);
this.context.setInputPoliciesPath(this.props.name);
const handleClick = () => {
setNewInputSelected(name);
context.setInputPoliciesPath(name);
if (this.state.showBackground) {
this.context.resetShouldDisplayPoliciesHint();
if (isSelected) {
context.resetShouldDisplayPoliciesHint();
} else {
this.context.setShouldDisplayPolicieshint();
setShouldDisplayPolicieshint();
}
};
render() {
return (
<Wrapper
className="col-md-4"
onMouseEnter={() => {
if (this.props.value) {
this.setState({ showCog: true });
}
}}
onMouseLeave={() => this.setState({ showCog: false })}
>
<div
className={`form-check ${
this.state.showBackground ? 'highlighted' : ''
}`}
return (
<Wrapper className="col-md-4">
<div className={`form-check ${isSelected ? 'highlighted' : ''}`}>
<Label
className={`form-check-label ${value ? 'checked' : ''}`}
htmlFor={name}
>
<Label
className={`form-check-label ${this.props.value ? 'checked' : ''}`}
htmlFor={this.props.name}
>
<input
className="form-check-input"
defaultChecked={this.props.value}
id={this.props.name}
name={this.props.name}
onChange={this.handleChange}
type="checkbox"
/>
{this.props.label}
</Label>
{this.state.showCog || this.state.showBackground ? (
<i className="fa fa-cog" onClick={this.handleClick} />
) : (
''
)}
</div>
</Wrapper>
);
}
<input
className="form-check-input"
defaultChecked={value}
id={name}
name={name}
onChange={handleChange}
type="checkbox"
/>
{label}
</Label>
<i className="fa fa-cog" onClick={handleClick} />
</div>
</Wrapper>
);
}
InputCheckboxPlugin.contextTypes = {

View File

@ -4,86 +4,57 @@
*
*/
import React from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { findIndex, has, includes, isEmpty, map, toLower } from 'lodash';
import PropTypes from 'prop-types';
import { findIndex, has, includes, isEmpty, map, toLower } from 'lodash';
import { Label } from 'strapi-helper-plugin';
import InputSearchLi from '../InputSearchLi';
import { Addon, List, Wrapper } from './Components';
class InputSearchContainer extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = {
errors: [],
filteredUsers: this.props.values,
isAdding: false,
isFocused: false,
users: this.props.values,
value: '',
};
function InputSearchContainer({
didDeleteUser,
label,
name,
onClickAdd,
onClickDelete,
values,
}) {
const searchInput = useRef(null);
console.log(values);
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.didDeleteUser !== this.props.didDeleteUser) {
this.setState({
users: nextProps.values,
filteredUsers: nextProps.values,
});
const [filteredUsers, setFilteredUsers] = useState(values);
const [isAdding, setIsAdding] = useState(false);
const [isFocused, setIsFocused] = useState(false);
const [errors, setErrors] = useState([]);
const [value, setValue] = useState('');
useEffect(() => {
if (values !== filteredUsers) {
setFilteredUsers(values);
}
}, [values]);
if (nextProps.didGetUsers !== this.props.didGetUsers) {
this.setState({
users: nextProps.values,
filteredUsers: nextProps.values,
});
}
const handleBlur = () => setIsFocused(prev => !prev);
if (nextProps.didFetchUsers !== this.props.didFetchUsers) {
this.setState({ filteredUsers: nextProps.users, isAdding: true });
}
}
const handleChange = () => {};
handleBlur = () => this.setState({ isFocused: !this.state.isFocused });
handleChange = ({ target }) => {
const filteredUsers = isEmpty(target.value)
? this.state.users
: this.state.users.filter(user =>
includes(toLower(user.name), toLower(target.value))
);
if (isEmpty(filteredUsers) && !isEmpty(target.value)) {
this.props.getUser(target.value);
}
if (isEmpty(target.value)) {
return this.setState({
value: target.value,
isAdding: false,
users: this.props.values,
filteredUsers: this.props.values,
});
}
this.setState({ value: target.value, filteredUsers });
};
handleFocus = () => this.setState({ isFocused: !this.state.isFocused });
handleClick = item => {
if (this.state.isAdding) {
const handleClick = item => {
console.log(item);
console.log(isAdding);
if (isAdding) {
const id = has(item, '_id') ? '_id' : 'id';
const users = this.props.values;
const users = values;
// Check if user is already associated with this role
if (findIndex(users, [id, item[id]]) === -1) {
this.props.onClickAdd(item);
onClickAdd(item);
users.push(item);
}
// Reset the input focus
this.searchInput.focus();
searchInput.focus();
// Empty the input and display users
this.setState({
value: '',
@ -92,56 +63,50 @@ class InputSearchContainer extends React.Component {
filteredUsers: users,
});
} else {
this.props.onClickDelete(item);
onClickDelete(item);
}
};
render() {
return (
<Wrapper className="col-md-6">
<Label htmlFor={this.props.name} message={this.props.label} />
<div className="input-group">
<Addon
className={`input-group-addon ${this.state.isFocused && 'focus'}`}
>
<i className="fas fa-search"></i>
</Addon>
<FormattedMessage id="users-permissions.InputSearch.placeholder">
{message => (
<input
className={`form-control ${
!isEmpty(this.state.errors) ? 'is-invalid' : ''
}`}
id={this.props.name}
name={this.props.name}
onBlur={this.handleBlur}
onChange={this.handleChange}
onFocus={this.handleFocus}
value={this.state.value}
placeholder={message}
type="text"
ref={input => {
this.searchInput = input;
}}
/>
)}
</FormattedMessage>
</div>
<List className={this.state.isFocused && 'focused'}>
<ul>
{map(this.state.filteredUsers, user => (
<InputSearchLi
key={user.id || user._id}
item={user}
isAdding={this.state.isAdding}
onClick={this.handleClick}
/>
))}
</ul>
</List>
</Wrapper>
);
}
const handleFocus = () => setIsFocused(prev => !prev);
return (
<Wrapper className="col-md-6">
<Label htmlFor={name} message={label} />
<div className="input-group">
<Addon className={`input-group-addon ${isFocused && 'focus'}`}>
<i className="fas fa-search"></i>
</Addon>
<FormattedMessage id="users-permissions.InputSearch.placeholder">
{message => (
<input
className={`form-control ${!isEmpty(errors) ? 'is-invalid' : ''}`}
id={name}
name={name}
onBlur={handleBlur}
onChange={handleChange}
onFocus={handleFocus}
value={value}
placeholder={message}
type="text"
ref={searchInput}
/>
)}
</FormattedMessage>
</div>
<List className={isFocused && 'focused'}>
<ul>
{map(filteredUsers, user => (
<InputSearchLi
key={user.id || user._id}
item={user}
isAdding={isAdding}
onClick={handleClick}
/>
))}
</ul>
</List>
</Wrapper>
);
}
InputSearchContainer.defaultProps = {

View File

@ -0,0 +1,168 @@
/**
*
* InputSearchContainer
*
*/
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { findIndex, has, includes, isEmpty, map, toLower } from 'lodash';
import PropTypes from 'prop-types';
import { Label } from 'strapi-helper-plugin';
import InputSearchLi from '../InputSearchLi';
import { Addon, List, Wrapper } from './Components';
class InputSearchContainer extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = {
errors: [],
filteredUsers: this.props.values,
isAdding: false,
isFocused: false,
users: this.props.values,
value: '',
};
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.didDeleteUser !== this.props.didDeleteUser) {
this.setState({
users: nextProps.values,
filteredUsers: nextProps.values,
});
}
if (nextProps.didGetUsers !== this.props.didGetUsers) {
this.setState({
users: nextProps.values,
filteredUsers: nextProps.values,
});
}
if (nextProps.didFetchUsers !== this.props.didFetchUsers) {
this.setState({ filteredUsers: nextProps.users, isAdding: true });
}
}
handleBlur = () => this.setState({ isFocused: !this.state.isFocused });
handleChange = ({ target }) => {
const filteredUsers = isEmpty(target.value)
? this.state.users
: this.state.users.filter(user =>
includes(toLower(user.name), toLower(target.value))
);
if (isEmpty(filteredUsers) && !isEmpty(target.value)) {
this.props.getUser(target.value);
}
if (isEmpty(target.value)) {
return this.setState({
value: target.value,
isAdding: false,
users: this.props.values,
filteredUsers: this.props.values,
});
}
this.setState({ value: target.value, filteredUsers });
};
handleFocus = () => this.setState({ isFocused: !this.state.isFocused });
handleClick = item => {
if (this.state.isAdding) {
const id = has(item, '_id') ? '_id' : 'id';
const users = this.props.values;
// Check if user is already associated with this role
if (findIndex(users, [id, item[id]]) === -1) {
this.props.onClickAdd(item);
users.push(item);
}
// Reset the input focus
this.searchInput.focus();
// Empty the input and display users
this.setState({
value: '',
isAdding: false,
users,
filteredUsers: users,
});
} else {
this.props.onClickDelete(item);
}
};
render() {
return (
<Wrapper className="col-md-6">
<Label htmlFor={this.props.name} message={this.props.label} />
<div className="input-group">
<Addon
className={`input-group-addon ${this.state.isFocused && 'focus'}`}
>
<i className="fas fa-search"></i>
</Addon>
<FormattedMessage id="users-permissions.InputSearch.placeholder">
{message => (
<input
className={`form-control ${
!isEmpty(this.state.errors) ? 'is-invalid' : ''
}`}
id={this.props.name}
name={this.props.name}
onBlur={this.handleBlur}
onChange={this.handleChange}
onFocus={this.handleFocus}
value={this.state.value}
placeholder={message}
type="text"
ref={input => {
this.searchInput = input;
}}
/>
)}
</FormattedMessage>
</div>
<List className={this.state.isFocused && 'focused'}>
<ul>
{map(this.state.filteredUsers, user => (
<InputSearchLi
key={user.id || user._id}
item={user}
isAdding={this.state.isAdding}
onClick={this.handleClick}
/>
))}
</ul>
</List>
</Wrapper>
);
}
}
InputSearchContainer.defaultProps = {
users: [],
values: [],
};
InputSearchContainer.propTypes = {
didDeleteUser: PropTypes.bool.isRequired,
didFetchUsers: PropTypes.bool.isRequired,
didGetUsers: PropTypes.bool.isRequired,
getUser: PropTypes.func.isRequired,
label: PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}).isRequired,
name: PropTypes.string.isRequired,
onClickAdd: PropTypes.func.isRequired,
onClickDelete: PropTypes.func.isRequired,
users: PropTypes.array,
values: PropTypes.array,
};
export default InputSearchContainer;

View File

@ -10,16 +10,17 @@ import PropTypes from 'prop-types';
import { Wrapper } from './Components';
function InputSearchLi({ onClick, isAdding, item }) {
const { id, username } = item;
const icon = isAdding ? 'fa-plus' : 'fa-minus-circle';
const liStyle = isAdding ? { cursor: 'pointer' } : {};
const handleClick = isAdding ? () => onClick(item) : () => {};
const path = `/admin/plugins/content-manager/user/${item.id}?redirectUrl=/plugins/content-manager/user/?page=1&limit=20&sort=id&source=users-permissions`;
const path = `/admin/plugins/content-manager/user/${id}?redirectUrl=/plugins/content-manager/user/?page=1&limit=20&sort=id&source=users-permissions`;
return (
<Wrapper style={liStyle} onClick={handleClick}>
<div>
<div>
{item.username}
{username}
<a href={`${path}`} target="_blank" rel="noopener noreferrer">
<i className="fa fa-external-link" />
</a>
@ -40,7 +41,8 @@ function InputSearchLi({ onClick, isAdding, item }) {
InputSearchLi.defaultProps = {
item: {
name: '',
id: null,
username: null,
},
};

View File

@ -9,13 +9,11 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { map, omitBy, size } from 'lodash';
// Components from strapi-helper-plugin
import { Button, LoadingBar, LoadingIndicator } from 'strapi-helper-plugin';
import { Flex, ListWrapper, Title, Wrapper } from './Components';
import ListRow from '../ListRow';
import { Flex, ListWrapper, Title, Wrapper } from './Components';
const generateListTitle = (data, settingType) => {
switch (settingType) {
case 'roles': {

View File

@ -9,13 +9,11 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { capitalize, get, includes } from 'lodash';
// Design
import { IcoContainer, PopUpWarning } from 'strapi-helper-plugin';
import { Container, Flex, Row, Wrapper } from './Components';
import en from '../../translations/en.json';
import { Container, Flex, Row, Wrapper } from './Components';
class ListRow extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { showModalDelete: false };