Design EditPage top block, started design inputSearch and add change dynamic

This commit is contained in:
cyril lopez 2017-11-07 16:33:15 +01:00
parent 9c65e2824e
commit c720955269
13 changed files with 357 additions and 36 deletions

View File

@ -0,0 +1,60 @@
/**
*
* InputSearch
*
*/
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { isEmpty } from 'lodash';
import cn from 'classnames';
import PropTypes from 'prop-types';
import styles from './styles.scss';
class InputSearch extends React.Component { // eslint-disable-line react/prefer-stateless-function
state = { errors: [] };
render() {
return (
<div className={cn(styles.inputSearch, 'col-md-6')}>
<label htmlFor={this.props.name}>
<FormattedMessage id={this.props.label} values={this.props.labelValues} />
</label>
<div className={cn('input-group')}>
<span className={cn('input-group-addon', styles.addon)} />
<FormattedMessage id="users-permissions.InputSearch.placeholder">
{(message) => (
<input
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}
placeholder={message}
type="text"
/>
)}
</FormattedMessage>
</div>
</div>
);
}
}
InputSearch.defaultProps = {
labelValues: {
number: 0,
},
value: '',
}
InputSearch.proptypes = {
label: PropTypes.string.isRequired,
labelValues: PropTypes.object,
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
value: PropTypes.string,
};
export default InputSearch;

View File

@ -0,0 +1,45 @@
.addon {
width: 3.2rem;
height: 3.4rem;
margin-top: .9rem;
background-color: rgba(16, 22, 34, 0.02);
border: 1px solid #E3E9F3;
border-radius: 0.25rem;
color: rgba(16, 22, 34, 0.5);
line-height: 3.2rem;
font-size: 1.3rem;
font-family: 'Lato';
font-weight: 600!important;
text-transform: capitalize;
-moz-appearance: none;
-webkit-appearance: none;
&:before {
content: '\f002';
display: inline-table;
font-family: 'FontAwesome';
}
}
.inputSearch {
min-width: 200px;
margin-bottom: 1.5rem;
font-size: 1.3rem;
label {
margin-bottom: 0;
font-weight: 500;
text-transform: capitalize;
}
input {
height: 3.4rem;
margin-top: .9rem;
padding-left: 1rem;
background-size: 0 !important;
border: 1px solid #E3E9F3;
border-radius: 0.25rem;
line-height: 3.4rem;
font-size: 1.3rem;
font-family: 'Lato' !important;
}
}

View File

