From 20bf046fa710e00f647bd466f5619cb697624c31 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Fri, 19 Apr 2019 04:10:35 +0530 Subject: [PATCH 01/15] feat(sessions): implement basic front end flow --- src/redux/actions/session-actions.js | 10 +++++++++- src/redux/reducers/session-reducer.js | 9 ++++++++- src/redux/types.js | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/redux/actions/session-actions.js b/src/redux/actions/session-actions.js index 3193030..e56af90 100644 --- a/src/redux/actions/session-actions.js +++ b/src/redux/actions/session-actions.js @@ -12,7 +12,8 @@ import { SET_SELECTED_CAMERA, SET_CAMERA_CONNECTION_STATUS, SET_SELECTED_APPLICATION, - INITIALIZE_SESSION + INITIALIZE_SESSION, + START_SESSION } from '../types'; import {API_ENDPOINTS} from '../../api'; import {HttpInterceptor} from '../../services'; @@ -33,6 +34,13 @@ export const initializeSession = data => (dispatch) => { }); }; +export const startSession = data => (dispatch) => { + dispatch({ + type: START_SESSION, + payload: data, + }); +}; + export const setSelectedApplication = app => (dispatch) => { return dispatch({ type: SET_SELECTED_APPLICATION, diff --git a/src/redux/reducers/session-reducer.js b/src/redux/reducers/session-reducer.js index b8e8995..a932760 100644 --- a/src/redux/reducers/session-reducer.js +++ b/src/redux/reducers/session-reducer.js @@ -13,13 +13,15 @@ import { SET_SELECTED_CAMERA, SET_CAMERA_CONNECTION_STATUS, SET_SELECTED_APPLICATION, - INITIALIZE_SESSION + INITIALIZE_SESSION, + START_SESSION } from '../types'; const initialState = { sessionTemp: {}, currentSession: {}, isSessionInitialized: false, + isSessionStarted: false, questionnaires: [], newQuestionnaire: {}, selectedApplication: {}, @@ -44,6 +46,11 @@ export function sessionReducer(state = initialState, action) { sessionTemp: {}, currentSession: action.payload, }; + case START_SESSION: + return { + ...state, + isSessionStarted: true, + }; case FETCH_QUESTIONNAIRES: return { ...state, diff --git a/src/redux/types.js b/src/redux/types.js index 9243ed7..4cec058 100644 --- a/src/redux/types.js +++ b/src/redux/types.js @@ -57,4 +57,5 @@ export const SET_CAMERA_CONNECTION_STATUS = 'SET_CAMERA_CONNECTION_STATUS'; export const SET_RAW_PHONE_FEED_WS_DATA = 'SET_RAW_PHONE_FEED_WS_DATA'; export const SET_LIST_OF_AVAILABLE_CAMERAS = 'SET_LIST_OF_AVAILABLE_CAMERAS'; export const SET_SELECTED_CAMERA = 'SET_SELECTED_CAMERA'; -export const INITIALIZE_SESSION = 'INITIALIZE_SESSION'; \ No newline at end of file +export const INITIALIZE_SESSION = 'INITIALIZE_SESSION'; +export const START_SESSION = 'START_SESSION'; From 20358559e5515d9b36990cffd48134fda9b4853a Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Wed, 24 Apr 2019 19:06:50 +0530 Subject: [PATCH 02/15] chore(env): add socket endpoints --- .env | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env b/.env index 04fc750..8033442 100644 --- a/.env +++ b/.env @@ -1,6 +1,8 @@ NODE_PATH=./src REACT_APP_PROD_API_ENDPOINT = 'http://localhost:5000/api/v1' REACT_APP_DEV_API_ENDPOINT = 'http://localhost:5000/api/v1' +REACT_APP_PROD_WEBSOCKET_ENDPOINT = 'http://127.0.0.1:5000' +REACT_APP_DEV_WEBSOCKET_ENDPOINT = 'http://127.0.0.1:5000' REACT_APP_COOKIE_NAME = 'cssi_user' REACT_APP_COOKIE_PATH = '/' REACT_APP_LOGOUT_PATH = '/login?logout=true' From 9481ba9233bc128aaf4a5f356fa8cffab053a4a1 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Wed, 24 Apr 2019 19:07:11 +0530 Subject: [PATCH 03/15] cgore(deps): add socket.io client dependency --- package-lock.json | 218 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 219 insertions(+) diff --git a/package-lock.json b/package-lock.json index 195af2a..b6b4a8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1321,6 +1321,11 @@ "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", "integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==" }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -1790,6 +1795,11 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -2427,6 +2437,11 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, "bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", @@ -2515,6 +2530,14 @@ "tweetnacl": "^0.14.3" } }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, "bfj": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", @@ -2536,6 +2559,11 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -2859,6 +2887,11 @@ "caller-callsite": "^2.0.0" } }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, "callsites": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", @@ -3813,11 +3846,21 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, "compressible": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz", @@ -5113,6 +5156,51 @@ "once": "^1.4.0" } }, + "engine.io-client": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", + "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, "enhanced-resolve": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", @@ -7699,6 +7787,26 @@ "ansi-regex": "^2.0.0" } }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -10732,6 +10840,11 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -11107,6 +11220,22 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=" }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "~1.0.0" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", @@ -16033,6 +16162,72 @@ "kind-of": "^3.2.0" } }, + "socket.io-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", + "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.3.1", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "sockjs": { "version": "0.3.19", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", @@ -16794,6 +16989,11 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -18207,6 +18407,14 @@ "signal-exit": "^3.0.2" } }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, "x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", @@ -18222,6 +18430,11 @@ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, "xregexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", @@ -18275,6 +18488,11 @@ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" } } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" } } } diff --git a/package.json b/package.json index 9b5465b..efd1114 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "redux-thunk": "^2.3.0", "semver": "^5.5.1", "sha256": "^0.2.0", + "socket.io-client": "^2.2.0", "uniqid": "^5.0.3", "universal-cookie": "^2.1.5", "uuid": "^3.3.2", From 6bcaf8af4c7423f80b2f9723034bc1f29e6b2945 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Wed, 24 Apr 2019 19:08:05 +0530 Subject: [PATCH 04/15] chore(emotions): add corresponding questionnaire fetching --- src/views/sessions/emotions.jsx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/views/sessions/emotions.jsx b/src/views/sessions/emotions.jsx index 48cd361..b977559 100644 --- a/src/views/sessions/emotions.jsx +++ b/src/views/sessions/emotions.jsx @@ -15,7 +15,7 @@ import disgustIcon from '../../assets/img/emotions/disgust.svg'; import surpriseIcon from '../../assets/img/emotions/surprise.svg'; import fearIcon from '../../assets/img/emotions/fear.svg'; import angerIcon from '../../assets/img/emotions/anger.svg'; -import {navigate} from '../../services'; +import { navigate } from '../../services'; import * as qs from 'query-string'; class Emotions extends Component { @@ -25,7 +25,7 @@ class Emotions extends Component { emotions: [ { displayName: 'Happiness', - name: 'happiness', + name: 'happy', icon: happinessIcon, selected: false }, @@ -37,13 +37,13 @@ class Emotions extends Component { }, { displayName: 'Sadness', - name: 'sadness', + name: 'sad', icon: sadnessIcon, selected: false }, { displayName: 'Anger', - name: 'anger', + name: 'angry', icon: angerIcon, selected: false }, @@ -55,13 +55,13 @@ class Emotions extends Component { }, { displayName: 'Fear', - name: 'fear', + name: 'scared', icon: fearIcon, selected: false }, { displayName: 'Surprise', - name: 'surprise', + name: 'surprised', icon: surpriseIcon, selected: false } @@ -71,7 +71,12 @@ class Emotions extends Component { } componentDidMount() { - const { actions, location, selectedApplication, selectedQuestionnaire } = this.props; + const { + actions, + location, + selectedApplication, + selectedQuestionnaire + } = this.props; const route = qs.parse(location.search); let notification = null; @@ -106,14 +111,14 @@ class Emotions extends Component { actions.notifications.addNotification(notification); setTimeout(() => { let searchParams = '?type=pre&app=' + selectedApplication.id; - navigate('questionnaire', searchParams) + navigate('questionnaire', searchParams); }, 2000); } } } componentWillReceiveProps(nextProps) { - const {actions, expectedEmotions} = this.props; + const { actions, expectedEmotions } = this.props; if (nextProps.expectedEmotions) { if (!_.isEqual(expectedEmotions, nextProps.expectedEmotions)) { actions.sessions.initializeSession(nextProps.sessionTemp); From 0231927f8e7bc6d2d5e68815a31c6f8b80fbab97 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Wed, 24 Apr 2019 19:08:34 +0530 Subject: [PATCH 05/15] chore(api): correct getquestionnaire endpoint --- src/api.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/api.js b/src/api.js index 3a1f308..33b4b4e 100644 --- a/src/api.js +++ b/src/api.js @@ -1,6 +1,7 @@ -const BASE_API = process.env.NODE_ENV === 'production' - ? process.env.REACT_APP_PROD_API_ENDPOINT - : process.env.REACT_APP_DEV_API_ENDPOINT; +const BASE_API = + process.env.NODE_ENV === 'production' + ? process.env.REACT_APP_PROD_API_ENDPOINT + : process.env.REACT_APP_DEV_API_ENDPOINT; const API_ENDPOINTS = { authorize: `${BASE_API}/auth/`, @@ -19,10 +20,10 @@ const API_ENDPOINTS = { editApplication: `${BASE_API}/applications/{}/`, deleteApplication: `${BASE_API}/applications/{}/`, getQuestionnaires: `${BASE_API}/questionnaires/`, - getQuestionnaireInfo: `${BASE_API}/questionnaires/{}/`, + getQuestionnaireInfo: `${BASE_API}/questionnaires/{}`, updateQuestionnaire: `${BASE_API}/questionnaires/{}/`, createQuestionnaire: `${BASE_API}/questionnaires/`, - initializeSession: `${BASE_API}/sessions/`, + initializeSession: `${BASE_API}/sessions/` }; export { API_ENDPOINTS }; From e2edb34fad55d146801ad4954b924796ea964510 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Wed, 24 Apr 2019 19:09:03 +0530 Subject: [PATCH 06/15] chore(reduc): add getquestionnaire action --- src/redux/actions/session-actions.js | 113 ++++++++++++++++----------- 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/src/redux/actions/session-actions.js b/src/redux/actions/session-actions.js index e56af90..5b3c24b 100644 --- a/src/redux/actions/session-actions.js +++ b/src/redux/actions/session-actions.js @@ -15,144 +15,163 @@ import { INITIALIZE_SESSION, START_SESSION } from '../types'; -import {API_ENDPOINTS} from '../../api'; -import {HttpInterceptor} from '../../services'; +import { API_ENDPOINTS } from '../../api'; +import { HttpInterceptor } from '../../services'; const http = new HttpInterceptor(); -export const initializeSession = data => (dispatch) => { +export const initializeSession = data => dispatch => { const endpoint = API_ENDPOINTS.initializeSession; - return http.post(endpoint, data) - .then((response) => { + return http + .post(endpoint, data) + .then(response => { dispatch({ type: INITIALIZE_SESSION, - payload: response.data.data, + payload: response.data.data }); }) - .catch((error) => { + .catch(error => { //console.log('[ERROR]', ' [Sessions, createQuestionnaire()]: HTTP POST - Callback Error', error); }); }; -export const startSession = data => (dispatch) => { +export const startSession = data => dispatch => { dispatch({ type: START_SESSION, - payload: data, + payload: data }); }; -export const setSelectedApplication = app => (dispatch) => { +export const setSelectedApplication = app => dispatch => { return dispatch({ type: SET_SELECTED_APPLICATION, - payload: app, + payload: app }); }; -export const fetchQuestionnaires = () => (dispatch) => { +export const fetchQuestionnaires = () => dispatch => { const endpoint = API_ENDPOINTS.getQuestionnaires; - return http.get(endpoint) - .then((response) => { + return http + .get(endpoint) + .then(response => { dispatch({ type: FETCH_QUESTIONNAIRES, - payload: response.data.data, + payload: response.data.data }); }) - .catch((error) => { + .catch(error => { //console.log('[ERROR]', ' [Sessions, fetchQuestionnaires()]: HTTP GET - Callback Error', error); }); }; -export const createQuestionnaire = data => (dispatch) => { +export const getQuestionnaireInfo = id => dispatch => { + const endpoint = API_ENDPOINTS.getQuestionnaireInfo.format(id); + return http + .get(endpoint) + .then(response => { + dispatch({ + type: SET_SELECTED_QUESTIONNAIRE, + payload: response.data.data + }); + }) + .catch(error => { + // console.log('[ERROR]', ' [Applications, fetchApplications()]: HTTP GET - Callback Error', error); + }); +}; + +export const createQuestionnaire = data => dispatch => { const endpoint = API_ENDPOINTS.createQuestionnaire; - return http.post(endpoint, data) - .then((response) => { + return http + .post(endpoint, data) + .then(response => { dispatch({ type: SET_SELECTED_QUESTIONNAIRE, - payload: response.data.data, + payload: response.data.data }); }) - .catch((error) => { + .catch(error => { //console.log('[ERROR]', ' [Sessions, createQuestionnaire()]: HTTP POST - Callback Error', error); }); }; -export const updateQuestionnaire = data => (dispatch) => { - const endpoint = API_ENDPOINTS.updateQuestionnaire - .format(data.id); +export const updateQuestionnaire = data => dispatch => { + const endpoint = API_ENDPOINTS.updateQuestionnaire.format(data.id); const body = { post: data.post }; - return http.patch(endpoint, body) - .then((response) => { + return http + .patch(endpoint, body) + .then(response => { dispatch({ type: UPDATE_QUESTIONNAIRE, - payload: _.assign({}, data, response.data.data), + payload: _.assign({}, data, response.data.data) }); }) - .catch((error) => { + .catch(error => { //console.log('[ERROR]', ' [Sessions, updateQuestionnaire()]: HTTP PATCH - Callback Error', error); }); }; -export const setExpectedEmotions = data => (dispatch) => { +export const setExpectedEmotions = data => dispatch => { dispatch({ type: SET_EXPECTED_EMOTIONS, - payload: data, + payload: data }); }; -export const setRawPhoneFeedWSURL = data => (dispatch) => { +export const setRawPhoneFeedWSURL = data => dispatch => { const endpoint = data + '/wsinfo'; - return http.get(endpoint) - .then((response) => { + return http + .get(endpoint) + .then(response => { dispatch({ type: SET_RAW_PHONE_FEED_WS_URL, - payload: response.data, + payload: response.data }); }) - .catch((error) => { + .catch(error => { //console.log('[ERROR]', ' [Sessions, setRawPhoneFeedWSURL()]: HTTP PATCH - Callback Error', error); }); }; -export const setRawPhoneFeedWSData = data => (dispatch) => { +export const setRawPhoneFeedWSData = data => dispatch => { dispatch({ type: SET_RAW_PHONE_FEED_WS_DATA, - payload: data, + payload: data }); }; -export const setRawPhoneFeedWSConnectionStatus = data => (dispatch) => { +export const setRawPhoneFeedWSConnectionStatus = data => dispatch => { dispatch({ type: SET_RAW_PHONE_FEED_WS_CONNECTION_STATUS, - payload: data, + payload: data }); }; -export const setCameraConnectionStatus = data => (dispatch) => { +export const setCameraConnectionStatus = data => dispatch => { dispatch({ type: SET_CAMERA_CONNECTION_STATUS, - payload: data, + payload: data }); }; -export const setListOfAvailableCameras = data => (dispatch) => { +export const setListOfAvailableCameras = data => dispatch => { dispatch({ type: SET_LIST_OF_AVAILABLE_CAMERAS, - payload: data, + payload: data }); }; -export const setSelectedCamera = data => (dispatch) => { +export const setSelectedCamera = data => dispatch => { dispatch({ type: SET_SELECTED_CAMERA, - payload: data, + payload: data }); }; -export const setSessionViewConfig = data => (dispatch) => { +export const setSessionViewConfig = data => dispatch => { dispatch({ type: SET_SESSION_VIEW_CONFIG, - payload: data, + payload: data }); }; From 4219005a0c9b0b50a4f130a0cf9f5fec72f6cd57 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:08:03 +0530 Subject: [PATCH 07/15] chore(vies): implement post questionnaire logic --- src/views/sessions/questionnaire.jsx | 91 ++++++++++++++++++---------- 1 file changed, 60 insertions(+), 31 deletions(-) diff --git a/src/views/sessions/questionnaire.jsx b/src/views/sessions/questionnaire.jsx index d4e007a..66af34d 100644 --- a/src/views/sessions/questionnaire.jsx +++ b/src/views/sessions/questionnaire.jsx @@ -26,45 +26,68 @@ class Questionnaire extends Component { } else if (route.type === 'post') { title = 'Post Exposure Questionnaire'; } - } - const questionnaireViewConfig = { - title: title, - type: route.type - }; - actions.sessions.setSessionViewConfig( - _.assign(viewConfig, { questionnaire: questionnaireViewConfig }) - ); + const questionnaireViewConfig = { + id: route.q_id, + title: title, + type: route.type + }; + actions.sessions.setSessionViewConfig( + _.assign({}, viewConfig, { questionnaire: questionnaireViewConfig }) + ); - // Check if an application is selected. If not show error and redirect to app page. - if (_.isEmpty(selectedApplication)) { - if (route.app) { - let appId = route.app; - actions.applications.getApplicationInfo(appId); - } else { - const notification = { - level: 3, - message: - 'You have not selected an application. The page will be automatically redirected.' - }; - actions.notifications.addNotification(notification); - setTimeout(() => { - navigate('newSession'); - }, 2000); + // Check if an application is selected. If not show error and redirect to app page. + if (route.type === 'pre') { + if (_.isEmpty(selectedApplication)) { + if (route.app) { + let appId = route.app; + actions.applications.getApplicationInfo(appId); + } else { + const notification = { + level: 3, + message: + 'You have not selected an application. The page will be automatically redirected.' + }; + actions.notifications.addNotification(notification); + setTimeout(() => { + navigate('newSession'); + }, 2000); + } + } + } else if (route.type === 'post') { + if (!route.session_id) { + const notification = { + level: 3, + message: + 'You have not completed a test session. The page will be automatically redirected.' + }; + actions.notifications.addNotification(notification); + setTimeout(() => { + navigate('newSession'); + }, 2000); + } } } } componentWillReceiveProps(nextProps) { - const { selectedQuestionnaire } = this.props; + const { selectedQuestionnaire, location } = this.props; + + const route = qs.parse(location.search); + if (nextProps.selectedQuestionnaire) { if (!_.isEqual(selectedQuestionnaire, nextProps.selectedQuestionnaire)) { - let searchParams = - '?app=' + - nextProps.selectedApplication.id + - '&q_id=' + - nextProps.selectedQuestionnaire.id; - navigate('emotions', searchParams); + if (route.type === 'pre') { + let searchParams = + '?app=' + + nextProps.selectedApplication.id + + '&q_id=' + + nextProps.selectedQuestionnaire.id; + navigate('emotions', searchParams); + } else if (route.type === 'post') { + let searchParams = '?session_id=' + route.session_id; + navigate('sessions', searchParams); + } } } } @@ -103,7 +126,13 @@ class Questionnaire extends Component { title={''} content={
- +
} /> From b50a70c4fa96bd085588a9ff0ca3d7bff12bd68e Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:08:22 +0530 Subject: [PATCH 08/15] chore(api): update endpoints --- src/api.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api.js b/src/api.js index 33b4b4e..a092c3c 100644 --- a/src/api.js +++ b/src/api.js @@ -21,9 +21,10 @@ const API_ENDPOINTS = { deleteApplication: `${BASE_API}/applications/{}/`, getQuestionnaires: `${BASE_API}/questionnaires/`, getQuestionnaireInfo: `${BASE_API}/questionnaires/{}`, - updateQuestionnaire: `${BASE_API}/questionnaires/{}/`, + updateQuestionnaire: `${BASE_API}/questionnaires/{}/post`, createQuestionnaire: `${BASE_API}/questionnaires/`, - initializeSession: `${BASE_API}/sessions/` + initializeSession: `${BASE_API}/sessions/`, + getSessionInfo: `${BASE_API}/sessions/{}` }; export { API_ENDPOINTS }; From ec51041e4c24ff7c4fd406a7586c7eec483f9037 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:09:35 +0530 Subject: [PATCH 09/15] chore(views): implement websocket closing logic ad unmount --- src/views/sessions/evaluation.jsx | 333 +++++++++++++++++++++--------- 1 file changed, 232 insertions(+), 101 deletions(-) diff --git a/src/views/sessions/evaluation.jsx b/src/views/sessions/evaluation.jsx index f0c7118..aba9290 100644 --- a/src/views/sessions/evaluation.jsx +++ b/src/views/sessions/evaluation.jsx @@ -1,29 +1,55 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import { - Grid, - Row, - Col, -} from 'react-bootstrap'; +import _ from 'lodash'; +import io from 'socket.io-client'; +import {Grid, Row, Col} from 'react-bootstrap'; import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; import 'react-sliding-pane/dist/react-sliding-pane.css'; import * as sessionActionCreators from '../../redux/actions/session-actions'; +import * as notificationActionCreators from '../../redux/actions/notification-actions'; import {Card} from '../../components'; import {CustomButton as Button} from '../../elements'; -import {PhoneFeedConnectionForm} from '../../forms' +import {PhoneFeedConnectionForm} from '../../forms'; import {CameraFeedConnectionForm} from '../../forms/sessions'; import {EmptyPlaceholder} from '../../components'; -import videCameraIcon from '../../assets/img/icons/video-camera.svg'; +import videoCameraIcon from '../../assets/img/icons/video-camera.svg'; import phoneIcon from '../../assets/img/icons/smartphone.svg'; +import * as qs from 'query-string'; +import {navigate} from '../../services'; + +const WEBSOCKET_ENDPOINT = + process.env.NODE_ENV === 'production' + ? process.env.REACT_APP_PROD_WEBSOCKET_ENDPOINT + : process.env.REACT_APP_DEV_WEBSOCKET_ENDPOINT; + +// Variable for the screen-share web-socket connection (javascript) +let ws; + +// Variable for the CSSI api web-socket connection (scoket-io) +let socket; class Evaluation extends Component { + constructor(props) { + super(props); + this.state = { + isSessionStarted: false + } + } componentDidMount() { - const {actions} = this.props; + const {actions, currentSession, location} = this.props; + + if (_.isEmpty(currentSession)) { + const route = qs.parse(location.search); + actions.sessions.getSessionInfo(route.session_id); + } actions.sessions.setCameraConnectionStatus(false); actions.sessions.setRawPhoneFeedWSConnectionStatus(false); - navigator.mediaDevices.enumerateDevices().then(this.extractCameras).catch(this.handleCameraError); + navigator.mediaDevices + .enumerateDevices() + .then(this.extractCameras) + .catch(this.handleCameraError); } componentWillReceiveProps(nextProps) { @@ -41,31 +67,7 @@ class Evaluation extends Component { } } - runWebSocket = (address) => { - const {actions} = this.props; - let ws; - - if ('WebSocket' in window) { - console.log('CSSI_DEBUG: WebSocket is supported by your Browser!'); - - ws = new WebSocket('ws://' + address); - - ws.onopen = function () { - actions.sessions.setRawPhoneFeedWSConnectionStatus(true); - }; - ws.onmessage = function (evt) { - actions.sessions.setRawPhoneFeedWSData(evt.data); - }; - ws.onclose = function () { - actions.sessions.setRawPhoneFeedWSConnectionStatus(false); - }; - } - else { - console.log('CSSI_DEBUG: WebSocket NOT supported by your Browser!'); - } - }; - - extractCameras = (devices) => { + extractCameras = devices => { const {actions} = this.props; let videoCaptureDevices = []; @@ -77,54 +79,144 @@ class Evaluation extends Component { }; option.value = device.deviceId; if (device.kind === 'videoinput') { - option.label = device.label || 'Camera ' + - (videoCaptureDevices.length + 1); + option.label = + device.label || 'Camera ' + (videoCaptureDevices.length + 1); videoCaptureDevices.push(option); } } actions.sessions.setListOfAvailableCameras(videoCaptureDevices); }; - startCameraStream = (source) => { + startCameraStream = source => { if (window.stream) { window.stream.getTracks().forEach(track => { track.stop(); }); } const constraints = { - video: {deviceId: source ? {exact: source} : undefined} + video: {deviceId: source ? {exact: source} : undefined}, + audio: false }; - navigator.mediaDevices.getUserMedia(constraints).then(this.attachStreamToCamera).then(this.extractCameras).catch(this.handleCameraError); + + navigator.mediaDevices + .getUserMedia(constraints) + .then(this.attachStreamToCamera) + .then(this.extractCameras) + .catch(this.handleCameraError); }; - attachStreamToCamera = (stream) => { - const {actions} = this.props; + stopCameraStream = () => { + if (window.stream) { + window.stream.getTracks().forEach(track => { + track.stop(); + }); + } + }; - const videoElement = document.querySelector('video'); + attachStreamToCamera = stream => { + const video = document.querySelector('video'); window.stream = stream; - videoElement.srcObject = stream; - // Refresh button list + video.srcObject = stream; + // Refresh camera list return navigator.mediaDevices.enumerateDevices(); }; - handleCameraError = (error) => { + handleCameraError = error => { const {actions} = this.props; actions.sessions.setCameraConnectionStatus(false); - console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name); + console.log( + 'navigator.MediaDevices.getUserMedia error: ', + error.message, + error.name + ); }; - render() { - const {isRawPhoneFeedWSConnected, rawPhoneFeedWSData, availableCameras, isCameraConnected} = this.props; + getScreenShot = () => { + const video = document.querySelector('video'); + let canvas = document.createElement('canvas'); + canvas.width = video.videoWidth; + canvas.height = video.videoHeight; + let ctx = canvas.getContext('2d'); + ctx.drawImage(video, 0, 0, canvas.width, canvas.height); + return canvas.toDataURL('image/png'); + }; + + runWebSocket = address => { + const {actions, location} = this.props; + const route = qs.parse(location.search); + let self = this; + + if ('WebSocket' in window) { + console.log('CSSI_DEBUG: WebSocket is supported by your Browser!'); - console.log(isRawPhoneFeedWSConnected) + ws = new WebSocket('ws://' + address); + socket = io(WEBSOCKET_ENDPOINT); + + ws.onopen = function () { + actions.sessions.setRawPhoneFeedWSConnectionStatus(true); + }; + ws.onmessage = function (evt) { + let phoneFeedData = 'data:image/png;base64,' + evt.data; + actions.sessions.setRawPhoneFeedWSData(phoneFeedData); + socket.emit( + 'test/start', + {head_frame: self.getScreenShot()}, + {scene_frame: phoneFeedData}, + {session_id: route.session_id} + ); + }; + ws.onclose = function () { + actions.sessions.setRawPhoneFeedWSConnectionStatus(false); + }; + + // Web socket connection with flask socket io + socket.on('connect', function () { + let notification = { + level: 1, + message: + 'Socket connection established with {}'.format(WEBSOCKET_ENDPOINT) + }; + actions.notifications.addNotification(notification); + }); + socket.on('event', function (data) { + console.log('Socket server message: {0}'.format(data)); + }); + socket.on('disconnect', function () { + console.log('Socket server disconnected'); + }); + } else { + console.log('CSSI_DEBUG: WebSocket NOT supported by your Browser!'); + } + }; + + stopTestSession = () => { + const {location, currentSession} = this.props; + + ws.close(); // close screen-share socket connection + socket.disconnect(); // close CSSI api socket connection + + this.stopCameraStream(); // stop the camera stream + + const route = qs.parse(location.search); + let searchParams = '?type=post&session_id=' + route.session_id + '&q_id=' + currentSession.questionnaire.id; + navigate('questionnaire', searchParams); + }; + + render() { + const { + isRawPhoneFeedWSConnected, + rawPhoneFeedWSData, + availableCameras, + isCameraConnected + } = this.props; let cameraTypeOptions = null; if (availableCameras) { - cameraTypeOptions = availableCameras - .map(cam => ( - {value: cam.value, label: cam.label} - )); + cameraTypeOptions = availableCameras.map(cam => ({ + value: cam.value, + label: cam.label + })); } return ( @@ -138,68 +230,102 @@ class Evaluation extends Component {
-
-

