Add group dropdown, update session after group creation.
authorAlexandre Segura <mex.zktk@gmail.com>
Wed, 28 Jun 2017 12:54:48 +0200
changeset 101 e165aa89ac82
parent 100 6fd752d98933
child 102 b0e36664f1f2
Add group dropdown, update session after group creation.
client/src/actions/sessionsActions.js
client/src/components/SessionForm.js
client/src/constants/actionTypes.js
client/src/reducers/authReducer.js
client/src/sagas/groupSaga.js
client/src/store/configureStore.js
client/src/store/sessionRecord.js
src/notes/api/views/auth.py
--- a/client/src/actions/sessionsActions.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/actions/sessionsActions.js	Wed Jun 28 12:54:48 2017 +0200
@@ -69,3 +69,15 @@
     type: types.LOAD_SESSIONS
   }
 }
+
+export const createGroupAndUpdateSession = (session, name) => {
+  const group = {
+    name
+  };
+
+  return {
+    type: types.GROUP_CREATE_AND_UPDATE_ASYNC,
+    session,
+    group,
+  };
+}
--- a/client/src/components/SessionForm.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/components/SessionForm.js	Wed Jun 28 12:54:48 2017 +0200
@@ -22,7 +22,7 @@
   onClickCreateGroup = (e) => {
     e.preventDefault();
     const groupName = this.groupName.value;
-    this.props.authActions.createGroup(groupName);
+    this.props.sessionsActions.createGroupAndUpdateSession(this.props.currentSession, groupName);
   }
 
   onChange = (e) => {
@@ -35,6 +35,19 @@
     this.props.sessionsActions.updateSession(this.props.currentSession, changes);
   }, 750)
 
+  onGroupChange = (e) => {
+    const groupId = parseInt(this.group.value, 10);
+    const group = this.props.groups.find(group => group.id === groupId);
+
+    this.props.sessionsActions.updateSession(this.props.currentSession, { group });
+  }
+
+  componentWillUpdate = (nextProps, nextState) => {
+    if (nextState.createGroup && nextProps.createGroup.get('success')) {
+      this.setState({ createGroup: false })
+    }
+  }
+
   renderCreateGroup = () => {
     const { createGroup } = this.props;
     const hasErrors = true === createGroup.get('error') && createGroup.get('errorMessages').has('name');
@@ -93,7 +106,7 @@
               defaultValue={ this.props.currentSession.title }
               onChange={ this.onChange }
               type="text"
-              placeholder="Enter a title for this session"
+              placeholder="Enter a title"
               inputRef={ ref => { this.title = ref; } }
             />
           </FormGroup>
@@ -104,11 +117,25 @@
               componentClass="textarea"
               defaultValue={ this.props.currentSession.description }
               onChange={ this.onChange }
-              placeholder="Enter a description for this session"
+              placeholder="Enter a description"
               inputRef={ ref => { this.description = ref; } }
             />
           </FormGroup>
           <FormGroup>
+            <ControlLabel>Group</ControlLabel>
+            <FormControl
+              name="group"
+              componentClass="select"
+              value={ this.props.group.id }
+              onChange={ this.onGroupChange }
+              inputRef={ ref => { this.group = ref; } }>
+              <option />
+              { this.props.groups.map((group, key) =>
+                <option key={ key } value={ group.id }>{ group.name }</option>
+              ) }
+            </FormControl>
+          </FormGroup>
+          <FormGroup>
             { this.renderCreateGroup() }
           </FormGroup>
         </form>
@@ -118,9 +145,17 @@
 }
 
 function mapStateToProps(state, props) {
+
+  let group;
+  if (props.session) {
+    group = state.groups.find(group => props.session.group.get('id') === group.id)
+  }
+
   return {
     currentSession: props.session,
-    createGroup: state.createGroup
+    createGroup: state.createGroup,
+    groups: state.groups,
+    group
   };
 }
 
--- a/client/src/constants/actionTypes.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/constants/actionTypes.js	Wed Jun 28 12:54:48 2017 +0200
@@ -26,9 +26,14 @@
 export const AUTH_DEAUTHENTICATE = 'AUTH_DEAUTHENTICATE';
 
 export const GROUP_CREATE_ASYNC = 'GROUP_CREATE_ASYNC';
