# HG changeset patch # User ymh # Date 1501582814 -7200 # Node ID 906a6c7c7943044a3391b479c5d5884afd6b17d3 # Parent adad5563603c09835009df1d4d7c041fb6f45d4c add group to sync + create groups + various component cleaning diff -r adad5563603c -r 906a6c7c7943 client/src/actions/groupActions.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/actions/groupActions.js Tue Aug 01 12:20:14 2017 +0200 @@ -0,0 +1,17 @@ +import * as types from '../constants/actionTypes'; + + +export const groupCreateSuccess = (group) => + ({ type: types.GROUP_CREATE_SUCCESS, group }); + +export const groupCreateError = (error) => + ({ type: types.GROUP_CREATE_ERROR, error }); + +export const groupLoadSucess = (groups) => + ({ type: types.GROUP_LOAD_SUCCESS, groups }); + +export const groupLoadError = (error) => + ({ type: types.GROUP_LOAD_ERROR, error }); + +export const groupLoadAsync = () => + ({ type: types.GROUP_LOAD_ASYNC }); diff -r adad5563603c -r 906a6c7c7943 client/src/actions/notesActions.js --- a/client/src/actions/notesActions.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/actions/notesActions.js Tue Aug 01 12:20:14 2017 +0200 @@ -45,6 +45,10 @@ return { type: types.DO_DELETE_NOTE, noteId }; } +export const doDeleteAllNote = () => { + return { type: types.DO_DELETE_ALL_NOTE }; +} + export const loadNote = (note) => { return { type: types.LOAD_NOTE, note }; } diff -r adad5563603c -r 906a6c7c7943 client/src/actions/sessionsActions.js --- a/client/src/actions/sessionsActions.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/actions/sessionsActions.js Tue Aug 01 12:20:14 2017 +0200 @@ -39,6 +39,10 @@ return { type: types.DO_DELETE_SESSION, sessionId }; } +export const doDeleteAllSession = () => ( + { type: types.DO_DELETE_ALL_SESSION } +) + export const loadSessions = () => { return { type: types.LOAD_SESSIONS diff -r adad5563603c -r 906a6c7c7943 client/src/components/GroupForm.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/GroupForm.js Tue Aug 01 12:20:14 2017 +0200 @@ -0,0 +1,106 @@ +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { FormGroup, FormControl, Button, InputGroup, HelpBlock, Glyphicon } from 'react-bootstrap'; +import * as authActions from '../actions/authActions'; +import * as sessionsActions from '../actions/sessionsActions'; + +class GroupForm extends Component { + + state = { + createGroup: false, + groupName: '' + } + + toggleCreateGroup = (e) => { + e.preventDefault(); + const { createGroup } = this.state; + this.setState({ createGroup: !createGroup }); + } + + onClickCreateGroup = (e) => { + e.preventDefault(); + const groupName = this.state.groupName; + this.props.sessionsActions.createGroupAndUpdateSession(this.props.session, groupName); + this.setState({ + createGroup: false, + groupName: '' + }) + } + + handleInputChange = (e) => { + const target = e.target; + const value = target.value; + const name = target.name; + + this.setState({ + [name]: value + }); + } + + + render = () => { + const { createGroup } = this.props; + const hasErrors = true === createGroup.get('error') && createGroup.get('errorMessages').has('name'); + + let errors = []; + if (hasErrors) { + const errorMessages = createGroup.get('errorMessages').toArray(); + errors = errorMessages.map((message, key) => { + return ( + { message } + ) + }) + } + + if (this.state.createGroup) { + return ( + + + + + + + + { errors } +
+ +
+ ) + } + + if(this.props.online) { + return ( + + + + ) + } + return null; + } + +} + +function mapStateToProps(state, props) { + + return { + createGroup: state.get('createGroup'), + online: state.getIn(['status', 'online']), + }; +} + +function mapDispatchToProps(dispatch) { + return { + sessionsActions: bindActionCreators(sessionsActions, dispatch), + authActions: bindActionCreators(authActions, dispatch), + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(GroupForm); diff -r adad5563603c -r 906a6c7c7943 client/src/components/SessionForm.js --- a/client/src/components/SessionForm.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/components/SessionForm.js Tue Aug 01 12:20:14 2017 +0200 @@ -1,7 +1,8 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { Panel, FormGroup, ControlLabel, FormControl, Button, InputGroup, HelpBlock, Glyphicon } from 'react-bootstrap'; +import { Panel, FormGroup, ControlLabel, FormControl } from 'react-bootstrap'; +import GroupForm from './GroupForm'; import '../App.css'; import * as sessionsActions from '../actions/sessionsActions'; import * as authActions from '../actions/authActions'; @@ -13,18 +14,6 @@ createGroup: false } - toggleCreateGroup = (e) => { - e.preventDefault(); - const { createGroup } = this.state; - this.setState({ createGroup: !createGroup }); - } - - onClickCreateGroup = (e) => { - e.preventDefault(); - const groupName = this.groupName.value; - this.props.sessionsActions.createGroupAndUpdateSession(this.props.currentSession, groupName); - } - onChange = (e) => { const { name, value } = e.target; const changes = { [name]: value } @@ -36,10 +25,9 @@ }, 750) onGroupChange = (e) => { - const groupId = parseInt(this.group.value, 10); - const group = this.props.groups.find(group => group.id === groupId); + const groupName = e.target.value; - this.props.sessionsActions.updateSession(this.props.currentSession, { group }); + this.props.sessionsActions.updateSession(this.props.currentSession, { group: groupName }); } componentWillUpdate = (nextProps, nextState) => { @@ -48,48 +36,6 @@ } } - renderCreateGroup = () => { - const { createGroup } = this.props; - const hasErrors = true === createGroup.get('error') && createGroup.get('errorMessages').has('name'); - - let errors = []; - if (hasErrors) { - const errorMessages = createGroup.get('errorMessages').toArray(); - errors = errorMessages.map((message, key) => { - return ( - { message } - ) - }) - } - - if (this.state.createGroup) { - return ( - - - { this.groupName = ref; } } /> - - - - - { errors } -
- -
- ) - } - - return ( - - - - ) - } - render() { if (!this.props.currentSession) { @@ -109,7 +55,6 @@ onChange={ this.onChange } type="text" placeholder="Enter a title" - inputRef={ ref => { this.title = ref; } } /> @@ -120,7 +65,6 @@ defaultValue={ this.props.currentSession.description } onChange={ this.onChange } placeholder="Enter a description" - inputRef={ ref => { this.description = ref; } } /> @@ -128,17 +72,15 @@ { this.group = ref; } }> - + ) } - { this.renderCreateGroup() } + @@ -149,8 +91,8 @@ function mapStateToProps(state, props) { let group; - if (props.session && props.session.group) { - group = state.groups.find(group => props.session.group.get('id') === group.id) + if (props.session && props.session.get('group')) { + group = state.get('groups').find(group => props.session.get('group') === group.get('name')) } return { diff -r adad5563603c -r 906a6c7c7943 client/src/constants/actionTypes.js --- a/client/src/constants/actionTypes.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/constants/actionTypes.js Tue Aug 01 12:20:14 2017 +0200 @@ -3,6 +3,7 @@ export const ADD_NOTE = 'ADD_NOTE'; export const DELETE_NOTE = 'DELETE_NOTE'; export const DO_DELETE_NOTE = 'DO_DELETE_NOTE'; +export const DO_DELETE_ALL_NOTE = 'DO_DELETE_ALL_NOTE'; export const UPDATE_NOTE = 'UPDATE_NOTE'; export const RESET_ACTION_NOTE = 'RESET_ACTION_NOTE'; export const LOAD_NOTE = 'LOAD_NOTE'; @@ -11,6 +12,7 @@ export const UPDATE_SESSION = 'UPDATE_SESSION'; export const DELETE_SESSION = 'DELETE_SESSION'; export const DO_DELETE_SESSION = 'DO_DELETE_SESSION'; +export const DO_DELETE_ALL_SESSION = 'DO_DELETE_ALL_SESSION'; export const LOAD_SESSIONS = 'LOAD_SESSIONS'; export const LOAD_SESSION = 'LOAD_SESSION'; export const RESET_ACTION_SESSION = 'RESET_ACTION_SESSION'; diff -r adad5563603c -r 906a6c7c7943 client/src/reducers/authReducer.js --- a/client/src/reducers/authReducer.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/reducers/authReducer.js Tue Aug 01 12:20:14 2017 +0200 @@ -1,8 +1,10 @@ import Immutable from 'immutable'; import * as types from '../constants/actionTypes'; import UserRecord from '../store/userRecord'; +import GroupRecord from '../store/groupRecord'; import asyncRequest from '../constants/asyncRequest'; import uuidV4 from 'uuid/v4'; +import _ from 'lodash'; export const isAuthenticated = (state = false, action) => { switch (action.type) { @@ -103,9 +105,20 @@ export const groups = (state = Immutable.List([]), action) => { switch (action.type) { case types.GROUP_LOAD_SUCCESS: - return Immutable.List(action.groups.results); + return Immutable.List( + action.groups.map((group) => GroupRecord({ + ...(_.omit(group, 'is_personal')), + isPersonal: group['is_personal'] + })) + ); case types.GROUP_CREATE_SUCCESS: - return state.push(action.group); + return state.push(GroupRecord({ + ...(_.omit(action.group, 'is_personal')), + isPersonal: action.group['is_personal'] + })); + case types.AUTH_LOGOUT: { + return Immutable.List(); // empty note list on logout + } default: return state } diff -r adad5563603c -r 906a6c7c7943 client/src/reducers/notesReducer.js --- a/client/src/reducers/notesReducer.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/reducers/notesReducer.js Tue Aug 01 12:20:14 2017 +0200 @@ -81,6 +81,9 @@ return state.push(noteRec); } } + case types.AUTH_LOGOUT: { + return Immutable.List(); // empty note list on logout + } default: return state; } diff -r adad5563603c -r 906a6c7c7943 client/src/reducers/sessionsReducer.js --- a/client/src/reducers/sessionsReducer.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/reducers/sessionsReducer.js Tue Aug 01 12:20:14 2017 +0200 @@ -75,6 +75,9 @@ const session = state.get(index); return state.set(index, session.merge({action: ActionEnum.NONE})); } + case types.AUTH_LOGOUT: { + return Immutable.List(); // empty session list on logout + } default: return state; } diff -r adad5563603c -r 906a6c7c7943 client/src/sagas/SessionSyncronizer.js --- a/client/src/sagas/SessionSyncronizer.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/sagas/SessionSyncronizer.js Tue Aug 01 12:20:14 2017 +0200 @@ -42,18 +42,20 @@ date: localObjInst.get('date'), title: localObjInst.get('title'), description: localObjInst.get('description'), + group: localObjInst.get('group'), protocol: '' }; } getLocalRecord(remoteObj) { - return new SessionRecord({ + return SessionRecord({ _id: remoteObj.ext_id, title: remoteObj.title, description: remoteObj.description, date: moment(remoteObj.date).toDate(), action: ActionEnum.NONE, - group: null + group: remoteObj.group, + protocol: remoteObj.protocol, }); } diff -r adad5563603c -r 906a6c7c7943 client/src/sagas/groupSaga.js --- a/client/src/sagas/groupSaga.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/sagas/groupSaga.js Tue Aug 01 12:20:14 2017 +0200 @@ -1,5 +1,7 @@ import { put, take, all } from 'redux-saga/effects' import * as types from '../constants/actionTypes'; +import { groupCreateSuccess, groupCreateError, groupLoadSucess, groupLoadError } from '../actions/groupActions'; +import { updateSession } from '../actions/sessionsActions'; function* watchCreateGroup(context) { while (true) { @@ -7,9 +9,9 @@ const client = context.client; try { const response = yield client.post('/api/auth/group/', group); - yield put({ type: types.GROUP_CREATE_SUCCESS, group: response }); + yield put(groupCreateSuccess(response)); } catch (e) { - yield put({ type: types.GROUP_CREATE_ERROR, error: e }); + yield put(groupCreateError(e)); } } } @@ -22,21 +24,13 @@ 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 }, - } + groupCreateSuccess(response), + updateSession(session, {group: response.name}) ]; - yield all(actions.map(action => put(action))); } catch (e) { - yield put({ type: types.GROUP_CREATE_ERROR, error: e }); + yield put(groupCreateError(e)); } } } @@ -47,9 +41,9 @@ yield take(types.GROUP_LOAD_ASYNC); try { const response = yield client.get('/api/auth/group/'); - yield put({ type: types.GROUP_LOAD_SUCCESS, groups: response }); + yield put(groupLoadSucess(response.results)); } catch (e) { - yield put({ type: types.GROUP_LOAD_ERROR, error: e }); + yield put(groupLoadError(e)); } } } diff -r adad5563603c -r 906a6c7c7943 client/src/sagas/syncSaga.js --- a/client/src/sagas/syncSaga.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/sagas/syncSaga.js Tue Aug 01 12:20:14 2017 +0200 @@ -1,10 +1,11 @@ -import { put, take, all, select, spawn, race, call} from 'redux-saga/effects' +import { put, take, all, select, spawn, race, call, fork} from 'redux-saga/effects' import { delay } from 'redux-saga'; import * as types from '../constants/actionTypes'; import { getLastSync, getOnline } from './selectors'; import moment from 'moment'; import { startSynchronize, endSynchronize, updateLastSync } from '../actions/syncActions'; import { forceSync } from '../actions/networkActions'; +import { groupLoadAsync } from '../actions/groupActions'; import SessionSynchronizer from './SessionSyncronizer'; import NoteSynchronizer from './NoteSyncronizer'; import config from '../config'; @@ -39,10 +40,15 @@ } +function* doLoadGroup() { + yield put(groupLoadAsync()); +} + function* watchDoSync(context) { while (true) { yield take(types.SYNC_DO_SYNC); - yield spawn(doSync, context); + yield spawn(doSync, context); //we use spawn + take, because we do not want it to be interupted + yield fork(doLoadGroup); yield take(types.SYNC_END_SYNC); } } diff -r adad5563603c -r 906a6c7c7943 client/src/store/configureStore.js --- a/client/src/store/configureStore.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/store/configureStore.js Tue Aug 01 12:20:14 2017 +0200 @@ -13,6 +13,7 @@ import NoteRecord from './noteRecord'; import SessionRecord from './sessionRecord'; import UserRecord from './userRecord'; +import GroupRecord from './groupRecord'; import APIClient from '../api/APIClient'; import config from '../config'; import asyncRequest from '../constants/asyncRequest'; @@ -45,15 +46,15 @@ }; const immutableTransformConfig = { - records: [NoteRecord, SessionRecord, UserRecord], - whitelist: ['sessions', 'notes', 'authStatus'] + records: [NoteRecord, SessionRecord, UserRecord, GroupRecord], + whitelist: ['sessions', 'notes', 'authStatus', 'groups'] } const persistOptions = { storage: localForage, - records: [NoteRecord, SessionRecord, UserRecord], + records: [NoteRecord, SessionRecord, UserRecord, GroupRecord], transforms: [immutableTransform(immutableTransformConfig)], - whitelist: ['sessions', 'notes', 'autoSubmit', 'authStatus'] + whitelist: ['sessions', 'notes', 'autoSubmit', 'authStatus', 'groups'] } const apiClient = new APIClient(config.apiRootUrl); diff -r adad5563603c -r 906a6c7c7943 client/src/store/groupRecord.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/store/groupRecord.js Tue Aug 01 12:20:14 2017 +0200 @@ -0,0 +1,10 @@ +import Immutable from 'immutable'; + +export default Immutable.Record({ + name: '', + + owner: '', + isPersonal: false, + description:'' + +}, 'Group'); diff -r adad5563603c -r 906a6c7c7943 client/src/store/sessionRecord.js --- a/client/src/store/sessionRecord.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/store/sessionRecord.js Tue Aug 01 12:20:14 2017 +0200 @@ -10,6 +10,7 @@ date: '', group: null, + protocol: '', action: ActionEnum.NONE, diff -r adad5563603c -r 906a6c7c7943 client/src/store/userRecord.js --- a/client/src/store/userRecord.js Mon Jul 31 23:18:38 2017 +0200 +++ b/client/src/store/userRecord.js Tue Aug 01 12:20:14 2017 +0200 @@ -6,6 +6,7 @@ email: '', first_name: '', - last_name: '' + last_name: '', + default_group: null, }, 'User'); diff -r adad5563603c -r 906a6c7c7943 src/notes/api/views/core.py --- a/src/notes/api/views/core.py Mon Jul 31 23:18:38 2017 +0200 +++ b/src/notes/api/views/core.py Tue Aug 01 12:20:14 2017 +0200 @@ -29,6 +29,7 @@ serializers = { 'list': ListSessionSerializer, 'retrieve': DetailSessionSerializer, + 'update': CreateSessionSerializer, 'create': CreateSessionSerializer, } diff -r adad5563603c -r 906a6c7c7943 src/notes/api/views/sync.py --- a/src/notes/api/views/sync.py Mon Jul 31 23:18:38 2017 +0200 +++ b/src/notes/api/views/sync.py Tue Aug 01 12:20:14 2017 +0200 @@ -36,7 +36,6 @@ Process log entries ''' log_entries = self.__filter_object(model, user, modified_since, client_id) - logger.debug("LOG ENTRies %r", list(log_entries)) res = {} for log_entry in log_entries: