# HG changeset patch # User ymh # Date 1501774380 -7200 # Node ID be36eed5e6e024eb65df278ae164234e21b66290 # Parent 6f3078f7fd47da7d656873da3e32fdc0d8e6f090 add menu to change current group and create a new group diff -r 6f3078f7fd47 -r be36eed5e6e0 client/src/actions/groupActions.js --- a/client/src/actions/groupActions.js Thu Aug 03 09:44:37 2017 +0200 +++ b/client/src/actions/groupActions.js Thu Aug 03 17:33:00 2017 +0200 @@ -15,3 +15,16 @@ export const groupLoadAsync = () => ({ type: types.GROUP_LOAD_ASYNC }); + +export const groupSetCurrent = (groupName) => + ({ type: types.GROUP_SET_GROUP, group: groupName }); + +export const createGroup = (name, description) => { + return { + type: types.GROUP_CREATE_ASYNC, + group: { + name, + description + } + }; +} diff -r 6f3078f7fd47 -r be36eed5e6e0 client/src/api/APIClient.js --- a/client/src/api/APIClient.js Thu Aug 03 09:44:37 2017 +0200 +++ b/client/src/api/APIClient.js Thu Aug 03 17:33:00 2017 +0200 @@ -1,4 +1,5 @@ import qs from 'qs'; +import { getToken, getClientId } from '../selectors/authSelectors' class APIClient { constructor(baseURL) { @@ -40,12 +41,12 @@ getToken = () => { const state = this.store.getState(); - return state.getIn(['authStatus', 'token']); + return getToken(state); } getClientId = () => { const state = this.store.getState(); - return state.getIn(['authStatus', 'clientId']); + return getClientId(state); } hasToken = () => { diff -r 6f3078f7fd47 -r be36eed5e6e0 client/src/components/CreateGroup.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/CreateGroup.js Thu Aug 03 17:33:00 2017 +0200 @@ -0,0 +1,124 @@ +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { Grid, Row, Col, Panel, FormGroup, ControlLabel, FormControl, Button, Alert, HelpBlock } from 'react-bootstrap'; +import '../App.css'; +import Navbar from './Navbar'; +import * as authActions from '../actions/authActions'; +import { getOnline, getCreateGroup } from '../selectors/authSelectors'; + +class CreateGroup extends Component { + + state = { + name: '', + description: '' + } + + createGroup = () => { + + const { name, description } = this.state; + + if(name && name.trim() !== "") { + this.props.authActions.createGroup(name, description); + } + } + + submit = (e) => { + e.preventDefault(); + + this.createGroup(); + } + + handleInputChange = (e) => { + const target = e.target; + const value = target.value; + const name = target.name; + + this.setState({ + [name]: value + }); + } + + renderErrorMessage(errorMessages, fieldname) { + if (errorMessages && fieldname in errorMessages) { + return errorMessages[fieldname].map((message, key) => + { message } + ); + } + } + + renderNonFieldErrors(errorMessages) { + if (errorMessages && 'non_field_errors' in errorMessages) { + const errors = errorMessages['non_field_errors']; + return ( + + { errors.map((message, key) => +

{ message }

+ ) } +
+ ) + } + } + + cancel = (e) => { + e.preventDefault(); + this.props.history.push('/sessions'); + } + + + render() { + + const panelHeader = ( +

Créer un groupe

+ ) + + const errorMessages = this.props.createGroup.getIn(['errorMessages', 'data']); + const okDisabled = (!this.state.name || this.state.name.trim() === ""); + + return ( +
+ + + + + +
+ + Nom + + { this.renderErrorMessage(errorMessages, 'name') } + + + Password + + { this.renderErrorMessage(errorMessages, 'description') } + + { this.renderNonFieldErrors(errorMessages) } + + + + +
+
+ +
+
+
+ ); + } +} + +function mapStateToProps(state, props) { + return { + createGroup: getCreateGroup(state), + online: getOnline(state), + }; +} + +function mapDispatchToProps(dispatch) { + return { + authActions: bindActionCreators(authActions, dispatch), + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(CreateGroup); diff -r 6f3078f7fd47 -r be36eed5e6e0 client/src/components/GroupForm.js --- a/client/src/components/GroupForm.js Thu Aug 03 09:44:37 2017 +0200 +++ b/client/src/components/GroupForm.js Thu Aug 03 17:33:00 2017 +0200 @@ -4,6 +4,7 @@ import { FormGroup, FormControl, Button, InputGroup, HelpBlock, Glyphicon } from 'react-bootstrap'; import * as authActions from '../actions/authActions'; import * as sessionsActions from '../actions/sessionsActions'; +import { getOnline, getCreateGroup } from '../selectors/authSelectors'; class GroupForm extends Component { @@ -91,8 +92,8 @@ function mapStateToProps(state, props) { return { - createGroup: state.get('createGroup'), - online: state.getIn(['status', 'online']), + createGroup: getCreateGroup(state), + online: getOnline(state), }; } diff -r 6f3078f7fd47 -r be36eed5e6e0 client/src/components/Login.js --- a/client/src/components/Login.js Thu Aug 03 09:44:37 2017 +0200 +++ b/client/src/components/Login.js Thu Aug 03 17:33:00 2017 +0200 @@ -8,9 +8,24 @@ class Login extends Component { + state = { + username: '', + password: '' + } + + handleInputChange = (e) => { + const target = e.target; + const value = target.value; + const name = target.name; + + this.setState({ + [name]: value + }); + } + + login = () => { - const username = this.username.value; - const password = this.password.value; + const { username, password } = this.state; this.props.authActions.loginSubmit(username, password); } @@ -65,12 +80,12 @@
Username - { this.username = ref; }} /> + { this.renderErrorMessage(errorMessages, 'username') } Password - { this.password = ref; }} /> + { this.renderErrorMessage(errorMessages, 'password') } { this.renderNonFieldErrors(errorMessages) } diff -r 6f3078f7fd47 -r be36eed5e6e0 client/src/components/Navbar.js --- a/client/src/components/Navbar.js Thu Aug 03 09:44:37 2017 +0200 +++ b/client/src/components/Navbar.js Thu Aug 03 17:33:00 2017 +0200 @@ -7,7 +7,9 @@ import { Navbar, Nav, NavItem, NavDropdown, MenuItem, Modal, Button } from 'react-bootstrap'; import * as authActions from '../actions/authActions'; import { forceSync } from '../actions/networkActions'; -import { ActionEnum } from '../constants'; +import { groupSetCurrent } from '../actions/groupActions'; +import { isAuthenticated, getCurrentUser, getOnline, getCurrentGroup, getGroups } from '../selectors/authSelectors'; +import { isSynchronizing, isSynchronized } from '../selectors/syncSelectors'; import './Navbar.css'; const LoginNav = ({isAuthenticated, currentUser, history, authActions, onLogout}) => { @@ -63,6 +65,27 @@ ) } +const GroupStatus = ({currentGroup, groups, onSelect}) => { + + if(currentGroup) { + const currentGroupName = currentGroup.get('name'); + return ( + + { groups && groups.map((group, key) => { + const groupName = group.get('name'); + const className = (groupName === currentGroupName)?'active':null; + return { groupName } + } + )} + Créer un groupe... + + ) + } else { + return null; + } + +} + class AppNavbar extends Component { state = { @@ -116,6 +139,14 @@ this.props.networkActions.forceSync(); } + onGroupSelect = (groupName) => { + if(groupName === "__create_group__") { + this.props.history.push('/create-group'); + } else { + this.props.groupActions.groupSetCurrent(groupName); + } + } + render() { return ( @@ -130,6 +161,7 @@ Sessions