@ -7,6 +7,7 @@
import React from 'react';
import cn from 'classnames';
import PropTypes from 'prop-types';
import { router } from 'app';
// Design
import IcoContainer from 'components/IcoContainer';
@ -23,13 +24,11 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
}
}
handleDelete = () => this.props.deleteData(this.props.item, this.props.settingType);
generateContent = () => {
let icons = [
{
icoType: 'pencil',
onClick: () => { console.log('edit') },
onClick: this.handleClick,
},
{
icoType: 'trash',
@ -90,7 +89,7 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
icons = [
{
icoType: 'pencil',
onClick: () => { console.log('edit') },
onClick: this.handleClick,
},
];
@ -117,9 +116,23 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
}
}
handleClick = () => {
switch (this.props.settingType) {
case 'roles':
return router.push(`${router.location.pathname}/${this.props.item.id}`);
case 'providers':
case 'email-templates':
return console.log('click');
default:
return;
}
}
handleDelete = () => this.props.deleteData(this.props.item, this.props.settingType);
render() {
return (
<li className={styles.li}>
<li className={styles.li} onClick={this.handleClick}>
<div className={styles.container}>
{this.generateContent()}
</div>

View File

@ -27,6 +27,12 @@ class App extends React.Component {
}
}
componentDidUpdate() {
if (!this.props.location.pathname.split('/')[3]) {
this.props.history.push('/plugins/users-permissions/roles');
}
}
render() {
return (
<div className={pluginId}>

View File

@ -5,11 +5,20 @@
*/
import {
DEFAULT_ACTION,
ON_CANCEL,
ON_CHANGE_INPUT,
} from './constants';
export function defaultAction() {
export function onCancel() {
return {
type: DEFAULT_ACTION,
type: ON_CANCEL,
};
}
export function onChangeInput({ target }) {
return {
type: ON_CHANGE_INPUT,
key: target.name,
value: target.value,
};
}

View File

@ -4,4 +4,5 @@
*
*/
export const DEFAULT_ACTION = 'UsersPermissions/EditPage/DEFAULT_ACTION';
export const ON_CANCEL = 'UsersPermissions/EditPage/ON_CANCEL';
export const ON_CHANGE_INPUT = 'UsersPermissions/EditPage/ON_CHANGE_INPUT';

View File

@ -5,42 +5,150 @@
*/
import React from 'react';
// import PropTypes from 'prop-types';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Helmet } from 'react-helmet';
import { createStructuredSelector } from 'reselect';
import { bindActionCreators, compose } from 'redux';
import { FormattedMessage } from 'react-intl';
import { get } from 'lodash';
import cn from 'classnames';
// Design
import BackHeader from 'components/BackHeader';
import Input from 'components/Input';
import InputSearch from 'components/InputSearch';
import PluginHeader from 'components/PluginHeader';
import injectSaga from 'utils/injectSaga';
import injectReducer from 'utils/injectReducer';
// Actions
import {
onCancel,
onChangeInput,
} from './actions';
// Selectors
import makeSelectEditPage from './selectors';
import reducer from './reducer';
import saga from './saga';
import styles from './styles.scss';
export class EditPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
pluginHeaderActions = [
{
label: 'users-permissions.EditPage.cancel',
kind: 'secondary',
onClick: this.props.onCancel,
type: 'button',
},
{
kind: 'primary',
label: 'users-permissions.EditPage.submit',
onClick: () => console.log('submit'),
type: 'submit',
},
];
render() {
const pluginHeaderTitle = this.props.match.params.id === 'create' ?
'users-permissions.EditPage.header.title.create'
: 'users-permissions.EditPage.header.title';
const pluginHeaderDescription = this.props.match.params.id === 'create' ?
'users-permissions.EditPage.header.description.create'
: 'users-permissions.EditPage.header.description';
const pluginHeaderActions = this.props.editPage.showButtons ? this.pluginHeaderActions : [];
return (
<div>
<Helmet>
<title>EditPage</title>
<meta name="description" content="Description of EditPage" />
</Helmet>
<BackHeader onClick={() => this.props.history.goBack()} />
<div className={cn('container-fluid', styles.containerFluid)}>
<PluginHeader
title={{
id: pluginHeaderTitle,
values: {
name: '',
},
}}
description={{
id: pluginHeaderDescription,
values: {
description: '',
},
}}
actions={pluginHeaderActions}
/>
<div className="row">
<div className="col-md-12">
<div className={styles.main_wrapper}>
<div className={styles.titleContainer}>
<FormattedMessage id="users-permissions.EditPage.form.roles" />
</div>
<form className={styles.form}>
<div className="row">
<div className="col-md-6">
<div className="row">
<Input
customBootstrapClass="col-md-12"
label="users-permissions.EditPage.form.roles.label.name"
name="name"
onChange={this.props.onChangeInput}
type="text"
validations={{ required: true }}
value={get(this.props.editPage, ['modifiedData', 'name'])}
/>
</div>
<div className="row">
<Input
customBootstrapClass="col-md-12"
label="users-permissions.EditPage.form.roles.label.description"
name="description"
onChange={this.props.onChangeInput}
type="textarea"
validations={{ required: true }}
value={get(this.props.editPage, ['modifiedData', 'description'])}
/>
</div>
</div>
<InputSearch
label="users-permissions.EditPage.form.roles.label.users"
labelValues={{ number: 0 }}
onChange={() => console.log('change')}
type="text"
validations={{ required: true }}
value=""
name="users"
/>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
}
EditPage.propTypes = {
history: PropTypes.object.isRequired,
onCancel: PropTypes.func.isRequired,
onChangeInput: PropTypes.func.isRequired,
};
const mapStateToProps = createStructuredSelector({
editpage: makeSelectEditPage(),
editPage: makeSelectEditPage(),
});
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{},
dispatch
{
onCancel,
onChangeInput,
},
dispatch,
);
}

View File

@ -4,17 +4,36 @@
*
*/
import { fromJS } from 'immutable';
import { fromJS, List, Map } from 'immutable';
import {
DEFAULT_ACTION,
ON_CANCEL,
ON_CHANGE_INPUT,
} from './constants';
const initialState = fromJS({});
const initialState = fromJS({
initialData: Map({
name: '',
description: '',
users: List([]),
}),
modifiedData: Map({
name: '',
description: '',
users: List([]),
}),
showButtons: false,
});
function editPageReducer(state = initialState, action) {
switch (action.type) {
case DEFAULT_ACTION:
return state;
case ON_CANCEL:
return state
.set('showButtons', false)
.set('modifiedData', state.get('initialData'));
case ON_CHANGE_INPUT:
return state
.set('showButtons', true)
.setIn(['modifiedData', action.key], action.value);
default:
return state;
}

View File

@ -0,0 +1,20 @@
.containerFluid {
padding: 18px 30px;
}
.form {
padding-top: 2rem;
}
.main_wrapper{
background: #ffffff;
padding: 22px 10px;
border-radius: 2px;
box-shadow: 0 2px 4px #E3E9F3;
}
.titleContainer {
font-size: 18px;
font-weight: bold;
line-height: 18px;
}

View File

@ -3,58 +3,69 @@
{
"name": "Owner",
"description": "Rule them all. This role can't be deleted",
"nb_users": 1
"nb_users": 1,
"id": 1
},
{
"name": "Administrator",
"description": "Full access to everything",
"nb_users": 3
"nb_users": 3,
"id": 2
},
{
"name": "Moderator",
"description": "Allow editing and deleting (except users)",
"nb_users": 12
"nb_users": 12,
"id": 3
},
{
"name": "Editor",
"description": "Allow creating and editing your entries",
"nb_users": 429
"nb_users": 429,
"id": 4
}
],
"providers": [
{
"name": "email",
"enabled": true,
"ico": "envelope"
"ico": "envelope",
"id": 1
},
{
"name": "facebook",
"enabled": false,
"ico": "facebook"
"ico": "facebook",
"id": 2
},
{
"name": "twitter",
"enabled": true,
"ico": "twitter"
"ico": "twitter",
"id": 3
},
{
"name": "google",
"enabled": false,
"ico": "google"
"ico": "google",
"id": 4
}
],
"email-templates": [
{
"name": "Email address validation",
"ico": "envelope"
"ico": "envelope",
"id": 1
},
{
"name": "Reset password",
"ico": "refresh"
"ico": "refresh",
"id": 2
},
{
"name": "Successfull sign-in",
"ico": "check"
"ico": "check",
"id": 3
}
]
}

View File

@ -47,16 +47,19 @@ export class HomePage extends React.Component {
}
}
onButtonClick = () => this.props.history.push(`${this.props.location.pathname}/create`);
render() {
const noButtonList = this.props.match.params.settingType === 'email-templates';
const component = this.props.match.params.settingType === 'advanced-settings' ?
<div>coucou</div> :
<List
data={this.props.data}
settingType={this.props.match.params.settingType}
noButton={noButtonList}
deleteActionSucceeded={this.props.deleteActionSucceeded}
deleteData={this.props.deleteData}
noButton={noButtonList}
onButtonClick={this.onButtonClick}
settingType={this.props.match.params.settingType}
/>;
return (
<div>

View File

@ -1,4 +1,15 @@
{
"EditPage.cancel": "Cancel",
"EditPage.submit": "Save",
"EditPage.form.roles": "Roles details",
"EditPage.form.roles.label.description": "Description",
"EditPage.form.roles.label.name": "Name",
"EditPage.form.roles.label.users": "Users associated with this role ({number})",
"EditPage.header.title": "{name}",
"EditPage.header.title.create": "Create a new role",
"EditPage.header.description": "{description}",
"EditPage.header.description.create": " ",
"HeaderNav.link.advancedSettings": "Advanced settings",
"HeaderNav.link.emailTemplates": "Email templates",
"HeaderNav.link.providers": "Providers",
@ -7,6 +18,8 @@
"HomePage.header.title": "Auth & Permissions",
"HomePage.header.description": "Define the roles and permissions for every one of them",
"InputSearch.placeholder": "Search for a user",
"List.button.roles": "Add a New Role",
"List.button.providers": "Add a New Provider",

View File

@ -1,4 +1,15 @@
{
"EditPage.cancel": "Cancel",
"EditPage.submit": "Sauvegarder",
"EditPage.form.roles": "Rôles détails",
"EditPage.form.roles.label.description": "Description",
"EditPage.form.roles.label.name": "Nom",
"EditPage.form.roles.label.users": "Utilisateurs associés avec ce rôle ({number})",
"EditPage.header.title": "{name}",
"EditPage.header.title.create": "Créez un nouveau rôle",
"EditPage.header.description": "{description}",
"EditPage.header.description.create": " ",
"HeaderNav.link.advancedSettings": "Paramètres avancés",
"HeaderNav.link.emailTemplates": "Templates d'email",
"HeaderNav.link.providers": "Fournisseurs",
@ -7,6 +18,8 @@
"HomePage.header.title": "Auth & Permissions",
"HomePage.header.description": "Définissez les rôles et permissions pour chacun d'eux",
"InputSearch.placeholder": "Recherez un utilisateur",
"List.button.roles": "Ajouter un Nouveau Rôle",
"List.button.providers": "Ajouter Un Nouveau Provider",