+export const GROUP_CREATE_AND_UPDATE_ASYNC = 'GROUP_CREATE_AND_UPDATE_ASYNC';
 export const GROUP_CREATE_SUCCESS = 'GROUP_CREATE_SUCCESS';
 export const GROUP_CREATE_ERROR = 'GROUP_CREATE_ERROR';
 
+export const GROUP_LOAD_ASYNC = 'GROUP_LOAD_ASYNC';
+export const GROUP_LOAD_SUCCESS = 'GROUP_LOAD_SUCCESS';
+export const GROUP_LOAD_ERROR = 'GROUP_LOAD_ERROR';
+
 export const USER_UPDATE_SETTINGS_ASYNC = 'USER_UPDATE_SETTINGS_ASYNC';
 export const USER_UPDATE_SETTINGS = 'USER_UPDATE_SETTINGS'
 export const USER_TOGGLE_AUTO_SUBMIT = 'USER_TOGGLE_AUTO_SUBMIT';
--- a/client/src/reducers/authReducer.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/reducers/authReducer.js	Wed Jun 28 12:54:48 2017 +0200
@@ -88,6 +88,10 @@
 
 export const groups = (state = Immutable.List([]), action) => {
   switch (action.type) {
+    case types.GROUP_LOAD_SUCCESS:
+      return Immutable.List(action.groups);
+    case types.GROUP_CREATE_SUCCESS:
+      return state.push(action.group);
     default:
       return state
   }
--- a/client/src/sagas/groupSaga.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/sagas/groupSaga.js	Wed Jun 28 12:54:48 2017 +0200
@@ -14,8 +14,50 @@
   }
 }
 
+function* watchCreateGroupAndUpdateSession(context) {
+  while (true) {
+    const { session, group } = yield take(types.GROUP_CREATE_AND_UPDATE_ASYNC);
+    const client = context.client;
+    try {
+      const response = yield client.post('/api/auth/group/', group);
+
+      const actions = [
+        {
+          type: types.GROUP_CREATE_SUCCESS,
+          group: response
+        },
+        {
+          type: types.UPDATE_SESSION,
+          session: session,
+          values: { group: response },
+        }
+      ];
+
+      yield all(actions.map(action => put(action)));
+
+    } catch (e) {
+      yield put({ type: types.GROUP_CREATE_ERROR, error: e });
+    }
+  }
+}
+
+function* watchLoadGroups(context) {
+  const client = context.client;
+  while (true) {
+    yield take(types.GROUP_LOAD_ASYNC);
+    try {
+      const response = yield client.get('/api/auth/group/');
+      yield put({ type: types.GROUP_LOAD_SUCCESS, groups: response });
+    } catch (e) {
+      yield put({ type: types.GROUP_LOAD_ERROR, error: e });
+    }
+  }
+}
+
 export default function* rootSaga(context) {
   yield all([
     watchCreateGroup(context),
+    watchCreateGroupAndUpdateSession(context),
+    watchLoadGroups(context),
   ])
 }
--- a/client/src/store/configureStore.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/store/configureStore.js	Wed Jun 28 12:54:48 2017 +0200
@@ -18,6 +18,7 @@
 import config from '../config';
 import { offlineConfigInitialized } from '../actions/networkActions';
 import asyncRequest from '../constants/asyncRequest';
+import * as types from '../constants/actionTypes';
 
 // const composeEnhancers = (process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ?
 //     window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
@@ -83,6 +84,7 @@
   saga.run(rootGroupSaga, context);
 
   store.dispatch(offlineConfigInitialized({ client: apiClient }))
+  store.dispatch({ type: types.GROUP_LOAD_ASYNC })
 
   return store;
 };
--- a/client/src/store/sessionRecord.js	Tue Jun 27 18:12:10 2017 +0200
+++ b/client/src/store/sessionRecord.js	Wed Jun 28 12:54:48 2017 +0200
@@ -8,4 +8,6 @@
 
   date: '',
 
+  group: null
+
 }, 'Session');
--- a/src/notes/api/views/auth.py	Tue Jun 27 18:12:10 2017 +0200
+++ b/src/notes/api/views/auth.py	Wed Jun 28 12:54:48 2017 +0200
@@ -10,5 +10,6 @@
 
 class GroupViewSet(viewsets.ModelViewSet):
     serializer_class = GroupSerializer
+    permission_classes = ()
     def get_queryset(self):
         return Group.objects.all()