Start Session

-
- Before starting the session make sure your camera and mobile screen feed is working properly. - Configure them properly and press the Start button to start the session. -
-
+ { + isRawPhoneFeedWSConnected && isCameraConnected ? + ( +
+

Session Started

+
+ Press the Stop Session button to terminate the test session. +
+
+ ) + : + ( +
+

Start Session

+
+ Select and connect the video camera first and then enter the Phone feed URL. +
+
+ ) + }
- + -
- { - isRawPhoneFeedWSConnected ? - - : - - } + content={ +
+
+ {isCameraConnected ? ( +
-
- )} + } /> - + -
- { - isCameraConnected ? - - : - - } - + content={ +
+
+ {isRawPhoneFeedWSConnected ? ( + + ) : ( + + )}
+
- )} + } />
+ - -
- -
- + +
+ +
+ + +
@@ -208,31 +334,36 @@ class Evaluation extends Component { } const injectedPropTypes = { - actions: PropTypes.shape({}), + actions: PropTypes.shape({}) }; Evaluation.propTypes = { - ...injectedPropTypes, + ...injectedPropTypes }; function mapStateToProps(state) { return { + currentSession: state.sessions.currentSession, isCameraConnected: state.sessions.isCameraConnected, isRawPhoneFeedWSConnected: state.sessions.isRawPhoneFeedWSConnected, rawPhoneFeedWSURL: state.sessions.rawPhoneFeedWSURL, rawPhoneFeedWSData: state.sessions.rawPhoneFeedWSData, availableCameras: state.sessions.availableCameras, selectedCamera: state.sessions.selectedCamera, - viewConfig: state.sessions.sessionViewConfig, + viewConfig: state.sessions.sessionViewConfig }; } function mapDispatchToProps(dispatch) { return { actions: { - sessions: bindActionCreators(sessionActionCreators, dispatch) - }, + sessions: bindActionCreators(sessionActionCreators, dispatch), + notifications: bindActionCreators(notificationActionCreators, dispatch), + } }; } -export default connect(mapStateToProps, mapDispatchToProps)(Evaluation); +export default connect( + mapStateToProps, + mapDispatchToProps +)(Evaluation); From 5382429cc33a9721532aa2514a9f45520c919982 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:10:14 +0530 Subject: [PATCH 10/15] fix(emotions): fix selected emotions array issue :bug: --- src/views/sessions/emotions.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/sessions/emotions.jsx b/src/views/sessions/emotions.jsx index b977559..8e59156 100644 --- a/src/views/sessions/emotions.jsx +++ b/src/views/sessions/emotions.jsx @@ -149,11 +149,11 @@ class Emotions extends Component { const _selectedEmotions = _.cloneDeep(selectedEmotions); - if (_emotion.selected) { + if (!emotion.selected) { _selectedEmotions.push(_emotion.name); } else { - const index_selected = _.findIndex(_selectedEmotions, _emotion.name); - _selectedEmotions.splice(index_selected, 1, _emotion.name); + const idx = _.indexOf(_selectedEmotions, _emotion.name); + _selectedEmotions.splice(idx, 1, _emotion.name); } this.setState({ selectedEmotions: _selectedEmotions }); From c8d2a4aa025eb86d20497febacfff30a11ebe71a Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:11:07 +0530 Subject: [PATCH 11/15] chore(services): add session route --- src/services/gobal.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/gobal.js b/src/services/gobal.js index 44c5ead..72a3087 100644 --- a/src/services/gobal.js +++ b/src/services/gobal.js @@ -36,8 +36,11 @@ export function navigate(route, searchParams) { if(route === 'evaluation') { path = '/new-session/evaluation'; } + if(route === 'sessions') { + path = '/sessions'; + } history.push({ pathname: path, search: searchParams - }) + }); } From 946481d47cecaccd5910f03d147ec7b3292c1190 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:11:30 +0530 Subject: [PATCH 12/15] chore(redux): add types to handle current session --- src/redux/types.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/redux/types.js b/src/redux/types.js index 4cec058..c08f56c 100644 --- a/src/redux/types.js +++ b/src/redux/types.js @@ -58,4 +58,5 @@ export const SET_RAW_PHONE_FEED_WS_DATA = 'SET_RAW_PHONE_FEED_WS_DATA'; export const SET_LIST_OF_AVAILABLE_CAMERAS = 'SET_LIST_OF_AVAILABLE_CAMERAS'; export const SET_SELECTED_CAMERA = 'SET_SELECTED_CAMERA'; export const INITIALIZE_SESSION = 'INITIALIZE_SESSION'; -export const START_SESSION = 'START_SESSION'; +export const SET_CURRENT_SESSION = 'SET_CURRENT_SESSION'; +export const SET_SESSION_STATUS = 'SET_SESSION_STATUS'; From c3a545700ecc2ab0063519ba26069b9521210a7f Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:12:07 +0530 Subject: [PATCH 13/15] chore(redux): update session reducer --- src/redux/reducers/session-reducer.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/redux/reducers/session-reducer.js b/src/redux/reducers/session-reducer.js index a932760..2919668 100644 --- a/src/redux/reducers/session-reducer.js +++ b/src/redux/reducers/session-reducer.js @@ -14,14 +14,15 @@ import { SET_CAMERA_CONNECTION_STATUS, SET_SELECTED_APPLICATION, INITIALIZE_SESSION, - START_SESSION + SET_SESSION_STATUS, + SET_CURRENT_SESSION } from '../types'; const initialState = { sessionTemp: {}, currentSession: {}, isSessionInitialized: false, - isSessionStarted: false, + sessionStatus: 'default', questionnaires: [], newQuestionnaire: {}, selectedApplication: {}, @@ -46,10 +47,15 @@ export function sessionReducer(state = initialState, action) { sessionTemp: {}, currentSession: action.payload, }; - case START_SESSION: + case SET_CURRENT_SESSION: return { ...state, - isSessionStarted: true, + currentSession: action.payload, + }; + case SET_SESSION_STATUS: + return { + ...state, + sessionStatus: action.payload, }; case FETCH_QUESTIONNAIRES: return { From 1ffd2d407d088e262c5e125d4c8964f80c7e0d65 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:12:39 +0530 Subject: [PATCH 14/15] chore(redux): add actions to handle session status and info --- src/redux/actions/session-actions.js | 34 +++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/redux/actions/session-actions.js b/src/redux/actions/session-actions.js index 5b3c24b..2c568b5 100644 --- a/src/redux/actions/session-actions.js +++ b/src/redux/actions/session-actions.js @@ -1,4 +1,3 @@ -import _ from 'lodash'; import { FETCH_QUESTIONNAIRES, SET_SESSION_VIEW_CONFIG, @@ -13,7 +12,8 @@ import { SET_CAMERA_CONNECTION_STATUS, SET_SELECTED_APPLICATION, INITIALIZE_SESSION, - START_SESSION + SET_SESSION_STATUS, + SET_CURRENT_SESSION } from '../types'; import { API_ENDPOINTS } from '../../api'; import { HttpInterceptor } from '../../services'; @@ -35,9 +35,23 @@ export const initializeSession = data => dispatch => { }); }; -export const startSession = data => dispatch => { +export const getSessionInfo = (id) => (dispatch) => { + const endpoint = API_ENDPOINTS.getSessionInfo.format(id); + return http.get(endpoint) + .then((response) => { + dispatch({ + type: SET_CURRENT_SESSION, + payload: response.data.data, + }); + }) + .catch((error) => { + // console.log('[ERROR]', ' [Applications, fetchApplications()]: HTTP GET - Callback Error', error); + }); +}; + +export const setSessionStatus = data => dispatch => { dispatch({ - type: START_SESSION, + type: SET_SESSION_STATUS, payload: data }); }; @@ -94,17 +108,21 @@ export const createQuestionnaire = data => dispatch => { }); }; -export const updateQuestionnaire = data => dispatch => { - const endpoint = API_ENDPOINTS.updateQuestionnaire.format(data.id); +export const updateQuestionnaire = (data, id) => dispatch => { + const endpoint = API_ENDPOINTS.updateQuestionnaire.format(id); const body = { - post: data.post + post: data }; return http .patch(endpoint, body) .then(response => { dispatch({ type: UPDATE_QUESTIONNAIRE, - payload: _.assign({}, data, response.data.data) + payload: response.data.data + }); + dispatch({ + type: SET_SELECTED_QUESTIONNAIRE, + payload: response.data.data }); }) .catch(error => { From 1ce5fa4c3bb35a507fef459cd36abefb7ee3d5e6 Mon Sep 17 00:00:00 2001 From: Brion Mario Date: Sat, 4 May 2019 01:13:18 +0530 Subject: [PATCH 15/15] chore(forms): implement logic to handle questionnaire update --- src/forms/sessions/create-questionnaire/submit.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/forms/sessions/create-questionnaire/submit.js b/src/forms/sessions/create-questionnaire/submit.js index 9dd48e0..5ed0915 100644 --- a/src/forms/sessions/create-questionnaire/submit.js +++ b/src/forms/sessions/create-questionnaire/submit.js @@ -1,17 +1,16 @@ import _ from 'lodash'; -import {createQuestionnaire} from '../../../redux/actions/session-actions'; +import {createQuestionnaire, updateQuestionnaire} from '../../../redux/actions/session-actions'; function submit(values, dispatch, props) { - let body = { - pre: {}, - post: {} - }; - if (props.config.type === 'pre') { + let body = { + pre: {}, + post: {} + }; _.assign(body.pre, values); dispatch(createQuestionnaire(body)); } else if (props.config.type === 'post') { - _.assign(body.post, values) + dispatch(updateQuestionnaire(values, props.config.id)); } }