diff --git a/diary-entry/__tests__/diaryentry-create.spec.js b/diary-entry/__tests__/diaryentry-create.spec.js new file mode 100644 index 0000000..1b369ef --- /dev/null +++ b/diary-entry/__tests__/diaryentry-create.spec.js @@ -0,0 +1,63 @@ +import DiaryentriesCreateComponent from '../diaryentry-create.component'; + +describe('Diaryentry Create', function() { + + beforeEach(angular.mock.module('ripple-ui')); + + let scope, ctrl, controller, template, state; + + beforeEach(inject(($injector, $controller, _$state_, _$stateParams_, _$ngRedux_, _diaryentriesActions_, _serviceRequests_) => { + controller = $controller; + scope = $injector.get('$rootScope').$new(); + state = _$state_; + + template = DiaryentriesCreateComponent.template; + ctrl = controller(DiaryentriesCreateComponent.controller, { + $scope: scope, + $state: state, + $stateParams: _$stateParams_, + $ngRedux: _$ngRedux_, + diaryentriesActions: _diaryentriesActions_, + serviceRequests: _serviceRequests_ + }); + })); + + beforeEach(function() { + spyOn(ctrl, 'goList'); + spyOn(ctrl, 'cancel'); + spyOn(ctrl, 'setCurrentPageData'); + spyOn(scope, 'actionLoadList'); + spyOn(scope, 'actionCreateDetail'); + spyOn(scope, 'create'); + + ctrl.goList(); + ctrl.cancel(); + ctrl.setCurrentPageData(); + scope.actionLoadList(); + scope.actionCreateDetail(); + scope.create(); + }); + + it('Template exist', function() { + expect(template).toBeDefined(); + }); + it('goList was called', function() { + expect(ctrl.goList).toHaveBeenCalled(); + }); + it('cancel was called', function() { + expect(ctrl.cancel).toHaveBeenCalled(); + }); + it('setCurrentPageData was called', function() { + expect(ctrl.setCurrentPageData).toHaveBeenCalled(); + }); + + it('actionLoadList was called', function() { + expect(scope.actionLoadList).toHaveBeenCalled(); + }); + it('actionCreateDetail was called', function() { + expect(scope.actionCreateDetail).toHaveBeenCalled(); + }); + it('create was called', function() { + expect(scope.create).toHaveBeenCalled(); + }); +}); diff --git a/diary-entry/__tests__/diaryentry-detail.spec.js b/diary-entry/__tests__/diaryentry-detail.spec.js new file mode 100644 index 0000000..267f8f8 --- /dev/null +++ b/diary-entry/__tests__/diaryentry-detail.spec.js @@ -0,0 +1,77 @@ +'use strict'; +import DiaryentriesCreateComponent from '../diaryentry-detail.component'; + +describe('Diaryentry Details', function() { + + beforeEach(angular.mock.module('ripple-ui')); + + let scope, ctrl, controller, template, stateParams, state, ngRedux, diaryentriesActions, usSpinnerService; + + beforeEach(inject(($injector, $controller, _$state_, _$stateParams_, _$ngRedux_, _diaryentriesActions_, _usSpinnerService_) => { + controller = $controller; + scope = $injector.get('$rootScope').$new(); + state = _$state_; + ngRedux = _$ngRedux_; + stateParams = _$stateParams_; + diaryentriesActions = _diaryentriesActions_; + usSpinnerService = _usSpinnerService_; + + template = DiaryentriesCreateComponent.template; + ctrl = controller(DiaryentriesCreateComponent.controller, { + $scope: scope, + $state: state, + $stateParams: stateParams, + $ngRedux: ngRedux, + diaryentriesActions: diaryentriesActions, + usSpinnerService: usSpinnerService + }); + })); + + beforeEach(function() { + spyOn(ctrl, 'actionLoadList'); + spyOn(ctrl, 'actionLoadDetail'); + spyOn(ctrl, 'edit'); + spyOn(ctrl, 'cancelEdit'); + spyOn(ctrl, 'setCurrentPageData'); + spyOn(scope, 'actionUpdateDetail'); + spyOn(scope, 'confirmEdit'); + + ctrl.actionLoadList(); + ctrl.actionLoadDetail(); + ctrl.edit(); + ctrl.cancelEdit(); + ctrl.setCurrentPageData(); + scope.actionUpdateDetail(); + scope.confirmEdit(); + }); + + it('Template exist', function() { + expect(template).toBeDefined(); + }); + it('Controller exist', function() { + expect(ctrl).toBeDefined(); + }); + + it('actionLoadList was called', function() { + expect(ctrl.actionLoadList).toHaveBeenCalled(); + }); + it('actionLoadDetail was called', function() { + expect(ctrl.actionLoadDetail).toHaveBeenCalled(); + }); + it('edit was called', function() { + expect(ctrl.edit).toHaveBeenCalled(); + }); + it('cancelEdit was called', function() { + expect(ctrl.cancelEdit).toHaveBeenCalled(); + }); + it('setCurrentPageData was called', function() { + expect(ctrl.setCurrentPageData).toHaveBeenCalled(); + }); + + it('actionUpdateDetail was called', function() { + expect(scope.actionUpdateDetail).toHaveBeenCalled(); + }); + it('confirmEdit was called', function() { + expect(scope.confirmEdit).toHaveBeenCalled(); + }); +}); diff --git a/diary-entry/__tests__/diaryentry-list.spec.js b/diary-entry/__tests__/diaryentry-list.spec.js new file mode 100644 index 0000000..1a1ddd5 --- /dev/null +++ b/diary-entry/__tests__/diaryentry-list.spec.js @@ -0,0 +1,94 @@ +'use strict'; +import DiaryentryListComponent from '../diaryentry-list.component'; +import * as types from '../action-types'; +import diaryentry from '../diaryentry-actions'; + +describe('Diaryentry List', function() { + + beforeEach(angular.mock.module('ripple-ui')); + + let scope, + ctrl, + controller, + template, + stateParams, + state, + ngRedux, + diaryentriesActions, + serviceRequests, + usSpinnerService, + fakeCall, + actions; + + beforeEach(inject(($injector, $controller, _$state_, _$stateParams_, _$ngRedux_, _diaryentriesActions_, _serviceRequests_, _usSpinnerService_) => { + controller = $controller; + scope = $injector.get('$rootScope').$new(); + state = _$state_; + serviceRequests = _serviceRequests_; + ngRedux = _$ngRedux_; + stateParams = _$stateParams_; + diaryentriesActions = _diaryentriesActions_; + usSpinnerService = _usSpinnerService_; + + template = DiaryentryListComponent.template; + + ctrl = controller(DiaryentryListComponent.controller, { + $scope: scope, + $state: state, + $stateParams: stateParams, + $ngRedux: ngRedux, + diaryentriesActions: diaryentriesActions, + serviceRequests: serviceRequests, + usSpinnerService: usSpinnerService + }); + + actions = $injector.get('diaryentriesActions'); + // scope.$digest(); + })); + + beforeEach(function() { + fakeCall = { + calldiaryentry: diaryentry + }; + + spyOn(fakeCall, 'calldiaryentry'); + + spyOn(ctrl, 'actionLoadList'); + spyOn(ctrl, 'create'); + spyOn(ctrl, 'go'); + spyOn(ctrl, 'setCurrentPageData'); + + fakeCall.calldiaryentry({}, types.DIATY_ENTRIES); + + ctrl.actionLoadList(); + ctrl.create(); + ctrl.go(); + ctrl.setCurrentPageData(); + }); + + it('Template exist', function() { + expect(template).toBeDefined(); + }); + it('Controller exist', function() { + expect(ctrl).toBeDefined(); + }); + it('Include diaryentriesActions in index actions file', function() { + expect(actions).toBeDefined(); + }); + it('Diaryentry reducer was called', function() { + expect(fakeCall.calldiaryentry).toHaveBeenCalled(); + }); + + it('actionLoadList was called', function() { + expect(ctrl.actionLoadList).toHaveBeenCalled(); + }); + it('create was called', function() { + expect(ctrl.create).toHaveBeenCalled(); + }); + it('go was called', function() { + expect(ctrl.go).toHaveBeenCalled(); + }); + it('setCurrentPageData was called', function() { + expect(ctrl.setCurrentPageData).toHaveBeenCalled(); + }); +}); diff --git a/diary-entry/action-types.js b/diary-entry/action-types.js new file mode 100644 index 0000000..6ab6e99 --- /dev/null +++ b/diary-entry/action-types.js @@ -0,0 +1,16 @@ +export const DIATY_ENTRIES = 'DIATY_ENTRIES'; +export const DIATY_ENTRIES_SUCCESS = 'DIATY_ENTRIES_SUCCESS'; +export const DIATY_ENTRIES_ERROR = 'DIATY_ENTRIES_ERROR'; +export const DIATY_ENTRIES__CLEAR = 'DIATY_ENTRIES__CLEAR'; + +export const DIATY_ENTRIES_GET = 'DIATY_ENTRIES_GET'; +export const DIATY_ENTRIES_GET_SUCCESS = 'DIATY_ENTRIES_GET_SUCCESS'; +export const DIATY_ENTRIES_GET_ERROR = 'DIATY_ENTRIES_GET_ERROR'; + +export const DIATY_ENTRIES_CREATE = 'DIATY_ENTRIES_CREATE'; +export const DIATY_ENTRIES_CREATE_SUCCESS = 'DIATY_ENTRIES_CREATE_SUCCESS'; +export const DIATY_ENTRIES_CREATE_ERROR = 'DIATY_ENTRIES_CREATE_ERROR'; + +export const DIATY_ENTRIES_UPDATE = 'DIATY_ENTRIES_UPDATE'; +export const DIATY_ENTRIES_UPDATE_SUCCESS = 'DIATY_ENTRIES_UPDATE_SUCCESS'; +export const DIATY_ENTRIES_UPDATE_ERROR = 'DIATY_ENTRIES_UPDATE_ERROR'; diff --git a/diary-entry/diaryentry-actions.js b/diary-entry/diaryentry-actions.js new file mode 100644 index 0000000..98779a4 --- /dev/null +++ b/diary-entry/diaryentry-actions.js @@ -0,0 +1,99 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + */ + +import { bindActionCreators } from 'redux'; +import * as types from './action-types'; + +export function clear() { + return { type: types.DIATY_ENTRIES__CLEAR } +} +export function all(patientId) { + return { + types: [types.DIATY_ENTRIES, types.DIATY_ENTRIES_SUCCESS, types.DIATY_ENTRIES_ERROR], + + shouldCallAPI: (state) => !state.diaryentries.response, + + config: { + method: 'get', + url: '/api/patients/' + patientId + '/diaryentries' + }, + + meta: { + patientId: patientId, + timestamp: Date.now() + } + }; +} +export function get(patientId, compositionId, source) { + return { + types: [types.DIATY_ENTRIES_GET, types.DIATY_ENTRIES_GET_SUCCESS, types.DIATY_ENTRIES_GET_ERROR], + + shouldCallAPI: (state) => !state.diaryentries.response, + + config: { + method: 'get', + url: '/api/patients/' + patientId + '/diaryentries/' + compositionId + }, + + meta: { + timestamp: Date.now() + } + }; +} +export function create(patientId, composition) { + return { + types: [types.DIATY_ENTRIES_CREATE, types.DIATY_ENTRIES_CREATE_SUCCESS, types.DIATY_ENTRIES_CREATE_ERROR], + + shouldCallAPI: (state) => !state.diaryentries.response, + + config: { + method: 'post', + url: '/api/patients/' + patientId + '/diaryentries', + data: composition + }, + + meta: { + timestamp: Date.now() + } + }; +} +export function update(patientId, sourceId, composition) { + return { + types: [types.DIATY_ENTRIES_UPDATE, types.DIATY_ENTRIES_UPDATE_SUCCESS, types.DIATY_ENTRIES_UPDATE_ERROR], + + shouldCallAPI: (state) => !state.diaryentries.response, + + config: { + method: 'put', + url: '/api/patients/' + patientId + '/diaryentries/' + sourceId, + data: composition + }, + + meta: { + timestamp: Date.now() + } + }; +} + +export default function diaryentriesActions($ngRedux) { + let actionCreator = { + all, clear, get, create, update + }; + + return bindActionCreators(actionCreator, $ngRedux.dispatch); +} + +diaryentriesActions.$inject = ['$ngRedux']; diff --git a/diary-entry/diaryentry-create.component.js b/diary-entry/diaryentry-create.component.js new file mode 100644 index 0000000..e2a58ac --- /dev/null +++ b/diary-entry/diaryentry-create.component.js @@ -0,0 +1,136 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +*/ + +let entryTypes = require('./entry-types'); +let templateDiaryentriesCreate = require('./diaryentry-create.html'); + +class DiaryentriesCreateController { + constructor($scope, $state, $stateParams, $ngRedux, diaryentriesActions, serviceRequests, serviceFormatted) { + $scope.actionLoadList = diaryentriesActions.all; + $scope.actionCreateDetail = diaryentriesActions.create; + + $scope.diaryEntryTypes = entryTypes.defaultEntryTypes; + + $scope.diaryentry = {}; + $scope.diaryentry.dateCreated = new Date().toISOString().slice(0, 10); + $scope.recognitionStarted = false; + $scope.hasSpeechRecognition = false; + + try { + let SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; + this.recognition = new SpeechRecognition(); + this.recognition.lang = 'en-US'; + this.recognition.continuous = true; + $scope.hasSpeechRecognition = true; + } catch(error) { + console.error(error); + } + + if ($scope.hasSpeechRecognition) { + this.recognition.onstart = function() { + console.log('Voice recognition activated. Try speaking into the microphone.'); + } + + this.recognition.onspeechend = function() { + console.log('You were quiet for a while so voice recognition turned itself off.'); + } + + this.recognition.onerror = function(event) { + if(event.error == 'no-speech') { + console.log('No speech was detected. Try again.'); + } + } + + this.recognition.onresult = function(event) { + var current = event.resultIndex; + var transcript = event.results[current][0].transcript; + + if (!$scope.diaryentry.notes) { + $scope.diaryentry.notes = ''; + } + $scope.diaryentry.notes += transcript; + $scope.$apply(); + } + } + + $scope.startSpeach = () => { + if ($scope.hasSpeechRecognition && !$scope.recognitionStarted) { + $scope.recognitionStarted = true; + this.recognition.start(); + } + } + + $scope.stopSpeach = () => { + if ($scope.hasSpeechRecognition && $scope.recognitionStarted) { + $scope.recognitionStarted = false; + this.recognition.stop(); + } + } + + this.goList = function () { + $state.go('diaryentries', { + patientId: $stateParams.patientId, + reportType: $stateParams.reportType, + searchString: $stateParams.searchString, + queryType: $stateParams.queryType + }); + }; + + this.cancel = function () { + this.goList(); + }; + + $scope.create = function (diaryentryForm, diaryentries) { + $scope.formSubmitted = true; + + if (diaryentryForm.$valid) { + let toAdd = { + noteType: diaryentries.noteType, + notes: diaryentries.notes, + dateCreated: diaryentries.dateCreated, + author: diaryentries.author, + source: 'openehr' + }; + serviceFormatted.propsToString(toAdd, 'dateCreated'); + $scope.actionCreateDetail($stateParams.patientId, toAdd); + } + }.bind(this); + + this.setCurrentPageData = function (data) { + if (data.diaryentries.dataCreate !== null) { + $scope.actionLoadList($stateParams.patientId); + this.goList(); + } + if (serviceRequests.currentUserData) { + $scope.currentUser = serviceRequests.currentUserData; + $scope.diaryentry.author = $scope.currentUser.email; + } + }; + + let unsubscribe = $ngRedux.connect(state => ({ + getStoreData: this.setCurrentPageData(state) + }))(this); + $scope.$on('$destroy', unsubscribe); + } +} + +const DiaryentriesCreateComponent = { + template: templateDiaryentriesCreate, + controller: DiaryentriesCreateController +}; + +DiaryentriesCreateController.$inject = ['$scope', '$state', '$stateParams', '$ngRedux', 'diaryentriesActions', 'serviceRequests', 'serviceFormatted']; +export default DiaryentriesCreateComponent; diff --git a/diary-entry/diaryentry-create.html b/diary-entry/diaryentry-create.html new file mode 100644 index 0000000..af473ce --- /dev/null +++ b/diary-entry/diaryentry-create.html @@ -0,0 +1,83 @@ + + +
+
+
+
+ + +
+

Create Diary Entry

+
+
+
+
+
+
+ +
+ +
+ You must enter a value. +
+ +
+ + + + + + + + + + + You must enter a value. +
+ +
+ +
+ +
+ You must enter a value. +
+ +
+ +
+
+ +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
diff --git a/diary-entry/diaryentry-detail.component.js b/diary-entry/diaryentry-detail.component.js new file mode 100644 index 0000000..eada60e --- /dev/null +++ b/diary-entry/diaryentry-detail.component.js @@ -0,0 +1,179 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +*/ + +let entryTypes = require('./entry-types'); +let templateDiaryentriesDetail = require('./diaryentry-detail.html'); + +class DiaryentriesDetailController { + constructor($scope, $state, $stateParams, $ngRedux, diaryentriesActions, serviceRequests, usSpinnerService, serviceFormatted) { + this.actionLoadList = diaryentriesActions.all; + this.actionLoadDetail = diaryentriesActions.get; + $scope.actionUpdateDetail = diaryentriesActions.update; + + $scope.diaryEntryTypes = entryTypes.defaultEntryTypes; + + usSpinnerService.spin('detail-spinner'); + this.actionLoadDetail($stateParams.patientId, $stateParams.detailsIndex); + + //Edit Diary Entry + $scope.isEdit = false; + + $scope.recognitionStarted = false; + $scope.hasSpeechRecognition = false; + + try { + let SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; + this.recognition = new SpeechRecognition(); + this.recognition.lang = 'en-US'; + this.recognition.continuous = true; + $scope.hasSpeechRecognition = true; + } catch(error) { + console.error(error); + } + + if ($scope.hasSpeechRecognition) { + this.recognition.onstart = function() { + console.log('Voice recognition activated. Try speaking into the microphone.'); + } + + this.recognition.onspeechend = function() { + console.log('You were quiet for a while so voice recognition turned itself off.'); + } + + this.recognition.onerror = function(event) { + if(event.error == 'no-speech') { + console.log('No speech was detected. Try again.'); + } + } + + this.recognition.onresult = function(event) { + var current = event.resultIndex; + var transcript = event.results[current][0].transcript; + + if (!$scope.diaryentryEdit || !$scope.diaryentryEdit.notes) { + $scope.diaryentryEdit.notes = ''; + } + $scope.diaryentryEdit.notes += transcript; + $scope.$apply(); + } + } + + $scope.startSpeach = () => { + if ($scope.hasSpeechRecognition && !$scope.recognitionStarted) { + $scope.recognitionStarted = true; + this.recognition.start(); + } + } + + $scope.stopSpeach = () => { + if ($scope.hasSpeechRecognition && $scope.recognitionStarted) { + $scope.recognitionStarted = false; + this.recognition.stop(); + } + } + + /* istanbul ignore next */ + this.edit = function () { + $scope.isEdit = true; + $scope.diaryentryEdit = Object.assign({}, this.diaryentry); + + $scope.diaryentryEdit.dateCreated = new Date(this.diaryentry.dateCreated); + }; + + this.cancelEdit = function () { + $scope.isEdit = false; + }; + + $scope.confirmEdit = function (diaryentryForm, diaryEntries) { + $scope.formSubmitted = true; + + /* istanbul ignore if */ + if (diaryentryForm.$valid) { + let toUpdate = { + noteType: diaryEntries.noteType, + notes: diaryEntries.notes, + author: diaryEntries.author, + source: diaryEntries.source, + sourceId: diaryEntries.sourceId, + dateCreated: new Date().getTime() + }; + + $scope.isEdit = false; + serviceFormatted.propsToString(toUpdate, 'dateCreated'); + $scope.actionUpdateDetail($stateParams.patientId, diaryEntries.sourceId, toUpdate); + } + }; + + this.setCurrentPageData = function (store) { + const state = store.diaryentries; + const { patientId, detailsIndex } = $stateParams; + + // TODO: remove this + state.dataGet = { + sourceId: 1, + author: "bob.smith@gmail.com", + dateCreated: "2018-04-07", + noteType: "Exam Report", + notes: "qwe", + source: "openehr" + }; + + // Get Details data + if (state.dataGet) { + this.diaryentry = state.dataGet; + this.dateCreated = moment(this.diaryentry.dateCreated).format('DD-MMM-YYYY'); + (detailsIndex === state.dataGet.sourceId) ? usSpinnerService.stop('detail-spinner') : null; + } + + // Update Detail + if (state.dataUpdate !== null) { + // After Update we request all list firstly + this.actionLoadList(patientId); + } + if (state.isUpdateProcess) { + usSpinnerService.spin('detail-update-spinner'); + if (!state.dataGet && !state.isGetFetching) { + // We request detail when data is empty + // Details are cleared after request LoadAll list + this.actionLoadDetail(patientId, detailsIndex); + } + } else { + usSpinnerService.stop('detail-update-spinner'); + } + if (serviceRequests.currentUserData) { + this.currentUser = serviceRequests.currentUserData; + } + + if (state.error) { + usSpinnerService.stop('detail-spinner'); + usSpinnerService.stop('detail-update-spinner'); + } + }; + + let unsubscribe = $ngRedux.connect(state => ({ + getStoreData: this.setCurrentPageData(state) + }))(this); + $scope.$on('$destroy', unsubscribe); + } +} + +const DiaryentriesDetailComponent = { + template: templateDiaryentriesDetail, + controller: DiaryentriesDetailController +}; + +DiaryentriesDetailController.$inject = ['$scope', '$state', '$stateParams', '$ngRedux', 'diaryentriesActions', 'serviceRequests', 'usSpinnerService', 'serviceFormatted']; +export default DiaryentriesDetailComponent; diff --git a/diary-entry/diaryentry-detail.html b/diary-entry/diaryentry-detail.html new file mode 100644 index 0000000..b2adb13 --- /dev/null +++ b/diary-entry/diaryentry-detail.html @@ -0,0 +1,135 @@ + +
+
+
+
+ + +
+

Diary Entry

+
+
+
+
+
+ +
+ +
{{ $ctrl.diaryentry.noteType }}
+
+ +
+ +
{{ $ctrl.diaryentry.notes }}
+
+ +
+ +
{{ $ctrl.diaryentry.author }}
+
+ +
+ +
{{ $ctrl.diaryentry.dateCreated | date:'dd-MMM-yyyy' }}
+
+ +
+ +
{{ $ctrl.diaryentry.source }}
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ + +
+

Edit Personal Note

+
+
+
+
+
+
+ +
+ +
+ You must enter a value. +
+ +
+ + + + + + + + + + + You must enter a value. +
+
+ +
+ +
+ You must enter a value. +
+
+ +
+
+ +
+ +
+
+ +
+
+ +
+
+
+
+ + +
+
+
+
+
+ + + +
diff --git a/diary-entry/diaryentry-list.component.js b/diary-entry/diaryentry-list.component.js new file mode 100644 index 0000000..c1e78aa --- /dev/null +++ b/diary-entry/diaryentry-list.component.js @@ -0,0 +1,94 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +*/ + +let templateDiaryentriesList = require('./diaryentry-list.html'); + +class DiaryentriesListController { + constructor($scope, $state, $stateParams, $ngRedux, diaryentriesActions, serviceRequests, usSpinnerService, serviceFormatted) { + serviceRequests.publisher('routeState', {state: $state.router.globals.current.views, breadcrumbs: $state.router.globals.current.breadcrumbs, name: 'patients-details'}); + serviceRequests.publisher('headerTitle', {title: 'Patients Details'}); + diaryentriesActions.clear(); + this.actionLoadList = diaryentriesActions.all; + + this.isShowCreateBtn = $state.router.globals.$current.name !== 'diaryentries-create'; + this.isShowExpandBtn = $state.router.globals.$current.name !== 'diaryentries'; + + + this.create = function () { + $state.go('diaryentries-create', { + patientId: $stateParams.patientId + }); + }; + + this.go = function (id, source) { + $state.go('diaryentries-detail', { + patientId: $stateParams.patientId, + detailsIndex: id, + page: $scope.currentPage || 1, + source: source + }); + }; + + this.setCurrentPageData = function (store) { + const state = store.diaryentries; + + // TODO: remove this + state.data = [{ + sourceId: 1, + author: "bob.smith@gmail.com", + dateCreated: "2018-04-07", + noteType: "Exam Report", + notes: "qwe", + source: "openehr" + }]; + + const pagesInfo = store.pagesInfo; + const pluginName = 'diaryEntries'; + + if (serviceRequests.checkIsCanLoadingListData(state, pagesInfo, pluginName, $stateParams.patientId)) { + this.actionLoadList($stateParams.patientId); + serviceRequests.setPluginPage(pluginName); + usSpinnerService.spin('list-spinner'); + } + if (state.data) { + this.diaryentries = state.data; + + serviceFormatted.formattingTablesDate(this.diaryentries, ['dateCreated'], serviceFormatted.formatCollection.DDMMMYYYY); + serviceFormatted.filteringKeys = ['noteType', 'author', 'dateCreated', 'source']; + } + if (state.data || state.error) { + usSpinnerService.stop('list-spinner'); + setTimeout(() => { usSpinnerService.stop('list-spinner') }, 0); + } + if (serviceRequests.currentUserData) { + this.currentUser = serviceRequests.currentUserData; + } + }; + + let unsubscribe = $ngRedux.connect(state => ({ + getStoreData: this.setCurrentPageData(state) + }))(this); + $scope.$on('$destroy', unsubscribe); + } +} + +const DiaryentriesListComponent = { + template: templateDiaryentriesList, + controller: DiaryentriesListController +}; + +DiaryentriesListController.$inject = ['$scope', '$state', '$stateParams', '$ngRedux', 'diaryentriesActions', 'serviceRequests', 'usSpinnerService', 'serviceFormatted']; +export default DiaryentriesListComponent; diff --git a/diary-entry/diaryentry-list.html b/diary-entry/diaryentry-list.html new file mode 100644 index 0000000..04c3972 --- /dev/null +++ b/diary-entry/diaryentry-list.html @@ -0,0 +1,82 @@ + + +
+
+
+ +
+
+ +
+

Diary Entries

+
+
+
+ +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeAuthorDate CreatedSource
{{ diaryentry.noteType }}{{ diaryentry.author }}{{ diaryentry.dateCreated }}{{ diaryentry.source }}
+ Loading... + No personal notes +
+ + + +
+
+
+ +
+
+ +
+
+
+
+
diff --git a/diary-entry/diaryentry-reducer-all.js b/diary-entry/diaryentry-reducer-all.js new file mode 100644 index 0000000..c6fb455 --- /dev/null +++ b/diary-entry/diaryentry-reducer-all.js @@ -0,0 +1,133 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + */ + +import * as types from './action-types'; + +const INITIAL_STATE = { + isFetching: false, + error: false, + data: null, + dataGet: null, + isGetFetching: false, + dataCreate: null, + dataUpdate: null, + isUpdateProcess: false, + patientId: null +}; + +export default function diaryentries(state = INITIAL_STATE, action) { + const {payload} = action; + + var actions = { + [types.DIATY_ENTRIES]: (state) => { + state.dataCreate = null; + state.dataUpdate = null; + return Object.assign({}, state, { + isFetching: true, + error: false + }); + }, + [types.DIATY_ENTRIES_SUCCESS]: (state) => { + if (state.isUpdateProcess) { + state.dataGet = null; + } + return Object.assign({}, state, { + isFetching: false, + data: payload.response, + patientId: payload.meta.patientId, + }); + }, + [types.DIATY_ENTRIES_ERROR]: (state) => { + return Object.assign({}, state, { + isFetching: false, + error: payload.error + }); + }, + [types.DIATY_ENTRIES__CLEAR]: (state) => { + return Object.assign({}, state, { + error: false, + }); + }, + + [types.DIATY_ENTRIES_GET]: (state) => { + return Object.assign({}, state, { + isFetching: true, + isGetFetching: true, + error: false + }); + }, + [types.DIATY_ENTRIES_GET_SUCCESS]: (state) => { + state.dataUpdate = null; + return Object.assign({}, state, { + isUpdateProcess: false, + isFetching: false, + isGetFetching: false, + error: false, + dataGet: payload.response + }); + }, + [types.DIATY_ENTRIES_GET_ERROR]: (state) => { + return Object.assign({}, state, { + isUpdateProcess: false, + isFetching: false, + isGetFetching: false, + error: payload.error + }); + }, + + [types.DIATY_ENTRIES_CREATE]: (state) => { + return Object.assign({}, state, { + isFetching: true, + error: false + }); + }, + [types.DIATY_ENTRIES_CREATE_SUCCESS]: (state) => { + return Object.assign({}, state, { + isFetching: false, + dataCreate: payload.response + }); + }, + [types.DIATY_ENTRIES_CREATE_ERROR]: (state) => { + return Object.assign({}, state, { + isFetching: false, + error: payload.error + }); + }, + [types.DIATY_ENTRIES_UPDATE]: (state) => { + return Object.assign({}, state, { + isUpdateProcess: true, + isFetching: true, + error: false + }); + }, + [types.DIATY_ENTRIES_UPDATE_SUCCESS]: (state) => { + return Object.assign({}, state, { + isFetching: false, + dataUpdate: payload.response + }); + }, + [types.DIATY_ENTRIES_UPDATE_ERROR]: (state) => { + return Object.assign({}, state, { + isFetching: false, + error: payload.error + }); + } + }; + + return actions[action.type] ? + actions[action.type](state) : + state; +} diff --git a/diary-entry/entry-types.js b/diary-entry/entry-types.js new file mode 100644 index 0000000..c496ad9 --- /dev/null +++ b/diary-entry/entry-types.js @@ -0,0 +1,5 @@ +export const defaultEntryTypes = [ + 'Exam Report', + 'Note', + 'Hypothesis' +]; diff --git a/diary-entry/index.js b/diary-entry/index.js new file mode 100644 index 0000000..7fdf6f3 --- /dev/null +++ b/diary-entry/index.js @@ -0,0 +1,40 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + */ +import routes from "./index.route"; +import reducer from "./diaryentry-reducer-all"; +import diaryentriesListComponent from './diaryentry-list.component'; +import diaryentriesCreateComponent from './diaryentry-create.component'; +import diaryentriesDetailComponent from './diaryentry-detail.component'; +import diaryentriesActions from './diaryentry-actions'; + +export default { + "name": 'diaryentries', + "routes": routes, + "reducer": reducer, + "components": { + diaryentriesListComponent, + diaryentriesCreateComponent, + diaryentriesDetailComponent + }, + "actions": { + diaryentriesActions + }, + "sidebarInfo": { + name: 'diaryentries', + link: 'diaryentries', + title: 'Diary Entries' + } +} diff --git a/diary-entry/index.route.js b/diary-entry/index.route.js new file mode 100644 index 0000000..344181f --- /dev/null +++ b/diary-entry/index.route.js @@ -0,0 +1,66 @@ +/* + ~ Copyright 2017 Ripple Foundation C.I.C. Ltd + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + */ +routeConfig.$inject = ['$stateProvider', '$urlRouterProvider']; + +function routeConfig($stateProvider, $urlRouterProvider) { + var breadcrumbs = [{ + title: 'Patient Listings', + state: 'patients-list' + }, { + title: 'Patient Summary', + state: 'patients-summary' + }, { + title: 'Diary Entries', + state: 'diaryentries' + }]; + + $stateProvider + .state('diaryentries', { + url: '/patients/{patientId:int}/diaryentries?reportType&searchString&queryType', + views: { + banner: {template: ''}, + actions: {template: ''}, + main: {template: ''} + }, + params: {patientId: null, reportType: null}, + breadcrumbs: breadcrumbs + }) + .state('diaryentries-create', { + url: '/patients/{patientId:int}/diaryentries/create?reportType&searchString&queryType', + views: { + banner: {template: ''}, + actions: {template: ''}, + main: {template: ''}, + detail: {template: ''} + }, + params: {patientId: null, reportType: null}, + breadcrumbs: breadcrumbs, + qweasd: 'lol' + }) + .state('diaryentries-detail', { + url: '/patients/{patientId:int}/diaryentries/{detailsIndex}?page&reportType&searchString&queryType&source', + views: { + banner: {template: ''}, + actions: {template: ''}, + main: {template: ''}, + detail: {template: ''} + }, + params: {patientId: null, reportType: null, detailsIndex: null}, + breadcrumbs: breadcrumbs + }); +} + +export default routeConfig; diff --git a/index.js b/index.js index 8814c1f..f2a07e3 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,9 @@ ~ limitations under the License. */ import genericPlugin from './generic-plugin/index'; +import diaryEntries from './diary-entry/index'; export default [ - genericPlugin -] \ No newline at end of file + genericPlugin, + diaryEntries +]