From 9b42447aaa90393056a35baa644aea3523e10ba5 Mon Sep 17 00:00:00 2001 From: Ashish Kurian Date: Wed, 23 Aug 2023 14:33:15 +0530 Subject: [PATCH 01/11] [Ashish]Add.Abilty to switch tabs in forms without filling mandatory fields and alerts added --- .../controllers/consultationController.js | 12 +++++++++--- ui/app/i18n/clinical/locale_en.json | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/app/clinical/consultation/controllers/consultationController.js b/ui/app/clinical/consultation/controllers/consultationController.js index 126b9589c2..ffe5fb1c95 100644 --- a/ui/app/clinical/consultation/controllers/consultationController.js +++ b/ui/app/clinical/consultation/controllers/consultationController.js @@ -473,9 +473,15 @@ angular.module('bahmni.clinical').controller('ConsultationController', _.each($scope.consultation.observationForms, function (observationForm) { if (valid && observationForm.component) { var value = observationForm.component.getValue(); - if (value.errors) { - messagingService.showMessage('error', "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"); - valid = false; + + if (value.errors) + { + if ($state.current.name === "patient.dashboard.show.observations") { + messagingService.showMessage('error', "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"); + } + else { + messagingService.showMessage('error', "{{'CLINICAL_FORM_ERRORS_ON_OBSERVATION_TAB_MESSAGE_KEY' | translate }}"); + } } } }); diff --git a/ui/app/i18n/clinical/locale_en.json b/ui/app/i18n/clinical/locale_en.json index b0207eda5c..3b0289e954 100644 --- a/ui/app/i18n/clinical/locale_en.json +++ b/ui/app/i18n/clinical/locale_en.json @@ -89,6 +89,7 @@ "CLINICAL_SAVE_TRANSLATION_KEY": "Save", "CLINICAL_SAVE_SUCCESS_MESSAGE_KEY": "Saved", "CLINICAL_SAVE_FAILURE_MESSAGE_KEY": "An error has occurred on the server. Information not saved.", + "CLINICAL_FORM_ERRORS_ON_OBSERVATION_TAB_MESSAGE_KEY": "Please enter values in the mandatory fields in observations to proceed", "CLINICAL_FORM_ERRORS_MESSAGE_KEY": "Please enter a value in the mandatory fields or correct the value in the highlighted fields to proceed", "CLINICAL_FORM_EDIT_ERROR_MESSAGE_KEY": "Form not found", "CLINICAL_ORDER_RADIOLOGY_NEED_PRINT": "Need Print for this order.", From 81b457808a4656310699ff243b8ee81bad3c9655 Mon Sep 17 00:00:00 2001 From: Ashish Kurian Date: Wed, 23 Aug 2023 15:02:14 +0530 Subject: [PATCH 02/11] [Ashish]Update . Allowing navigation between tabs in concultation without filling the mandatory fields --- .../consultation/controllers/consultationController.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/app/clinical/consultation/controllers/consultationController.js b/ui/app/clinical/consultation/controllers/consultationController.js index ffe5fb1c95..b9bb230361 100644 --- a/ui/app/clinical/consultation/controllers/consultationController.js +++ b/ui/app/clinical/consultation/controllers/consultationController.js @@ -478,9 +478,11 @@ angular.module('bahmni.clinical').controller('ConsultationController', { if ($state.current.name === "patient.dashboard.show.observations") { messagingService.showMessage('error', "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"); + valid = false; } else { messagingService.showMessage('error', "{{'CLINICAL_FORM_ERRORS_ON_OBSERVATION_TAB_MESSAGE_KEY' | translate }}"); + valid = false; } } } @@ -499,7 +501,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', var errorMessage = discontinuedDrugOrderValidationMessage; messagingService.showMessage('error', errorMessage); } - return shouldAllow && !discontinuedDrugOrderValidationMessage && isObservationFormValid(); + return shouldAllow && !discontinuedDrugOrderValidationMessage ; }; var copyConsultationToScope = function (consultationWithDiagnosis) { @@ -516,7 +518,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', }); $scope.save = function (toStateConfig) { - if (!isFormValid()) { + if (isFormValid() && !isObservationFormValid()) { $scope.$parent.$parent.$broadcast("event:errorsOnForm"); return $q.when({}); } From 25086742fef4cef8456cd22ddd50a7f46a20bbc3 Mon Sep 17 00:00:00 2001 From: Arjun-Go Date: Thu, 31 Aug 2023 20:58:07 +0530 Subject: [PATCH 03/11] fix. test failures after cherry-picks --- .../controllers/consultationController.js | 42 ++-- .../addTreatmentController.spec.js | 1 + .../consultationController.spec.js | 223 +++++++++--------- 3 files changed, 136 insertions(+), 130 deletions(-) diff --git a/ui/app/clinical/consultation/controllers/consultationController.js b/ui/app/clinical/consultation/controllers/consultationController.js index b9bb230361..7205dbe7d7 100644 --- a/ui/app/clinical/consultation/controllers/consultationController.js +++ b/ui/app/clinical/consultation/controllers/consultationController.js @@ -7,10 +7,10 @@ angular.module('bahmni.clinical').controller('ConsultationController', 'ngDialog', '$filter', 'configurations', 'visitConfig', 'conditionsService', 'configurationService', 'auditLogService', 'confirmBox', 'virtualConsultService', 'adhocTeleconsultationService', function ($scope, $rootScope, $state, $location, $translate, clinicalAppConfigService, diagnosisService, urlHelper, contextChangeHandler, - spinner, encounterService, messagingService, sessionService, retrospectiveEntryService, patientContext, $q, - patientVisitHistoryService, $stateParams, $window, visitHistory, clinicalDashboardConfig, appService, - ngDialog, $filter, configurations, visitConfig, conditionsService, configurationService, auditLogService, confirmBox, - virtualConsultService, adhocTeleconsultationService) { + spinner, encounterService, messagingService, sessionService, retrospectiveEntryService, patientContext, $q, + patientVisitHistoryService, $stateParams, $window, visitHistory, clinicalDashboardConfig, appService, + ngDialog, $filter, configurations, visitConfig, conditionsService, configurationService, auditLogService, confirmBox, + virtualConsultService, adhocTeleconsultationService) { var ERROR = 1; var DateUtil = Bahmni.Common.Util.DateUtil; var getPreviousActiveCondition = Bahmni.Common.Domain.Conditions.getPreviousActiveCondition; @@ -181,7 +181,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', var initialize = function () { var appExtensions = clinicalAppConfigService.getAllConsultationBoards(); - $scope.adtNavigationConfig = {forwardUrl: Bahmni.Clinical.Constants.adtForwardUrl, title: $translate.instant("CLINICAL_GO_TO_DASHBOARD_LABEL"), privilege: Bahmni.Clinical.Constants.adtPrivilege }; + $scope.adtNavigationConfig = { forwardUrl: Bahmni.Clinical.Constants.adtForwardUrl, title: $translate.instant("CLINICAL_GO_TO_DASHBOARD_LABEL"), privilege: Bahmni.Clinical.Constants.adtPrivilege }; $scope.availableBoards = $scope.availableBoards.concat(appExtensions); $scope.showSaveConfirmDialogConfig = appService.getAppDescriptor().getConfigValue('showSaveConfirmDialog'); var adtNavigationConfig = appService.getAppDescriptor().getConfigValue('adtNavigationConfig'); @@ -203,7 +203,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', event.preventDefault(); spinner.hide(toState.spinnerToken); ngDialog.close(); - $scope.toStateConfig = {toState: toState, toParams: toParams}; + $scope.toStateConfig = { toState: toState, toParams: toParams }; $scope.displayConfirmationDialog(); } } @@ -212,7 +212,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', }); $scope.adtNavigationURL = function (visitUuid) { - return appService.getAppDescriptor().formatUrl($scope.adtNavigationConfig.forwardUrl, {'patientUuid': $scope.patient.uuid, 'visitUuid': visitUuid}); + return appService.getAppDescriptor().formatUrl($scope.adtNavigationConfig.forwardUrl, { 'patientUuid': $scope.patient.uuid, 'visitUuid': visitUuid }); }; var cleanUpListenerErrorsOnForm = $scope.$on("event:errorsOnForm", function () { @@ -225,7 +225,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', event.preventDefault(); $scope.targetUrl = event.currentTarget.getAttribute('href'); } - ngDialog.openConfirm({template: '../common/ui-helper/views/saveConfirmation.html', scope: $scope}); + ngDialog.openConfirm({ template: '../common/ui-helper/views/saveConfirmation.html', scope: $scope }); } if ($scope.showTeleConsultationWindow) { var childScope = {}; @@ -235,7 +235,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', event.preventDefault(); confirmBox({ scope: childScope, - actions: [{name: 'ok', display: 'Ok'}], + actions: [{ name: 'ok', display: 'Ok' }], className: "ngdialog-theme-default delete-program-popup" }); } @@ -473,10 +473,9 @@ angular.module('bahmni.clinical').controller('ConsultationController', _.each($scope.consultation.observationForms, function (observationForm) { if (valid && observationForm.component) { var value = observationForm.component.getValue(); - - if (value.errors) - { - if ($state.current.name === "patient.dashboard.show.observations") { + + if (value.errors) { + if ($state.current !== undefined && $state.current.name === "patient.dashboard.show.observations") { messagingService.showMessage('error', "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"); valid = false; } @@ -501,7 +500,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', var errorMessage = discontinuedDrugOrderValidationMessage; messagingService.showMessage('error', errorMessage); } - return shouldAllow && !discontinuedDrugOrderValidationMessage ; + return shouldAllow && !discontinuedDrugOrderValidationMessage; }; var copyConsultationToScope = function (consultationWithDiagnosis) { @@ -543,13 +542,12 @@ angular.module('bahmni.clinical').controller('ConsultationController', $rootScope.cdssAlerts = cdssAlerts; } preSaveEvents(); - return spinner.forPromise($q.all([preSavePromise(), - encounterService.getEncounterType($state.params.programUuid, sessionService.getLoginLocationUuid())]).then(function (results) { - var encounterData = results[0]; - encounterData.encounterTypeUuid = results[1].uuid; - var params = angular.copy($state.params); - params.cachebuster = Math.random(); - return encounterService.create(encounterData) + return spinner.forPromise($q.all([preSavePromise(), encounterService.getEncounterType($state.params.programUuid, sessionService.getLoginLocationUuid())]).then(function (results) { + var encounterData = results[0]; + encounterData.encounterTypeUuid = results[1].uuid; + var params = angular.copy($state.params); + params.cachebuster = Math.random(); + return encounterService.create(encounterData) .then(function (saveResponse) { $state.dirtyConsultationForm = false; $state.orderRemoved = false; @@ -591,7 +589,7 @@ angular.module('bahmni.clinical').controller('ConsultationController', var message = Bahmni.Clinical.Error.translate(error) || "{{'CLINICAL_SAVE_FAILURE_MESSAGE_KEY' | translate}}"; messagingService.showMessage('error', message); }); - })); + })); } catch (error) { var displayErrors = function (error) { if (angular.isArray(error)) { diff --git a/ui/test/unit/clinical/controllers/addTreatmentController.spec.js b/ui/test/unit/clinical/controllers/addTreatmentController.spec.js index 03a6cec44b..2349715565 100644 --- a/ui/test/unit/clinical/controllers/addTreatmentController.spec.js +++ b/ui/test/unit/clinical/controllers/addTreatmentController.spec.js @@ -250,6 +250,7 @@ describe("AddTreatmentController", function () { }; var orderSets; + let appDescriptor; var treatmentConfig = { getDrugConceptSet: function () { diff --git a/ui/test/unit/clinical/controllers/consultationController.spec.js b/ui/test/unit/clinical/controllers/consultationController.spec.js index cecf62525f..ed0961a908 100644 --- a/ui/test/unit/clinical/controllers/consultationController.spec.js +++ b/ui/test/unit/clinical/controllers/consultationController.spec.js @@ -4,7 +4,7 @@ describe("ConsultationController", function () { var scope, rootScope, state, contextChangeHandler, urlHelper, location, clinicalAppConfigService, stateParams, appService, ngDialog, q, appDescriptor, controller, visitConfig, _window_, clinicalDashboardConfig, sessionService, conditionsService, encounterService, configurations, diagnosisService, messagingService, spinnerMock, - auditLogService, confirmBox, virtualConsultService, adhocTeleconsultationService; + auditLogService, confirmBox, virtualConsultService, adhocTeleconsultationService; var encounterData = { "bahmniDiagnoses": [], @@ -128,7 +128,7 @@ describe("ConsultationController", function () { urlHelper: urlHelper, contextChangeHandler: contextChangeHandler, sessionService: sessionService, - patientContext: {patient: {}}, + patientContext: { patient: {} }, $q: Q, $stateParams: stateParams, $window: _window_, @@ -177,7 +177,7 @@ describe("ConsultationController", function () { return "uuid"; } }; - stateParams = {configName: 'default'}; + stateParams = { configName: 'default' }; state = { name: "patient.dashboard.show", params: { @@ -194,7 +194,7 @@ describe("ConsultationController", function () { }; contextChangeHandler = { execute: function () { - return {allow: true}; + return { allow: true }; }, reset: function () { } }; @@ -207,7 +207,7 @@ describe("ConsultationController", function () { rootScope.collapseControlPanel = function () { }; rootScope.currentProvider = { uuid: 'providerUuid' }; - scope.lastConsultationTabUrl = {url: {}}; + scope.lastConsultationTabUrl = { url: {} }; q = jasmine.createSpyObj('q', ['all', 'defer']); visitConfig = {}; configurations = { @@ -235,12 +235,12 @@ describe("ConsultationController", function () { }; conditionsService = jasmine.createSpyObj('conditionalService', ['save', 'getConditions']); conditionsService.save.and.returnValue(specUtil.simplePromise({})); - conditionsService.getConditions.and.returnValue([{uuid: "condition-uuid", conditionNonCoded: "fever"}]); + conditionsService.getConditions.and.returnValue([{ uuid: "condition-uuid", conditionNonCoded: "fever" }]); encounterService = jasmine.createSpyObj('encounterService', ['getEncounterType', 'create', 'getEncountersForEncounterType', 'then']); encounterService.getEncounterType.and.returnValue(specUtil.simplePromise({})); encounterService.getEncountersForEncounterType.and.callFake(function () { var deferred = Q.defer(); - deferred.resolve({data: {results: []}}); + deferred.resolve({ data: { results: [] } }); return deferred.promise; }); messagingService = jasmine.createSpyObj('messagingService', ['showMessage']); @@ -250,10 +250,10 @@ describe("ConsultationController", function () { encounterService.create.and.returnValue(specUtil.createFakePromise(encounterData)); encounterService.create.and.callFake(function () { var deferred = Q.defer(); - deferred.resolve({data: encounterData}); + deferred.resolve({ data: encounterData }); return deferred.promise; }); - encounterService.then.and.returnValue({data: {results: []}}); + encounterService.then.and.returnValue({ data: { results: [] } }); spinnerMock = { forPromise: function (promise, element) { return promise; @@ -276,8 +276,8 @@ describe("ConsultationController", function () { return url; }, getConfigValue: function (value) { - if(value === 'adtNavigationConfig') { - return {forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt"}; + if (value === 'adtNavigationConfig') { + return { forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt" }; } return true; } @@ -335,13 +335,13 @@ describe("ConsultationController", function () { return url; }, getConfigValue: function (value) { - if(value === 'adtNavigationConfig') { - return {forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt"}; + if (value === 'adtNavigationConfig') { + return { forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt" }; } return true; } }; - scope.adtNavigationConfig = {forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}"}; + scope.adtNavigationConfig = { forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}" }; appService.getAppDescriptor.and.returnValue(appDescriptor); createController(); expect(scope.adtNavigationConfig.forwardUrl).toEqual("../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}"); @@ -350,8 +350,8 @@ describe("ConsultationController", function () { describe("tabUrl", function () { it("should return proper URL when showing a different board", function () { - scope.lastConsultationTabUrl = {url: undefined}; - scope.consultation = {discontinuedDrugs: [{dateStopped: new Date()}]}; + scope.lastConsultationTabUrl = { url: undefined }; + scope.consultation = { discontinuedDrugs: [{ dateStopped: new Date() }] }; var newUrl = scope.showBoard(1); expect(newUrl).toEqual("/default/patient/somePatientUuid/dashboard/treatment?encounterUuid=someEncounterUuid&programUuid=someProgramUuid&enrollment=somePatientProgramUuid&tabConfigName=tbTabConfig"); expect(scope.currentBoard.label).toBe("Treatment"); @@ -360,15 +360,15 @@ describe("ConsultationController", function () { }); it("should return proper URL with extension params as parameters with url", function () { - scope.lastConsultationTabUrl = {url: undefined}; - scope.consultation = {discontinuedDrugs: [{dateStopped: new Date()}]}; + scope.lastConsultationTabUrl = { url: undefined }; + scope.consultation = { discontinuedDrugs: [{ dateStopped: new Date() }] }; var newUrl = scope.showBoard(1); expect(newUrl).toEqual("/default/patient/somePatientUuid/dashboard/treatment?encounterUuid=someEncounterUuid&programUuid=someProgramUuid&enrollment=somePatientProgramUuid&tabConfigName=tbTabConfig"); }); it("should not append encounterUuid in query params if not available", function () { - scope.lastConsultationTabUrl = {url: undefined}; - scope.consultation = {discontinuedDrugs: [{dateStopped: new Date()}]}; + scope.lastConsultationTabUrl = { url: undefined }; + scope.consultation = { discontinuedDrugs: [{ dateStopped: new Date() }] }; state.params.encounterUuid = null; var newUrl = scope.showBoard(1); expect(newUrl).toEqual("/default/patient/somePatientUuid/dashboard/treatment?programUuid=someProgramUuid&enrollment=somePatientProgramUuid&tabConfigName=tbTabConfig"); @@ -430,7 +430,7 @@ describe("ConsultationController", function () { }); it("should validate the current tab drug orders", function () { - scope.consultation = {discontinuedDrugs: [{concept: {name: "Paracetmol"}}]}; + scope.consultation = { discontinuedDrugs: [{ concept: { name: "Paracetmol" } }] }; spyOn(scope.$parent, '$broadcast'); scope.showBoard(1); @@ -438,7 +438,7 @@ describe("ConsultationController", function () { }); it("should be on currentBoard if click on same tab", function () { - scope.consultation = {discontinuedDrugs: [{dateStopped: new Date()}]}; + scope.consultation = { discontinuedDrugs: [{ dateStopped: new Date() }] }; scope.showBoard(1); expect(scope.currentBoard.label).toBe('Treatment'); @@ -456,11 +456,11 @@ describe("ConsultationController", function () { }); it("should save and go to target state if 'save and continue' is selected", function () { - scope.toState = {name: "patient.search"}; - scope.toParams = {config: 'default'}; + scope.toState = { name: "patient.search" }; + scope.toParams = { config: 'default' }; expect(state.name).toEqual("patient.dashboard.show"); scope.save = jasmine.createSpy('save'); - var toStateConfig = {toState: "", toParams: ""}; + var toStateConfig = { toState: "", toParams: "" }; scope.toStateConfig = toStateConfig; scope.saveAndContinue(); expect(scope.save).toHaveBeenCalledWith(toStateConfig); @@ -468,11 +468,11 @@ describe("ConsultationController", function () { }); it("should not save and go to target state if 'don't save' is selected", function () { - scope.toState = {name: "patient.search"}; - scope.toParams = {config: 'default'}; + scope.toState = { name: "patient.search" }; + scope.toParams = { config: 'default' }; expect(state.name).toEqual("patient.dashboard.show"); state.go = jasmine.createSpy('go'); - var toStateConfig = {toState: "patient.search", toParams: "default"}; + var toStateConfig = { toState: "patient.search", toParams: "default" }; scope.toStateConfig = toStateConfig; scope.continueWithoutSaving(); expect(state.go).toHaveBeenCalledWith(toStateConfig.toState, toStateConfig.toParams); @@ -480,34 +480,34 @@ describe("ConsultationController", function () { }); it("should not show dialog to confirm save where the target state falls within consultation", function () { - var toState = {name: "patient.dashboard.show.diagnosis"}; - var fromState = {name: "some.state"}; - var params = {patientUUid: 'patientUuid'}; + var toState = { name: "patient.dashboard.show.diagnosis" }; + var fromState = { name: "some.state" }; + var params = { patientUUid: 'patientUuid' }; expect(scope.shouldDisplaySaveConfirmDialogForStateChange(toState, params, fromState, params)).toEqual(false); - toState = {name: "patient.search"}; + toState = { name: "patient.search" }; expect(scope.shouldDisplaySaveConfirmDialogForStateChange(toState, params, fromState, params)).toEqual(true); - toState = {name: "patient.dashboard.show"}; + toState = { name: "patient.dashboard.show" }; expect(scope.shouldDisplaySaveConfirmDialogForStateChange(toState, params, fromState, params)).toEqual(false); }); it("should not show dialog to confirm save if from state is equal to to state and the patient uuid is same.", function () { - var fromState = {name: "patient.dashboard.show"}; - var toState = {name: "patient.dashboard.show"}; - var params = {patientUUid: 'patientUuid'}; + var fromState = { name: "patient.dashboard.show" }; + var toState = { name: "patient.dashboard.show" }; + var params = { patientUUid: 'patientUuid' }; expect(scope.shouldDisplaySaveConfirmDialogForStateChange(toState, params, fromState, params)).toEqual(false); }); it("should show dialog to confirm save if from state is equal to to state and the patient uuid is different", function () { - var fromState = {name: "patient.dashboard.show"}; - var toState = {name: "patient.dashboard.show"}; - expect(scope.shouldDisplaySaveConfirmDialogForStateChange(toState, {patientUuid: 'patientUuid1'}, fromState, {patientUuid: 'patientUuid2'})).toEqual(true); + var fromState = { name: "patient.dashboard.show" }; + var toState = { name: "patient.dashboard.show" }; + expect(scope.shouldDisplaySaveConfirmDialogForStateChange(toState, { patientUuid: 'patientUuid1' }, fromState, { patientUuid: 'patientUuid2' })).toEqual(true); }); it("should display save confirm dialog if the config is set", function () { - var fromState = {name: "patient.dashboard.show"}; - var toState = {name: "patient.dashboard.show.observations"}; + var fromState = { name: "patient.dashboard.show" }; + var toState = { name: "patient.dashboard.show.observations" }; rootScope.hasVisitedConsultation = true; scope.shouldDisplaySaveConfirmDialogForStateChange = jasmine.createSpy('shouldDisplaySaveConfirmDialogForStateChange'); @@ -518,8 +518,8 @@ describe("ConsultationController", function () { }); it("should not display save confirm dialog if the config is not set", function () { - var fromState = {name: "patient.dashboard.show"}; - var toState = {name: "patient.dashboard.show.observations"}; + var fromState = { name: "patient.dashboard.show" }; + var toState = { name: "patient.dashboard.show.observations" }; rootScope.hasVisitedConsultation = true; scope.showSaveConfirmDialogConfig = false; scope.shouldDisplaySaveConfirmDialogForStateChange = jasmine.createSpy('shouldDisplaySaveConfirmDialogForStateChange'); @@ -534,8 +534,8 @@ describe("ConsultationController", function () { it("should not broadcast page unload event if not configured to prompt", function () { appService.getAppDescriptor.and.returnValue({ getConfigValue: function (value) { - if(value === 'adtNavigationConfig') { - return {forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt"}; + if (value === 'adtNavigationConfig') { + return { forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt" }; } return false; } @@ -550,8 +550,8 @@ describe("ConsultationController", function () { it("should broadcast page unload event if configured to prompt", function () { appService.getAppDescriptor.and.returnValue({ getConfigValue: function (value) { - if(value === 'adtNavigationConfig') { - return {forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt"}; + if (value === 'adtNavigationConfig') { + return { forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}", "privilege": "app:adt" }; } return true; } @@ -648,14 +648,14 @@ describe("ConsultationController", function () { describe("save", function () { it("should save encounter data", function (done) { - scope.consultation = {discontinuedDrugs: [{dateStopped: new Date()}], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [], conditions: [{condition: {}}]}; + scope.consultation = { discontinuedDrugs: [{ dateStopped: new Date() }], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [], conditions: [{ condition: {} }] }; scope.patient = { uuid: "patient-uuid" }; diagnosisService.populateDiagnosisInformation.and.returnValue(specUtil.createFakePromise(scope.consultation)); - scope.save({toState: {}}).then(function () { + scope.save({ toState: {} }).then(function () { expect(encounterService.create).toHaveBeenCalled(); - expect(auditLogService.log).toHaveBeenCalledWith(scope.patient.uuid, "EDIT_ENCOUNTER", {encounterUuid: encounterData.encounterUuid, encounterType: encounterData.encounterType}, "MODULE_LABEL_CLINICAL_KEY"); + expect(auditLogService.log).toHaveBeenCalledWith(scope.patient.uuid, "EDIT_ENCOUNTER", { encounterUuid: encounterData.encounterUuid, encounterType: encounterData.encounterType }, "MODULE_LABEL_CLINICAL_KEY"); expect(conditionsService.save).toHaveBeenCalledWith(scope.consultation.conditions, "patient-uuid"); expect(messagingService.showMessage).toHaveBeenCalledWith('info', "{{'CLINICAL_SAVE_SUCCESS_MESSAGE_KEY' | translate}}"); done(); @@ -663,9 +663,15 @@ describe("ConsultationController", function () { }); it("should not save encounter data if there errors in form", function (done) { - scope.consultation = {discontinuedDrugs: [{dateStopped: new Date()}], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [], conditions: [{condition: {}}], observationForms: [{component: {getValue: function () { - return {errors: {}}; - }}}]}; + scope.consultation = { + discontinuedDrugs: [{ dateStopped: new Date() }], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [], conditions: [{ condition: {} }], observationForms: [{ + component: { + getValue: function () { + return { errors: {} }; + } + } + }] + }; scope.patient = { uuid: "patient-uuid" }; @@ -678,7 +684,7 @@ describe("ConsultationController", function () { }; spyOn(scope.$parent.$parent, '$broadcast'); diagnosisService.populateDiagnosisInformation.and.returnValue(specUtil.createFakePromise(scope.consultation)); - scope.save({toState: {}}).then(function () { + scope.save({ toState: {} }).then(function () { expect(scope.$parent.$parent.$broadcast).toHaveBeenCalledWith('event:errorsOnForm'); done(); }); @@ -686,18 +692,18 @@ describe("ConsultationController", function () { it("should save conditions to consultation after encounter save", function (done) { scope.consultation = { - discontinuedDrugs: [{dateStopped: new Date()}], + discontinuedDrugs: [{ dateStopped: new Date() }], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [] }; - var conditions = [ {uuid: undefined, conditionNonCoded: "fever"}]; + var conditions = [{ uuid: undefined, conditionNonCoded: "fever" }]; scope.consultation["conditions"] = conditions; scope.patient = { uuid: "patient-uuid" }; diagnosisService.populateDiagnosisInformation.and.returnValue(specUtil.simplePromise(scope.consultation)); - scope.save({toState: {}}).then(function () { + scope.save({ toState: {} }).then(function () { expect(encounterService.create).toHaveBeenCalled(); expect(conditionsService.save).toHaveBeenCalledWith(conditions, "patient-uuid"); expect(messagingService.showMessage).toHaveBeenCalledWith('info', "{{'CLINICAL_SAVE_SUCCESS_MESSAGE_KEY' | translate}}"); @@ -708,11 +714,11 @@ describe("ConsultationController", function () { it("should throw error if save conditions failed after encounter save", function (done) { scope.consultation = { - discontinuedDrugs: [{dateStopped: new Date()}], + discontinuedDrugs: [{ dateStopped: new Date() }], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [], - conditions: [{uuid: undefined, conditionNonCoded: "fever"}] + conditions: [{ uuid: undefined, conditionNonCoded: "fever" }] }; scope.patient = { uuid: "patient-uuid" @@ -723,7 +729,7 @@ describe("ConsultationController", function () { deferred1.reject("error"); return deferred1.promise; }); - scope.save({toState: {}}).then(function () { + scope.save({ toState: {} }).then(function () { expect(encounterService.create).toHaveBeenCalled(); expect(conditionsService.save).toHaveBeenCalledWith(scope.consultation.conditions, "patient-uuid"); expect(scope.$parent.consultation.conditions[0].uuid).toEqual(undefined); @@ -733,42 +739,42 @@ describe("ConsultationController", function () { it("should not make api calls and call showMessage of messagingService when there is error in form save " + "event when there is a single error", function (done) { - scope.consultation = { - discontinuedDrugs: [{dateStopped: new Date()}], - preSaveHandler: new Bahmni.Clinical.Notifier(), - postSaveHandler: new Bahmni.Clinical.Notifier(), - observations: [], - observationForms: [{ - isAdded: true, - component: { - getValue: function () { - return {} + scope.consultation = { + discontinuedDrugs: [{ dateStopped: new Date() }], + preSaveHandler: new Bahmni.Clinical.Notifier(), + postSaveHandler: new Bahmni.Clinical.Notifier(), + observations: [], + observationForms: [{ + isAdded: true, + component: { + getValue: function () { + return {} + }, + state: { data: {} }, + props: { patient: {} }, }, - state: {data: {}}, - props: {patient: {}}, - }, - events: { - onFormSave: 'Save event' - } - }], - conditions: [{uuid: undefined, conditionNonCoded: "fever"}] - }; - window.runEventScript = function() { - throw {message: 'Error'}; - }; - - scope.save({toState: {}}).then(function () { - expect(encounterService.getEncounterType).not.toHaveBeenCalled(); - expect(encounterService.create).not.toHaveBeenCalled(); - expect(conditionsService.save).not.toHaveBeenCalled(); - expect(messagingService.showMessage).toHaveBeenCalledWith('error', 'Error'); - done(); + events: { + onFormSave: 'Save event' + } + }], + conditions: [{ uuid: undefined, conditionNonCoded: "fever" }] + }; + window.runEventScript = function () { + throw { message: 'Error' }; + }; + + scope.save({ toState: {} }).then(function () { + expect(encounterService.getEncounterType).not.toHaveBeenCalled(); + expect(encounterService.create).not.toHaveBeenCalled(); + expect(conditionsService.save).not.toHaveBeenCalled(); + expect(messagingService.showMessage).toHaveBeenCalledWith('error', 'Error'); + done(); + }); }); - }); it("should call messagingService n times for n number of errors and api calls aren't made on FormSave event ", function (done) { scope.consultation = { - discontinuedDrugs: [{dateStopped: new Date()}], + discontinuedDrugs: [{ dateStopped: new Date() }], preSaveHandler: new Bahmni.Clinical.Notifier(), postSaveHandler: new Bahmni.Clinical.Notifier(), observations: [], @@ -778,20 +784,20 @@ describe("ConsultationController", function () { getValue: function () { return {} }, - state: {data: {}}, - props: {patient: {}}, + state: { data: {} }, + props: { patient: {} }, }, events: { onFormSave: 'Save event' } }], - conditions: [{uuid: undefined, conditionNonCoded: "fever"}] + conditions: [{ uuid: undefined, conditionNonCoded: "fever" }] }; window.runEventScript = function () { - throw [{message: 'Error1'}, {message: ''}, {mesage: 'Error3'}]; + throw [{ message: 'Error1' }, { message: '' }, { mesage: 'Error3' }]; }; - scope.save({toState: {}}).then(function () { + scope.save({ toState: {} }).then(function () { expect(encounterService.getEncounterType).not.toHaveBeenCalled(); expect(encounterService.create).not.toHaveBeenCalled(); expect(conditionsService.save).not.toHaveBeenCalled(); @@ -804,7 +810,7 @@ describe("ConsultationController", function () { }); }); - describe("startAdhocTeleconsultationLink", function () { + describe("startAdhocTeleconsultationLink", function () { it("should get ad-hoc teleconsultation link", function () { scope.patient = { uuid: "patient-uuid" @@ -813,14 +819,15 @@ describe("ConsultationController", function () { username: "username" }; scope.adhocTeleconsultationData = { - uuid:"GAN203006", - link:"https://meet.jit.si/GAN203006", - notificationResults:[ + uuid: "GAN203006", + link: "https://meet.jit.si/GAN203006", + notificationResults: [ { - uuid:"", - medium:"EMAIL", - status:1, - message:"Unable to send tele-consultation appointment information through EMAIL"} + uuid: "", + medium: "EMAIL", + status: 1, + message: "Unable to send tele-consultation appointment information through EMAIL" + } ] }; console.log(adhocTeleconsultationService) @@ -847,7 +854,7 @@ describe("ConsultationController", function () { return true; } }; - scope.adtNavigationConfig = {forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}"}; + scope.adtNavigationConfig = { forwardUrl: "../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}" }; appService.getAppDescriptor.and.returnValue(appDescriptor); expect(scope.adtNavigationURL()).toEqual("../bedmanagement/#/bedManagement/patient/{{patientUuid}}/visit/{{visitUuid}}"); @@ -856,7 +863,7 @@ describe("ConsultationController", function () { it("should initialize with default adtNavigationConfig if we are not mentioning anything in config", function () { appService.getAppDescriptor.and.returnValue({ getConfigValue: function (value) { - if(value === 'adtNavigationConfig') { + if (value === 'adtNavigationConfig') { return {}; } return true; @@ -873,8 +880,8 @@ describe("ConsultationController", function () { it("should initialize with adtNavigationConfig if we mention in config", function () { appService.getAppDescriptor.and.returnValue({ getConfigValue: function (value) { - if(value === 'adtNavigationConfig') { - return {privilege: "app:ipd", title: "Go to ADT Dashboard"}; + if (value === 'adtNavigationConfig') { + return { privilege: "app:ipd", title: "Go to ADT Dashboard" }; } return true; } From ca828f62d2150ace415216793a97430233d3056e Mon Sep 17 00:00:00 2001 From: Arjun-Go Date: Fri, 1 Sep 2023 12:08:19 +0530 Subject: [PATCH 04/11] refactor. comment out copy error button --- ui/app/common/ui-helper/messages.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/common/ui-helper/messages.html b/ui/app/common/ui-helper/messages.html index e4ee5edfd8..9cf6087468 100644 --- a/ui/app/common/ui-helper/messages.html +++ b/ui/app/common/ui-helper/messages.html @@ -27,7 +27,7 @@
- +
From 37c9d67394706dde1b879dd9641a2fe069d39f6f Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:47:14 +0530 Subject: [PATCH 05/11] Fix: Able to navigate through form 1 forms with mandatory errors (#732) * Handle navigation for form1 mandatory errors * Fix the bacteriology tab error --- .../controllers/bacteriologyController.js | 2 +- .../controllers/consultationController.js | 31 ++++- .../consultationController.spec.js | 111 ++++++++++++++++++ 3 files changed, 141 insertions(+), 3 deletions(-) diff --git a/ui/app/clinical/consultation/controllers/bacteriologyController.js b/ui/app/clinical/consultation/controllers/bacteriologyController.js index 5a4045d355..308f93f9b9 100644 --- a/ui/app/clinical/consultation/controllers/bacteriologyController.js +++ b/ui/app/clinical/consultation/controllers/bacteriologyController.js @@ -55,7 +55,7 @@ angular.module('bahmni.clinical') }; $scope.$on('$stateChangeStart', function () { - if ($scope.bacteriologyForm.$dirty) { + if ($scope.bacteriologyForm && $scope.bacteriologyForm.$dirty) { $state.dirtyConsultationForm = true; } }); diff --git a/ui/app/clinical/consultation/controllers/consultationController.js b/ui/app/clinical/consultation/controllers/consultationController.js index 7205dbe7d7..3ccc736adf 100644 --- a/ui/app/clinical/consultation/controllers/consultationController.js +++ b/ui/app/clinical/consultation/controllers/consultationController.js @@ -23,7 +23,6 @@ angular.module('bahmni.clinical').controller('ConsultationController', }; $scope.showComment = true; $scope.showSaveAndContinueButton = true; - $scope.visitHistory = visitHistory; $scope.consultationBoardLink = clinicalAppConfigService.getConsultationBoardLink(); $scope.showControlPanel = false; @@ -351,6 +350,11 @@ angular.module('bahmni.clinical').controller('ConsultationController', if ($scope.currentBoard === board) { return; } + $scope.isObservationPage = board.id == "bahmni.clinical.consultation.observations" ? true : false; + $scope.isSave = false; + if ($scope.currentBoard) { + $scope.isSwitchedFromObservationToOtherPage = $scope.currentBoard.id == "bahmni.clinical.consultation.observations" ? true : false; + } if (!isFormValid()) { $scope.$parent.$broadcast("event:errorsOnForm"); return; @@ -489,10 +493,32 @@ angular.module('bahmni.clinical').controller('ConsultationController', return valid; }; + var checkForObservationPageError = function (shouldAllow, contxChange) { + if (!$scope.isSave) { + if ($scope.isSwitchedFromObservationToOtherPage && !shouldAllow) { + $scope.isErrorPresentInObsTab = true; + shouldAllow = $scope.isErrorPresentInObsTab; + } else if ($scope.isSwitchedFromObservationToOtherPage && shouldAllow) { + $scope.isErrorPresentInObsTab = false; + } + } else if ($scope.isSave) { + if ($scope.isErrorPresentInObsTab) { + if (!$scope.isObservationPage) { + var errorMessage = contxChange["errorMessage"] ? contxChange["errorMessage"] : "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"; + messagingService.showMessage('error', errorMessage); + } else if ($scope.isObservationPage) { + $scope.isErrorPresentInObsTab = false; + } + } + } + return shouldAllow; + }; + var isFormValid = function () { var contxChange = contextChange(); var shouldAllow = contxChange["allow"]; var discontinuedDrugOrderValidationMessage = discontinuedDrugOrderValidation($scope.consultation.discontinuedDrugs); + shouldAllow = checkForObservationPageError(shouldAllow, contxChange); if (!shouldAllow) { var errorMessage = contxChange["errorMessage"] ? contxChange["errorMessage"] : "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"; messagingService.showMessage('error', errorMessage); @@ -517,7 +543,8 @@ angular.module('bahmni.clinical').controller('ConsultationController', }); $scope.save = function (toStateConfig) { - if (isFormValid() && !isObservationFormValid()) { + $scope.isSave = true; + if (!isFormValid() || !isObservationFormValid() || $scope.isErrorPresentInObsTab) { $scope.$parent.$parent.$broadcast("event:errorsOnForm"); return $q.when({}); } diff --git a/ui/test/unit/clinical/controllers/consultationController.spec.js b/ui/test/unit/clinical/controllers/consultationController.spec.js index ed0961a908..44ad97ab49 100644 --- a/ui/test/unit/clinical/controllers/consultationController.spec.js +++ b/ui/test/unit/clinical/controllers/consultationController.spec.js @@ -445,6 +445,117 @@ describe("ConsultationController", function () { scope.showBoard(1); expect(scope.currentBoard.label).toBe('Treatment'); }); + + it("should allow the observation tab with mandatory error fields to navigate to other tabs", function () { + scope.consultation = { observations: [{ + conceptNameToDisplay: "Cleft Lip/Palate -Operative Report", + groupMembers : [{ + conceptNameToDisplay: "Anesthesia Start Time", + valueAsString : "2023-10-01 15:07:00" + }, + { + conceptNameToDisplay: "Surgical Finish Time", + valueAsString : "2023-10-10 15:06:00" + }] + }]}; + location = { + path: function () { + }, url: function (url) { + return "/default/patient/somePatientUuid/dashboard/concept-set-group/observations"; + } + }; + var observationTab = { + "default": true, + "extensionPointId": "org.bahmni.clinical.consultation.board", + "icon": "fa-user-md", + "id": "bahmni.clinical.consultation.observations", + "isSelectedTab": true, + "label": "Observations", + "order": 1, + "requiredPrivilege": "app:clinical:observationTab", + "translationKey": "OBSERVATIONS_BOARD_LABEL_KEY", + "type": "link", + "url": "concept-set-group/observations" + }; + boards.push(observationTab); + + createController(); + + var expectedCurrentBoard = observationTab; + expectedCurrentBoard.isSelectedTab = true; + expect(scope.currentBoard.id).toBe('bahmni.clinical.consultation.observations'); + scope.isErrorPresentInObsTab = true + scope.showBoard(2); + spyOn(scope.$parent, '$broadcast'); + expect(scope.$parent.$broadcast).not.toHaveBeenCalledWith('event:errorsOnForm'); + expect(messagingService.showMessage).not.toHaveBeenCalledWith('error'); + }); + it("should throw error for mandatory fields for observation tab while saving from any other tab", function () { + scope.consultation = { observations: [{ + conceptNameToDisplay: "Cleft Lip/Palate -Operative Report", + groupMembers : [{ + conceptNameToDisplay: "Anesthesia Start Time", + valueAsString : "2023-10-01 15:07:00" + }, + { + conceptNameToDisplay: "Surgical Finish Time", + valueAsString : "2023-10-10 15:06:00" + }] + }]}; + scope.$parent = { + $parent: { + $broadcast: function () { + return {}; + } + } + }; + scope.isErrorPresentInObsTab = true + scope.save(); + spyOn(scope.$parent.$parent, '$broadcast'); + expect(scope.isSave).toBe(true); + expect(scope.isErrorPresentInObsTab).toBe(true); + expect(messagingService.showMessage).toHaveBeenCalled(); + }); + it("should be able to save the consultation after the mandatory issue fix", function () { + scope.consultation = { observations: [{ + conceptNameToDisplay: "Cleft Lip/Palate -Operative Report", + groupMembers : [{ + conceptNameToDisplay: "Anesthesia Start Time", + valueAsString : "2023-10-01 15:07:00" + }, + { + conceptNameToDisplay: "Surgical Finish Time", + valueAsString : "2023-10-10 15:06:00" + }] + }]}; + location = { + path: function () { + }, url: function (url) { + return "/default/patient/somePatientUuid/dashboard/concept-set-group/observations"; + } + }; + var observationTab = { + "default": true, + "extensionPointId": "org.bahmni.clinical.consultation.board", + "icon": "fa-user-md", + "id": "bahmni.clinical.consultation.observations", + "isSelectedTab": true, + "label": "Observations", + "order": 1, + "requiredPrivilege": "app:clinical:observationTab", + "translationKey": "OBSERVATIONS_BOARD_LABEL_KEY", + "type": "link", + "url": "concept-set-group/observations" + }; + boards.push(observationTab); + + createController(); + scope.isErrorPresentInObsTab = true + scope.isObservationPage = true + scope.save(); + expect(scope.isSave).toBe(true); + expect(scope.isErrorPresentInObsTab).toBe(false); + }); }); describe("showSaveConfirmDialogConfig", function () { From c6c16eaf97b6f78f8377b5a8fe00344e6a6c3fb2 Mon Sep 17 00:00:00 2001 From: sowmya-AS <76809502+sowmya-AS@users.noreply.github.com> Date: Fri, 13 Oct 2023 17:10:32 +0530 Subject: [PATCH 06/11] Sowmya | A-1205582341920482 | UAT Feedback - Alerts for unsaved observation (#737) --- .../concept-set/directives/conceptSet.js | 16 ++++- .../concept-set/directives/formControls.js | 69 ++++++++++++++++++- .../common/concept-set/views/conceptSet.html | 2 +- .../directives/formControls.spec.js | 3 +- .../concept-set/directives/conceptSet.spec.js | 13 +++- 5 files changed, 96 insertions(+), 7 deletions(-) diff --git a/ui/app/common/concept-set/directives/conceptSet.js b/ui/app/common/concept-set/directives/conceptSet.js index d9e085b57f..70ea1a4533 100644 --- a/ui/app/common/concept-set/directives/conceptSet.js +++ b/ui/app/common/concept-set/directives/conceptSet.js @@ -1,8 +1,8 @@ 'use strict'; angular.module('bahmni.common.conceptSet') - .directive('conceptSet', ['contextChangeHandler', 'appService', 'observationsService', 'messagingService', 'conceptSetService', 'conceptSetUiConfigService', 'spinner', - function (contextChangeHandler, appService, observationsService, messagingService, conceptSetService, conceptSetUiConfigService, spinner) { + .directive('conceptSet', ['contextChangeHandler', 'appService', 'observationsService', 'messagingService', 'conceptSetService', 'conceptSetUiConfigService', 'spinner', '$state', + function (contextChangeHandler, appService, observationsService, messagingService, conceptSetService, conceptSetUiConfigService, spinner, $state) { var controller = function ($scope) { var conceptSetName = $scope.conceptSetName; var ObservationUtil = Bahmni.Common.Obs.ObservationUtil; @@ -412,6 +412,18 @@ angular.module('bahmni.common.conceptSet') deregisterAddMore(); cleanUpListenerShowPrevious(); }); + + $scope.$on('$stateChangeStart', function () { + if ($scope.obsForm && $scope.obsForm.$dirty) { + $state.dirtyConsultationForm = true; + } + }); + + $scope.$on("event:changes-saved", function () { + if ($scope.obsForm) { + $scope.obsForm.$dirty = false; + } + }); }; return { diff --git a/ui/app/common/concept-set/directives/formControls.js b/ui/app/common/concept-set/directives/formControls.js index 694d349669..a4fa27aa4e 100644 --- a/ui/app/common/concept-set/directives/formControls.js +++ b/ui/app/common/concept-set/directives/formControls.js @@ -1,8 +1,8 @@ 'use strict'; angular.module('bahmni.common.conceptSet') - .directive('formControls', ['formService', 'spinner', '$timeout', '$translate', - function (formService, spinner, $timeout, $translate) { + .directive('formControls', ['formService', 'spinner', '$timeout', '$translate', '$state', 'messagingService', 'exitAlertService', + function (formService, spinner, $timeout, $translate, $state, messagingService, exitAlertService) { var loadedFormDetails = {}; var loadedFormTranslations = {}; var unMountReactContainer = function (formUuid) { @@ -78,6 +78,71 @@ angular.module('bahmni.common.conceptSet') } } }); + function checkGroupMembers (formObservation, consultationObservation) { + var isGroupMemberChanged = []; + if (formObservation.groupMembers && formObservation.groupMembers.length > 0 && consultationObservation.groupMembers && consultationObservation.groupMembers.length > 0) { + for (var formGroupIndex = 0; formGroupIndex < formObservation.groupMembers.length; formGroupIndex++) { + var formGroupMember = formObservation.groupMembers[formGroupIndex]; + for (var consultationGroupIndex = 0; consultationGroupIndex < consultationObservation.groupMembers.length; consultationGroupIndex++) { + var consultationGroupMember = consultationObservation.groupMembers[consultationGroupIndex]; + (formGroupMember.value && formGroupMember.value.uuid && consultationGroupMember.value && consultationGroupMember.value.uuid) ? + isGroupMemberChanged[formGroupIndex] = (consultationGroupMember.value.uuid === formGroupMember.value.uuid) ? false : true : + isGroupMemberChanged[formGroupIndex] = (consultationGroupMember.value === formGroupMember.value) ? false : true; + if (!isGroupMemberChanged[formGroupIndex]) { + break; + } + } + } + return isGroupMemberChanged.includes(true) ? true : false; + } else { + if (formObservation.value && formObservation.value.uuid && consultationObservation.value && consultationObservation.value.uuid) { + return (consultationObservation.value.uuid === formObservation.value.uuid) ? false : true; + } else { + return (consultationObservation.value === formObservation.value) ? false : true; + } + } + } + + function checkFormChanges ($scope) { + var isChanged = []; + $scope.dirtyForm = false; + if ($scope.form.observations.length > 0) { + if ($scope.$parent.consultation.observations.length === 0) { + return true; + } + for (var formIndex = 0; formIndex < $scope.form.observations.length; formIndex++) { + var formObservation = $scope.form.observations[i]; + for (var consultationIndex = 0; consultationIndex < $scope.$parent.consultation.observations.length; consultationIndex++) { + var consultationObservation = $scope.$parent.consultation.observations[consultationIndex]; + isChanged[formIndex] = checkGroupMembers(formObservation, consultationObservation); + if (!isChanged[formIndex]) { + break; + } + } + } + return isChanged.includes(true); + } + } + + $scope.$on('$stateChangeStart', function (event, next, current) { + var uuid = $state.params.patientUuid; + var currentUuid = current.patientUuid; + if ($scope.form.component) { + var formObservations = $scope.form.component.getValue(); + $scope.form.observations = formObservations.observations; + } + if (!$scope.changesSaved) { + $scope.dirtyForm = checkFormChanges($scope); + } + var isNavigating = exitAlertService.setIsNavigating(next, uuid, currentUuid); + $state.dirtyConsultationForm = $state.discardChanges ? false : $scope.dirtyForm; + exitAlertService.showExitAlert(isNavigating, $state.dirtyConsultationForm, event, next.spinnerToken); + }); + + $scope.$on("event:changes-saved", function () { + $scope.changesSaved = true; + $scope.dirtyForm = false; + }); }; return { diff --git a/ui/app/common/concept-set/views/conceptSet.html b/ui/app/common/concept-set/views/conceptSet.html index c45e9eb14c..be644d4b4c 100644 --- a/ui/app/common/concept-set/views/conceptSet.html +++ b/ui/app/common/concept-set/views/conceptSet.html @@ -1,4 +1,4 @@ -
+
{{::conceptSetName}} {{ 'CONCEPT_NOT_FOUND_MESSAGE'|translate }}
Date: Tue, 17 Oct 2023 10:22:03 +0530 Subject: [PATCH 07/11] Sowmya | A-1205582341920482 | Alerts for unsaved observation - fix errors (#742) * Sowmya | A-1205582341920482 | Alerts for unsaved observation - fix errors * Sowmya | A-1205582341920482 | Alerts for unsaved observation - adds test for coverage --------- Co-authored-by: sowmya198 --- .../concept-set/directives/formControls.js | 27 +++++++++---------- .../directives/bedAssignmentDialog.spec.js | 24 +++++++++++++++++ .../directives/formControls.spec.js | 16 ++++++++++- 3 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 ui/test/unit/adt/directives/bedAssignmentDialog.spec.js diff --git a/ui/app/common/concept-set/directives/formControls.js b/ui/app/common/concept-set/directives/formControls.js index a4fa27aa4e..d8b4be48e4 100644 --- a/ui/app/common/concept-set/directives/formControls.js +++ b/ui/app/common/concept-set/directives/formControls.js @@ -1,8 +1,7 @@ 'use strict'; - angular.module('bahmni.common.conceptSet') - .directive('formControls', ['formService', 'spinner', '$timeout', '$translate', '$state', 'messagingService', 'exitAlertService', - function (formService, spinner, $timeout, $translate, $state, messagingService, exitAlertService) { + .directive('formControls', ['formService', 'spinner', '$timeout', '$translate', '$state', 'messagingService', + function (formService, spinner, $timeout, $translate, $state, messagingService) { var loadedFormDetails = {}; var loadedFormTranslations = {}; var unMountReactContainer = function (formUuid) { @@ -11,7 +10,6 @@ angular.module('bahmni.common.conceptSet') unMountForm(document.getElementById(formUuid)); }); }; - var controller = function ($scope) { var formUuid = $scope.form.formUuid; var formVersion = $scope.form.formVersion; @@ -20,7 +18,6 @@ angular.module('bahmni.common.conceptSet') var collapse = $scope.form.collapseInnerSections && $scope.form.collapseInnerSections.value; var validateForm = $scope.validateForm || false; var locale = $translate.use(); - if (!loadedFormDetails[formUuid]) { spinner.forPromise(formService.getFormDetail(formUuid, { v: "custom:(resources:(value))" }) .then(function (response) { @@ -56,7 +53,6 @@ angular.module('bahmni.common.conceptSet') unMountReactContainer($scope.form.formUuid); }, 0, false); } - $scope.$watch('form.collapseInnerSections', function () { var collapse = $scope.form.collapseInnerSections && $scope.form.collapseInnerSections.value; if (loadedFormDetails[formUuid]) { @@ -64,13 +60,11 @@ angular.module('bahmni.common.conceptSet') formUuid, collapse, $scope.patient, validateForm, locale, loadedFormTranslations[formUuid]); } }); - $scope.$on('$destroy', function () { if ($scope.$parent.consultation && $scope.$parent.consultation.observationForms) { if ($scope.form.component) { var formObservations = $scope.form.component.getValue(); $scope.form.observations = formObservations.observations; - var hasError = formObservations.errors; if (!_.isEmpty(hasError)) { $scope.form.isValid = false; @@ -102,7 +96,6 @@ angular.module('bahmni.common.conceptSet') } } } - function checkFormChanges ($scope) { var isChanged = []; $scope.dirtyForm = false; @@ -111,7 +104,7 @@ angular.module('bahmni.common.conceptSet') return true; } for (var formIndex = 0; formIndex < $scope.form.observations.length; formIndex++) { - var formObservation = $scope.form.observations[i]; + var formObservation = $scope.form.observations[formIndex]; for (var consultationIndex = 0; consultationIndex < $scope.$parent.consultation.observations.length; consultationIndex++) { var consultationObservation = $scope.$parent.consultation.observations[consultationIndex]; isChanged[formIndex] = checkGroupMembers(formObservation, consultationObservation); @@ -123,7 +116,6 @@ angular.module('bahmni.common.conceptSet') return isChanged.includes(true); } } - $scope.$on('$stateChangeStart', function (event, next, current) { var uuid = $state.params.patientUuid; var currentUuid = current.patientUuid; @@ -134,17 +126,22 @@ angular.module('bahmni.common.conceptSet') if (!$scope.changesSaved) { $scope.dirtyForm = checkFormChanges($scope); } - var isNavigating = exitAlertService.setIsNavigating(next, uuid, currentUuid); + $state.newPatientUuid = currentUuid; + next.url.includes("/patient/search") ? $state.isPatientSearch = true : $state.isPatientSearch = false; + var isNavigating = next.url.includes("/patient/search") || (uuid !== currentUuid); $state.dirtyConsultationForm = $state.discardChanges ? false : $scope.dirtyForm; - exitAlertService.showExitAlert(isNavigating, $state.dirtyConsultationForm, event, next.spinnerToken); + if (isNavigating && $state.dirtyConsultationForm) { + messagingService.showMessage('alert', "{{'ALERT_MESSAGE_ON_EXIT' | translate }}"); + $state.reviewButtonFocused = true; + event.preventDefault(); + spinner.hide(next.spinnerToken); + } }); - $scope.$on("event:changes-saved", function () { $scope.changesSaved = true; $scope.dirtyForm = false; }); }; - return { restrict: 'E', scope: { diff --git a/ui/test/unit/adt/directives/bedAssignmentDialog.spec.js b/ui/test/unit/adt/directives/bedAssignmentDialog.spec.js new file mode 100644 index 0000000000..96879269f9 --- /dev/null +++ b/ui/test/unit/adt/directives/bedAssignmentDialog.spec.js @@ -0,0 +1,24 @@ +describe('bedAssignmentDialog directive', function () { + var $compile, $rootScope, $document; + beforeEach(module('bahmni.adt')); + beforeEach(inject(function (_$compile_, _$rootScope_, _$document_) { + $compile = _$compile_; + $rootScope = _$rootScope_; + $document = _$document_; + })); + it('should set bed details and position the bed info element', function () { + var scope = $rootScope.$new(); + var element = angular.element('
'); + $compile(element)(scope); + scope.cell = { + bed: { + bedId: 1, + bedNumber: '1' + } + }; + scope.setBedDetails = jasmine.createSpy('setBedDetails'); + + element.triggerHandler('click'); + expect(scope.setBedDetails).toHaveBeenCalledWith(scope.cell); + }); +}); diff --git a/ui/test/unit/clinical/consultation/directives/formControls.spec.js b/ui/test/unit/clinical/consultation/directives/formControls.spec.js index b8e0bef961..2472f737e9 100644 --- a/ui/test/unit/clinical/consultation/directives/formControls.spec.js +++ b/ui/test/unit/clinical/consultation/directives/formControls.spec.js @@ -10,6 +10,10 @@ describe("Form Controls", function () { provide = $provide; formService = jasmine.createSpyObj('formService', ['getFormDetail', 'getFormTranslations']); spinner = jasmine.createSpyObj('spinner', ['forPromise']); + $state = { + patientUuid: 'patientUuid', + dirtyConsultationForm: false + }; provide.value('formService', formService); translate = { use: function(){ return 'en' } @@ -19,9 +23,10 @@ describe("Form Controls", function () { provide.value('$state', $state); }); - inject(function (_$compile_, $rootScope) { + inject(function (_$compile_, $rootScope, _$state_) { $compile = _$compile_; scope = $rootScope.$new(); + $state = _$state_; }); renderHelper = { @@ -82,6 +87,15 @@ describe("Form Controls", function () { expect(renderHelper.renderWithControlsCalledTimes).toBe(2); }); + it("should set dirtyForm flag when changes are saved", function () { + mockObservationService({ resources: [{ value: '{"name":"Vitals", "controls": [{"type":"obsControl", "controls":[]}] }' }] }); + createElement(); + scope.$digest(); + + scope.$broadcast("$event:changes-saved"); + expect($state.dirtyForm).toBeFalsy(); + }); + var createElement = function () { document.body.innerHTML += '
'; element = angular.element(""); From 1e450d4c7a7ff9b305a54fddce7cda8f5125a2a0 Mon Sep 17 00:00:00 2001 From: sowmya-AS <76809502+sowmya-AS@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:08:08 +0530 Subject: [PATCH 08/11] Sowmya | fix alerts showing for unsaved observation even after all observations have been saved (#748) --- ui/app/common/concept-set/directives/formControls.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/app/common/concept-set/directives/formControls.js b/ui/app/common/concept-set/directives/formControls.js index d8b4be48e4..c347f66f4e 100644 --- a/ui/app/common/concept-set/directives/formControls.js +++ b/ui/app/common/concept-set/directives/formControls.js @@ -92,6 +92,10 @@ angular.module('bahmni.common.conceptSet') if (formObservation.value && formObservation.value.uuid && consultationObservation.value && consultationObservation.value.uuid) { return (consultationObservation.value.uuid === formObservation.value.uuid) ? false : true; } else { + if (angular.isNumber(formObservation.value)) { + formObservation.value = formObservation.value.toString(); + } + return (consultationObservation.value === formObservation.value) ? false : true; } } From 8684c3fb701c5b0fde53cb9f47c23691d013b901 Mon Sep 17 00:00:00 2001 From: sowmya-AS <76809502+sowmya-AS@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:09:55 +0530 Subject: [PATCH 09/11] Sowmya | fix alerts showing for unsaved observation even after all observations have been saved (#749) --- ui/app/common/concept-set/directives/formControls.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/app/common/concept-set/directives/formControls.js b/ui/app/common/concept-set/directives/formControls.js index c347f66f4e..23dfae08ca 100644 --- a/ui/app/common/concept-set/directives/formControls.js +++ b/ui/app/common/concept-set/directives/formControls.js @@ -92,11 +92,7 @@ angular.module('bahmni.common.conceptSet') if (formObservation.value && formObservation.value.uuid && consultationObservation.value && consultationObservation.value.uuid) { return (consultationObservation.value.uuid === formObservation.value.uuid) ? false : true; } else { - if (angular.isNumber(formObservation.value)) { - formObservation.value = formObservation.value.toString(); - } - - return (consultationObservation.value === formObservation.value) ? false : true; + return !((consultationObservation.value === formObservation.value || (formObservation.value && consultationObservation.value === formObservation.value.toString()))); } } } From 009a826e697c52522a00d35954bcb4452c1002ee Mon Sep 17 00:00:00 2001 From: sowmya-AS <76809502+sowmya-AS@users.noreply.github.com> Date: Wed, 18 Oct 2023 23:14:00 +0530 Subject: [PATCH 10/11] Sowmya | fix alerts showing for unsaved observation even after all observations have been saved (#751) --- ui/app/common/concept-set/directives/formControls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/common/concept-set/directives/formControls.js b/ui/app/common/concept-set/directives/formControls.js index 23dfae08ca..1fc31c3da0 100644 --- a/ui/app/common/concept-set/directives/formControls.js +++ b/ui/app/common/concept-set/directives/formControls.js @@ -81,7 +81,7 @@ angular.module('bahmni.common.conceptSet') var consultationGroupMember = consultationObservation.groupMembers[consultationGroupIndex]; (formGroupMember.value && formGroupMember.value.uuid && consultationGroupMember.value && consultationGroupMember.value.uuid) ? isGroupMemberChanged[formGroupIndex] = (consultationGroupMember.value.uuid === formGroupMember.value.uuid) ? false : true : - isGroupMemberChanged[formGroupIndex] = (consultationGroupMember.value === formGroupMember.value) ? false : true; + isGroupMemberChanged[formGroupIndex] = (consultationGroupMember.value === formGroupMember.value || (formGroupMember.value && consultationGroupMember.value === formGroupMember.value.toString())) ? false : true; if (!isGroupMemberChanged[formGroupIndex]) { break; } From 29388eae2da3f26fadcda39e29d134a0a99705d6 Mon Sep 17 00:00:00 2001 From: Phanindra-tw Date: Thu, 19 Oct 2023 14:50:21 +0530 Subject: [PATCH 11/11] Phani | Fix patient dashboard error reading undefined 'patient' (#754) * Fix Css to incorporate Scroll bar * Fix TypeError in patient dashboard * Fix patient dashboard in Bed management * Fix patient dashboard in Bed management * Fix eslint --- .../dashboard/directives/dashboard.js | 18 ++++++++++-------- .../dashboard/Directives/dashboard.spec.js | 1 - 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ui/app/common/displaycontrols/dashboard/directives/dashboard.js b/ui/app/common/displaycontrols/dashboard/directives/dashboard.js index f20834545c..f5ab05b14b 100644 --- a/ui/app/common/displaycontrols/dashboard/directives/dashboard.js +++ b/ui/app/common/displaycontrols/dashboard/directives/dashboard.js @@ -1,14 +1,14 @@ 'use strict'; angular.module('bahmni.common.displaycontrol.dashboard') - .directive('dashboard', ['appService', '$stateParams', '$bahmniCookieStore', 'configurations', 'encounterService', 'spinner', 'auditLogService', 'messagingService', '$state', '$translate', function (appService, $stateParams, $bahmniCookieStore, configurations, encounterService, spinner, auditLogService, messagingService, $state, $translate) { + .directive('dashboard', ['appService', '$stateParams', '$bahmniCookieStore', 'configurations', 'encounterService', 'spinner', 'messagingService', '$state', '$translate', function (appService, $stateParams, $bahmniCookieStore, configurations, encounterService, spinner, messagingService, $state, $translate) { var controller = function ($scope, $filter, $rootScope) { var init = function () { + $scope.tabConfigName = $stateParams.tabConfigName || 'default'; $scope.dashboard = Bahmni.Common.DisplayControl.Dashboard.create($scope.config || {}, $filter); }; - $scope.tabConfigName = $stateParams.tabConfigName || 'default'; - if ($scope.patient !== undefined) { + if ($scope.patient !== undefined && $state.current.name.includes('patient.dashboard.show')) { $scope.formData = { patientUuid: $scope.patient.uuid, patient: $scope.patient, @@ -24,11 +24,13 @@ angular.module('bahmni.common.displaycontrol.dashboard') $scope.formApi = { handleEditSave: function (encounter) { spinner.forPromise(encounterService.create(encounter).then(function (savedResponse) { - var messageParams = { - encounterUuid: savedResponse.data.encounterUuid, - encounterType: savedResponse.data.encounterType - }; - auditLogService.log($scope.patient.uuid, "EDIT_ENCOUNTER", messageParams, "MODULE_LABEL_CLINICAL_KEY"); + // TODO: Fix the Audit log Service + + // var messageParams = { + // encounterUuid: savedResponse.data.encounterUuid, + // encounterType: savedResponse.data.encounterType + // }; + // auditLogService.log($scope.patient.uuid, "EDIT_ENCOUNTER", messageParams, "MODULE_LABEL_CLINICAL_KEY"); $rootScope.hasVisitedConsultation = false; $state.go($state.current, {}, {reload: true}); messagingService.showMessage('info', "{{'CLINICAL_SAVE_SUCCESS_MESSAGE_KEY' | translate}}"); diff --git a/ui/test/unit/common/displaycontrols/dashboard/Directives/dashboard.spec.js b/ui/test/unit/common/displaycontrols/dashboard/Directives/dashboard.spec.js index 2abddcbd2b..9c49267e42 100644 --- a/ui/test/unit/common/displaycontrols/dashboard/Directives/dashboard.spec.js +++ b/ui/test/unit/common/displaycontrols/dashboard/Directives/dashboard.spec.js @@ -21,7 +21,6 @@ describe('Dashboard', function () { $provide.value('$stateParams', {tabConfigName: 'default'}); $provide.value('encounterService', {}); $provide.value('spinner', {}); - $provide.value('auditLogService', {}); $provide.value('messagingService', {}); $provide.value('$state', {}); $provide.value('$translate', {});