mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 07:03:38 +00:00
Design InputSearch ul and handle delete user dynamic
This commit is contained in:
parent
c720955269
commit
42bbf2b852
@ -6,14 +6,33 @@
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { includes, isEmpty, map, toLower } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import InputSearchLi from 'components/InputSearchLi';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
class InputSearch extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
state = { errors: [] };
|
||||
state = { errors: [], value: '', users: this.props.values, filteredUsers: this.props.values };
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.didDeleteUser !== this.props.didDeleteUser) {
|
||||
this.setState({ users: nextProps.values, filteredUsers: nextProps.values });
|
||||
}
|
||||
}
|
||||
|
||||
handleChange = ({ target }) => {
|
||||
const filteredUsers = isEmpty(target.value) ?
|
||||
this.state.users
|
||||
: this.state.users.filter((user) => {
|
||||
if (includes(toLower(user.name), toLower(target.value))) {
|
||||
return user;
|
||||
}
|
||||
});
|
||||
this.setState({ value: target.value, filteredUsers });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
@ -29,14 +48,21 @@ class InputSearch extends React.Component { // eslint-disable-line react/prefer-
|
||||
className={cn('form-control', !isEmpty(this.state.errors) ? 'is-invalid': '')}
|
||||
id={this.props.name}
|
||||
name={this.props.name}
|
||||
onChange={this.props.onChange}
|
||||
value={this.props.value}
|
||||
onChange={this.handleChange}
|
||||
value={this.state.value}
|
||||
placeholder={message}
|
||||
type="text"
|
||||
/>
|
||||
)}
|
||||
</FormattedMessage>
|
||||
</div>
|
||||
<div className={styles.ulContainer}>
|
||||
<ul>
|
||||
{map(this.state.filteredUsers, (user) => (
|
||||
<InputSearchLi key={user.name} item={user} onClickDelete={this.props.onClickDelete} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -54,6 +80,7 @@ InputSearch.proptypes = {
|
||||
labelValues: PropTypes.object,
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onClickDelete: PropTypes.func.isRequired,
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
background-color: rgba(16, 22, 34, 0.02);
|
||||
border: 1px solid #E3E9F3;
|
||||
border-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0;
|
||||
color: rgba(16, 22, 34, 0.5);
|
||||
line-height: 3.2rem;
|
||||
font-size: 1.3rem;
|
||||
@ -38,8 +39,23 @@
|
||||
background-size: 0 !important;
|
||||
border: 1px solid #E3E9F3;
|
||||
border-radius: 0.25rem;
|
||||
border-bottom-right-radius: 0;
|
||||
line-height: 3.4rem;
|
||||
font-size: 1.3rem;
|
||||
font-family: 'Lato' !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ulContainer {
|
||||
height: 16.3rem;
|
||||
overflow: scroll;
|
||||
border: 1px solid #E3E9F3;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-top: none;
|
||||
border-radius: 0.25rem;
|
||||
> ul {
|
||||
list-style: none;
|
||||
padding: 1px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
/**
|
||||
*
|
||||
* InputSearchLi
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './styles.scss';
|
||||
|
||||
function InputSearchLi({ item, onClickDelete }) {
|
||||
return (
|
||||
<li className={styles.li}>
|
||||
<div>
|
||||
<div>
|
||||
{item.name}
|
||||
</div>
|
||||
<div onClick={() => onClickDelete(item)}>
|
||||
<i className="fa fa-minus-circle" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
InputSearchLi.defaultProps = {
|
||||
item: {
|
||||
name: '',
|
||||
}
|
||||
}
|
||||
|
||||
InputSearchLi.proptypes = {
|
||||
item: PropTypes.object,
|
||||
onClickDelete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default InputSearchLi;
|
||||
@ -0,0 +1,29 @@
|
||||
.li {
|
||||
height: 3.6rem;
|
||||
margin: 0 !important;
|
||||
padding: 0rem 1rem;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 3.6rem;
|
||||
border-bottom: 1px solid #F6F6F6;
|
||||
&:hover {
|
||||
background-color: #FAFAFB;
|
||||
background-size: 3.6rem;
|
||||
> div {
|
||||
>div:last-child {
|
||||
color: #4B515A;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
> div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> div:last-child {
|
||||
color: #B3B5B9;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,10 +5,19 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
ADD_USER,
|
||||
ON_CANCEL,
|
||||
ON_CHANGE_INPUT,
|
||||
ON_CLICK_DELETE,
|
||||
} from './constants';
|
||||
|
||||
export function addUser(newUser) {
|
||||
return {
|
||||
type: ADD_USER,
|
||||
newUser,
|
||||
};
|
||||
}
|
||||
|
||||
export function onCancel() {
|
||||
return {
|
||||
type: ON_CANCEL,
|
||||
@ -22,3 +31,10 @@ export function onChangeInput({ target }) {
|
||||
value: target.value,
|
||||
};
|
||||
}
|
||||
|
||||
export function onClickDelete(itemToDelete) {
|
||||
return {
|
||||
type: ON_CLICK_DELETE,
|
||||
itemToDelete,
|
||||
};
|
||||
}
|
||||
|
||||
@ -4,5 +4,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
export const ADD_USER = 'UsersPermissions/EditPage/ADD_USER';
|
||||
export const ON_CANCEL = 'UsersPermissions/EditPage/ON_CANCEL';
|
||||
export const ON_CHANGE_INPUT = 'UsersPermissions/EditPage/ON_CHANGE_INPUT';
|
||||
export const ON_CLICK_DELETE = 'UsersPermissions/EditPage/ON_CLICK_DELETE';
|
||||
|
||||
@ -10,7 +10,7 @@ import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { get } from 'lodash';
|
||||
import { get, size } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
|
||||
// Design
|
||||
@ -24,8 +24,10 @@ import injectReducer from 'utils/injectReducer';
|
||||
|
||||
// Actions
|
||||
import {
|
||||
addUser,
|
||||
onCancel,
|
||||
onChangeInput,
|
||||
onClickDelete,
|
||||
} from './actions';
|
||||
|
||||
// Selectors
|
||||
@ -61,6 +63,7 @@ export class EditPage extends React.Component { // eslint-disable-line react/pre
|
||||
: 'users-permissions.EditPage.header.description';
|
||||
|
||||
const pluginHeaderActions = this.props.editPage.showButtons ? this.pluginHeaderActions : [];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<BackHeader onClick={() => this.props.history.goBack()} />
|
||||
@ -113,13 +116,15 @@ export class EditPage extends React.Component { // eslint-disable-line react/pre
|
||||
</div>
|
||||
</div>
|
||||
<InputSearch
|
||||
addUser={this.props.addUser}
|
||||
didDeleteUser={this.props.editPage.didDeleteUser}
|
||||
label="users-permissions.EditPage.form.roles.label.users"
|
||||
labelValues={{ number: 0 }}
|
||||
onChange={() => console.log('change')}
|
||||
labelValues={{ number: size(get(this.props.editPage, ['modifiedData', 'users'])) }}
|
||||
type="text"
|
||||
validations={{ required: true }}
|
||||
value=""
|
||||
values={get(this.props.editPage, ['modifiedData', 'users'])}
|
||||
name="users"
|
||||
onClickDelete={this.props.onClickDelete}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
@ -133,9 +138,11 @@ export class EditPage extends React.Component { // eslint-disable-line react/pre
|
||||
}
|
||||
|
||||
EditPage.propTypes = {
|
||||
addUser: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onChangeInput: PropTypes.func.isRequired,
|
||||
onClickDelete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@ -145,8 +152,10 @@ const mapStateToProps = createStructuredSelector({
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{
|
||||
addUser,
|
||||
onCancel,
|
||||
onChangeInput,
|
||||
onClickDelete,
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
||||
@ -6,34 +6,55 @@
|
||||
|
||||
import { fromJS, List, Map } from 'immutable';
|
||||
import {
|
||||
ADD_USER,
|
||||
ON_CANCEL,
|
||||
ON_CHANGE_INPUT,
|
||||
ON_CLICK_DELETE,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
didDeleteUser: false,
|
||||
initialData: Map({
|
||||
name: '',
|
||||
description: '',
|
||||
users: List([]),
|
||||
users: List([
|
||||
{ name: 'Pierre Burgy' },
|
||||
{ name: 'Jim Laurie' },
|
||||
{ name: 'Aurelien Georget' },
|
||||
{ name: 'Cyril Lopez' },
|
||||
]),
|
||||
}),
|
||||
modifiedData: Map({
|
||||
name: '',
|
||||
description: '',
|
||||
users: List([]),
|
||||
users: List([
|
||||
{ name: 'Pierre Burgy' },
|
||||
{ name: 'Jim Laurie' },
|
||||
{ name: 'Aurelien Georget' },
|
||||
{ name: 'Cyril Lopez' },
|
||||
]),
|
||||
}),
|
||||
showButtons: false,
|
||||
});
|
||||
|
||||
function editPageReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case ADD_USER:
|
||||
return state.updateIn(['modifiedData', 'users'], list => list.push(action.newUser));
|
||||
case ON_CANCEL:
|
||||
return state
|
||||
.set('showButtons', false)
|
||||
.set('didDeleteUser', !state.get('didDeleteUser'))
|
||||
.set('modifiedData', state.get('initialData'));
|
||||
case ON_CHANGE_INPUT:
|
||||
return state
|
||||
.set('showButtons', true)
|
||||
.setIn(['modifiedData', action.key], action.value);
|
||||
case ON_CLICK_DELETE:
|
||||
return state
|
||||
.set('didDeleteUser', !state.get('didDeleteUser'))
|
||||
.set('showButtons', true)
|
||||
.updateIn(['modifiedData', 'users'], list => list.filter(o => o.name !== action.itemToDelete.name));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user