'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; (function () { var hostUrl = localStorage.getItem('host') ? ("https://" + localStorage.getItem('host')) : ""; var rootDir = localStorage.getItem('rootDir') || ""; var RESTWS = hostUrl + "/openmrs/ws/rest"; var RESTWS_V1 = hostUrl + "/openmrs/ws/rest/v1"; var BAHMNI_CORE = RESTWS_V1 + "/bahmnicore"; var EMRAPI = RESTWS + "/emrapi"; var BACTERIOLOGY = RESTWS_V1; var BASE_URL = hostUrl + "/bahmni_config/openmrs/apps/"; var CUSTOM_URL = hostUrl + "/implementation_config/openmrs/apps/"; var serverErrorMessages = [ { serverMessage: "Cannot have more than one active order for the same orderable and care setting at same time", clientMessage: "One or more drugs you are trying to order are already active. Please change the start date of the conflicting drug or remove them from the new prescription." }, { serverMessage: "[Order.cannot.have.more.than.one]", clientMessage: "One or more drugs you are trying to order are already active. Please change the start date of the conflicting drug or remove them from the new prescription." } ]; var representation = "custom:(uuid,name,names,conceptClass," + "setMembers:(uuid,name,names,conceptClass," + "setMembers:(uuid,name,names,conceptClass," + "setMembers:(uuid,name,names,conceptClass))))"; var unAuthenticatedReferenceDataMap = { "/openmrs/ws/rest/v1/location?tags=Login+Location&s=byTags&v=default": "LoginLocations", "/openmrs/ws/rest/v1/bahmnicore/sql/globalproperty?property=locale.allowed.list": "LocaleList" }; var authenticatedReferenceDataMap = { "/openmrs/ws/rest/v1/idgen/identifiertype": "IdentifierTypes", "/openmrs/module/addresshierarchy/ajax/getOrderedAddressHierarchyLevels.form": "AddressHierarchyLevels", "/openmrs/ws/rest/v1/bahmnicore/sql/globalproperty?property=mrs.genders": "Genders", "/openmrs/ws/rest/v1/bahmnicore/sql/globalproperty?property=bahmni.encountersession.duration": "encounterSessionDuration", "/openmrs/ws/rest/v1/bahmnicore/sql/globalproperty?property=bahmni.relationshipTypeMap": "RelationshipTypeMap", "/openmrs/ws/rest/v1/bahmnicore/config/bahmniencounter?callerContext=REGISTRATION_CONCEPTS": "RegistrationConcepts", "/openmrs/ws/rest/v1/relationshiptype?v=custom:(aIsToB,bIsToA,uuid)": "RelationshipType", "/openmrs/ws/rest/v1/personattributetype?v=custom:(uuid,name,sortWeight,description,format,concept)": "PersonAttributeType", "/openmrs/ws/rest/v1/entitymapping?mappingType=loginlocation_visittype&s=byEntityAndMappingType": "LoginLocationToVisitTypeMapping", "/openmrs/ws/rest/v1/bahmnicore/config/patient": "PatientConfig", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=Consultation+Note&v=custom:(uuid,name,answers)": "ConsultationNote", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=Lab+Order+Notes&v=custom:(uuid,name)": "LabOrderNotes", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=Impression&v=custom:(uuid,name)": "RadiologyImpressionConfig", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=All_Tests_and_Panels&v=custom:(uuid,name:(uuid,name),setMembers:(uuid,name:(uuid,name)))": "AllTestsAndPanelsConcept", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=Dosage+Frequency&v=custom:(uuid,name,answers)": "DosageFrequencyConfig", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=Dosage+Instructions&v=custom:(uuid,name,answers)": "DosageInstructionConfig", "/openmrs/ws/rest/v1/bahmnicore/sql/globalproperty?property=bahmni.encounterType.default": "DefaultEncounterType", "/openmrs/ws/rest/v1/concept?s=byFullySpecifiedName&name=Stopped+Order+Reason&v=custom:(uuid,name,answers)": "StoppedOrderReasonConfig", "/openmrs/ws/rest/v1/ordertype": "OrderType", "/openmrs/ws/rest/v1/bahmnicore/config/drugOrders": "DrugOrderConfig", "/openmrs/ws/rest/v1/bahmnicore/sql/globalproperty?property=drugOrder.drugOther": "NonCodedDrugConcept" }; authenticatedReferenceDataMap["/openmrs/ws/rest/v1/entitymapping?mappingType=location_encountertype&s=byEntityAndMappingType&entityUuid=" + (localStorage.getItem("LoginInformation") ? JSON.parse(localStorage.getItem("LoginInformation")).currentLocation.uuid : "")] = "LoginLocationToEncounterTypeMapping"; Bahmni.Common.Constants = { hostURL: hostUrl, dateFormat: "dd/mm/yyyy", dateDisplayFormat: "DD-MMM-YYYY", timeDisplayFormat: "hh:mm", emrapiDiagnosisUrl: EMRAPI + "/diagnosis", bahmniDiagnosisUrl: BAHMNI_CORE + "/diagnosis/search", bahmniDeleteDiagnosisUrl: BAHMNI_CORE + "/diagnosis/delete", diseaseTemplateUrl: BAHMNI_CORE + "/diseaseTemplates", AllDiseaseTemplateUrl: BAHMNI_CORE + "/diseaseTemplate", emrapiConceptUrl: EMRAPI + "/concept", encounterConfigurationUrl: BAHMNI_CORE + "/config/bahmniencounter", patientConfigurationUrl: BAHMNI_CORE + "/config/patient", drugOrderConfigurationUrl: BAHMNI_CORE + "/config/drugOrders", emrEncounterUrl: EMRAPI + "/encounter", encounterUrl: RESTWS_V1 + "/encounter", locationUrl: RESTWS_V1 + "/location", bahmniVisitLocationUrl: BAHMNI_CORE + "/visitLocation", bahmniOrderUrl: BAHMNI_CORE + "/orders", bahmniDrugOrderUrl: BAHMNI_CORE + "/drugOrders", bahmniDispositionByVisitUrl: BAHMNI_CORE + "/disposition/visit", bahmniDispositionByPatientUrl: BAHMNI_CORE + "/disposition/patient", bahmniSearchUrl: BAHMNI_CORE + "/search", bahmniLabOrderResultsUrl: BAHMNI_CORE + "/labOrderResults", bahmniEncounterUrl: BAHMNI_CORE + "/bahmniencounter", conceptUrl: RESTWS_V1 + "/concept", bahmniConceptAnswerUrl: RESTWS_V1 + "/bahmniconceptanswer", conceptSearchByFullNameUrl: RESTWS_V1 + "/concept?s=byFullySpecifiedName", visitUrl: RESTWS_V1 + "/visit", endVisitUrl: BAHMNI_CORE + "/visit/endVisit", endVisitAndCreateEncounterUrl: BAHMNI_CORE + "/visit/endVisitAndCreateEncounter", visitTypeUrl: RESTWS_V1 + "/visittype", patientImageUrlByPatientUuid: RESTWS_V1 + "/patientImage?patientUuid=", labResultUploadedFileNameUrl: "/uploaded_results/", visitSummaryUrl: BAHMNI_CORE + "/visit/summary", encounterModifierUrl: BAHMNI_CORE + "/bahmniencountermodifier", openmrsUrl: hostUrl + "/openmrs", loggingUrl: hostUrl + "/log/", idgenConfigurationURL: RESTWS_V1 + "/idgen/identifiertype", bahmniRESTBaseURL: BAHMNI_CORE + "", observationsUrl: BAHMNI_CORE + "/observations", obsRelationshipUrl: BAHMNI_CORE + "/obsrelationships", encounterImportUrl: BAHMNI_CORE + "/admin/upload/encounter", programImportUrl: BAHMNI_CORE + "/admin/upload/program", conceptImportUrl: BAHMNI_CORE + "/admin/upload/concept", conceptSetImportUrl: BAHMNI_CORE + "/admin/upload/conceptset", drugImportUrl: BAHMNI_CORE + "/admin/upload/drug", labResultsImportUrl: BAHMNI_CORE + "/admin/upload/labResults", referenceTermsImportUrl: BAHMNI_CORE + "/admin/upload/referenceterms", relationshipImportUrl: BAHMNI_CORE + "/admin/upload/relationship", conceptSetExportUrl: BAHMNI_CORE + "/admin/export/conceptset?conceptName=:conceptName", patientImportUrl: BAHMNI_CORE + "/admin/upload/patient", adminImportStatusUrl: BAHMNI_CORE + "/admin/upload/status", programUrl: RESTWS_V1 + "/program", programEnrollPatientUrl: RESTWS_V1 + "/bahmniprogramenrollment", programStateDeletionUrl: RESTWS_V1 + "/programenrollment", programEnrollmentDefaultInformation: "default", programEnrollmentFullInformation: "full", programAttributeTypes: RESTWS_V1 + "/programattributetype", relationshipTypesUrl: RESTWS_V1 + "/relationshiptype", personAttributeTypeUrl: RESTWS_V1 + "/personattributetype", diseaseSummaryPivotUrl: BAHMNI_CORE + "/diseaseSummaryData", allTestsAndPanelsConceptName: 'All_Tests_and_Panels', dosageFrequencyConceptName: 'Dosage Frequency', dosageInstructionConceptName: 'Dosage Instructions', stoppedOrderReasonConceptName: 'Stopped Order Reason', consultationNoteConceptName: 'Consultation Note', diagnosisConceptSet: 'Diagnosis Concept Set', radiologyOrderType: 'Radiology Order', radiologyResultConceptName: "Radiology Result", investigationEncounterType: "INVESTIGATION", validationNotesEncounterType: "VALIDATION NOTES", labOrderNotesConcept: "Lab Order Notes", impressionConcept: "Impression", qualifiedByRelationshipType: "qualified-by", dispositionConcept: "Disposition", dispositionGroupConcept: "Disposition Set", dispositionNoteConcept: "Disposition Note", ruledOutDiagnosisConceptName: 'Ruled Out Diagnosis', emrapiConceptMappingSource: "org.openmrs.module.emrapi", abbreviationConceptMappingSource: "Abbreviation", includeAllObservations: false, openmrsObsUrl: RESTWS_V1 + "/obs", openmrsObsRepresentation: "custom:(uuid,obsDatetime,value:(uuid,name:(uuid,name)))", admissionCode: 'ADMIT', dischargeCode: 'DISCHARGE', transferCode: 'TRANSFER', undoDischargeCode: 'UNDO_DISCHARGE', vitalsConceptName: "Vitals", heightConceptName: "HEIGHT", weightConceptName: "WEIGHT", bmiConceptName: "BMI", // TODO : shruthi : revove this when this logic moved to server side bmiStatusConceptName: "BMI STATUS", // TODO : shruthi : revove this when this logic moved to server side abnormalObservationConceptName: "IS_ABNORMAL", documentsPath: '/document_images', documentsConceptName: 'Document', miscConceptClassName: 'Misc', abnormalConceptClassName: 'Abnormal', unknownConceptClassName: 'Unknown', durationConceptClassName: 'Duration', conceptDetailsClassName: 'Concept Details', admissionEncounterTypeName: 'ADMISSION', dischargeEncounterTypeName: 'DISCHARGE', imageClassName: 'Image', videoClassName: 'Video', locationCookieName: 'bahmni.user.location', retrospectiveEntryEncounterDateCookieName: 'bahmni.clinical.retrospectiveEncounterDate', JSESSIONID: "JSESSIONID", rootScopeRetrospectiveEntry: 'retrospectiveEntry.encounterDate', patientFileConceptName: 'Patient file', serverErrorMessages: serverErrorMessages, currentUser: 'bahmni.user', retrospectivePrivilege: 'app:clinical:retrospective', locationPickerPrivilege: 'app:clinical:locationpicker', onBehalfOfPrivilege: 'app:clinical:onbehalf', nutritionalConceptName: 'Nutritional Values', messageForNoObservation: "NO_OBSERVATIONS_CAPTURED", messageForNoDisposition: "NO_DISPOSTIONS_AVAILABLE_MESSAGE_KEY", messageForNoFulfillment: "NO_FULFILMENT_MESSAGE", reportsUrl: "/bahmnireports", uploadReportTemplateUrl: "/bahmnireports/upload", ruledOutdiagnosisStatus: "Ruled Out Diagnosis", registartionConsultationPrivilege: 'app:common:registration_consultation_link', manageIdentifierSequencePrivilege: "Manage Identifier Sequence", closeVisitPrivilege: 'app:common:closeVisit', deleteDiagnosisPrivilege: 'app:clinical:deleteDiagnosis', viewPatientsPrivilege: 'View Patients', editPatientsPrivilege: 'Edit Patients', addVisitsPrivilege: 'Add Visits', deleteVisitsPrivilege: 'Delete Visits', grantProviderAccess: "app:clinical:grantProviderAccess", grantProviderAccessDataCookieName: "app.clinical.grantProviderAccessData", globalPropertyUrl: BAHMNI_CORE + "/sql/globalproperty", passwordPolicyUrl: BAHMNI_CORE + "/globalProperty/passwordPolicyProperties", fulfillmentConfiguration: "fulfillment", fulfillmentFormSuffix: " Fulfillment Form", noNavigationLinksMessage: "NO_NAVIGATION_LINKS_AVAILABLE_MESSAGE", conceptSetRepresentationForOrderFulfillmentConfig: representation, entityMappingUrl: RESTWS_V1 + "/entitymapping", encounterTypeUrl: RESTWS_V1 + "/encountertype", defaultExtensionName: "default", orderSetMemberAttributeTypeUrl: RESTWS_V1 + "/ordersetmemberattributetype", orderSetUrl: RESTWS_V1 + "/bahmniorderset", primaryOrderSetMemberAttributeTypeName: "Primary", bahmniBacteriologyResultsUrl: BACTERIOLOGY + "/specimen", bedFromVisit: RESTWS_V1 + "/beds", ordersUrl: RESTWS_V1 + "/order", formDataUrl: RESTWS_V1 + "/obs", providerUrl: RESTWS_V1 + "/provider", drugUrl: RESTWS_V1 + "/drug", orderTypeUrl: RESTWS_V1 + "/ordertype", userUrl: RESTWS_V1 + "/user", passwordUrl: RESTWS_V1 + "/password", formUrl: RESTWS_V1 + "/form", allFormsUrl: RESTWS_V1 + "/bahmniie/form/allForms", latestPublishedForms: RESTWS_V1 + "/bahmniie/form/latestPublishedForms", formTranslationsUrl: RESTWS_V1 + "/bahmniie/form/translations", sqlUrl: BAHMNI_CORE + "/sql", patientAttributeDateFieldFormat: "org.openmrs.util.AttributableDate", platform: "user.platform", RESTWS_V1: RESTWS_V1, baseUrl: BASE_URL, customUrl: CUSTOM_URL, faviconUrl: hostUrl + "/bahmni/favicon.ico", platformType: { other: 'other' }, numericDataType: "Numeric", encryptionType: { SHA3: 'SHA3' }, LoginInformation: 'LoginInformation', // orderSetSpecialUnits:["mg/kg","mg/m2"], ServerDateTimeFormat: 'YYYY-MM-DDTHH:mm:ssZZ', calculateDose: BAHMNI_CORE + "/calculateDose", unAuthenticatedReferenceDataMap: unAuthenticatedReferenceDataMap, authenticatedReferenceDataMap: authenticatedReferenceDataMap, rootDir: rootDir, dischargeUrl: BAHMNI_CORE + "/discharge", uuidRegex: "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", eventlogFilterUrl: hostUrl + "/openmrs/ws/rest/v1/eventlog/filter", bahmniConnectMetaDataDb: "metaData", serverDateTimeUrl: "/cgi-bin/systemdate", loginText: "/bahmni_config/openmrs/apps/home/whiteLabel.json", auditLogUrl: RESTWS_V1 + "/auditlog", appointmentServiceUrl: RESTWS_V1 + "/appointmentService", conditionUrl: EMRAPI + '/condition', conditionHistoryUrl: EMRAPI + '/conditionhistory', followUpConditionConcept: 'Follow-up Condition', localeLangs: "/bahmni_config/openmrs/apps/home/locale_languages.json", privilegeRequiredErrorMessage: "PRIVILEGE_REQUIRED", defaultPossibleRelativeSearchLimit: 10 }; })(); /** * @license * lodash 4.3.0 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE * Build: `lodash -o ./dist/lodash.js` */ ;(function(){function n(n,t){return n.set(t[0],t[1]),n}function t(n,t){return n.add(t),n}function r(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function e(n,t,r,e){for(var u=-1,o=n.length;++ut&&!o||!u||r&&!i&&f||e&&f)return 1;if(t>n&&!r||!f||o&&!e&&u||i&&u)return-1}return 0}function S(n){return Un[n]}function R(n){return zn[n]}function W(n){return"\\"+$n[n]}function B(n,t,r){var e=n.length;for(t+=r?0:-1;r?t--:++t-1&&0==n%1&&(null==t?9007199254740991:t)>n}function z(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}function M(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function L(n,t){for(var r=-1,e=n.length,u=-1,o=[];++rr?false:(r==n.length-1?n.pop():Ou.call(n,r,1),true)}function Zn(n,t){var r=qn(n,t);return 0>r?Z:n[r][1]}function qn(n,t){for(var r=n.length;r--;)if(se(n[r][0],t))return r;return-1}function Pn(n,t,r){var e=qn(n,t);0>e?n.push([t,r]):n[e][1]=r}function Tn(n,t,r,e){return n===Z||se(n,iu[r])&&!cu.call(e,r)?t:n}function Gn(n,t,r){(r!==Z&&!se(n[t],r)||typeof t=="number"&&r===Z&&!(t in n))&&(n[t]=r)}function Yn(n,t,r){var e=n[t];(!se(e,r)||se(e,iu[t])&&!cu.call(n,t)||r===Z&&!(t in n))&&(n[t]=r); }function Hn(n,t,r,e){return Ju(n,function(n,u,o){t(e,n,r(n),o)}),e}function Qn(n,t){return n&&Ht(t,Fe(t),n)}function Xn(n,t){for(var r=-1,e=null==n,u=t.length,o=Array(u);++rr?r:n),t!==Z&&(n=t>n?t:n)),n}function tt(n,t,r,e,o,i){var f;if(r&&(f=o?r(n,e,o,i):r(n)),f!==Z)return f;if(!xe(n))return n;if(e=No(n)){if(f=Ir(n),!t)return Yt(n,f)}else{var c=kr(n),a="[object Function]"==c||"[object GeneratorFunction]"==c;if(Do(n))return Kt(n,t); if("[object Object]"!=c&&"[object Arguments]"!=c&&(!a||o))return Cn[c]?Rr(n,c,t):o?n:{};if(C(n))return o?n:{};if(f=Sr(a?{}:n),!t)return Xt(n,Qn(f,n))}return i||(i=new $n),(o=i.get(n))?o:(i.set(n,f),(e?u:at)(n,function(e,u){Yn(f,u,tt(e,t,r,u,n,i))}),e?f:Xt(n,f))}function rt(n){var t=Fe(n),r=t.length;return function(e){if(null==e)return!r;for(var u=r;u--;){var o=t[u],i=n[o],f=e[o];if(f===Z&&!(o in Object(e))||!i(f))return false}return true}}function et(n,t,r){if(typeof n!="function")throw new uu("Expected a function"); return Au(function(){n.apply(Z,r)},t)}function ut(n,t,r,e){var u=-1,o=f,i=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=a(t,w(r))),e?(o=c,i=false):t.length>=200&&(o=Ln,i=false,t=new Mn(t));n:for(;++ur;)n=n[t[r++]];return r&&r==e?n:Z}function pt(n,t){return cu.call(n,t)||typeof n=="object"&&t in n&&null===xu(n)}function _t(n,t){return t in Object(n); }function gt(n,t,r){for(var e=r?c:f,u=n.length,o=u,i=Array(u),l=[];o--;){var s=n[o];o&&t&&(s=a(s,w(t))),i[o]=r||!t&&120>s.length?Z:new Mn(o&&s)}var s=n[0],h=-1,p=s.length,_=i[0];n:for(;++h=f){e=c;break n}e=c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function Et(n,t){return n=Object(n),s(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function It(n,t){var r={};return ct(n,function(n,e){t(n,e)&&(r[e]=n)}),r}function St(n){return function(t){return null==t?Z:t[n]}}function Rt(n){return function(t){return ht(t,n)}}function Wt(n,t,r){ var e=-1,u=t.length,o=n;for(r&&(o=a(n,function(n){return r(n)}));++et&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e=u){for(;u>e;){var o=e+u>>>1,i=n[o];(r?t>=i:t>i)&&null!==i?e=o+1:u=o; }return u}return $t(n,t,Ve,r)}function $t(n,t,r,e){t=r(t);for(var u=0,o=n?n.length:0,i=t!==t,f=null===t,c=t===Z;o>u;){var a=Eu((u+o)/2),l=r(n[a]),s=l!==Z,h=l===l;(i?h||e:f?h&&s&&(e||null!=l):c?h&&(e||s):null==l?0:e?t>=l:t>l)?u=a+1:o=a}return Bu(o,4294967294)}function Ft(n,t){for(var r=0,e=n.length,u=n[0],o=t?t(u):u,i=o,f=0,c=[u];++re?t[e]:Z);return i}function Kt(n,t){if(t)return n.slice();var r=new n.constructor(n.length);return n.copy(r),r}function Gt(n){var t=new n.constructor(n.byteLength);return new du(t).set(new du(n)),t}function Vt(n,t,r){for(var e=r.length,u=-1,o=Wu(n.length-e,0),i=-1,f=t.length,c=Array(f+o);++i1?r[u-1]:Z,i=u>2?r[2]:Z,o=typeof o=="function"?(u--, o):Z;for(i&&Br(r[0],r[1],i)&&(o=3>u?Z:o,u=1),t=Object(t);++ei&&c[0]!==l&&c[i-1]!==l?[]:L(c,l),i-=f.length,e>i?vr(n,t,lr,l,Z,c,f,Z,Z,e-i):r(a,this,c)}var o=fr(n);return u}function ar(n){return le(function(t){t=ft(t);var r=t.length,e=r,u=wn.prototype.thru; for(n&&t.reverse();e--;){var o=t[e];if(typeof o!="function")throw new uu("Expected a function");if(u&&!i&&"wrapper"==mr(o))var i=new wn([],true)}for(e=i?e:r;++e=200)return i.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++uy)return vr(n,t,lr,b,r,x,j,f,c,a-y)}if(y=h?r:this,b=p?y[n]:n,f)for(var j=x.length,m=Bu(f.length,j),w=Yt(x);m--;){var A=f[m];x[m]=U(A,j)?w[A]:Z}else v&&x.length>1&&x.reverse();return s&&x.length>c&&(x.length=c),this&&this!==Vn&&this instanceof l&&(b=d||fr(b)),b.apply(y,x)}var s=128&t,h=1&t,p=2&t,_=8&t,g=16&t,v=512&t,d=p?Z:fr(n); return l}function sr(n,t){return function(r,e){return vt(r,n,t(e),{})}}function hr(n){return le(function(t){return t=a(ft(t),wr()),le(function(e){var u=this;return n(t,function(n){return r(n,u,e)})})})}function pr(n,t,r){return t=We(t),n=F(n),t&&t>n?(t-=n,r=r===Z?" ":r+"",n=Te(r,ku(t/F(r))),En.test(r)?n.match(kn).slice(0,t).join(""):n.slice(0,t)):""}function _r(n,t,e,u){function o(){for(var t=-1,c=arguments.length,a=-1,l=u.length,s=Array(l+c),h=this&&this!==Vn&&this instanceof o?f:n;++at?1:-1:Ce(e)||0;var u=-1;r=Wu(ku((r-t)/(e||1)),0);for(var o=Array(r);r--;)o[n?r:++u]=t,t+=e;return o}}function vr(n,t,r,e,u,o,i,f,c,a){var l=8&t;f=f?Yt(f):Z;var s=l?i:Z;i=l?Z:i;var h=l?o:Z;return o=l?Z:o,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),t=[n,t,u,h,s,o,i,f,c,a],r=r.apply(Z,t), zr(n)&&uo(r,t),r.placeholder=e,r}function dr(n){var t=ru[n];return function(n,r){if(n=Ce(n),r=We(r)){var e=(ze(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(ze(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function yr(n,t,r,e,u,o,i,f){var c=2&t;if(!c&&typeof n!="function")throw new uu("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=Z),i=i===Z?i:Wu(We(i),0),f=f===Z?f:We(f),a-=u?u.length:0,64&t){var l=e,s=u;e=u=Z}var h=c?Z:to(n);return o=[n,t,r,e,u,l,s,o,i,f],h&&(r=o[1],n=h[1], t=r|n,e=128==n&&8==r||128==n&&256==r&&h[8]>=o[7].length||384==n&&h[8]>=h[7].length&&8==r,131>t||e)&&(1&n&&(o[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=o[3],o[3]=e?Vt(e,r,h[4]):Yt(r),o[4]=e?L(o[3],"__lodash_placeholder__"):Yt(h[4])),(r=h[5])&&(e=o[5],o[5]=e?Jt(e,r,h[6]):Yt(r),o[6]=e?L(o[5],"__lodash_placeholder__"):Yt(h[6])),(r=h[7])&&(o[7]=Yt(r)),128&n&&(o[8]=null==o[8]?h[8]:Bu(o[8],h[8])),null==o[9]&&(o[9]=h[9]),o[0]=h[0],o[1]=t),n=o[0],t=o[1],r=o[2],e=o[3],u=o[4],f=o[9]=null==o[9]?c?0:n.length:Wu(o[9]-a,0), !f&&24&t&&(t&=-25),c=t&&1!=t?8==t||16==t?cr(n,t,f):32!=t&&33!=t||u.length?lr.apply(Z,o):_r(n,t,r,e):ur(n,t,r),(h?Xu:uo)(c,o)}function br(n,t,r,e,u,o){var i=-1,f=2&u,c=1&u,a=n.length,l=t.length;if(!(a==l||f&&l>a))return false;if(l=o.get(n))return l==t;for(l=true,o.set(n,t);++it?0:t,e)):[]}function Pr(n,t,r){var e=n?n.length:0;return e?(t=r||t===Z?1:We(t),t=e-t,zt(n,0,0>t?0:t)):[]}function Tr(n){return n?n[0]:Z}function Kr(n){var t=n?n.length:0;return t?n[t-1]:Z}function Gr(n,t){return n&&n.length&&t&&t.length?Wt(n,t):n; }function Vr(n){return n?zu.call(n):n}function Jr(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){return ge(n)?(t=Wu(n.length,t),true):void 0}),j(t,function(t){return a(n,St(t))})}function Yr(n,t){if(!n||!n.length)return[];var e=Jr(n);return null==t?e:a(e,function(n){return r(t,Z,n)})}function Hr(n){return n=yn(n),n.__chain__=true,n}function Qr(n,t){return t(n)}function Xr(){return this}function ne(n,t){return typeof t=="function"&&No(n)?u(n,t):Ju(n,Dr(t))}function te(n,t){var r;if(typeof t=="function"&&No(n)){ for(r=n.length;r--&&false!==t(n[r],r,n););r=n}else r=Yu(n,Dr(t));return r}function re(n,t){return(No(n)?a:mt)(n,wr(t,3))}function ee(n,t){var r=-1,e=Re(n),u=e.length,o=u-1;for(t=nt(We(t),0,u);++r=n&&(t=Z),r}}function ie(n,t,r){ return t=r?Z:t,n=yr(n,8,Z,Z,Z,Z,Z,t),n.placeholder=yn.placeholder||ie.placeholder,n}function fe(n,t,r){return t=r?Z:t,n=yr(n,16,Z,Z,Z,Z,Z,t),n.placeholder=yn.placeholder||fe.placeholder,n}function ce(n,t,r){function e(){p&&yu(p),a&&yu(a),g=0,c=a=h=p=_=Z}function u(t,r){r&&yu(r),a=p=_=Z,t&&(g=Wo(),l=n.apply(h,c),p||a||(c=h=Z))}function o(){var n=t-(Wo()-s);0>=n||n>t?u(_,a):p=Au(o,n)}function i(){u(y,p)}function f(){if(c=arguments,s=Wo(),h=this,_=y&&(p||!v),false===d)var r=v&&!p;else{g||a||v||(g=s);var e=d-(s-g),u=0>=e||e>d; u?(a&&(a=yu(a)),g=s,l=n.apply(h,c)):a||(a=Au(i,e))}return u&&p?p=yu(p):p||t===d||(p=Au(o,t)),r&&(u=true,l=n.apply(h,c)),!u||p||a||(c=h=Z),l}var c,a,l,s,h,p,_,g=0,v=false,d=false,y=true;if(typeof n!="function")throw new uu("Expected a function");return t=Ce(t)||0,xe(r)&&(v=!!r.leading,d="maxWait"in r&&Wu(Ce(r.maxWait)||0,t),y="trailing"in r?!!r.trailing:y),f.cancel=e,f.flush=function(){return(p&&_||a&&y)&&(l=n.apply(h,c)),e(),l},f}function ae(n,t){if(typeof n!="function"||t&&typeof t!="function")throw new uu("Expected a function"); var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=n.apply(this,e),r.cache=o.set(u,e),e)};return r.cache=new ae.Cache,r}function le(n,t){if(typeof n!="function")throw new uu("Expected a function");return t=Wu(t===Z?n.length-1:We(t),0),function(){for(var e=arguments,u=-1,o=Wu(e.length-t,0),i=Array(o);++ut}function pe(n){return ge(n)&&cu.call(n,"callee")&&(!wu.call(n,"callee")||"[object Arguments]"==su.call(n))}function _e(n){return null!=n&&!(typeof n=="function"&&de(n))&&be(ro(n))}function ge(n){return je(n)&&_e(n)}function ve(n){return je(n)&&typeof n.message=="string"&&"[object Error]"==su.call(n)}function de(n){return n=xe(n)?su.call(n):"","[object Function]"==n||"[object GeneratorFunction]"==n}function ye(n){ return typeof n=="number"&&n==We(n)}function be(n){return typeof n=="number"&&n>-1&&0==n%1&&9007199254740991>=n}function xe(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function je(n){return!!n&&typeof n=="object"}function me(n){return null==n?false:de(n)?pu.test(fu.call(n)):je(n)&&(C(n)?pu:vn).test(n)}function we(n){return typeof n=="number"||je(n)&&"[object Number]"==su.call(n)}function Ae(n){if(!je(n)||"[object Object]"!=su.call(n)||C(n))return false;var t=iu;return typeof n.constructor=="function"&&(t=xu(n)), null===t?true:(n=t.constructor,typeof n=="function"&&n instanceof n&&fu.call(n)==lu)}function Oe(n){return xe(n)&&"[object RegExp]"==su.call(n)}function ke(n){return typeof n=="string"||!No(n)&&je(n)&&"[object String]"==su.call(n)}function Ee(n){return typeof n=="symbol"||je(n)&&"[object Symbol]"==su.call(n)}function Ie(n){return je(n)&&be(n.length)&&!!Bn[su.call(n)]}function Se(n,t){return t>n}function Re(n){if(!n)return[];if(_e(n))return ke(n)?n.match(kn):Yt(n);if(mu&&n[mu])return z(n[mu]());var t=kr(n); return("[object Map]"==t?M:"[object Set]"==t?$:Ze)(n)}function We(n){if(!n)return 0===n?n:0;if(n=Ce(n),n===q||n===-q)return 1.7976931348623157e308*(0>n?-1:1);var t=n%1;return n===n?t?n-t:n:0}function Be(n){return n?nt(We(n),0,4294967295):0}function Ce(n){if(xe(n)&&(n=de(n.valueOf)?n.valueOf():n,n=xe(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(fn,"");var t=gn.test(n);return t||dn.test(n)?Nn(n.slice(2),t?2:8):_n.test(n)?P:+n}function Ue(n){return Ht(n,Ne(n))}function ze(n){if(typeof n=="string")return n; if(null==n)return"";if(Ee(n))return vu?Ku.call(n):"";var t=n+"";return"0"==t&&1/n==-q?"-0":t}function Me(n,t,r){return n=null==n?Z:ht(n,t),n===Z?r:n}function Le(n,t){return Er(n,t,pt)}function $e(n,t){return Er(n,t,_t)}function Fe(n){var t=Mr(n);if(!t&&!_e(n))return Ru(Object(n));var r,e=Wr(n),u=!!e,e=e||[],o=e.length;for(r in n)!pt(n,r)||u&&("length"==r||U(r,o))||t&&"constructor"==r||e.push(r);return e}function Ne(n){for(var t=-1,r=Mr(n),e=jt(n),u=e.length,o=Wr(n),i=!!o,o=o||[],f=o.length;++tt||t>9007199254740991)return r;do t%2&&(r+=n),t=Eu(t/2),n+=n;while(t);return r}function Ke(n,t,r){return n=ze(n),t=r?Z:t,t===Z&&(t=Rn.test(n)?Sn:In),n.match(t)||[]}function Ge(n){ return function(){return n}}function Ve(n){return n}function Je(n){return xt(typeof n=="function"?n:tt(n,true))}function Ye(n,t,r){var e=Fe(t),o=st(t,e);null!=r||xe(t)&&(o.length||!e.length)||(r=t,t=n,n=this,o=st(t,Fe(t)));var i=xe(r)&&"chain"in r?r.chain:true,f=de(n);return u(o,function(r){var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=Yt(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,l([this.value()],arguments)); })}),n}function He(){}function Qe(n){return Cr(n)?St(n):Rt(n)}function Xe(n){return n&&n.length?x(n,Ve):0}E=E?Jn.defaults({},E,Jn.pick(Vn,Wn)):Vn;var nu=E.Date,tu=E.Error,ru=E.Math,eu=E.RegExp,uu=E.TypeError,ou=E.Array.prototype,iu=E.Object.prototype,fu=E.Function.prototype.toString,cu=iu.hasOwnProperty,au=0,lu=fu.call(Object),su=iu.toString,hu=Vn._,pu=eu("^"+fu.call(cu).replace(un,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),_u=Kn?E.Buffer:Z,gu=E.Reflect,vu=E.Symbol,du=E.Uint8Array,yu=E.clearTimeout,bu=gu?gu.enumerate:Z,xu=Object.getPrototypeOf,ju=Object.getOwnPropertySymbols,mu=typeof(mu=vu&&vu.iterator)=="symbol"?mu:Z,wu=iu.propertyIsEnumerable,Au=E.setTimeout,Ou=ou.splice,ku=ru.ceil,Eu=ru.floor,Iu=E.isFinite,Su=ou.join,Ru=Object.keys,Wu=ru.max,Bu=ru.min,Cu=E.parseInt,Uu=ru.random,zu=ou.reverse,Mu=Or(E,"Map"),Lu=Or(E,"Set"),$u=Or(E,"WeakMap"),Fu=Or(Object,"create"),Nu=$u&&new $u,Du=Mu?fu.call(Mu):"",Zu=Lu?fu.call(Lu):"",qu=$u?fu.call($u):"",Pu=vu?vu.prototype:Z,Tu=vu?Pu.valueOf:Z,Ku=vu?Pu.toString:Z,Gu={}; yn.templateSettings={escape:Q,evaluate:X,interpolate:nn,variable:"",imports:{_:yn}};var Vu=function(){function n(){}return function(t){if(xe(t)){n.prototype=t;var r=new n;n.prototype=Z}return r||{}}}(),Ju=rr(at),Yu=rr(lt,true),Hu=er(),Qu=er(true);bu&&!wu.call({valueOf:1},"valueOf")&&(jt=function(n){return z(bu(n))});var Xu=Nu?function(n,t){return Nu.set(n,t),n}:Ve,no=Lu&&2===new Lu([1,2]).size?function(n){return new Lu(n)}:He,to=Nu?function(n){return Nu.get(n)}:He,ro=St("length"),eo=ju||function(){return[]; };(Mu&&"[object Map]"!=kr(new Mu)||Lu&&"[object Set]"!=kr(new Lu)||$u&&"[object WeakMap]"!=kr(new $u))&&(kr=function(n){var t=su.call(n);if(n="[object Object]"==t?n.constructor:null,n=typeof n=="function"?fu.call(n):"")switch(n){case Du:return"[object Map]";case Zu:return"[object Set]";case qu:return"[object WeakMap]"}return t});var uo=function(){var n=0,t=0;return function(r,e){var u=Wo(),o=16-(u-t);if(t=u,o>0){if(150<=++n)return r}else n=0;return Xu(r,e)}}(),oo=le(function(n,t){No(n)||(n=null==n?[]:[Object(n)]), t=ft(t);for(var r=n,e=t,u=-1,o=r.length,i=-1,f=e.length,c=Array(o+f);++u1?n[t-1]:Z,t=typeof t=="function"?(n.pop(),t):Z;return Yr(n,t)}),Ao=le(function(n){n=ft(n);var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return Xn(t,n)};return 1>=t&&!this.__actions__.length&&e instanceof An&&U(r)?(e=e.slice(r,+r+(t?1:0)),e.__actions__.push({func:Qr,args:[u],thisArg:Z}),new wn(e,this.__chain__).thru(function(n){return t&&!n.length&&n.push(Z), n})):this.thru(u)}),Oo=nr(function(n,t,r){cu.call(n,r)?++n[r]:n[r]=1}),ko=nr(function(n,t,r){cu.call(n,r)?n[r].push(t):n[r]=[t]}),Eo=le(function(n,t,e){var u=-1,o=typeof t=="function",i=Cr(t),f=_e(n)?Array(n.length):[];return Ju(n,function(n){var c=o?t:i&&null!=n?n[t]:Z;f[++u]=c?r(c,n,e):dt(n,t,e)}),f}),Io=nr(function(n,t,r){n[r]=t}),So=nr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Ro=le(function(n,t){if(null==n)return[];var r=t.length;return r>1&&Br(n,t[0],t[1])?t=[]:r>2&&Br(t[0],t[1],t[2])&&(t.length=1), kt(n,ft(t),[])}),Wo=nu.now,Bo=le(function(n,t,r){var e=1;if(r.length)var u=L(r,yn.placeholder||Bo.placeholder),e=32|e;return yr(n,e,t,r,u)}),Co=le(function(n,t,r){var e=3;if(r.length)var u=L(r,yn.placeholder||Co.placeholder),e=32|e;return yr(t,e,n,r,u)}),Uo=le(function(n,t){return et(n,1,t)}),zo=le(function(n,t,r){return et(n,Ce(t)||0,r)}),Mo=le(function(n,t){t=a(ft(t),wr());var e=t.length;return le(function(u){for(var o=-1,i=Bu(u.length,e);++oe.length?Pn(e,n,t):(r.array=null,r.map=new zn(e))),(r=r.map)&&r.set(n,t),this},ae.Cache=zn,yn.after=function(n,t){if(typeof t!="function")throw new uu("Expected a function");return n=We(n),function(){return 1>--n?t.apply(this,arguments):void 0}},yn.ary=ue,yn.assign=Zo,yn.assignIn=qo,yn.assignInWith=Po,yn.assignWith=To,yn.at=Ko,yn.before=oe,yn.bind=Bo,yn.bindAll=si,yn.bindKey=Co,yn.chain=Hr,yn.chunk=function(n,t){t=Wu(We(t),0); var r=n?n.length:0;if(!r||1>t)return[];for(var e=0,u=-1,o=Array(ku(r/t));r>e;)o[++u]=zt(n,e,e+=t);return o},yn.compact=function(n){for(var t=-1,r=n?n.length:0,e=-1,u=[];++tr&&(r=-r>u?0:u+r),e=e===Z||e>u?u:We(e),0>e&&(e+=u),e=r>e?0:Be(e);e>r;)n[r++]=t;return n},yn.filter=function(n,t){return(No(n)?i:it)(n,wr(t,3))},yn.flatMap=function(n,t){return ft(re(n,t))},yn.flatten=function(n){return n&&n.length?ft(n):[]},yn.flattenDeep=function(n){return n&&n.length?ft(n,true):[]},yn.flip=function(n){return yr(n,512)},yn.flow=hi,yn.flowRight=pi,yn.fromPairs=function(n){for(var t=-1,r=n?n.length:0,e={};++tt?0:t)):[]},yn.takeRight=function(n,t,r){var e=n?n.length:0;return e?(t=r||t===Z?1:We(t),t=e-t,zt(n,0>t?0:t,e)):[]},yn.takeRightWhile=function(n,t){return n&&n.length?Zt(n,wr(t,3),false,true):[]},yn.takeWhile=function(n,t){return n&&n.length?Zt(n,wr(t,3)):[]},yn.tap=function(n,t){return t(n),n},yn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new uu("Expected a function");return xe(r)&&(e="leading"in r?!!r.leading:e, u="trailing"in r?!!r.trailing:u),ce(n,t,{leading:e,maxWait:t,trailing:u})},yn.thru=Qr,yn.toArray=Re,yn.toPairs=De,yn.toPairsIn=function(n){return m(n,Ne(n))},yn.toPath=function(n){return No(n)?a(n,String):Fr(n)},yn.toPlainObject=Ue,yn.transform=function(n,t,r){var e=No(n)||Ie(n);if(t=wr(t,4),null==r)if(e||xe(n)){var o=n.constructor;r=e?No(n)?new o:[]:Vu(de(o)?o.prototype:Z)}else r={};return(e?u:at)(n,function(n,e,u){return t(r,n,e,u)}),r},yn.unary=function(n){return ue(n,1)},yn.union=_o,yn.unionBy=go, yn.unionWith=vo,yn.uniq=function(n){return n&&n.length?Dt(n):[]},yn.uniqBy=function(n,t){return n&&n.length?Dt(n,wr(t)):[]},yn.uniqWith=function(n,t){return n&&n.length?Dt(n,Z,t):[]},yn.unset=function(n,t){var r;if(null==n)r=true;else{r=n;var e=t,e=Cr(e,r)?[e+""]:Nt(e);r=$r(r,e),e=Kr(e),r=null!=r&&Le(r,e)?delete r[e]:true}return r},yn.unzip=Jr,yn.unzipWith=Yr,yn.values=Ze,yn.valuesIn=function(n){return null==n?A(n,Ne(n)):[]},yn.without=yo,yn.words=Ke,yn.wrap=function(n,t){return t=null==t?Ve:t,Lo(t,n); },yn.xor=bo,yn.xorBy=xo,yn.xorWith=jo,yn.zip=mo,yn.zipObject=function(n,t){return Tt(n||[],t||[],Yn)},yn.zipObjectDeep=function(n,t){return Tt(n||[],t||[],Ut)},yn.zipWith=wo,yn.extend=qo,yn.extendWith=Po,Ye(yn,yn),yn.add=function(n,t){var r;return n===Z&&t===Z?0:(n!==Z&&(r=n),t!==Z&&(r=r===Z?t:r+t),r)},yn.attempt=li,yn.camelCase=ri,yn.capitalize=qe,yn.ceil=ji,yn.clamp=function(n,t,r){return r===Z&&(r=t,t=Z),r!==Z&&(r=Ce(r),r=r===r?r:0),t!==Z&&(t=Ce(t),t=t===t?t:0),nt(Ce(n),t,r)},yn.clone=function(n){ return tt(n)},yn.cloneDeep=function(n){return tt(n,true)},yn.cloneDeepWith=function(n,t){return tt(n,true,t)},yn.cloneWith=function(n,t){return tt(n,false,t)},yn.deburr=Pe,yn.endsWith=function(n,t,r){n=ze(n),t=typeof t=="string"?t:t+"";var e=n.length;return r=r===Z?e:nt(We(r),0,e),r-=t.length,r>=0&&n.indexOf(t,r)==r},yn.eq=se,yn.escape=function(n){return(n=ze(n))&&H.test(n)?n.replace(J,R):n},yn.escapeRegExp=function(n){return(n=ze(n))&&on.test(n)?n.replace(un,"\\$&"):n},yn.every=function(n,t,r){var e=No(n)?o:ot; return r&&Br(n,t,r)&&(t=Z),e(n,wr(t,3))},yn.find=function(n,t){if(t=wr(t,3),No(n)){var r=v(n,t);return r>-1?n[r]:Z}return g(n,t,Ju)},yn.findIndex=function(n,t){return n&&n.length?v(n,wr(t,3)):-1},yn.findKey=function(n,t){return g(n,wr(t,3),at,true)},yn.findLast=function(n,t){if(t=wr(t,3),No(n)){var r=v(n,t,true);return r>-1?n[r]:Z}return g(n,t,Yu)},yn.findLastIndex=function(n,t){return n&&n.length?v(n,wr(t,3),true):-1},yn.findLastKey=function(n,t){return g(n,wr(t,3),lt,true)},yn.floor=mi,yn.forEach=ne,yn.forEachRight=te, yn.forIn=function(n,t){return null==n?n:Hu(n,Dr(t),Ne)},yn.forInRight=function(n,t){return null==n?n:Qu(n,Dr(t),Ne)},yn.forOwn=function(n,t){return n&&at(n,Dr(t))},yn.forOwnRight=function(n,t){return n&<(n,Dr(t))},yn.get=Me,yn.gt=he,yn.gte=function(n,t){return n>=t},yn.has=Le,yn.hasIn=$e,yn.head=Tr,yn.identity=Ve,yn.includes=function(n,t,r,e){return n=_e(n)?n:Ze(n),r=r&&!e?We(r):0,e=n.length,0>r&&(r=Wu(e+r,0)),ke(n)?e>=r&&-1r&&(r=Wu(e+r,0)),d(n,t,r)):-1},yn.inRange=function(n,t,r){return t=Ce(t)||0,r===Z?(r=t,t=0):r=Ce(r)||0,n=Ce(n),n>=Bu(t,r)&&n=-9007199254740991&&9007199254740991>=n},yn.isSet=function(n){return je(n)&&"[object Set]"==kr(n)},yn.isString=ke,yn.isSymbol=Ee, yn.isTypedArray=Ie,yn.isUndefined=function(n){return n===Z},yn.isWeakMap=function(n){return je(n)&&"[object WeakMap]"==kr(n)},yn.isWeakSet=function(n){return je(n)&&"[object WeakSet]"==su.call(n)},yn.join=function(n,t){return n?Su.call(n,t):""},yn.kebabCase=ei,yn.last=Kr,yn.lastIndexOf=function(n,t,r){var e=n?n.length:0;if(!e)return-1;var u=e;if(r!==Z&&(u=We(r),u=(0>u?Wu(e+u,0):Bu(u,e-1))+1),t!==t)return B(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},yn.lowerCase=ui,yn.lowerFirst=oi,yn.lt=Se, yn.lte=function(n,t){return t>=n},yn.max=function(n){return n&&n.length?_(n,Ve,he):Z},yn.maxBy=function(n,t){return n&&n.length?_(n,wr(t),he):Z},yn.mean=function(n){return Xe(n)/(n?n.length:0)},yn.min=function(n){return n&&n.length?_(n,Ve,Se):Z},yn.minBy=function(n,t){return n&&n.length?_(n,wr(t),Se):Z},yn.noConflict=function(){return Vn._===this&&(Vn._=hu),this},yn.noop=He,yn.now=Wo,yn.pad=function(n,t,r){n=ze(n),t=We(t);var e=F(n);return t&&t>e?(e=(t-e)/2,t=Eu(e),e=ku(e),pr("",t,r)+n+pr("",e,r)):n; },yn.padEnd=function(n,t,r){return n=ze(n),n+pr(n,t,r)},yn.padStart=function(n,t,r){return n=ze(n),pr(n,t,r)+n},yn.parseInt=function(n,t,r){return r||null==t?t=0:t&&(t=+t),n=ze(n).replace(fn,""),Cu(n,t||(pn.test(n)?16:10))},yn.random=function(n,t,r){if(r&&typeof r!="boolean"&&Br(n,t,r)&&(t=r=Z),r===Z&&(typeof t=="boolean"?(r=t,t=Z):typeof n=="boolean"&&(r=n,n=Z)),n===Z&&t===Z?(n=0,t=1):(n=Ce(n)||0,t===Z?(t=n,n=0):t=Ce(t)||0),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Uu(),Bu(n+r*(t-n+Fn("1e-"+((r+"").length-1))),t)):Ct(n,t); },yn.reduce=function(n,t,r){var e=No(n)?s:y,u=3>arguments.length;return e(n,wr(t,4),r,u,Ju)},yn.reduceRight=function(n,t,r){var e=No(n)?h:y,u=3>arguments.length;return e(n,wr(t,4),r,u,Yu)},yn.repeat=Te,yn.replace=function(){var n=arguments,t=ze(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},yn.result=function(n,t,r){if(Cr(t,n))e=null==n?Z:n[t];else{t=Nt(t);var e=Me(n,t);n=$r(n,t)}return e===Z&&(e=r),de(e)?e.call(n):e},yn.round=wi,yn.runInContext=D,yn.sample=function(n){n=_e(n)?n:Ze(n);var t=n.length; return t>0?n[Ct(0,t-1)]:Z},yn.size=function(n){if(null==n)return 0;if(_e(n)){var t=n.length;return t&&ke(n)?F(n):t}return Fe(n).length},yn.snakeCase=fi,yn.some=function(n,t,r){var e=No(n)?p:Mt;return r&&Br(n,t,r)&&(t=Z),e(n,wr(t,3))},yn.sortedIndex=function(n,t){return Lt(n,t)},yn.sortedIndexBy=function(n,t,r){return $t(n,t,wr(r))},yn.sortedIndexOf=function(n,t){var r=n?n.length:0;if(r){var e=Lt(n,t);if(r>e&&se(n[e],t))return e}return-1},yn.sortedLastIndex=function(n,t){return Lt(n,t,true)},yn.sortedLastIndexBy=function(n,t,r){ return $t(n,t,wr(r),true)},yn.sortedLastIndexOf=function(n,t){if(n&&n.length){var r=Lt(n,t,true)-1;if(se(n[r],t))return r}return-1},yn.startCase=ci,yn.startsWith=function(n,t,r){return n=ze(n),r=nt(We(r),0,n.length),n.lastIndexOf(t,r)==r},yn.subtract=function(n,t){var r;return n===Z&&t===Z?0:(n!==Z&&(r=n),t!==Z&&(r=r===Z?t:r-t),r)},yn.sum=Xe,yn.sumBy=function(n,t){return n&&n.length?x(n,wr(t)):0},yn.template=function(n,t,r){var e=yn.templateSettings;r&&Br(n,t,r)&&(t=Z),n=ze(n),t=Po({},t,e,Tn),r=Po({},t.imports,e.imports,Tn); var u,o,i=Fe(r),f=A(r,i),c=0;r=t.interpolate||xn;var a="__p+='";r=eu((t.escape||xn).source+"|"+r.source+"|"+(r===nn?sn:xn).source+"|"+(t.evaluate||xn).source+"|$","g");var l="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,i,f,l){return e||(e=i),a+=n.slice(c,l).replace(jn,W),r&&(u=true,a+="'+__e("+r+")+'"),f&&(o=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=t.variable)||(a="with(obj){"+a+"}"),a=(o?a.replace(T,""):a).replace(K,"$1").replace(G,"$1;"), a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=li(function(){return Function(i,l+"return "+a).apply(Z,f)}),t.source=a,ve(t))throw t;return t},yn.times=function(n,t){if(n=We(n),1>n||n>9007199254740991)return[];var r=4294967295,e=Bu(n,4294967295);for(t=Dr(t),n-=4294967295,e=j(e,t);++r=o)return n;if(o=r-F(e),1>o)return e;if(r=i?i.slice(0,o).join(""):n.slice(0,o),u===Z)return r+e;if(i&&(o+=r.length-o),Oe(u)){if(n.slice(o).search(u)){var f=r;for(u.global||(u=eu(u.source,ze(hn.exec(u))+"g")),u.lastIndex=0;i=u.exec(f);)var c=i.index; r=r.slice(0,c===Z?o:c)}}else n.indexOf(u,o)!=o&&(u=r.lastIndexOf(u),u>-1&&(r=r.slice(0,u)));return r+e},yn.unescape=function(n){return(n=ze(n))&&Y.test(n)?n.replace(V,N):n},yn.uniqueId=function(n){var t=++au;return ze(n)+t},yn.upperCase=ai,yn.upperFirst=ii,yn.each=ne,yn.eachRight=te,yn.first=Tr,Ye(yn,function(){var n={};return at(yn,function(t,r){cu.call(yn.prototype,r)||(n[r]=t)}),n}(),{chain:false}),yn.VERSION="4.3.0",u("bind bindKey curry curryRight partial partialRight".split(" "),function(n){yn[n].placeholder=yn; }),u(["drop","take"],function(n,t){An.prototype[n]=function(r){var e=this.__filtered__;if(e&&!t)return new An(this);r=r===Z?1:Wu(We(r),0);var u=this.clone();return e?u.__takeCount__=Bu(r,u.__takeCount__):u.__views__.push({size:Bu(r,4294967295),type:n+(0>u.__dir__?"Right":"")}),u},An.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),u(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;An.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({ iteratee:wr(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),u(["head","last"],function(n,t){var r="take"+(t?"Right":"");An.prototype[n]=function(){return this[r](1).value()[0]}}),u(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");An.prototype[n]=function(){return this.__filtered__?new An(this):this[r](1)}}),An.prototype.compact=function(){return this.filter(Ve)},An.prototype.find=function(n){return this.filter(n).head()},An.prototype.findLast=function(n){return this.reverse().find(n); },An.prototype.invokeMap=le(function(n,t){return typeof n=="function"?new An(this):this.map(function(r){return dt(r,n,t)})}),An.prototype.reject=function(n){return n=wr(n,3),this.filter(function(t){return!n(t)})},An.prototype.slice=function(n,t){n=We(n);var r=this;return r.__filtered__&&(n>0||0>t)?new An(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==Z&&(t=We(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},An.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},An.prototype.toArray=function(){ return this.take(4294967295)},at(An.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=yn[e?"take"+("last"==t?"Right":""):t],o=e||/^find/.test(t);u&&(yn.prototype[t]=function(){var t=this.__wrapped__,i=e?[1]:arguments,f=t instanceof An,c=i[0],a=f||No(t),s=function(n){return n=u.apply(yn,l([n],i)),e&&h?n[0]:n};a&&r&&typeof c=="function"&&1!=c.length&&(f=a=false);var h=this.__chain__,p=!!this.__actions__.length,c=o&&!h,f=f&&!p;return!o&&a?(t=f?t:new An(this), t=n.apply(t,i),t.__actions__.push({func:Qr,args:[s],thisArg:Z}),new wn(t,h)):c&&f?n.apply(this,i):(t=this.thru(s),c?e?t.value()[0]:t.value():t)})}),u("pop push shift sort splice unshift".split(" "),function(n){var t=ou[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);yn.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),at(An.prototype,function(n,t){var r=yn[t];if(r){var e=r.name+"";(Gu[e]||(Gu[e]=[])).push({ name:t,func:r})}}),Gu[lr(Z,2).name]=[{name:"wrapper",func:Z}],An.prototype.clone=function(){var n=new An(this.__wrapped__);return n.__actions__=Yt(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Yt(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Yt(this.__views__),n},An.prototype.reverse=function(){if(this.__filtered__){var n=new An(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},An.prototype.value=function(){ var n,t=this.__wrapped__.value(),r=this.__dir__,e=No(t),u=0>r,o=e?t.length:0;n=0;for(var i=o,f=this.__views__,c=-1,a=f.length;++co||o==n&&a==n)return qt(t,this.__actions__);e=[];n:for(;n--&&a>c;){for(u+=r,o=-1,l=t[u];++o=this.__values__.length,t=n?Z:this.__values__[this.__index__++];return{done:n,value:t}},yn.prototype.plant=function(n){ for(var t,r=this;r instanceof mn;){var e=Zr(r);e.__index__=0,e.__values__=Z,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},yn.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof An?(this.__actions__.length&&(n=new An(this)),n=n.reverse(),n.__actions__.push({func:Qr,args:[Vr],thisArg:Z}),new wn(n,this.__chain__)):this.thru(Vr)},yn.prototype.toJSON=yn.prototype.valueOf=yn.prototype.value=function(){return qt(this.__wrapped__,this.__actions__)},mu&&(yn.prototype[mu]=Xr), yn}var Z,q=1/0,P=NaN,T=/\b__p\+='';/g,K=/\b(__p\+=)''\+/g,G=/(__e\(.*?\)|\b__t\))\+'';/g,V=/&(?:amp|lt|gt|quot|#39|#96);/g,J=/[&<>"'`]/g,Y=RegExp(V.source),H=RegExp(J.source),Q=/<%-([\s\S]+?)%>/g,X=/<%([\s\S]+?)%>/g,nn=/<%=([\s\S]+?)%>/g,tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,rn=/^\w*$/,en=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g,un=/[\\^$.*+?()[\]{}|]/g,on=RegExp(un.source),fn=/^\s+|\s+$/g,cn=/^\s+/,an=/\s+$/,ln=/\\(\\)?/g,sn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,hn=/\w*$/,pn=/^0x/i,_n=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,vn=/^\[object .+?Constructor\]$/,dn=/^0o[0-7]+$/i,yn=/^(?:0|[1-9]\d*)$/,bn=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,xn=/($^)/,jn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?)*",wn="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,An="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]?|[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",On=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]","g"),kn=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+An+mn,"g"),En=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0\\ufe0e\\ufe0f]"),In=/[a-zA-Z0-9]+/g,Sn=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2018\\u2019\\u201c\\u201d \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2018\\u2019\\u201c\\u201d \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2018\\u2019\\u201c\\u201d \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2018\\u2019\\u201c\\u201d \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2018\\u2019\\u201c\\u201d \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+|[A-Z\\xc0-\\xd6\\xd8-\\xde]+|\\d+",wn].join("|"),"g"),Rn=/[a-z][A-Z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Reflect RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Bn={}; Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false; var Cn={};Cn["[object Arguments]"]=Cn["[object Array]"]=Cn["[object ArrayBuffer]"]=Cn["[object Boolean]"]=Cn["[object Date]"]=Cn["[object Float32Array]"]=Cn["[object Float64Array]"]=Cn["[object Int8Array]"]=Cn["[object Int16Array]"]=Cn["[object Int32Array]"]=Cn["[object Map]"]=Cn["[object Number]"]=Cn["[object Object]"]=Cn["[object RegExp]"]=Cn["[object Set]"]=Cn["[object String]"]=Cn["[object Symbol]"]=Cn["[object Uint8Array]"]=Cn["[object Uint8ClampedArray]"]=Cn["[object Uint16Array]"]=Cn["[object Uint32Array]"]=true, Cn["[object Error]"]=Cn["[object Function]"]=Cn["[object WeakMap]"]=false;var Un={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O", "\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss"},zn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Mn={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ln={"function":true,object:true},$n={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029" },Fn=parseFloat,Nn=parseInt,Dn=Ln[typeof exports]&&exports&&!exports.nodeType?exports:null,Zn=Ln[typeof module]&&module&&!module.nodeType?module:null,qn=E(Dn&&Zn&&typeof global=="object"&&global),Pn=E(Ln[typeof self]&&self),Tn=E(Ln[typeof window]&&window),Kn=Zn&&Zn.exports===Dn?Dn:null,Gn=E(Ln[typeof this]&&this),Vn=qn||Tn!==(Gn&&Gn.window)&&Tn||Pn||Gn||Function("return this")(),Jn=D();(Tn||Pn||{})._=Jn,typeof define=="function"&&typeof define.amd=="object"&&define.amd? define(function(){return Jn; }):Dn&&Zn?(Kn&&((Zn.exports=Jn)._=Jn),Dn._=Jn):Vn._=Jn}).call(this); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.Util = Bahmni.Common.Util || {}; angular.module('bahmni.common.util', []) .provider('$bahmniCookieStore', [function () { var self = this; self.defaultOptions = {}; var fixedEncodeURIComponent = function (str) { return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { return '%' + c.charCodeAt(0).toString(16); }); }; self.setDefaultOptions = function (options) { self.defaultOptions = options; }; self.$get = function () { return { get: function (name) { var jsonCookie = $.cookie(name); if (jsonCookie) { return angular.fromJson(decodeURIComponent(jsonCookie)); } return null; }, put: function (name, value, options) { options = $.extend({}, self.defaultOptions, options); $.cookie.raw = true; $.cookie(name, fixedEncodeURIComponent(angular.toJson(value)), options); }, remove: function (name, options) { options = $.extend({}, self.defaultOptions, options); $.removeCookie(name, options); } }; }; }]) ; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.Models = Bahmni.Common.Models || {}; angular.module('bahmni.common.models', []); 'use strict'; angular.module('bahmni.common.models') .factory('age', [function () { var dateUtil = Bahmni.Common.Util.DateUtil; var fromBirthDate = function (birthDate) { var today = dateUtil.now(); var period = dateUtil.diffInYearsMonthsDays(birthDate, today); return create(period.years, period.months, period.days); }; var create = function (years, months, days) { var isEmpty = function () { return !(this.years || this.months || this.days); }; return { years: years, months: months, days: days, isEmpty: isEmpty }; }; var calculateBirthDate = function (age) { var birthDate = dateUtil.now(); birthDate = dateUtil.subtractYears(birthDate, age.years); birthDate = dateUtil.subtractMonths(birthDate, age.months); birthDate = dateUtil.subtractDays(birthDate, age.days); return birthDate; }; return { fromBirthDate: fromBirthDate, create: create, calculateBirthDate: calculateBirthDate }; }] ); Bahmni.Common.AuditLogEventDetails = { "USER_LOGIN_SUCCESS": {eventType: "USER_LOGIN_SUCCESS", message: "USER_LOGIN_SUCCESS_MESSAGE"}, "USER_LOGIN_FAILED": {eventType: "USER_LOGIN_FAILED", message: "USER_LOGIN_FAILED_MESSAGE"}, "USER_LOGOUT_SUCCESS": {eventType: "USER_LOGOUT_SUCCESS", message: "USER_LOGOUT_SUCCESS_MESSAGE"}, "OPEN_VISIT": {eventType: "OPEN_VISIT", message: "OPEN_VISIT_MESSAGE"}, "EDIT_VISIT": {eventType: "EDIT_VISIT", message: "EDIT_VISIT_MESSAGE"}, "CLOSE_VISIT": {eventType: "CLOSE_VISIT", message: "CLOSE_VISIT_MESSAGE"}, "CLOSE_VISIT_FAILED": {eventType: "CLOSE_VISIT_FAILED", message: "CLOSE_VISIT_FAILED_MESSAGE"}, "EDIT_ENCOUNTER": {eventType: "EDIT_ENCOUNTER", message: "EDIT_ENCOUNTER_MESSAGE"}, "VIEWED_REGISTRATION_PATIENT_SEARCH": {eventType: "VIEWED_REGISTRATION_PATIENT_SEARCH", message: "VIEWED_REGISTRATION_PATIENT_SEARCH_MESSAGE"}, "VIEWED_NEW_PATIENT_PAGE": {eventType: "VIEWED_NEW_PATIENT_PAGE", message: "VIEWED_NEW_PATIENT_PAGE_MESSAGE"}, "REGISTER_NEW_PATIENT": {eventType: "REGISTER_NEW_PATIENT", message: "REGISTER_NEW_PATIENT_MESSAGE"}, "EDIT_PATIENT_DETAILS": {eventType: "EDIT_PATIENT_DETAILS", message: "EDIT_PATIENT_DETAILS_MESSAGE"}, "ACCESSED_REGISTRATION_SECOND_PAGE": {eventType: "ACCESSED_REGISTRATION_SECOND_PAGE", message: "ACCESSED_REGISTRATION_SECOND_PAGE_MESSAGE"}, "VIEWED_PATIENT_DETAILS": {eventType: "VIEWED_PATIENT_DETAILS", message: "VIEWED_PATIENT_DETAILS_MESSAGE"}, "PRINT_PATIENT_STICKER": {eventType: "PRINT_PATIENT_STICKER", message: "PRINT_PATIENT_STICKER_MESSAGE"}, "VIEWED_CLINICAL_PATIENT_SEARCH": {eventType: "VIEWED_CLINICAL_PATIENT_SEARCH", message: "VIEWED_PATIENT_SEARCH_MESSAGE"}, "VIEWED_CLINICAL_DASHBOARD": {eventType: "VIEWED_CLINICAL_DASHBOARD", message: "VIEWED_CLINICAL_DASHBOARD_MESSAGE"}, "VIEWED_OBSERVATIONS_TAB": {eventType: "VIEWED_OBSERVATIONS_TAB", message: "VIEWED_OBSERVATIONS_TAB_MESSAGE"}, "VIEWED_DIAGNOSIS_TAB": {eventType: "VIEWED_DIAGNOSIS_TAB", message: "VIEWED_DIAGNOSIS_TAB_MESSAGE"}, "VIEWED_TREATMENT_TAB": {eventType: "VIEWED_TREATMENT_TAB", message: "VIEWED_TREATMENT_TAB_MESSAGE"}, "VIEWED_DISPOSITION_TAB": {eventType: "VIEWED_DISPOSITION_TAB", message: "VIEWED_DISPOSITION_TAB_MESSAGE"}, "VIEWED_DASHBOARD_SUMMARY": {eventType: "VIEWED_DASHBOARD_SUMMARY", message: "VIEWED_DASHBOARD_SUMMARY_MESSAGE"}, "VIEWED_ORDERS_TAB": {eventType: "VIEWED_ORDERS_TAB", message: "VIEWED_ORDERS_TAB_MESSAGE"}, "VIEWED_BACTERIOLOGY_TAB": {eventType: "VIEWED_BACTERIOLOGY_TAB", message: "VIEWED_BACTERIOLOGY_TAB_MESSAGE"}, "VIEWED_INVESTIGATION_TAB": {eventType: "VIEWED_INVESTIGATION_TAB", message: "VIEWED_INVESTIGATION_TAB_MESSAGE"}, "VIEWED_SUMMARY_PRINT": {eventType: "VIEWED_SUMMARY_PRINT", message: "VIEWED_SUMMARY_PRINT_MESSAGE"}, "VIEWED_VISIT_DASHBOARD": {eventType: "VIEWED_VISIT_DASHBOARD", message: "VIEWED_VISIT_DASHBOARD_MESSAGE"}, "VIEWED_VISIT_PRINT": {eventType: "VIEWED_VISIT_PRINT", message: "VIEWED_VISIT_PRINT_MESSAGE"}, "VIEWED_DASHBOARD_OBSERVATION": {eventType: "VIEWED_DASHBOARD_OBSERVATION", message: "VIEWED_DASHBOARD_OBSERVATION_MESSAGE"}, "VIEWED_PATIENTPROGRAM": {eventType: "VIEWED_PATIENTPROGRAM", message: "VIEWED_PATIENTPROGRAM_MESSAGE"}, "RUN_REPORT": {eventType: "RUN_REPORT", message: "RUN_REPORT_MESSAGE"} }; angular.module('FredrikSandell.worker-pool', []).service('WorkerService', [ '$q', function ($q) { var that = {}; //this should be configured from the app in the future var urlToAngular = 'http://localhost:9876/base/bower_components/angular/angular.js'; var serviceToUrlMap = {}; var storage = {}; var scriptsToLoad = []; that.setAngularUrl = function (urlToAngularJs) { urlToAngular = urlToAngularJs; }; function createAngularWorkerTemplate() { /*jshint laxcomma:true */ /*jshint quotmark: false */ var workerTemplate = [ '', '//try {', 'var window = self;', 'self.history = {};', 'var Node = function() {};', 'var app', 'var localStorage = {storage: , getItem: function(key) {return this.storage[key]}, setItem: function(key, value) {this.storage[key]=value}}', 'var document = {', ' readyState: \'complete\',', ' cookie: \'\',', ' querySelector: function () {},', ' createElement: function () {', ' return {', ' pathname: \'\',', ' setAttribute: function () {}', ' };', ' }', '};', 'importScripts(\'\');', '', 'angular = window.angular;', 'var workerApp = angular.module(\'WorkerApp\', []);', 'workerApp.run([\'$q\', function ($q) {', ' self.addEventListener(\'message\', function(e) {', ' var input = e.data;', ' var output = $q.defer();', ' var promise = output.promise;', ' promise.then(function(success) {', ' self.postMessage({event:\'success\', data : success});', ' }, function(reason) {', ' self.postMessage({event:\'failure\', data : reason});', ' }, function(update) {', ' self.postMessage({event:\'update\', data : update});', ' });', ' ;', ' });', ' self.postMessage({event:\'initDone\'});', '}]);', 'angular.bootstrap(null, [\'WorkerApp\']);', '//} catch(e) {self.postMessage(JSON.stringify(e));}' ]; return workerTemplate.join('\n'); } var workerTemplate = createAngularWorkerTemplate(); that.addDependency = function (serviceName, moduleName, url) { serviceToUrlMap[serviceName] = { url: url, moduleName: moduleName }; return that; }; that.includeScripts = function(url) { scriptsToLoad.push(url); }; that.addToLocalStorage = function(key, value) { storage[key] = value; }; function createIncludeStatements(listOfServiceNames) { var includeString = ''; angular.forEach(scriptsToLoad, function(script) { includeString += 'importScripts(\'' + script + '\');'; }); angular.forEach(listOfServiceNames, function (serviceName) { if (serviceToUrlMap[serviceName]) { includeString += 'importScripts(\'' + serviceToUrlMap[serviceName].url + '\');'; } }); return includeString; } function createModuleList(listOfServiceNames) { var moduleNameList = []; angular.forEach(listOfServiceNames, function (serviceName) { if (serviceToUrlMap[serviceName]) { moduleNameList.push('\'' + serviceToUrlMap[serviceName].moduleName + '\''); } }); return moduleNameList.join(','); } function createDependencyMetaData(dependencyList) { var dependencyServiceNames = dependencyList.filter(function (dep) { return dep !== 'input' && dep !== 'output' && dep !== '$q'; }); var depMetaData = { dependencies: dependencyServiceNames, moduleList: createModuleList(dependencyServiceNames), angularDepsAsStrings: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.map(function (dep) { return '\'' + dep + '\''; }).join(',') : '', angularDepsAsParamList: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.join(',') : '', servicesIncludeStatements: createIncludeStatements(dependencyServiceNames) }; depMetaData.workerFuncParamList = 'input,output' + depMetaData.angularDepsAsParamList; return depMetaData; } function populateWorkerTemplate(workerFunc, dependencyMetaData) { return workerTemplate .replace('', urlToAngular) .replace('', dependencyMetaData.servicesIncludeStatements) .replace('', dependencyMetaData.moduleList) .replace('', dependencyMetaData.angularDepsAsStrings) .replace('', dependencyMetaData.angularDepsAsParamList) .replace('', JSON.stringify(storage)) .replace('', workerFunc.toString()); } var buildAngularWorker = function (initializedWorker) { var that = {}; that.worker = initializedWorker; that.run = function (input) { var deferred = $q.defer(); initializedWorker.addEventListener('message', function (e) { var eventId = e.data.event; //console.log(e.data); if (eventId === 'initDone') { throw 'Received worker initialization in run method. This should already have occurred!'; } else if (eventId === 'success') { deferred.resolve(e.data.data); } else if (eventId === 'failure') { deferred.reject(e.data.data); } else if (eventId === 'update') { deferred.notify(e.data.data); } else { deferred.reject(e); } }); initializedWorker.postMessage(input); return deferred.promise; }; that.terminate = function () { initializedWorker.terminate(); }; return that; }; var extractDependencyList = function (depFuncList) { return depFuncList.slice(0, depFuncList.length - 1); }; var workerFunctionToString = function (func, paramList) { return '(' + func.toString() + ')(' + paramList + ')'; }; /** * example call: * WorkerService.createAngularWorker(['input', 'output', '$http', function(input, output, $http) * {body of function}]); * Parameters "input" and "output" is required. Not defining them will cause a runtime error. * Declaring services to be injected, as '$http' is above, requires the web worker to be able to resolve them. * '$http' service is a part of the standard angular package which means it will resolve without additional information * since angular source is always loaded in the web worker. * But if a custom service was to be injected the WorkerService would need be be informed on how to resolve the. * @param depFuncList */ that.createAngularWorker = function (depFuncList) { //validate the input if (!Array.isArray(depFuncList) || depFuncList.length < 3 || typeof depFuncList[depFuncList.length - 1] !== 'function') { throw 'Input needs to be: [\'workerInput\',\'deferredOutput\'/*optional additional dependencies*/,\n' + ' function(workerInput, deferredOutput /*optional additional dependencies*/)\n' + ' {/*worker body*/}' + ']'; } var deferred = $q.defer(); var dependencyMetaData = createDependencyMetaData(extractDependencyList(depFuncList)); var blobURL = (window.webkitURL ? webkitURL : URL).createObjectURL(new Blob([populateWorkerTemplate(workerFunctionToString(depFuncList[depFuncList.length - 1], dependencyMetaData.workerFuncParamList), dependencyMetaData)], { type: 'application/javascript' })); var worker = new Worker(blobURL); //wait for the worker to load resources worker.addEventListener('message', function (e) { var eventId = e.data.event; console.log(e.data); if (eventId === 'initDone') { deferred.resolve(buildAngularWorker(worker)); } else { deferred.reject(e); } }); return deferred.promise; }; return that; } ]); 'use strict'; angular.module('bahmni.common.routeErrorHandler', ['ui.router']) .run(['$rootScope', function ($rootScope) { $rootScope.$on('$stateChangeError', function (event) { event.preventDefault(); }); }]); 'use strict'; Bahmni.Common.Util.DateUtil = { diffInDays: function (dateFrom, dateTo) { return Math.floor((this.parse(dateTo) - this.parse(dateFrom)) / (60 * 1000 * 60 * 24)); }, diffInMinutes: function (dateFrom, dateTo) { return moment(dateTo).diff(moment(dateFrom), 'minutes'); }, diffInSeconds: function (dateFrom, dateTo) { return moment(dateFrom).diff(moment(dateTo), 'seconds'); }, isInvalid: function (date) { return date == "Invalid Date"; }, diffInDaysRegardlessOfTime: function (dateFrom, dateTo) { var from = new Date(dateFrom); var to = new Date(dateTo); from.setHours(0, 0, 0, 0); to.setHours(0, 0, 0, 0); return Math.floor((to - from) / (60 * 1000 * 60 * 24)); }, addSeconds: function (date, seconds) { return moment(date).add(seconds, 'seconds').toDate(); }, addMinutes: function (date, minutes) { return this.addSeconds(date, minutes * 60); }, addDays: function (date, days) { return moment(date).add(days, 'day').toDate(); }, addMonths: function (date, months) { return moment(date).add(months, 'month').toDate(); }, addYears: function (date, years) { return moment(date).add(years, 'year').toDate(); }, subtractSeconds: function (date, seconds) { return moment(date).subtract(seconds, 'seconds').toDate(); }, subtractDays: function (date, days) { return this.addDays(date, -1 * days); }, subtractMonths: function (date, months) { return this.addMonths(date, -1 * months); }, subtractYears: function (date, years) { return this.addYears(date, -1 * years); }, createDays: function (startDate, endDate) { var startDate = this.getDate(startDate); var endDate = this.getDate(endDate); var numberOfDays = this.diffInDays(startDate, endDate); var days = []; for (var i = 0; i <= numberOfDays; i++) { days.push({dayNumber: i + 1, date: this.addDays(startDate, i)}); } return days; }, getDayNumber: function (referenceDate, date) { return this.diffInDays(this.getDate(referenceDate), this.getDate(date)) + 1; }, getDateWithoutTime: function (datetime) { return datetime ? moment(datetime).format("YYYY-MM-DD") : null; }, getDateWitTime: function (datetime) { return datetime ? moment(datetime).format("YYYY-MM-DD HH:mm:ss") : null; }, getDateInMonthsAndYears: function (date, format) { var format = format || "MMM YY"; var dateRepresentation = isNaN(Number(date)) ? date : Number(date); if (!moment(dateRepresentation).isValid()) { return date; } return dateRepresentation ? moment(dateRepresentation).format(format) : null; }, formatDateWithTime: function (datetime) { var dateRepresentation = isNaN(Number(datetime)) ? datetime : Number(datetime); if (!moment(dateRepresentation).isValid()) { return datetime; } return dateRepresentation ? moment(dateRepresentation).format("DD MMM YY h:mm a") : null; }, formatDateWithoutTime: function (date) { var dateRepresentation = isNaN(Number(date)) ? date : Number(date); if (!moment(dateRepresentation).isValid()) { return date; } return dateRepresentation ? moment(dateRepresentation).format("DD MMM YY") : null; }, formatDateInStrictMode: function (date) { var dateRepresentation = isNaN(Number(date)) ? date : Number(date); if (moment(dateRepresentation, 'YYYY-MM-DD', true).isValid()) { return moment(dateRepresentation).format("DD MMM YY"); } if (moment(dateRepresentation, 'YYYY-MM-DDTHH:mm:ss.SSSZZ', true).isValid()) { return moment(dateRepresentation).format("DD MMM YY"); } return date; }, formatTime: function (date) { var dateRepresentation = isNaN(Number(date)) ? date : Number(date); if (!moment(dateRepresentation).isValid()) { return date; } return dateRepresentation ? moment(dateRepresentation).format("h:mm a") : null; }, getDate: function (dateTime) { return moment(this.parse(dateTime)).startOf('day').toDate(); }, parse: function (dateString) { return dateString ? moment(dateString).toDate() : null; }, parseDatetime: function (dateTimeString) { return dateTimeString ? moment(dateTimeString) : null; }, now: function () { return new Date(); }, today: function () { return this.getDate(this.now()); }, endOfToday: function () { return moment(this.parse(this.now())).endOf('day').toDate(); }, getDateWithoutHours: function (dateString) { return moment(dateString).toDate().setHours(0, 0, 0, 0); }, getDateTimeWithoutSeconds: function (dateString) { return moment(dateString).toDate().setSeconds(0, 0); }, isSameDateTime: function (date1, date2) { if (date1 == null || date2 == null) { return false; } var dateOne = this.parse(date1); var dateTwo = this.parse(date2); return dateOne.getTime() == dateTwo.getTime(); }, isBeforeDate: function (date1, date2) { return moment(date1).isBefore(moment(date2)); }, isSameDate: function (date1, date2) { if (date1 == null || date2 == null) { return false; } var dateOne = this.parse(date1); var dateTwo = this.parse(date2); return dateOne.getFullYear() === dateTwo.getFullYear() && dateOne.getMonth() === dateTwo.getMonth() && dateOne.getDate() === dateTwo.getDate(); }, diffInYearsMonthsDays: function (dateFrom, dateTo) { dateFrom = this.parse(dateFrom); dateTo = this.parse(dateTo); var from = { d: dateFrom.getDate(), m: dateFrom.getMonth(), y: dateFrom.getFullYear() }; var to = { d: dateTo.getDate(), m: dateTo.getMonth(), y: dateTo.getFullYear() }; var age = { d: 0, m: 0, y: 0 }; var daysFebruary = to.y % 4 != 0 || (to.y % 100 == 0 && to.y % 400 != 0) ? 28 : 29; var daysInMonths = [31, daysFebruary, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; age.y = to.y - from.y; age.m = to.m - from.m; if (from.m > to.m) { age.y = age.y - 1; age.m = to.m - from.m + 12; } age.d = to.d - from.d; if (from.d > to.d) { age.m = age.m - 1; if (from.m == to.m) { age.y = age.y - 1; age.m = age.m + 12; } age.d = to.d - from.d + daysInMonths[parseInt(from.m)]; } return { days: age.d, months: age.m, years: age.y }; }, convertToUnits: function (minutes) { var allUnits = {"Years": 365 * 24 * 60, "Months": 30 * 24 * 60, "Weeks": 7 * 24 * 60, "Days": 24 * 60, "Hours": 60, "Minutes": 1}; var durationRepresentation = function (value, unitName, unitValueInMinutes) { return {"value": value, "unitName": unitName, "unitValueInMinutes": unitValueInMinutes, "allUnits": allUnits }; }; for (var unitName in allUnits) { var unitValueInMinutes = allUnits[unitName]; if (minutes || minutes !== 0) { if (minutes >= unitValueInMinutes && minutes % unitValueInMinutes === 0) { return durationRepresentation(minutes / unitValueInMinutes, unitName, unitValueInMinutes); } } } return durationRepresentation(undefined, undefined, undefined); }, getEndDateFromDuration: function (dateFrom, value, unit) { dateFrom = this.parse(dateFrom); var from = { h: dateFrom.getHours(), d: dateFrom.getDate(), m: dateFrom.getMonth(), y: dateFrom.getFullYear() }; var to = new Date(from.y, from.m, from.d, from.h); if (unit === "Months") { to.setMonth(from.m + value); } else if (unit === "Weeks") { to.setDate(from.d + (value * 7)); } else if (unit === "Days") { to.setDate(from.d + value); } else if (unit === "Hours") { to.setHours(from.h + value); } return to; }, parseLongDateToServerFormat: function (longDate) { return longDate ? moment(longDate).format("YYYY-MM-DDTHH:mm:ss.SSS") : null; }, parseServerDateToDate: function (longDate) { return longDate ? moment(longDate, "YYYY-MM-DDTHH:mm:ss.SSSZZ").toDate() : null; }, getDateTimeInSpecifiedFormat: function (date, format) { return date ? moment(date).format(format) : null; }, getISOString: function (date) { return date ? moment(date).toDate().toISOString() : null; }, isBeforeTime: function (time, otherTime) { return moment(time, 'hh:mm a').format('YYYY-MM-DD'); } }; 'use strict'; Bahmni.Common.Util.ValidationUtil = (function () { var isAcceptableType = function (propertyToCheck) { return _.includes(["string", "boolean", "number", "object"], typeof propertyToCheck); }; var flattenObject = function (ob) { var toReturn = {}; for (var i in ob) { if (!ob.hasOwnProperty(i) || !isAcceptableType(ob[i])) { continue; } if ((typeof ob[i]) == 'object' && !(ob[i] instanceof Date)) { var flatObject = flattenObject(ob[i]); for (var x in flatObject) { if (!flatObject.hasOwnProperty(x) || !isAcceptableType(flatObject[x])) { continue; } toReturn[i + '.' + x] = flatObject[x]; } } else { toReturn[i] = ob[i]; } } return toReturn; }; // This will work only for patient attributes, since we are passing concept behind the attribute. // To have a generic one, we need to remove the concept dependency.. And concept will be null for non concept fields var validate = function (complexObject, objectConfiguration) { var allCustomValidators = Bahmni.Registration.customValidator; if (!allCustomValidators) { return []; } var dataArray = flattenObject(complexObject); var errorMessages = []; _.every(dataArray, function (value, field) { var isValid = true; var fieldSpecificValidator = allCustomValidators[field]; if (!fieldSpecificValidator) { return isValid; } if (typeof fieldSpecificValidator.method == 'function' && value) { var personAttributeTypeConfig = _.find(objectConfiguration, {name: field}); isValid = fieldSpecificValidator.method(field, value, personAttributeTypeConfig); if (!isValid) { errorMessages.push(fieldSpecificValidator.errorMessage); isValid = true; } } return isValid; }); return errorMessages; }; return { validate: validate }; })(); 'use strict'; Bahmni.Common.Util.DynamicResourceLoader = (function () { return { includeJs: function (script) { var element = document.createElement('script'); element.setAttribute('src', script); document.body.appendChild(element); }, includeCss: function (url) { var element = document.createElement('link'); element.setAttribute('href', url); element.setAttribute('rel', "stylesheet"); element.setAttribute('type', "text/css"); document.head.appendChild(element); } }; })(); 'use strict'; Bahmni.Common.Util.ArrayUtil = { chunk: function (array, chunkSize) { var chunks = []; for (var i = 0; i < array.length; i += chunkSize) { chunks.push(array.slice(i, i + chunkSize)); } return chunks; }, groupByPreservingOrder: function (records, groupingFunction, keyName, valueName) { var groups = []; records.forEach(function (record) { var recordKey = groupingFunction(record); var existingGroup = _.find(groups, function (group) { return group[keyName] === recordKey; }); if (existingGroup) { existingGroup[valueName].push(record); } else { var newGroup = {}; newGroup[keyName] = recordKey; newGroup[valueName] = [record]; groups.push(newGroup); } }); return groups; } }; 'use strict'; angular.module('httpErrorInterceptor', []) .config(['$httpProvider', function ($httpProvider) { var interceptor = ['$rootScope', '$q', function ($rootScope, $q) { var serverErrorMessages = Bahmni.Common.Constants.serverErrorMessages; var showError = function (errorMessage) { var result = _.find(serverErrorMessages, function (listItem) { return listItem.serverMessage === errorMessage; }); if (_.isEmpty(result)) { $rootScope.$broadcast('event:serverError', errorMessage); } }; function stringAfter (value, searchString) { var indexOfFirstColon = value.indexOf(searchString); return value.substr(indexOfFirstColon + 1).trim(); } function getServerError (message) { return stringAfter(message, ':'); } function success (response) { return response; } function shouldRedirectToLogin (response) { var errorMessage = response.data.error ? response.data.error.message : response.data; if (errorMessage.search("HTTP Status 403 - Session timed out") > 0) { return true; } } function error (response) { var data = response.data; var unexpectedError = "There was an unexpected issue on the server. Please try again"; if (response.status === 500) { var errorMessage = data.error && data.error.message ? getServerError(data.error.message) : unexpectedError; showError(errorMessage); } else if (response.status === 409) { var errorMessage = data.error && data.error.message ? getServerError(data.error.message) : "Duplicate entry error"; showError(errorMessage); } else if (response.status === 0) { showError("Could not connect to the server. Please check your connection and try again"); } else if (response.status === 405) { showError(unexpectedError); } else if (response.status === 400) { var errorMessage = data.error && data.error.message ? data.error.message : (data.localizedMessage || "Could not connect to the server. Please check your connection and try again"); showError(errorMessage); } else if (response.status === 403) { var errorMessage = data.error && data.error.message ? data.error.message : unexpectedError; if (shouldRedirectToLogin(response)) { $rootScope.$broadcast('event:auth-loginRequired'); } else { showError(errorMessage); } } else if (response.status === 404) { if (!_.includes(response.config.url, "implementation_config") && !_.includes(response.config.url, "locale_") && !_.includes(response.config.url, "offlineMetadata")) { showError("The requested information does not exist"); } } return $q.reject(response); } return { response: success, responseError: error }; }]; $httpProvider.interceptors.push(interceptor); }]); 'use strict'; Bahmni.Common.VisitControl = function (visitTypes, defaultVisitTypeName, encounterService, $translate, visitService) { var self = this; self.visitTypes = visitTypes; self.defaultVisitTypeName = defaultVisitTypeName; self.defaultVisitType = visitTypes.filter(function (visitType) { return visitType.name === defaultVisitTypeName; })[0]; self.startButtonText = function (visitType) { return $translate.instant('REGISTRATION_START_VISIT', {visitType: visitType.name}); }; self.startVisit = function (visitType) { self.onStartVisit(); self.selectedVisitType = visitType; }; self.createVisitOnly = function (patientUuid, visitLocationUuid) { var visitType = self.selectedVisitType || self.defaultVisitType; var visitDetails = {patient: patientUuid, visitType: visitType.uuid, location: visitLocationUuid}; return visitService.createVisit(visitDetails); }; }; angular.module('bahmni.common.config', []); 'use strict'; angular.module('bahmni.common.config') .service('configurations', ['configurationService', function (configurationService) { this.configs = {}; this.load = function (configNames) { var self = this; return configurationService.getConfigurations(_.difference(configNames, Object.keys(this.configs))).then(function (configurations) { angular.extend(self.configs, configurations); }); }; this.dosageInstructionConfig = function () { return this.configs.dosageInstructionConfig || []; }; this.stoppedOrderReasonConfig = function () { return this.configs.stoppedOrderReasonConfig || []; }; this.dosageFrequencyConfig = function () { return this.configs.dosageFrequencyConfig || []; }; this.allTestsAndPanelsConcept = function () { return this.configs.allTestsAndPanelsConcept.results[0] || []; }; this.impressionConcept = function () { return this.configs.radiologyImpressionConfig.results[0] || []; }; this.labOrderNotesConcept = function () { return this.configs.labOrderNotesConfig.results[0] || []; }; this.consultationNoteConcept = function () { return this.configs.consultationNoteConfig.results[0] || []; }; this.patientConfig = function () { return this.configs.patientConfig || {}; }; this.encounterConfig = function () { return angular.extend(new EncounterConfig(), this.configs.encounterConfig || []); }; this.patientAttributesConfig = function () { return this.configs.patientAttributesConfig.results; }; this.identifierTypesConfig = function () { return this.configs.identifierTypesConfig; }; this.genderMap = function () { return this.configs.genderMap; }; this.addressLevels = function () { return this.configs.addressLevels; }; this.relationshipTypes = function () { return this.configs.relationshipTypeConfig.results || []; }; this.relationshipTypeMap = function () { return this.configs.relationshipTypeMap || {}; }; this.loginLocationToVisitTypeMapping = function () { return this.configs.loginLocationToVisitTypeMapping || {}; }; this.defaultEncounterType = function () { return this.configs.defaultEncounterType; }; }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.Domain = Bahmni.Common.Domain || {}; Bahmni.Common.Domain.Helper = Bahmni.Common.Domain.Helper || {}; angular.module('bahmni.common.domain', []); 'use strict'; (function () { Bahmni.Common.Domain.ObservationFilter = function () { var self = this; var voidExistingObservationWithOutValue = function (observations) { observations.forEach(function (observation) { voidExistingObservationWithOutValue(observation.groupMembers); observation.voided = observation.voided || observation.canBeVoided(); if (observation.voided) { voidAllChildren(observation); } }); }; var voidAllChildren = function (voidedObservation) { voidedObservation.groupMembers.forEach(function (childWithVoidedParent) { childWithVoidedParent.voided = true; voidAllChildren(childWithVoidedParent); }); }; var removeNewObservationsWithoutValue = function (observations) { observations.forEach(function (observation) { observation.groupMembers = removeNewObservationsWithoutValue(observation.groupMembers); }); return observations.filter(function (observation) { var validObs = observation.isExisting() || observation.hasValue() || observation.hasMemberWithValue(); return (validObs && !observation.voided) || (observation.isExisting() && observation.voided); }); }; var removeNewObservationsWhichAreVoided = function (observations) { observations.forEach(function (observation) { observation.groupMembers = removeNewObservationsWhichAreVoided(observation.groupMembers); }); return _.reject(observations, function (observation) { return observation.isNew() && observation.voided; }); }; self.filter = function (observations) { var wrappedObservations = observations.map(Observation.wrap); var filteredObservations = removeNewObservationsWithoutValue(wrappedObservations); filteredObservations = removeNewObservationsWhichAreVoided(filteredObservations); voidExistingObservationWithOutValue(filteredObservations); return filteredObservations; }; }; var Observation = function (observationData) { angular.extend(this, observationData); this.isNew = function () { return !this.uuid; }; this.isExisting = function () { return !this.isNew(); }; this.hasValue = function () { return this.value !== undefined && this.value !== null && this.value !== ''; }; this.hasMemberWithValue = function () { return this.groupMembers.some(function (groupMember) { return groupMember.hasValue() || groupMember.hasMemberWithValue(); }); }; this.isGroup = function () { return this.groupMembers.length > 0; }; this.isLeaf = function () { return !this.isGroup(); }; this.isGroupWithOnlyVoidedMembers = function () { return this.isGroup() && this.groupMembers.every(function (groupMember) { return groupMember.voided; }); }; this.isLeafNodeWithOutValue = function () { return this.isLeaf() && !this.hasValue(); }; this.canBeVoided = function () { return this.isExisting() && (this.isLeafNodeWithOutValue() || this.isGroupWithOnlyVoidedMembers()); }; }; Observation.wrap = function (observationData) { var observation = new Observation(observationData); observation.groupMembers = observation.groupMembers ? observation.groupMembers.map(Observation.wrap) : []; return observation; }; })(); 'use strict'; Bahmni.Common.Domain.Helper.getHintForNumericConcept = function (concept) { if (!concept) { return; } if (concept.hiNormal != null && concept.lowNormal != null) { return '(' + concept.lowNormal + ' - ' + concept.hiNormal + ')'; } if (concept.hiNormal != null && concept.lowNormal == null) { return '(< ' + concept.hiNormal + ')'; } if (concept.hiNormal == null && concept.lowNormal != null) { return '(> ' + concept.lowNormal + ')'; } return ''; }; 'use strict'; Bahmni.Common.Domain.ConceptMapper = function () { this.map = function (openMrsConcept) { if (!openMrsConcept) { return null; } if (alreadyMappedConcept(openMrsConcept)) { return openMrsConcept; } // TODO: Clean up: God knows why people are passing already mapped concept. Keeping this non sense check in this one line alone to avoid confusion var openMrsDescription = openMrsConcept.descriptions ? openMrsConcept.descriptions[0] : null; var shortConceptName = _.find(openMrsConcept.names, {conceptNameType: "SHORT"}); return { uuid: openMrsConcept.uuid, name: openMrsConcept.name.name, shortName: shortConceptName ? shortConceptName.name : null, description: openMrsDescription ? openMrsDescription.description : null, set: openMrsConcept.set, dataType: openMrsConcept.datatype ? openMrsConcept.datatype.name : null, hiAbsolute: openMrsConcept.hiAbsolute, lowAbsolute: openMrsConcept.lowAbsolute, hiNormal: openMrsConcept.hiNormal, handler: openMrsConcept.handler, allowDecimal: openMrsConcept.allowDecimal, lowNormal: openMrsConcept.lowNormal, conceptClass: openMrsConcept.conceptClass ? openMrsConcept.conceptClass.name : null, answers: openMrsConcept.answers, units: openMrsConcept.units, displayString: shortConceptName ? shortConceptName.name : openMrsConcept.name.name, names: openMrsConcept.names }; }; var alreadyMappedConcept = function (concept) { return !concept.name.name; }; }; 'use strict'; angular.module('bahmni.common.domain') .factory('providerService', ['$http', function ($http) { var search = function (fieldValue) { return $http.get(Bahmni.Common.Constants.providerUrl, { method: "GET", params: {q: fieldValue, v: "full"}, withCredentials: true }); }; var searchByUuid = function (uuid) { return $http.get(Bahmni.Common.Constants.providerUrl, { method: "GET", params: { user: uuid }, cache: false }); }; var list = function (params) { return $http.get(Bahmni.Common.Constants.providerUrl, { method: "GET", cache: false, params: params }); }; return { search: search, searchByUuid: searchByUuid, list: list }; }]); 'use strict'; /* exported EncounterConfig */ var EncounterConfig = (function () { function EncounterConfig (encounterTypes) { this.encounterTypes = encounterTypes; } EncounterConfig.prototype = { getConsultationEncounterTypeUuid: function () { return this.getEncounterTypeUuid("Consultation"); }, getAdmissionEncounterTypeUuid: function () { return this.getEncounterTypeUuid("ADMISSION"); }, getDischargeEncounterTypeUuid: function () { return this.getEncounterTypeUuid("DISCHARGE"); }, getTransferEncounterTypeUuid: function () { return this.getEncounterTypeUuid("TRANSFER"); }, getRadiologyEncounterTypeUuid: function () { return this.getEncounterTypeUuid("RADIOLOGY"); }, getPatientDocumentEncounterTypeUuid: function () { return this.getEncounterTypeUuid("Patient Document"); }, getValidationEncounterTypeUuid: function () { return this.getEncounterTypeUuid(Bahmni.Common.Constants.validationNotesEncounterType); }, getEncounterTypeUuid: function (encounterTypeName) { return this.encounterTypes[encounterTypeName]; }, getVisitTypes: function () { var visitTypesArray = []; for (var name in this.visitTypes) { visitTypesArray.push({name: name, uuid: this.visitTypes[name]}); } return visitTypesArray; }, getEncounterTypes: function () { var encounterTypesArray = []; for (var name in this.encounterTypes) { encounterTypesArray.push({name: name, uuid: this.encounterTypes[name]}); } return encounterTypesArray; }, getVisitTypeByUuid: function (uuid) { var visitTypes = this.getVisitTypes(); return visitTypes.filter(function (visitType) { return visitType.uuid === uuid; })[0]; }, getEncounterTypeByUuid: function (uuid) { var encounterType = this.getEncounterTypes(); return encounterType.filter(function (encounterType) { return encounterType.uuid === uuid; })[0]; } }; return EncounterConfig; })(); 'use strict'; (function () { var nameFor = { "Date": function (obs) { return moment(obs.value).format('D-MMM-YYYY'); }, "Datetime": function (obs) { var date = Bahmni.Common.Util.DateUtil.parseDatetime(obs.value); return date != null ? Bahmni.Common.Util.DateUtil.formatDateWithTime(date) : ""; }, "Boolean": function (obs) { return obs.value === true ? "Yes" : obs.value === false ? "No" : obs.value; }, "Coded": function (obs) { return obs.value.shortName || obs.value.name || obs.value; }, "Object": function (obs) { return nameFor.Coded(obs); }, "MultiSelect": function (obs) { return obs.getValues().join(", "); }, "Default": function (obs) { return obs.value; } }; Bahmni.Common.Domain.ObservationValueMapper = { getNameFor: nameFor, map: function (obs) { var type = (obs.concept && obs.concept.dataType) || obs.type; if (!(type in nameFor)) { type = (typeof obs.value === "object" && "Object") || (obs.isMultiSelect && "MultiSelect") || "Default"; } return (nameFor[type])(obs); } }; })(); angular.module('bahmni.common.uiHelper', ['ngClipboard']); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('nonBlank', function () { return function ($scope, element, attrs) { var addNonBlankAttrs = function () { element.attr({'required': 'required'}); }; var removeNonBlankAttrs = function () { element.removeAttr('required'); }; if (!attrs.nonBlank) { return addNonBlankAttrs(element); } $scope.$watch(attrs.nonBlank, function (value) { return value ? addNonBlankAttrs() : removeNonBlankAttrs(); }); }; }) .directive('datepicker', function () { var link = function ($scope, element, attrs, ngModel) { var maxDate = attrs.maxDate; var minDate = attrs.minDate || "-120y"; var format = attrs.dateFormat || 'dd-mm-yy'; element.datepicker({ changeYear: true, changeMonth: true, maxDate: maxDate, minDate: minDate, yearRange: 'c-120:c+120', dateFormat: format, onSelect: function (dateText) { $scope.$apply(function () { ngModel.$setViewValue(dateText); }); } }); }; return { require: 'ngModel', link: link }; }) .directive('myAutocomplete', ['$parse', function ($parse) { var link = function (scope, element, attrs, ngModelCtrl) { var ngModel = $parse(attrs.ngModel); var source = scope.source(); var responseMap = scope.responseMap(); var onSelect = scope.onSelect(); element.autocomplete({ autofocus: true, minLength: 2, source: function (request, response) { source(attrs.id, request.term, attrs.itemType).then(function (data) { var results = responseMap ? responseMap(data.data) : data.data; response(results); }); }, select: function (event, ui) { scope.$apply(function (scope) { ngModelCtrl.$setViewValue(ui.item.value); scope.$eval(attrs.ngChange); if (onSelect != null) { onSelect(ui.item); } }); return true; }, search: function (event) { var searchTerm = $.trim(element.val()); if (searchTerm.length < 2) { event.preventDefault(); } } }); }; return { link: link, require: 'ngModel', scope: { source: '&', responseMap: '&', onSelect: '&' } }; }]) .directive('bmForm', ['$timeout', function ($timeout) { var link = function (scope, elem, attrs) { $timeout(function () { $(elem).unbind('submit').submit(function (e) { var formScope = scope.$parent; var formName = attrs.name; e.preventDefault(); if (scope.autofillable) { $(elem).find('input').trigger('change'); } if (formScope[formName].$valid) { formScope.$apply(attrs.ngSubmit); $(elem).removeClass('submitted-with-error'); } else { $(elem).addClass('submitted-with-error'); } }); }, 0); }; return { link: link, require: 'form', scope: { autofillable: "=" } }; }]) .directive('patternValidate', ['$timeout', function ($timeout) { return function ($scope, element, attrs) { var addPatternToElement = function () { if ($scope.fieldValidation && $scope.fieldValidation[attrs.id]) { element.attr({"pattern": $scope.fieldValidation[attrs.id].pattern, "title": $scope.fieldValidation[attrs.id].errorMessage, "type": "text"}); } }; $timeout(addPatternToElement); }; }]) .directive('validateOn', function () { var link = function (scope, element, attrs, ngModelCtrl) { var validationMessage = attrs.validationMessage || 'Please enter a valid detail'; var setValidity = function (value) { var valid = value ? true : false; ngModelCtrl.$setValidity('blank', valid); element[0].setCustomValidity(!valid ? validationMessage : ''); }; scope.$watch(attrs.validateOn, setValidity, true); }; return { link: link, require: 'ngModel' }; }); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('toggle', function () { var link = function ($scope, element) { $scope.toggle = $scope.toggle === undefined ? false : $scope.toggle; $(element).click(function () { $scope.$apply(function () { $scope.toggle = !$scope.toggle; }); }); $scope.$watch('toggle', function () { $(element).toggleClass('active', $scope.toggle); }); $scope.$on("$destroy", function () { element.off('click'); }); }; return { scope: { toggle: "=" }, link: link }; }); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('bmPopOver', function () { var controller = function ($scope) { $scope.targetElements = []; var hideTargetElements = function () { $scope.targetElements.forEach(function (el) { el.hide(); }); }; var showTargetElements = function () { $scope.targetElements.forEach(function (el) { el.show(); }); }; this.registerTriggerElement = function (triggerElement) { $scope.triggerElement = triggerElement; var docClickHandler = function () { if (!$scope.autoclose) { return; } hideTargetElements(); $scope.isTargetOpen = false; $(document).off('click', docClickHandler); }; $scope.triggerElement.on('click', function (event) { if ($scope.isTargetOpen) { $scope.isTargetOpen = false; hideTargetElements(0); $(document).off('click', docClickHandler); } else { $scope.isTargetOpen = true; showTargetElements(); $(document).on('click', docClickHandler); event.stopImmediatePropagation(); } }); $scope.$on('$destroy', function () { $(document).off('click', docClickHandler); }); }; this.registerTargetElement = function (targetElement) { targetElement.hide(); $scope.targetElements.push(targetElement); }; var hideOrShowTargetElements = function () { if ($scope.isTargetOpen) { $scope.isTargetOpen = false; hideTargetElements(0); } }; $(document).on('click', '.reg-wrapper', hideOrShowTargetElements); $scope.$on('$destroy', function () { $(document).off('click', '.reg-wrapper', hideOrShowTargetElements); }); }; return { restrict: 'A', controller: controller, scope: { autoclose: "=" } }; }) .directive('bmPopOverTarget', function () { var link = function ($scope, element, attrs, popOverController) { popOverController.registerTargetElement(element); }; return { restrict: 'A', require: '^bmPopOver', link: link }; }) .directive('bmPopOverTrigger', function () { var link = function ($scope, element, attrs, popOverController) { popOverController.registerTriggerElement(element); }; return { restrict: 'A', require: '^bmPopOver', link: link }; }); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('splitButton', ['$timeout', function ($timeout) { var controller = function ($scope) { $scope.primaryOption = $scope.primaryOption || $scope.options[0]; $scope.secondaryOptions = _.without($scope.options, $scope.primaryOption); $scope.hasMultipleOptions = function () { return $scope.secondaryOptions.length > 0; }; }; var link = function (scope, element) { var shouldScroll = function (elementPosition, elementHeight) { var windowHeight = window.innerHeight + $(window).scrollTop(); return windowHeight < (elementHeight + elementPosition); }; scope.scrollToBottom = function () { var timeout = $timeout(function () { var scrollHeight = $(element)[0].scrollHeight; if (shouldScroll(element.position().top, scrollHeight)) { window.scrollBy(0, scrollHeight); $timeout.cancel(timeout); } }); }; }; return { restrict: 'A', template: '
' + '' + '
    ' + '
  • ' + '' + '
  • ' + '
      ' + '
    • ' + '' + '
    • ' + '
    ' + '
' + '
', controller: controller, link: link, scope: { options: '=', primaryOption: '=', optionText: '&', optionClick: '&', optionDisabled: '=' } }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('focusOn', ['$timeout', function ($timeout) { return function (scope, elem, attrs) { if (Modernizr.ios) { return; } scope.$watch(attrs.focusOn, function (value) { if (value) { $timeout(function () { $(elem).focus(); }); } }); }; }]); (function () { 'use strict'; var constructSearchResult = function (concept, searchString) { var matchingName = null; var conceptName = concept.name; if (!_.includes(_.toLower(conceptName), _.toLower(searchString))) { var synonyms = _.map(concept.names, 'name'); matchingName = _.find(synonyms, function (name) { return (name !== conceptName) && name.search(new RegExp(searchString, "i")) !== -1; }); } return { label: matchingName ? matchingName + " => " + conceptName : conceptName, value: conceptName, concept: concept, uuid: concept.uuid, name: conceptName }; }; var searchWithDefaultConcept = function (searchMethod, request, response) { var searchTerm = _.toLower(request.term.trim()); var isMatching = function (answer) { var conceptNameFound = _.find(answer.names, function (name) { return _.includes(_.toLower(name.name), searchTerm); }); var conceptDrugNameFound = _.includes(_.toLower(answer.name), searchTerm); return conceptNameFound || conceptDrugNameFound; }; var responseMap = _.partial(constructSearchResult, _, searchTerm); searchMethod() .then(_.partial(_.filter, _, isMatching))// == .then(function(value){return _.filter(value,isMatching);}) .then(_.partial(_.map, _, responseMap)) .then(response); }; var searchWithGivenConcept = function (searchMethod, request, response) { var searchTerm = request.term.trim(); var responseMap = _.partial(constructSearchResult, _, searchTerm); searchMethod() .then(_.partial(_.map, _, responseMap)) .then(response); }; var toBeInjected = ['$parse', '$http', 'conceptService']; var conceptAutocomplete = function ($parse, $http, conceptService) { var link = function (scope, element, attrs, ngModelCtrl) { var minLength = scope.minLength || 2; var previousValue = scope.previousValue; var validator = function (searchTerm) { if (!scope.strictSelect) { return; } if (!scope.illegalValue && (_.isEmpty(searchTerm) || searchTerm === previousValue)) { element.removeClass('illegalValue'); return; } element.addClass('illegalValue'); }; element.autocomplete({ autofocus: true, minLength: minLength, source: function (request, response) { var searchMethod; if (!scope.answersConceptName && scope.defaultConcept) { searchMethod = _.partial(conceptService.getAnswers, scope.defaultConcept); searchWithDefaultConcept(searchMethod, request, response); } else { searchMethod = _.partial(conceptService.getAnswersForConceptName, { term: request.term, answersConceptName: scope.answersConceptName }); searchWithGivenConcept(searchMethod, request, response); } }, select: function (event, ui) { scope.$apply(function (scope) { ngModelCtrl.$setViewValue(ui.item); if (scope.blurOnSelect) { element.blur(); } previousValue = ui.item.value; validator(previousValue); scope.$eval(attrs.ngChange); }); return true; }, search: function (event) { var searchTerm = $.trim(element.val()); if (searchTerm.length < minLength) { event.preventDefault(); } previousValue = null; } }); var blurHandler = function () { var searchTerm = $.trim(element.val()); validator(searchTerm); }; element.on('blur', blurHandler); scope.$on("$destroy", function () { element.off('blur', blurHandler); }); }; return { link: link, require: 'ngModel', scope: { illegalValue: '=', defaultConcept: '=', answersConceptName: '=', minLength: '=', blurOnSelect: '=', strictSelect: '=?', previousValue: '=' } }; }; conceptAutocomplete.$inject = toBeInjected; angular.module('bahmni.common.uiHelper').directive('conceptAutocomplete', conceptAutocomplete); })(); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) { return { link: function (scope, element, attrs) { var model = $parse(attrs.focusMe); scope.$watch(model, function (value) { if (value === true) { $timeout(function () { element[0].focus(); }); } }); } }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('bahmniAutocomplete', ['$translate', function ($translate) { var link = function (scope, element, attrs, ngModelCtrl) { var source = scope.source(); var responseMap = scope.responseMap && scope.responseMap(); var onSelect = scope.onSelect(); var onEdit = scope.onEdit && scope.onEdit(); var minLength = scope.minLength || 2; var formElement = element[0]; var validationMessage = scope.validationMessage || $translate.instant("SELECT_VALUE_FROM_AUTOCOMPLETE_DEFAULT_MESSAGE"); var validateIfNeeded = function (value) { if (!scope.strictSelect) { return; } scope.isInvalid = (value !== scope.selectedValue); if (_.isEmpty(value)) { scope.isInvalid = false; } }; scope.$watch('initialValue', function () { if (scope.initialValue) { scope.selectedValue = scope.initialValue; scope.isInvalid = false; } }); element.autocomplete({ autofocus: true, minLength: minLength, source: function (request, response) { source({elementId: attrs.id, term: request.term, elementType: attrs.type}).then(function (data) { var results = responseMap ? responseMap(data) : data; response(results); }); }, select: function (event, ui) { scope.selectedValue = ui.item.value; ngModelCtrl.$setViewValue(ui.item.value); if (onSelect != null) { onSelect(ui.item); } validateIfNeeded(ui.item.value); if (scope.blurOnSelect) { element.blur(); } scope.$apply(); scope.$eval(attrs.ngDisabled); scope.$apply(); return true; }, search: function (event, ui) { if (onEdit != null) { onEdit(ui.item); } var searchTerm = $.trim(element.val()); validateIfNeeded(searchTerm); if (searchTerm.length < minLength) { event.preventDefault(); } } }); var changeHanlder = function (e) { validateIfNeeded(element.val()); }; var keyUpHandler = function (e) { validateIfNeeded(element.val()); scope.$apply(); }; element.on('change', changeHanlder); element.on('keyup', keyUpHandler); scope.$watch('isInvalid', function () { ngModelCtrl.$setValidity('selection', !scope.isInvalid); formElement.setCustomValidity(scope.isInvalid ? validationMessage : ''); }); scope.$on("$destroy", function () { element.off('change', changeHanlder); element.off('keyup', keyUpHandler); }); }; return { link: link, require: 'ngModel', scope: { source: '&', responseMap: '&?', onSelect: '&', onEdit: '&?', minLength: '=?', blurOnSelect: '=?', strictSelect: '=?', validationMessage: '@', isInvalid: "=?", initialValue: "=?" } }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .factory('spinner', ['messagingService', '$timeout', function (messagingService, $timeout) { var tokens = []; var topLevelDiv = function (element) { return $(element).find("div").eq(0); }; var showSpinnerForElement = function (element) { if ($(element).find(".dashboard-section-loader").length === 0) { topLevelDiv(element) .addClass('spinnable') .append('
'); } return { element: $(element).find(".dashboard-section-loader") }; }; var showSpinnerForOverlay = function () { var token = Math.random(); tokens.push(token); if ($('#overlay').length === 0) { $('body').prepend('
'); } var spinnerElement = $('#overlay'); spinnerElement.stop().show(); return { element: spinnerElement, token: token }; }; var show = function (element) { if (element !== undefined) { return showSpinnerForElement(element); } return showSpinnerForOverlay(); }; var hide = function (spinner, parentElement) { var spinnerElement = spinner.element; if (spinner.token) { _.pull(tokens, spinner.token); if (tokens.length === 0) { spinnerElement.fadeOut(300); } } else { topLevelDiv(parentElement).removeClass('spinnable'); spinnerElement && spinnerElement.remove(); } }; var forPromise = function (promise, element) { return $timeout(function () { // Added timeout to push a new event into event queue. So that its callback will be invoked once DOM is completely rendered var spinner = show(element); // Don't inline this element promise['finally'](function () { hide(spinner, element); }); return promise; }); }; var forAjaxPromise = function (promise, element) { var spinner = show(element); promise.always(function () { hide(spinner, element); }); return promise; }; return { forPromise: forPromise, forAjaxPromise: forAjaxPromise, show: show, hide: hide }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .factory('printer', ['$rootScope', '$compile', '$http', '$timeout', '$q', 'spinner', function ($rootScope, $compile, $http, $timeout, $q, spinner) { var printHtml = function (html) { var deferred = $q.defer(); var hiddenFrame = $('').appendTo('body')[0]; hiddenFrame.contentWindow.printAndRemove = function () { hiddenFrame.contentWindow.print(); $(hiddenFrame).remove(); deferred.resolve(); }; var htmlContent = "" + "" + '' + html + '' + ""; var doc = hiddenFrame.contentWindow.document.open("text/html", "replace"); doc.write(htmlContent); doc.close(); return deferred.promise; }; var openNewWindow = function (html) { var newWindow = window.open("printTest.html"); newWindow.addEventListener('load', function () { $(newWindow.document.body).html(html); }, false); }; var print = function (templateUrl, data) { $rootScope.isBeingPrinted = true; $http.get(templateUrl).then(function (templateData) { var template = templateData.data; var printScope = $rootScope.$new(); angular.extend(printScope, data); var element = $compile($('
' + template + '
'))(printScope); var renderAndPrintPromise = $q.defer(); var waitForRenderAndPrint = function () { if (printScope.$$phase || $http.pendingRequests.length) { $timeout(waitForRenderAndPrint, 1000); } else { // Replace printHtml with openNewWindow for debugging printHtml(element.html()).then(function () { $rootScope.isBeingPrinted = false; renderAndPrintPromise.resolve(); }); printScope.$destroy(); } return renderAndPrintPromise.promise; }; spinner.forPromise(waitForRenderAndPrint()); }); }; var printFromScope = function (templateUrl, scope, afterPrint) { $rootScope.isBeingPrinted = true; $http.get(templateUrl).then(function (response) { var template = response.data; var printScope = scope; var element = $compile($('
' + template + '
'))(printScope); var renderAndPrintPromise = $q.defer(); var waitForRenderAndPrint = function () { if (printScope.$$phase || $http.pendingRequests.length) { $timeout(waitForRenderAndPrint); } else { printHtml(element.html()).then(function () { $rootScope.isBeingPrinted = false; if (afterPrint) { afterPrint(); } renderAndPrintPromise.resolve(); }); } return renderAndPrintPromise.promise; }; spinner.forPromise(waitForRenderAndPrint()); }); }; return { print: print, printFromScope: printFromScope }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .service('contextChangeHandler', ['$rootScope', function ($rootScope) { var callbacks = []; var self = this; $rootScope.$on('$stateChangeSuccess', function () { self.reset(); }); this.reset = function () { callbacks = []; }; this.add = function (callback) { callbacks.push(callback); }; this.execute = function () { var allow = true; var callBackReturn = null; var errorMessage = null; callbacks.forEach(function (callback) { callBackReturn = callback(); allow = allow && callBackReturn["allow"]; if (_.isEmpty(errorMessage)) { errorMessage = callBackReturn["errorMessage"]; } }); if (callBackReturn && errorMessage) { return {allow: allow, errorMessage: errorMessage}; } return {allow: allow}; }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .controller('MessageController', ['$scope', 'messagingService', function ($scope, messagingService) { $scope.messages = messagingService.messages; $scope.getMessageText = function (level) { var string = ""; $scope.messages[level].forEach(function (message) { string = string.concat(message.value); }); return string; }; $scope.hideMessage = function (level) { messagingService.hideMessages(level); }; $scope.isErrorMessagePresent = function () { return $scope.messages.error.length > 0; }; $scope.isInfoMessagePresent = function () { return $scope.messages.info.length > 0; }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .service('messagingService', ['$rootScope', '$timeout', function ($rootScope, $timeout) { this.messages = {error: [], info: []}; var self = this; $rootScope.$on('event:serverError', function (event, errorMessage) { self.showMessage('error', errorMessage, 'serverError'); }); this.showMessage = function (level, message, errorEvent) { var messageObject = {'value': '', 'isServerError': false}; messageObject.value = message; if (errorEvent) { messageObject.isServerError = true; } else if (level == 'info') { this.createTimeout('info', 4000); } var index = _.findIndex(this.messages[level], function (msg) { return msg.value == messageObject.value; }); if (index >= 0) { this.messages[level].splice(index, 1); } this.messages[level].push(messageObject); }; this.createTimeout = function (level, time) { $timeout(function () { self.messages[level] = []; }, time, true); }; this.hideMessages = function (level) { self.messages[level].length = 0; }; this.clearAll = function () { self.messages["error"] = []; self.messages["info"] = []; }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('ngConfirmClick', function () { var link = function (scope, element, attr) { var msg = attr.confirmMessage || "Are you sure?"; var clickAction = attr.ngConfirmClick; element.bind('click', function () { if (window.confirm(msg)) { scope.$apply(clickAction); } }); }; return { restrict: 'A', link: link }; }); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('bmShow', ['$rootScope', function ($rootScope) { var link = function ($scope, element) { $scope.$watch('bmShow', function () { if ($rootScope.isBeingPrinted || $scope.bmShow) { element.removeClass('ng-hide'); } else { element.addClass('ng-hide'); } }); }; return { scope: { bmShow: "=" }, link: link }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('monthyearpicker', ['$translate', function ($translate) { var link = function ($scope) { var monthNames = $translate.instant('MONTHS'); $scope.monthNames = monthNames.split(","); var getYearList = function () { var minYear = $scope.minYear ? $scope.minYear : moment().toDate().getFullYear() - 15; var maxYear = $scope.maxYear ? $scope.maxYear : moment().toDate().getFullYear() + 5; var yearList = []; for (var i = maxYear; i >= minYear; i--) { yearList.push(i); } return yearList; }; $scope.years = getYearList(); var valueCompletelyFilled = function () { return ($scope.selectedMonth != null && $scope.selectedYear != null); }; var valueNotFilled = function () { return $scope.selectedMonth == null && $scope.selectedYear == null; }; var getCompleteDate = function () { var month = $scope.selectedMonth + 1; return $scope.selectedYear + "-" + month + "-01"; }; $scope.updateModel = function () { if (valueCompletelyFilled()) { $scope.model = getCompleteDate(); } else if (!$scope.isValid()) { $scope.model = "Invalid Date"; } else { $scope.model = ""; } }; $scope.isValid = function () { return valueNotFilled() || valueCompletelyFilled(); }; $scope.illegalMonth = function () { return ($scope.selectedMonth === undefined || $scope.selectedMonth === null) && ($scope.selectedYear !== null && $scope.selectedYear !== undefined); }; $scope.illegalYear = function () { return ($scope.selectedMonth !== null && $scope.selectedMonth !== undefined) && ($scope.selectedYear === undefined || $scope.selectedYear === null); }; if ($scope.model) { var date = moment($scope.model).toDate(); $scope.selectedMonth = date.getMonth(); $scope.selectedYear = date.getFullYear(); } }; return { restrict: 'E', link: link, scope: { observation: "=", minYear: "=", maxYear: "=", illegalValue: '=', model: "=" }, template: '' + '' }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('singleClick', function () { var ignoreClick = false; var link = function (scope, element) { var clickHandler = function () { if (ignoreClick) { return; } ignoreClick = true; scope.singleClick().finally(function () { ignoreClick = false; }); }; element.on('click', clickHandler); scope.$on("$destroy", function () { element.off('click', clickHandler); }); }; return { scope: { singleClick: '&' }, restrict: 'A', link: link }; }); 'use strict'; angular.module('bahmni.common.uiHelper') .directive('singleSubmit', function () { var ignoreSubmit = false; var link = function (scope, element) { var submitHandler = function () { if (ignoreSubmit) { return; } ignoreSubmit = true; scope.singleSubmit().finally(function () { ignoreSubmit = false; }); }; element.on('submit', submitHandler); scope.$on("$destroy", function () { element.off('submit', submitHandler); }); }; return { scope: { singleSubmit: '&' }, restrict: 'A', link: link }; }); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.UIControls = Bahmni.Common.UIControls || {}; angular.module('bahmni.common.uicontrols', []); (function () { 'use strict'; var constructSearchResult = function (concept) { var conceptName = concept.shortName || concept.name.name || concept.name; return { label: conceptName, value: conceptName, concept: concept, uuid: concept.uuid, name: conceptName }; }; var find = function (allAnswers, savedAnswer) { return _.find(allAnswers, function (answer) { return savedAnswer && (savedAnswer.uuid === answer.concept.uuid); }); }; var toBeInjected = ['conceptService']; var conceptDropdown = function (conceptService) { var controller = function ($scope) { $scope.onChange = $scope.onChange(); var response = function (answers) { $scope.answers = answers; $scope.selectedAnswer = find(answers, $scope.selectedAnswer); }; if (!$scope.answersConceptName && $scope.defaultConcept) { conceptService.getAnswers($scope.defaultConcept).then(function (results) { return _.map(results, constructSearchResult); }).then(response); return; } conceptService.getAnswersForConceptName({ answersConceptName: $scope.answersConceptName }).then(function (results) { return _.map(results, constructSearchResult); }).then(response); }; return { controller: controller, restrict: 'E', scope: { selectedAnswer: '=model', answersConceptName: '=?', defaultConcept: '=', onChange: '&', onInvalidClass: '@', isValid: '=', ngDisabled: '=' }, templateUrl: '../common/uicontrols/concept-dropdown/views/conceptDropdown.html' }; }; conceptDropdown.$inject = toBeInjected; angular.module('bahmni.common.uicontrols').directive('conceptDropdown', conceptDropdown); })(); 'use strict'; angular.module('bahmni.common.attributeTypes', []).directive('attributeTypes', [function () { return { scope: { targetModel: '=', attribute: '=', fieldValidation: '=', isAutoComplete: '&', getAutoCompleteList: '&', getDataResults: '&', handleUpdate: '&', isReadOnly: '&', isForm: '=?' }, templateUrl: '../common/attributeTypes/views/attributeInformation.html', restrict: 'E', controller: function ($scope) { $scope.getAutoCompleteList = $scope.getAutoCompleteList(); $scope.getDataResults = $scope.getDataResults(); // to avoid watchers in one way binding $scope.isAutoComplete = $scope.isAutoComplete() || function () { return false; }; $scope.isReadOnly = $scope.isReadOnly() || function () { return false; }; $scope.handleUpdate = $scope.handleUpdate() || function () { return false; }; $scope.appendConceptNameToModel = function (attribute) { var attributeValueConceptType = $scope.targetModel[attribute.name]; var concept = _.find(attribute.answers, function (answer) { return answer.conceptId === attributeValueConceptType.conceptUuid; }); attributeValueConceptType.value = concept && concept.fullySpecifiedName; }; } }; }]); angular.module('bahmni.common.photoCapture', []); 'use strict'; angular.module('bahmni.common.photoCapture') .directive('capturePhoto', ['$parse', '$window', function factory ($parse, $window) { var link = function (scope, iElement, iAttrs) { var captureDialogElement = iElement.find(".photoCaptureDialog"), captureVideo = captureDialogElement.find("video")[0], captureActiveStream, captureCanvas = captureDialogElement.find("canvas")[0], captureContext = captureCanvas.getContext("2d"), captureConfirmImageButton = captureDialogElement.find(".confirmImage"), uploadDialogElement = iElement.find(".photoUploadDialog"), uploadCanvas = uploadDialogElement.find("canvas")[0], uploadContext = uploadCanvas.getContext("2d"), uploadConfirmImageButton = uploadDialogElement.find(".confirmImage"), uploadField = iElement.find(".fileUpload")[0], dialogOpen = false, pixelRatio = window.devicePixelRatio; captureContext.scale(pixelRatio, pixelRatio); uploadContext.scale(pixelRatio, pixelRatio); var confirmImage = function (canvas, dialogElement) { var image = canvas.toDataURL("image/jpeg"); var onConfirmationSuccess = function (image) { var ngModel = $parse(iAttrs.ngModel); ngModel.assign(scope, image); dialogElement.dialog('close'); }; if (iAttrs.capturePhoto) { var onConfirmationPromise = scope[iAttrs.capturePhoto](image); onConfirmationPromise.then(function () { onConfirmationSuccess(image); }, function () { alert("Failed to save image. Please try again later"); }); } else { onConfirmationSuccess(image); } }; var drawImage = function (canvas, context, image, imageWidth, imageHeight) { var sourceX = 0; var sourceY = 0; var destX = 0; var destY = 0; var stretchRatio, sourceWidth, sourceHeight; if (canvas.width > canvas.height) { stretchRatio = (imageWidth / canvas.width); sourceWidth = imageWidth; sourceHeight = Math.floor(canvas.height * stretchRatio); sourceY = Math.floor((imageHeight - sourceHeight) / 2); } else { stretchRatio = (imageHeight / canvas.height); sourceWidth = Math.floor(canvas.width * stretchRatio); sourceHeight = imageHeight; sourceX = Math.floor((imageWidth - sourceWidth) / 2); } var destWidth = Math.floor(canvas.width / pixelRatio); var destHeight = Math.floor(canvas.height / pixelRatio); context.drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight); }; scope.launchPhotoCapturePopup = function () { if (dialogOpen) { alert("Please allow access to web camera and wait for photo capture dialog to be launched"); return; } dialogOpen = true; var navigatorUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; if (navigator.mediaDevices) { navigator.mediaDevices.getUserMedia({video: true, audio: false}) .then(function (localMediaStream) { captureVideo.srcObject = localMediaStream; captureActiveStream = localMediaStream; captureDialogElement.dialog('open'); }).catch(function (e) { alert("Could not get access to web camera. Please allow access to web camera"); }); } else if (navigatorUserMedia) { navigatorUserMedia( {video: true, audio: false}, function (localMediaStream) { captureVideo.src = $window.URL.createObjectURL(localMediaStream); captureActiveStream = localMediaStream; captureDialogElement.dialog('open'); }, function () { alert("Could not get access to web camera. Please allow access to web camera"); } ); } else { alert('Photo capture is not supported in your browser. Please use chrome'); } }; scope.captureConfirmImage = function () { confirmImage(captureCanvas, captureDialogElement); }; scope.captureClickImage = function () { drawImage(captureCanvas, captureContext, captureVideo, captureVideo.videoWidth, captureVideo.videoHeight); captureConfirmImageButton.prop('disabled', false); captureConfirmImageButton.focus(); }; captureDialogElement.dialog({autoOpen: false, height: 300, width: 500, modal: true, close: function () { dialogOpen = false; if (captureActiveStream) { var captureActiveStreamTrack = captureActiveStream.getTracks(); if (captureActiveStreamTrack) { captureActiveStreamTrack[0].stop(); } } } }); scope.uploadConfirmImage = function () { confirmImage(uploadCanvas, uploadDialogElement); }; scope.launchPhotoUploadPopup = function () { if (dialogOpen) { alert("Please wait for photo upload dialog to be launched"); return; } dialogOpen = true; uploadDialogElement.dialog('open'); }; scope.uploadImage = function () { if (this.files && this.files[0]) { var fileReader = new FileReader(); fileReader.onload = function (e) { var image = new Image(); image.onload = function () { drawImage(uploadCanvas, uploadContext, image, image.width, image.height); }; image.src = e.target.result; }; fileReader.readAsDataURL(this.files[0]); } uploadConfirmImageButton.prop('disabled', false); uploadConfirmImageButton.focus(); }; uploadDialogElement.dialog({autoOpen: false, height: 350, width: 350, modal: true, close: function () { dialogOpen = false; } }); iElement.bind("$destroy", function () { captureDialogElement.dialog("destroy"); uploadDialogElement.dialog("destroy"); }); uploadField.addEventListener("change", scope.uploadImage, false); }; return { templateUrl: '../common/photo-capture/views/photo.html', restrict: 'A', scope: true, link: link }; }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Auth = Bahmni.Auth || {}; angular.module('authentication', ['ui.router']); 'use strict'; Bahmni.Auth.User = function (user) { angular.extend(this, user); this.userProperties = user.userProperties || {}; this.favouriteObsTemplates = this.userProperties.favouriteObsTemplates ? this.userProperties.favouriteObsTemplates.split("###") : []; this.favouriteWards = this.userProperties.favouriteWards ? this.userProperties.favouriteWards.split("###") : []; this.recentlyViewedPatients = this.userProperties.recentlyViewedPatients ? JSON.parse(this.userProperties.recentlyViewedPatients) : []; this.toContract = function () { var user = angular.copy(this); user.userProperties.favouriteObsTemplates = this.favouriteObsTemplates.join("###"); user.userProperties.favouriteWards = this.favouriteWards.join("###"); user.userProperties.recentlyViewedPatients = JSON.stringify(this.recentlyViewedPatients); delete user.favouriteObsTemplates; delete user.favouriteWards; delete user.recentlyViewedPatients; return user; }; this.addDefaultLocale = function (locale) { this.userProperties['defaultLocale'] = locale; }; this.addToRecentlyViewed = function (patient, maxPatients) { if (!_.some(this.recentlyViewedPatients, {'uuid': patient.uuid})) { this.recentlyViewedPatients.unshift({ uuid: patient.uuid, name: patient.name, identifier: patient.identifier }); if (_.size(this.recentlyViewedPatients) >= maxPatients) { this.recentlyViewedPatients = _.take(this.recentlyViewedPatients, maxPatients); } } }; this.isFavouriteObsTemplate = function (conceptName) { return _.includes(this.favouriteObsTemplates, conceptName); }; this.toggleFavoriteObsTemplate = function (conceptName) { if (this.isFavouriteObsTemplate(conceptName)) { this.favouriteObsTemplates = _.without(this.favouriteObsTemplates, conceptName); } else { this.favouriteObsTemplates.push(conceptName); } }; this.isFavouriteWard = function (wardName) { return _.includes(this.favouriteWards, wardName); }; this.toggleFavoriteWard = function (wardName) { if (this.isFavouriteWard(wardName)) { this.favouriteWards = _.without(this.favouriteWards, wardName); } else { this.favouriteWards.push(wardName); } }; }; 'use strict'; angular.module('authentication') .service('userService', ['$rootScope', '$http', '$q', function ($rootScope, $http, $q) { var getUserFromServer = function (userName) { return $http.get(Bahmni.Common.Constants.userUrl, { method: "GET", params: { username: userName, v: "custom:(username,uuid,person:(uuid,),privileges:(name,retired),userProperties)" }, cache: false }); }; this.getUser = function (userName) { var deferrable = $q.defer(); getUserFromServer(userName).success(function (data) { deferrable.resolve(data); }).error(function () { deferrable.reject('Unable to get user data'); }); return deferrable.promise; }; this.savePreferences = function () { var deferrable = $q.defer(); var user = $rootScope.currentUser.toContract(); $http.post(Bahmni.Common.Constants.userUrl + "/" + user.uuid, {"uuid": user.uuid, "userProperties": user.userProperties}, { withCredentials: true }).then(function (response) { $rootScope.currentUser.userProperties = response.data.userProperties; deferrable.resolve(); }); return deferrable.promise; }; var getProviderFromServer = function (uuid) { return $http.get(Bahmni.Common.Constants.providerUrl, { method: "GET", params: { user: uuid }, cache: false }); }; this.getProviderForUser = function (uuid) { var deferrable = $q.defer(); getProviderFromServer(uuid).success(function (data) { if (data.results.length > 0) { var providerName = data.results[0].display.split("-")[1]; data.results[0].name = providerName ? providerName.trim() : providerName; deferrable.resolve(data); } else { deferrable.reject("UNABLE_TO_GET_PROVIDER_DATA"); } }).error(function () { deferrable.reject("UNABLE_TO_GET_PROVIDER_DATA"); }); return deferrable.promise; }; this.getPasswordPolicies = function () { return $http.get(Bahmni.Common.Constants.passwordPolicyUrl, { method: "GET", withCredentials: true }); }; }]); 'use strict'; angular.module('authentication') .config(['$httpProvider', function ($httpProvider) { var interceptor = ['$rootScope', '$q', function ($rootScope, $q) { function success (response) { return response; } function error (response) { if (response.status === 401) { $rootScope.$broadcast('event:auth-loginRequired'); } return $q.reject(response); } return { response: success, responseError: error }; }]; $httpProvider.interceptors.push(interceptor); }]).run(['$rootScope', '$window', '$timeout', function ($rootScope, $window, $timeout) { $rootScope.$on('event:auth-loginRequired', function () { $timeout(function () { $window.location = "../home/index.html#/login"; }); }); }]).service('sessionService', ['$rootScope', '$http', '$q', '$bahmniCookieStore', 'userService', function ($rootScope, $http, $q, $bahmniCookieStore, userService) { var sessionResourcePath = Bahmni.Common.Constants.RESTWS_V1 + '/session?v=custom:(uuid)'; var getAuthFromServer = function (username, password, otp) { var btoa = otp ? username + ':' + password + ':' + otp : username + ':' + password; return $http.get(sessionResourcePath, { headers: {'Authorization': 'Basic ' + window.btoa(btoa)}, cache: false }); }; this.resendOTP = function (username, password) { var btoa = username + ':' + password; return $http.get(sessionResourcePath + '&resendOTP=true', { headers: {'Authorization': 'Basic ' + window.btoa(btoa)}, cache: false }); }; var createSession = function (username, password, otp) { var deferrable = $q.defer(); destroySessionFromServer().success(function () { getAuthFromServer(username, password, otp).then(function (response) { if (response.status == 204) { deferrable.resolve({"firstFactAuthorization": true}); } deferrable.resolve(response.data); }, function (response) { if (response.status == 401) { deferrable.reject('LOGIN_LABEL_WRONG_OTP_MESSAGE_KEY'); } else if (response.status == 410) { deferrable.reject('LOGIN_LABEL_OTP_EXPIRED'); } else if (response.status == 429) { // Too many requests deferrable.reject('LOGIN_LABEL_MAX_FAILED_ATTEMPTS'); } deferrable.reject('LOGIN_LABEL_LOGIN_ERROR_MESSAGE_KEY'); }); }).error(function () { deferrable.reject('LOGIN_LABEL_LOGIN_ERROR_MESSAGE_KEY'); }); return deferrable.promise; }; var hasAnyActiveProvider = function (providers) { return _.filter(providers, function (provider) { return (provider.retired == undefined || provider.retired == "false"); }).length > 0; }; var self = this; var destroySessionFromServer = function () { return $http.delete(sessionResourcePath); }; var sessionCleanup = function () { delete $.cookie(Bahmni.Common.Constants.currentUser, null, {path: "/"}); delete $.cookie(Bahmni.Common.Constants.currentUser, null, {path: "/"}); delete $.cookie(Bahmni.Common.Constants.retrospectiveEntryEncounterDateCookieName, null, {path: "/"}); delete $.cookie(Bahmni.Common.Constants.grantProviderAccessDataCookieName, null, {path: "/"}); $rootScope.currentUser = undefined; }; this.destroy = function () { var deferrable = $q.defer(); destroySessionFromServer().then(function () { sessionCleanup(); deferrable.resolve(); }); return deferrable.promise; }; this.loginUser = function (username, password, location, otp) { var deferrable = $q.defer(); createSession(username, password, otp).then(function (data) { if (data.authenticated) { $bahmniCookieStore.put(Bahmni.Common.Constants.currentUser, username, {path: '/', expires: 7}); if (location != undefined) { $bahmniCookieStore.remove(Bahmni.Common.Constants.locationCookieName); $bahmniCookieStore.put(Bahmni.Common.Constants.locationCookieName, {name: location.display, uuid: location.uuid}, {path: '/', expires: 7}); } deferrable.resolve(data); } else if (data.firstFactAuthorization) { deferrable.resolve(data); } else { deferrable.reject('LOGIN_LABEL_LOGIN_ERROR_MESSAGE_KEY'); } }, function (errorInfo) { deferrable.reject(errorInfo); }); return deferrable.promise; }; this.get = function () { return $http.get(sessionResourcePath, { cache: false }); }; this.loadCredentials = function () { var deferrable = $q.defer(); var currentUser = $bahmniCookieStore.get(Bahmni.Common.Constants.currentUser); if (!currentUser) { this.destroy().finally(function () { $rootScope.$broadcast('event:auth-loginRequired'); deferrable.reject("No User in session. Please login again."); }); return deferrable.promise; } userService.getUser(currentUser).then(function (data) { userService.getProviderForUser(data.results[0].uuid).then(function (providers) { if (!_.isEmpty(providers.results) && hasAnyActiveProvider(providers.results)) { $rootScope.currentUser = new Bahmni.Auth.User(data.results[0]); $rootScope.currentUser.currentLocation = $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName).name; $rootScope.$broadcast('event:user-credentialsLoaded', data.results[0]); deferrable.resolve(data.results[0]); } else { self.destroy(); deferrable.reject("YOU_HAVE_NOT_BEEN_SETUP_PROVIDER"); } }, function () { self.destroy(); deferrable.reject("COULD_NOT_GET_PROVIDER"); }); }, function () { self.destroy(); deferrable.reject('Could not get roles for the current user.'); }); return deferrable.promise; }; this.getLoginLocationUuid = function () { return $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName) ? $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName).uuid : null; }; this.changePassword = function (currentUserUuid, oldPassword, newPassword) { return $http({ method: 'POST', url: Bahmni.Common.Constants.passwordUrl, data: { "oldPassword": oldPassword, "newPassword": newPassword }, headers: {'Content-Type': 'application/json'} }); }; this.loadProviders = function (userInfo) { return $http.get(Bahmni.Common.Constants.providerUrl, { method: "GET", params: { user: userInfo.uuid }, cache: false }).success(function (data) { var providerUuid = (data.results.length > 0) ? data.results[0].uuid : undefined; $rootScope.currentProvider = { uuid: providerUuid }; }); }; }]).factory('authenticator', ['$rootScope', '$q', '$window', 'sessionService', function ($rootScope, $q, $window, sessionService) { var authenticateUser = function () { var defer = $q.defer(); var sessionDetails = sessionService.get(); sessionDetails.then(function (response) { if (response.data.authenticated) { defer.resolve(); } else { defer.reject('User not authenticated'); $rootScope.$broadcast('event:auth-loginRequired'); } }); return defer.promise; }; return { authenticateUser: authenticateUser }; }]).directive('logOut', ['sessionService', '$window', 'configurationService', 'auditLogService', function (sessionService, $window, configurationService, auditLogService) { return { link: function (scope, element) { element.bind('click', function () { scope.$apply(function () { auditLogService.log(undefined, 'USER_LOGOUT_SUCCESS', undefined, 'MODULE_LABEL_LOGOUT_KEY').then(function () { sessionService.destroy().then( function () { $window.location = "../home/index.html#/login"; }); }); }); }); } }; }]) .directive('btnUserInfo', [function () { return { restrict: 'CA', link: function (scope, elem) { elem.bind('click', function (event) { $(this).next().toggleClass('active'); event.stopPropagation(); }); $(document).find('body').bind('click', function () { $(elem).next().removeClass('active'); }); } }; } ]); angular.module('bahmni.common.appFramework', ['authentication']); var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.AppFramework = Bahmni.Common.AppFramework || {}; 'use strict'; Bahmni.Common.AppFramework.AppDescriptor = function (context, inheritContext, retrieveUserCallback, mergeService) { this.id = null; this.instanceOf = null; this.description = null; this.contextModel = null; this.baseExtensionPoints = []; this.customExtensionPoints = []; this.baseExtensions = {}; this.customExtensions = {}; this.customConfigs = {}; this.baseConfigs = {}; this.extensionPath = context; this.contextPath = inheritContext ? context.split("/")[0] : context; var self = this; var setExtensionPointsFromExtensions = function (currentExtensions, currentExtensionPoints) { _.values(currentExtensions).forEach(function (extn) { if (extn) { var existing = self[currentExtensionPoints].filter(function (ep) { return ep.id === extn.extensionPointId; }); if (existing.length === 0) { self[currentExtensionPoints].push({ id: extn.extensionPointId, description: extn.description }); } } }); }; this.setExtensions = function (baseExtensions, customExtensions) { if (customExtensions) { setExtensionPointsFromExtensions(customExtensions, "customExtensionPoints"); self.customExtensions = customExtensions; } self.baseExtensions = baseExtensions; setExtensionPointsFromExtensions(baseExtensions, "baseExtensionPoints"); }; this.setTemplate = function (template) { self.instanceOf = template.id; self.description = self.description || template.description; self.contextModel = self.contextModel || template.contextModel; if (template.configOptions) { _.values(template.configOptions).forEach(function (opt) { var existing = self.configs.filter(function (cfg) { return cfg.name === opt.name; }); if (existing.length > 0) { existing[0].description = opt.description; } else { self.configs.push({ name: opt.name, description: opt.description, value: opt.defaultValue }); } }); } }; var setConfig = function (instance, currentConfig) { for (var configName in instance.config) { var existingConfig = getConfig(self[currentConfig], configName); if (existingConfig) { existingConfig.value = instance.config[configName]; } else { self[currentConfig][configName] = { name: configName, value: instance.config[configName] }; } } }; var setDefinitionExtensionPoints = function (extensionPoints, currentExtensionPoints) { if (extensionPoints) { extensionPoints.forEach(function (iep) { if (iep) { var existing = self[currentExtensionPoints].filter(function (ep) { return ep.id === iep.id; }); if (existing.length === 0) { self[currentExtensionPoints].push(iep); } } }); } }; this.setDefinition = function (baseInstance, customInstance) { self.instanceOf = (customInstance && customInstance.instanceOf) ? customInstance.instanceOf : baseInstance.instanceOf; self.id = (customInstance && customInstance.id) ? customInstance.id : baseInstance.id; self.description = (customInstance && customInstance.description) ? customInstance.description : baseInstance.description; self.contextModel = (customInstance && customInstance.contextModel) ? customInstance.contextModel : baseInstance.contextModel; setDefinitionExtensionPoints(baseInstance.extensionPoints, "baseExtensionPoints"); setConfig(baseInstance, "baseConfigs"); if (customInstance) { setDefinitionExtensionPoints(customInstance.extensionPoints, "customExtensionPoints"); setConfig(customInstance, "customConfigs"); } }; var getExtensions = function (extPointId, type, extensions) { var currentUser = retrieveUserCallback(); var currentExtensions = _.values(extensions); if (currentUser && currentExtensions) { var extnType = type || 'all'; var userPrivileges = currentUser.privileges.map(function (priv) { return priv.retired ? "" : priv.name; }); var appsExtns = currentExtensions.filter(function (extn) { return ((extnType === 'all') || (extn.type === extnType)) && (extn.extensionPointId === extPointId) && (!extn.requiredPrivilege || (userPrivileges.indexOf(extn.requiredPrivilege) >= 0)); }); appsExtns.sort(function (extn1, extn2) { return extn1.order - extn2.order; }); return appsExtns; } }; this.getExtensions = function (extPointId, type, shouldMerge) { if (shouldMerge || shouldMerge === undefined) { var mergedExtensions = mergeService.merge(self.baseExtensions, self.customExtensions); return getExtensions(extPointId, type, mergedExtensions); } return [getExtensions(extPointId, type, self.baseExtensions), getExtensions(extPointId, type, self.customExtensions)]; }; this.getExtensionById = function (id, shouldMerge) { if (shouldMerge || shouldMerge === undefined) { var mergedExtensions = _.values(mergeService.merge(self.baseExtensions, self.customExtensions)); return mergedExtensions.filter(function (extn) { return extn.id === id; })[0]; } else { return [self.baseExtensions.filter(function (extn) { return extn.id === id; })[0], self.customExtensions.filter(function (extn) { return extn.id === id; })[0]]; } }; var getConfig = function (config, configName) { var cfgList = _.values(config).filter(function (cfg) { return cfg.name === configName; }); return (cfgList.length > 0) ? cfgList[0] : null; }; this.getConfig = function (configName, shouldMerge) { if (shouldMerge || shouldMerge === undefined) { return getConfig(mergeService.merge(self.baseConfigs, self.customConfigs), configName); } else { return [getConfig(self.baseConfigs, configName), getConfig(self.customConfigs, configName)]; } }; this.getConfigValue = function (configName, shouldMerge) { var config = this.getConfig(configName, shouldMerge); if (shouldMerge || shouldMerge === undefined) { return config ? config.value : null; } return config; }; this.formatUrl = function (url, options, useQueryParams) { var pattern = /{{([^}]*)}}/g, matches = url.match(pattern), replacedString = url, checkQueryParams = useQueryParams || false, queryParameters = this.parseQueryParams(); if (matches) { matches.forEach(function (el) { var key = el.replace("{{", '').replace("}}", ''); var value = options[key]; if (!value && (checkQueryParams === true)) { value = queryParameters[key] || null; } replacedString = replacedString.replace(el, value); }); } return replacedString.trim(); }; this.parseQueryParams = function (locationSearchString) { var urlParams; var match, pl = /\+/g, // Regex for replacing addition symbol with a space search = /([^&=]+)=?([^&]*)/g, decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, queryString = locationSearchString || window.location.search.substring(1); urlParams = {}; while (match = search.exec(queryString)) { // eslint-disable-line no-cond-assign urlParams[decode(match[1])] = decode(match[2]); } return urlParams; }; this.addConfigForPage = function (pageName, baseConfig, customConfig) { self.basePageConfigs = self.basePageConfigs || {}; self.basePageConfigs[pageName] = baseConfig; self.customPageConfigs = self.customPageConfigs || {}; self.customPageConfigs[pageName] = customConfig; }; this.getConfigForPage = function (pageName, shouldMerge) { if (shouldMerge || shouldMerge === undefined) { return mergeService.merge(self.basePageConfigs[pageName], self.customPageConfigs[pageName]); } return [_.values(self.basePageConfigs[pageName]), _.values(self.customPageConfigs[pageName])]; }; }; 'use strict'; angular.module('bahmni.common.appFramework') .config(['$compileProvider', function ($compileProvider) { $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|file):/); }]) .service('appService', ['$http', '$q', 'sessionService', '$rootScope', 'mergeService', 'loadConfigService', 'messagingService', '$translate', function ($http, $q, sessionService, $rootScope, mergeService, loadConfigService, messagingService, $translate) { var currentUser = null; var baseUrl = Bahmni.Common.Constants.baseUrl; var customUrl = Bahmni.Common.Constants.customUrl; var appDescriptor = null; var loadConfig = function (url) { return loadConfigService.loadConfig(url, appDescriptor.contextPath); }; var loadTemplate = function (appDescriptor) { var deferrable = $q.defer(); loadConfig(baseUrl + appDescriptor.contextPath + "/appTemplate.json").then( function (result) { if (_.keys(result.data).length > 0) { appDescriptor.setTemplate(result.data); } deferrable.resolve(appDescriptor); }, function (error) { if (error.status !== 404) { deferrable.reject(error); } else { deferrable.resolve(appDescriptor); } } ); return deferrable.promise; }; var setDefinition = function (baseResultData, customResultData) { if (customResultData && (_.keys(baseResultData).length > 0 || _.keys(customResultData.length > 0))) { appDescriptor.setDefinition(baseResultData, customResultData); } else if (_.keys(baseResultData).length > 0) { appDescriptor.setDefinition(baseResultData); } }; var loadDefinition = function (appDescriptor) { var deferrable = $q.defer(); loadConfig(baseUrl + appDescriptor.contextPath + "/app.json").then( function (baseResult) { if (baseResult.data.shouldOverRideConfig) { loadConfig(customUrl + appDescriptor.contextPath + "/app.json").then(function (customResult) { setDefinition(baseResult.data, customResult.data); deferrable.resolve(appDescriptor); }, function () { setDefinition(baseResult.data); deferrable.resolve(appDescriptor); }); } else { setDefinition(baseResult.data); deferrable.resolve(appDescriptor); } }, function (error) { if (error.status !== 404) { deferrable.reject(error); } else { deferrable.resolve(appDescriptor); } }); return deferrable.promise; }; var setExtensions = function (baseResultData, customResultData) { if (customResultData) { appDescriptor.setExtensions(baseResultData, customResultData); } else { appDescriptor.setExtensions(baseResultData); } }; var loadExtensions = function (appDescriptor, extensionFileName) { var deferrable = $q.defer(); loadConfig(baseUrl + appDescriptor.extensionPath + extensionFileName).then(function (baseResult) { if (baseResult.data.shouldOverRideConfig) { loadConfig(customUrl + appDescriptor.extensionPath + extensionFileName).then( function (customResult) { setExtensions(baseResult.data, customResult.data); deferrable.resolve(appDescriptor); }, function () { setExtensions(baseResult.data); deferrable.resolve(appDescriptor); }); } else { setExtensions(baseResult.data); deferrable.resolve(appDescriptor); } }, function (error) { if (error.status !== 404) { deferrable.reject(error); } else { deferrable.resolve(appDescriptor); } }); return deferrable.promise; }; var setDefaultPageConfig = function (pageName, baseResultData, customResultData) { if (customResultData && (_.keys(customResultData).length > 0 || _.keys(baseResultData).length > 0)) { appDescriptor.addConfigForPage(pageName, baseResultData, customResultData); } else if (_.keys(baseResultData).length > 0) { appDescriptor.addConfigForPage(pageName, baseResultData); } }; var hasPrivilegeOf = function (privilegeName) { return _.some(currentUser.privileges, {name: privilegeName}); }; var loadPageConfig = function (pageName, appDescriptor) { var deferrable = $q.defer(); loadConfig(baseUrl + appDescriptor.contextPath + "/" + pageName + ".json").then( function (baseResult) { if (baseResult.data.shouldOverRideConfig) { loadConfig(customUrl + appDescriptor.contextPath + "/" + pageName + ".json").then( function (customResult) { setDefaultPageConfig(pageName, baseResult.data, customResult.data); deferrable.resolve(appDescriptor); }, function () { setDefaultPageConfig(pageName, baseResult.data); deferrable.resolve(appDescriptor); }); } else { setDefaultPageConfig(pageName, baseResult.data); deferrable.resolve(appDescriptor); } }, function (error) { if (error.status !== 404) { messagingService.showMessage('error', "Incorrect Configuration: " + error.message); deferrable.reject(error); } else { deferrable.resolve(appDescriptor); } }); return deferrable.promise; }; this.getAppDescriptor = function () { return appDescriptor; }; this.configBaseUrl = function () { return baseUrl; }; this.loadCsvFileFromConfig = function (name) { return loadConfig(baseUrl + appDescriptor.contextPath + "/" + name); }; this.loadConfig = function (name, shouldMerge) { return loadConfig(baseUrl + appDescriptor.contextPath + "/" + name).then( function (baseResponse) { if (baseResponse.data.shouldOverRideConfig) { return loadConfig(customUrl + appDescriptor.contextPath + "/" + name).then(function (customResponse) { if (shouldMerge || shouldMerge === undefined) { return mergeService.merge(baseResponse.data, customResponse.data); } return [baseResponse.data, customResponse.data]; }, function () { return baseResponse.data; }); } else { return baseResponse.data; } } ); }; this.loadMandatoryConfig = function (path) { return $http.get(path); }; this.getAppName = function () { return this.appName; }; this.checkPrivilege = function (privilegeName) { if (hasPrivilegeOf(privilegeName)) { return $q.when(true); } messagingService.showMessage("error", $translate.instant(Bahmni.Common.Constants.privilegeRequiredErrorMessage) + " [Privileges required: " + privilegeName + "]"); return $q.reject(); }; this.initApp = function (appName, options, extensionFileSuffix, configPages) { this.appName = appName; var appLoader = $q.defer(); var extensionFileName = (extensionFileSuffix && extensionFileSuffix.toLowerCase() !== 'default') ? "/extension-" + extensionFileSuffix + ".json" : "/extension.json"; var promises = []; var opts = options || {'app': true, 'extension': true}; var inheritAppContext = (!opts.inherit) ? true : opts.inherit; appDescriptor = new Bahmni.Common.AppFramework.AppDescriptor(appName, inheritAppContext, function () { return currentUser; }, mergeService); var loadCredentialsPromise = sessionService.loadCredentials(); var loadProviderPromise = loadCredentialsPromise.then(sessionService.loadProviders); promises.push(loadCredentialsPromise); promises.push(loadProviderPromise); if (opts.extension) { promises.push(loadExtensions(appDescriptor, extensionFileName)); } if (opts.template) { promises.push(loadTemplate(appDescriptor)); } if (opts.app) { promises.push(loadDefinition(appDescriptor)); } if (!_.isEmpty(configPages)) { configPages.forEach(function (configPage) { promises.push(loadPageConfig(configPage, appDescriptor)); }); } $q.all(promises).then(function (results) { currentUser = results[0]; appLoader.resolve(appDescriptor); $rootScope.$broadcast('event:appExtensions-loaded'); }, function (errors) { appLoader.reject(errors); }); return appLoader.promise; }; }]); 'use strict'; angular.module('bahmni.common.appFramework') .service('mergeService', [function () { this.merge = function (base, custom) { var mergeResult = $.extend(true, {}, base, custom); return deleteNullValuedKeys(mergeResult); }; var deleteNullValuedKeys = function (currentObject) { _.forOwn(currentObject, function (value, key) { if (_.isUndefined(value) || _.isNull(value) || _.isNaN(value) || (_.isObject(value) && _.isNull(deleteNullValuedKeys(value)))) { delete currentObject[key]; } }); return currentObject; }; }]); angular.module('bahmni.common.patient', []); 'use strict'; angular.module('bahmni.common.patient') .filter('age', function () { return function (age) { if (age.years) { return age.years + " y"; } if (age.months) { return age.months + " m"; } return age.days + " d"; }; }); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.ConceptSet = Bahmni.ConceptSet || {}; Bahmni.ConceptSet.FormConditions = Bahmni.ConceptSet.FormConditions || {}; angular.module('bahmni.common.conceptSet', ['bahmni.common.uiHelper', 'ui.select2', 'pasvaz.bindonce', 'ngSanitize', 'ngTagsInput']); 'use strict'; angular.module('bahmni.common.conceptSet') .controller('ConceptSetGroupController', ['$scope', 'contextChangeHandler', 'spinner', 'messagingService', 'conceptSetService', '$rootScope', 'sessionService', 'encounterService', 'treatmentConfig', 'retrospectiveEntryService', 'userService', 'conceptSetUiConfigService', '$timeout', 'clinicalAppConfigService', '$stateParams', '$translate', function ($scope, contextChangeHandler, spinner, messagingService, conceptSetService, $rootScope, sessionService, encounterService, treatmentConfig, retrospectiveEntryService, userService, conceptSetUiConfigService, $timeout, clinicalAppConfigService, $stateParams, $translate) { var conceptSetUIConfig = conceptSetUiConfigService.getConfig(); var init = function () { $scope.validationHandler = new Bahmni.ConceptSet.ConceptSetGroupPanelViewValidationHandler($scope.allTemplates); contextChangeHandler.add($scope.validationHandler.validate); }; $scope.toggleSideBar = function () { $rootScope.showLeftpanelToggle = !$rootScope.showLeftpanelToggle; }; $scope.showLeftpanelToggle = function () { return $rootScope.showLeftpanelToggle; }; $scope.togglePref = function (conceptSet, conceptName) { $rootScope.currentUser.toggleFavoriteObsTemplate(conceptName); spinner.forPromise(userService.savePreferences()); }; $scope.getNormalized = function (conceptName) { return conceptName.replace(/['\.\s\(\)\/,\\]+/g, "_"); }; $scope.showPreviousButton = function (conceptSetName) { return conceptSetUIConfig[conceptSetName] && conceptSetUIConfig[conceptSetName].showPreviousButton; }; $scope.showPrevious = function (conceptSetName, event) { event.stopPropagation(); $timeout(function () { $scope.$broadcast('event:showPrevious' + conceptSetName); }); }; $scope.isInEditEncounterMode = function () { return $stateParams.encounterUuid !== undefined && $stateParams.encounterUuid !== 'active'; }; $scope.computeField = function (conceptSet, event) { event.stopPropagation(); $scope.consultation.preSaveHandler.fire(); var defaultRetrospectiveVisitType = clinicalAppConfigService.getVisitTypeForRetrospectiveEntries(); var encounterData = new Bahmni.Clinical.EncounterTransactionMapper().map(angular.copy($scope.consultation), $scope.patient, sessionService.getLoginLocationUuid(), retrospectiveEntryService.getRetrospectiveEntry(), defaultRetrospectiveVisitType, $scope.isInEditEncounterMode()); encounterData = encounterService.buildEncounter(encounterData); encounterData.drugOrders = []; var conceptSetData = {name: conceptSet.conceptName, uuid: conceptSet.uuid}; var data = { encounterModifierObservations: encounterData.observations, drugOrders: encounterData.drugOrders, conceptSetData: conceptSetData, patientUuid: encounterData.patientUuid, encounterDateTime: encounterData.encounterDateTime }; spinner.forPromise(treatmentConfig().then(function (treatmentConfig) { $scope.treatmentConfiguration = treatmentConfig; return conceptSetService.getComputedValue(data); }).then(function (response) { response = response.data; copyValues($scope.consultation.observations, response.encounterModifierObservations); $scope.consultation.newlyAddedTreatments = $scope.consultation.newlyAddedTreatments || []; response.drugOrders.forEach(function (drugOrder) { $scope.consultation.newlyAddedTreatments.push(Bahmni.Clinical.DrugOrderViewModel.createFromContract(drugOrder, $scope.treatmentConfiguration)); }); })); }; $scope.canRemove = function (index) { var observations = $scope.allTemplates[index].observations; if (observations === undefined || _.isEmpty(observations)) { return true; } return observations[0].uuid === undefined; }; $scope.clone = function (index) { var clonedObj = $scope.allTemplates[index].clone(); $scope.allTemplates.splice(index + 1, 0, clonedObj); $.scrollTo('#concept-set-' + (index + 1), 200, {offset: {top: -400}}); }; $scope.clonePanelConceptSet = function (conceptSet) { var index = _.findIndex($scope.allTemplates, conceptSet); messagingService.showMessage("info", $translate.instant("CLINICAL_TEMPLATE_ADDED_SUCCESS_KEY", {label: $scope.allTemplates[index].label})); $scope.clone(index); $scope.showLeftPanelConceptSet($scope.allTemplates[index + 1]); }; $scope.isClonedSection = function (conceptSetTemplate, allTemplates) { if (allTemplates) { var index = allTemplates.indexOf(conceptSetTemplate); return (index > 0) ? allTemplates[index].label == allTemplates[index - 1].label : false; } return false; }; $scope.isLastClonedSection = function (conceptSetTemplate) { var index = _.findIndex($scope.allTemplates, conceptSetTemplate); if ($scope.allTemplates) { if (index == $scope.allTemplates.length - 1 || $scope.allTemplates[index].label != $scope.allTemplates[index + 1].label) { return true; } } return false; }; $scope.remove = function (index) { var label = $scope.allTemplates[index].label; var currentTemplate = $scope.allTemplates[index]; var anotherTemplate = _.find($scope.allTemplates, function (template) { return template.label == currentTemplate.label && template !== currentTemplate; }); if (anotherTemplate) { $scope.allTemplates.splice(index, 1); } else { var clonedObj = $scope.allTemplates[index].clone(); $scope.allTemplates[index] = clonedObj; $scope.allTemplates[index].isAdded = false; $scope.allTemplates[index].isOpen = false; $scope.allTemplates[index].klass = ""; $scope.allTemplates[index].isLoaded = false; } $scope.leftPanelConceptSet = ""; messagingService.showMessage("info", $translate.instant("CLINICAL_TEMPLATE_REMOVED_SUCCESS_KEY", {label: label})); }; $scope.openActiveForm = function (conceptSet) { if (conceptSet && conceptSet.klass == 'active' && conceptSet != $scope.leftPanelConceptSet) { $scope.showLeftPanelConceptSet(conceptSet); } return conceptSet.klass; }; var copyValues = function (existingObservations, modifiedObservations) { existingObservations.forEach(function (observation, index) { if (observation.groupMembers && observation.groupMembers.length > 0) { copyValues(observation.groupMembers, modifiedObservations[index].groupMembers); } else { observation.value = modifiedObservations[index].value; } }); }; var collapseExistingActiveSection = function (section) { if (section) { section.klass = ""; section.isOpen = false; section.isLoaded = false; } }; $scope.showLeftPanelConceptSet = function (selectedConceptSet) { collapseExistingActiveSection($scope.leftPanelConceptSet); $scope.leftPanelConceptSet = selectedConceptSet; $scope.leftPanelConceptSet.isOpen = true; $scope.leftPanelConceptSet.isLoaded = true; $scope.leftPanelConceptSet.klass = "active"; $scope.leftPanelConceptSet.atLeastOneValueIsSet = selectedConceptSet.hasSomeValue(); $scope.leftPanelConceptSet.isAdded = true; $scope.consultation.lastvisited = selectedConceptSet.id || selectedConceptSet.formUuid; $(window).scrollTop(0); }; $scope.focusOnErrors = function () { var errorMessage = $scope.leftPanelConceptSet.errorMessage ? $scope.leftPanelConceptSet.errorMessage : "{{'CLINICAL_FORM_ERRORS_MESSAGE_KEY' | translate }}"; messagingService.showMessage('error', errorMessage); $scope.$parent.$parent.$broadcast("event:errorsOnForm"); }; $scope.isFormTemplate = function (data) { return data.formUuid; }; init(); }]) .directive('conceptSetGroup', function () { return { restrict: 'EA', scope: { conceptSetGroupExtensionId: "=?", observations: "=", allTemplates: "=", context: "=", autoScrollEnabled: "=", patient: "=", consultation: "=" }, controller: 'ConceptSetGroupController', templateUrl: '../common/concept-set/views/conceptSetGroup.html' }; }); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('conceptSet', ['contextChangeHandler', 'appService', 'observationsService', 'messagingService', 'conceptSetService', 'conceptSetUiConfigService', 'spinner', function (contextChangeHandler, appService, observationsService, messagingService, conceptSetService, conceptSetUiConfigService, spinner) { var controller = function ($scope) { var conceptSetName = $scope.conceptSetName; var ObservationUtil = Bahmni.Common.Obs.ObservationUtil; var conceptSetUIConfig = conceptSetUiConfigService.getConfig(); var observationMapper = new Bahmni.ConceptSet.ObservationMapper(); var validationHandler = $scope.validationHandler() || contextChangeHandler; var id = "#" + $scope.sectionId; $scope.atLeastOneValueIsSet = $scope.atLeastOneValueIsSet || false; $scope.conceptSetRequired = false; $scope.showTitleValue = $scope.showTitle(); $scope.numberOfVisits = conceptSetUIConfig[conceptSetName] && conceptSetUIConfig[conceptSetName].numberOfVisits ? conceptSetUIConfig[conceptSetName].numberOfVisits : null; $scope.hideAbnormalButton = conceptSetUIConfig[conceptSetName] && conceptSetUIConfig[conceptSetName].hideAbnormalButton; var focusFirstObs = function () { if ($scope.conceptSetFocused && $scope.rootObservation.groupMembers && $scope.rootObservation.groupMembers.length > 0) { var firstObs = _.find($scope.rootObservation.groupMembers, function (obs) { return obs.isFormElement && obs.isFormElement(); }); if (firstObs) { firstObs.isFocused = true; } } }; var updateObservationsOnRootScope = function () { if ($scope.rootObservation) { for (var i = 0; i < $scope.observations.length; i++) { if ($scope.observations[i].concept.uuid === $scope.rootObservation.concept.uuid) { $scope.observations[i] = $scope.rootObservation; return; } } $scope.observations.push($scope.rootObservation); } }; var getObservationsOfCurrentTemplate = function () { return _.filter($scope.observations, function (observation) { return _.toLower(observation.conceptSetName) === _.toLower($scope.rootObservation.concept.name); }); }; var getDefaults = function () { var conceptSetUI = appService.getAppDescriptor().getConfigValue("conceptSetUI"); if (!conceptSetUI || !conceptSetUI.defaults) { return; } return conceptSetUI.defaults || {}; }; var getCodedAnswerWithDefaultAnswerString = function (defaults, groupMember) { var possibleAnswers = groupMember.possibleAnswers; var defaultAnswer = defaults[groupMember.concept.name]; var defaultCodedAnswer; if (defaultAnswer instanceof Array) { defaultCodedAnswer = []; _.each(defaultAnswer, function (answer) { defaultCodedAnswer.push(_.find(possibleAnswers, {displayString: answer})); }); } else { defaultCodedAnswer = _.find(possibleAnswers, {displayString: defaultAnswer}); } return defaultCodedAnswer; }; var setDefaultsForGroupMembers = function (groupMembers, defaults) { if (defaults) { _.each(groupMembers, function (groupMember) { var conceptFullName = groupMember.concept.name; var present = _.includes(_.keys(defaults), conceptFullName); if (present && groupMember.value == undefined) { if (groupMember.concept.dataType == "Coded") { setDefaultsForCodedObservations(groupMember, defaults); } else { groupMember.value = defaults[conceptFullName]; } } if (groupMember.groupMembers && groupMember.groupMembers.length > 0) { setDefaultsForGroupMembers(groupMember.groupMembers, defaults); if (groupMember instanceof Bahmni.ConceptSet.ObservationNode && defaults[groupMember.label] && groupMember.abnormalObs && groupMember.abnormalObs.value == undefined) { groupMember.onValueChanged(groupMember.value); } } }); } }; var setDefaultsForCodedObservations = function (observation, defaults) { var defaultCodedAnswer = getCodedAnswerWithDefaultAnswerString(defaults, observation); if (observation.isMultiSelect) { if (!observation.hasValue()) { _.each(defaultCodedAnswer, function (answer) { observation.selectAnswer(answer); }); } } else if (!(defaultCodedAnswer instanceof Array)) { observation.value = defaultCodedAnswer; } }; var getFlattenedObsValues = function (flattenedObs) { return _.reduce(flattenedObs, function (flattenedObsValues, obs) { if (flattenedObsValues[obs.concept.name + '|' + obs.uniqueId] == undefined) { if (obs.isMultiSelect) { var selectedObsConceptNames = []; _.each(obs.selectedObs, function (observation) { if (!observation.voided) { selectedObsConceptNames.push(observation.value.name); } if (!observation.voided) { selectedObsConceptNames.push(observation.value.name); } }); flattenedObsValues[obs.concept.name + '|' + obs.uniqueId] = selectedObsConceptNames; } else if (obs.conceptUIConfig.multiSelect) { var alreadyProcessedMultiSelect = []; _.each(_.keys(flattenedObsValues), function (eachObsKey) { eachObsKey.split('|')[0] == obs.concept.name && alreadyProcessedMultiSelect.push(eachObsKey); }); if (alreadyProcessedMultiSelect.length < 2) { flattenedObsValues[obs.concept.name + '|' + obs.uniqueId] = flattenedObsValues[obs.concept.name + '|' + undefined]; // Set the individual Observation of Multi Select to be the MultiSelect Obs } } else if (obs.value instanceof Object) { flattenedObsValues[obs.concept.name + '|' + obs.uniqueId] = (obs.value.name instanceof Object) ? obs.value.name.name : obs.value.name; } else { flattenedObsValues[obs.concept.name + '|' + obs.uniqueId] = obs.value; } } return flattenedObsValues; }, {}); }; var clearFieldValuesOnDisabling = function (obs) { obs.comment = undefined; if (obs.value || obs.isBoolean) { obs.value = undefined; } else if (obs.isMultiSelect) { for (var key in obs.selectedObs) { if (!obs.selectedObs[key].voided) { obs.toggleSelection(obs.selectedObs[key].value); } } } }; var setObservationState = function (obsArray, disable, error, hide) { if (!_.isEmpty(obsArray)) { _.each(obsArray, function (obs) { obs.disabled = disable || hide; obs.error = error; obs.hide = hide; if (hide || obs.disabled) { clearFieldValuesOnDisabling(obs); } if (obs.groupMembers) { _.each(obs.groupMembers, function (groupMember) { // TODO : Hack to fix issue with formconditions on multiselect - Swathi groupMember && setObservationState([groupMember], disable, error, hide); }); } }); } }; var processConditions = function (flattenedObs, fields, disable, error, hide) { _.each(fields, function (field) { var matchingObsArray = []; var clonedObsInSameGroup; flattenedObs.forEach(function (obs) { if (clonedObsInSameGroup != false && obs.concept.name == field) { matchingObsArray.push(obs); clonedObsInSameGroup = true; } else if (clonedObsInSameGroup && obs.concept.name != field) { clonedObsInSameGroup = false; } }); if (!_.isEmpty(matchingObsArray)) { setObservationState(matchingObsArray, disable, error, hide); } else { messagingService.showMessage("error", "No element found with name : " + field); } }); }; var runFormConditionForObs = function (enableCase, formName, formCondition, conceptName, flattenedObs) { var conceptSetObsValues = getFlattenedObsValues(flattenedObs); _.each(_.keys(conceptSetObsValues), function (eachObsKey) { if (eachObsKey.split('|')[0] == conceptName && eachObsKey.split('|')[1] != 'undefined') { var valueMap = _.reduce(conceptSetObsValues, function (conceptSetValueMap, obsValue, conceptName) { conceptSetValueMap[conceptName.split('|')[0]] = obsValue; return conceptSetValueMap; }, {}); var conditions = formCondition(formName, valueMap, $scope.patient); if (!_.isUndefined(conditions)) { if (conditions.error && !_.isEmpty(conditions.error)) { messagingService.showMessage('error', conditions.error); processConditions(flattenedObs, [conceptName], false, true, false); } else { enableCase && processConditions(flattenedObs, [conceptName], false, false, false); } processConditions(flattenedObs, conditions.disable, true); processConditions(flattenedObs, conditions.enable, false); processConditions(flattenedObs, conditions.show, false, undefined, false); processConditions(flattenedObs, conditions.hide, false, undefined, true); _.each(conditions.enable, function (subConditionConceptName) { var conditionFn = Bahmni.ConceptSet.FormConditions.rules && Bahmni.ConceptSet.FormConditions.rules[subConditionConceptName]; if (conditionFn != null) { runFormConditionForObs(true, formName, conditionFn, subConditionConceptName, flattenedObs); } }); _.each(conditions.disable, function (subConditionConceptName) { var conditionFn = Bahmni.ConceptSet.FormConditions.rules && Bahmni.ConceptSet.FormConditions.rules[subConditionConceptName]; if (conditionFn != null) { _.each(flattenedObs, function (obs) { if (obs.concept.name == subConditionConceptName) { runFormConditionForObs(false, formName, conditionFn, subConditionConceptName, flattenedObs); } }); } }); _.each(conditions.show, function (subConditionConceptName) { var conditionFn = Bahmni.ConceptSet.FormConditions.rules && Bahmni.ConceptSet.FormConditions.rules[subConditionConceptName]; if (conditionFn) { runFormConditionForObs(true, formName, conditionFn, subConditionConceptName, flattenedObs); } }); _.each(conditions.hide, function (subConditionConceptName) { var conditionFn = Bahmni.ConceptSet.FormConditions.rules && Bahmni.ConceptSet.FormConditions.rules[subConditionConceptName]; if (conditionFn) { _.each(flattenedObs, function (obs) { if (obs.concept.name == subConditionConceptName) { runFormConditionForObs(false, formName, conditionFn, subConditionConceptName, flattenedObs); } }); } }); } } }); }; var updateFormConditions = function (observationsOfCurrentTemplate, rootObservation) { if (Bahmni.ConceptSet.FormConditions.rules) { runFormConditionForAllObsRecursively(rootObservation.concept.name, rootObservation); } }; var runFormConditionForAllObsRecursively = function (formName, rootObservation) { _.each(rootObservation.groupMembers, function (observation) { var conditionFn = Bahmni.ConceptSet.FormConditions.rules && Bahmni.ConceptSet.FormConditions.rules[observation.concept.name]; if (conditionFn != null) { var flattenedObs = ObservationUtil.flattenObsToArray([rootObservation]); runFormConditionForObs(false, formName, conditionFn, observation.concept.name, flattenedObs); } if (observation.groupMembers && observation.groupMembers.length > 0) { runFormConditionForAllObsRecursively(formName, observation); } }); }; var addDummyImage = function () { _.each($scope.rootObservation.groupMembers, function (observation) { addDummyImageObservationForSavedObs(observation, $scope.rootObservation); }); }; var addDummyImageObservationForSavedObs = function (observation, rootObservation) { _.each(observation.groupMembers, function (childObservation) { addDummyImageObservationForSavedObs(childObservation, observation); }); if (observation.getControlType() === 'image' && observation.value && rootObservation.groupMembers.indexOf(observation) === rootObservation.groupMembers.length - 1) { rootObservation.groupMembers.push(observation.cloneNew()); return; } }; var init = function () { return conceptSetService.getConcept({ name: conceptSetName, v: "bahmni" }).then(function (response) { $scope.conceptSet = response.data.results[0]; $scope.rootObservation = $scope.conceptSet ? observationMapper.map($scope.observations, $scope.conceptSet, conceptSetUIConfig) : null; if ($scope.rootObservation) { $scope.rootObservation.conceptSetName = $scope.conceptSetName; focusFirstObs(); updateObservationsOnRootScope(); var groupMembers = getObservationsOfCurrentTemplate()[0].groupMembers; var defaults = getDefaults(); addDummyImage(); setDefaultsForGroupMembers(groupMembers, defaults); var observationsOfCurrentTemplate = getObservationsOfCurrentTemplate(); updateFormConditions(observationsOfCurrentTemplate, $scope.rootObservation); } else { $scope.showEmptyConceptSetMessage = true; } }).catch(function (error) { messagingService.showMessage('error', error.message); }); }; spinner.forPromise(init(), id); var validateObservationTree = function () { if (typeof $scope.rootObservation === "undefined" || $scope.rootObservation === null) { return {allow: true, errorMessage: null }; } $scope.atLeastOneValueIsSet = $scope.rootObservation && $scope.rootObservation.atLeastOneValueSet(); $scope.conceptSetRequired = $scope.required ? $scope.required : true; var nodes = $scope.rootObservation && findInvalidNodes($scope.rootObservation.groupMembers, $scope.rootObservation); return {allow: !nodes.status, errorMessage: nodes.message}; }; // TODO: Write unit test for this function var findInvalidNodes = function (members, parentNode) { var errorMessage = null; var status = members.some(function (childNode) { if (childNode.voided) { return false; } var groupMembers = childNode.groupMembers || []; for (var index in groupMembers) { var information = groupMembers[index].groupMembers && groupMembers[index].groupMembers.length ? findInvalidNodes(groupMembers[index].groupMembers, groupMembers[index]) : validateChildNode(groupMembers[index], childNode); if (information.status) { errorMessage = information.message; return true; } } information = validateChildNode(childNode, parentNode); if (information.status) { errorMessage = information.message; return true; } return !childNode.isValid($scope.atLeastOneValueIsSet, $scope.conceptSetRequired); }); return {message: errorMessage, status: status}; }; var validateChildNode = function (childNode, parentNode) { var errorMessage; if (childNode.possibleAnswers && !childNode.possibleAnswers.length) { if (typeof childNode.isValueInAbsoluteRange == 'function' && !childNode.isValueInAbsoluteRange()) { errorMessage = "The value you entered (red field) is outside the range of allowable values for that record. Please check the value."; return {message: errorMessage, status: true}; } if (childNode.isNumeric()) { if (!childNode.isValidNumeric()) { errorMessage = "Please enter Integer value, decimal value is not allowed"; return {message: errorMessage, status: true}; } if (parentNode) { if (!childNode.isValidNumericValue() || !parentNode.isValidNumericValue()) { errorMessage = "Please enter Numeric values"; return {message: errorMessage, status: true}; } } else { if (!childNode.isValidNumericValue()) { errorMessage = "Please enter Numeric values"; return {message: errorMessage, status: true}; } } } } return {status: false}; }; validationHandler.add(validateObservationTree); var cleanUpListenerShowPrevious = $scope.$on('event:showPrevious' + conceptSetName, function () { return spinner.forPromise(observationsService.fetch($scope.patient.uuid, $scope.conceptSetName, null, $scope.numberOfVisits, null, true), id).then(function (response) { var recentObservations = ObservationUtil.flattenObsToArray(response.data); var conceptSetObservation = $scope.observations.filter(function (observation) { return observation.conceptSetName === $scope.conceptSetName; }); ObservationUtil.flattenObsToArray(conceptSetObservation).forEach(function (obs) { var correspondingRecentObs = _.filter(recentObservations, function (recentObs) { return obs.concept.uuid === recentObs.concept.uuid; }); if (correspondingRecentObs != null && correspondingRecentObs.length > 0) { correspondingRecentObs.sort(function (obs1, obs2) { return new Date(obs2.encounterDateTime) - new Date(obs1.encounterDateTime); }); obs.previous = correspondingRecentObs.map(function (previousObs) { return { value: Bahmni.Common.Domain.ObservationValueMapper.map(previousObs), date: previousObs.observationDateTime }; }); } }); }); }); var deregisterAddMore = $scope.$root.$on("event:addMore", function (event, observation) { updateFormConditions([observation], observation); }); var deregisterObservationUpdated = $scope.$root.$on("event:observationUpdated-" + conceptSetName, function (event, conceptName, rootObservation) { var formName = rootObservation.concept.name; var formCondition = Bahmni.ConceptSet.FormConditions.rules && Bahmni.ConceptSet.FormConditions.rules[conceptName]; if (formCondition) { var flattenedObs = ObservationUtil.flattenObsToArray([rootObservation]); runFormConditionForObs(true, formName, formCondition, conceptName, flattenedObs); } }); $scope.$on('$destroy', function () { deregisterObservationUpdated(); deregisterAddMore(); cleanUpListenerShowPrevious(); }); }; return { restrict: 'E', scope: { conceptSetName: "=", observations: "=?", required: "=?", showTitle: "&", validationHandler: "&", patient: "=", conceptSetFocused: "=?", collapseInnerSections: "=?", atLeastOneValueIsSet: "=?", sectionId: "=" }, templateUrl: '../common/concept-set/views/conceptSet.html', controller: controller }; }]); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('formControls', ['formService', 'spinner', '$timeout', '$translate', function (formService, spinner, $timeout, $translate) { var loadedFormDetails = {}; var loadedFormTranslations = {}; var unMountReactContainer = function (formUuid) { var reactContainerElement = angular.element(document.getElementById(formUuid)); reactContainerElement.on('$destroy', function () { unMountForm(document.getElementById(formUuid)); }); }; var controller = function ($scope) { var formUuid = $scope.form.formUuid; var formVersion = $scope.form.formVersion; var formName = $scope.form.formName; var formObservations = $scope.form.observations; 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) { var formDetailsAsString = _.get(response, 'data.resources[0].value'); if (formDetailsAsString) { var formDetails = JSON.parse(formDetailsAsString); formDetails.version = formVersion; loadedFormDetails[formUuid] = formDetails; var formParams = { formName: formName, formVersion: formVersion, locale: locale, formUuid: formDetails.uuid }; spinner.forPromise(formService.getFormTranslations(formDetails.translationsUrl, formParams) .then(function (response) { var formTranslations = !_.isEmpty(response.data) ? response.data[0] : {}; loadedFormTranslations[formUuid] = formTranslations; $scope.form.component = renderWithControls(formDetails, formObservations, formUuid, collapse, $scope.patient, validateForm, locale, formTranslations); }, function () { var formTranslations = {}; loadedFormTranslations[formUuid] = formTranslations; $scope.form.component = renderWithControls(formDetails, formObservations, formUuid, collapse, $scope.patient, validateForm, locale, formTranslations); }) ); } unMountReactContainer($scope.form.formUuid); }) ); } else { $timeout(function () { $scope.form.component = renderWithControls(loadedFormDetails[formUuid], formObservations, formUuid, collapse, $scope.patient, validateForm, locale, loadedFormTranslations[formUuid]); unMountReactContainer($scope.form.formUuid); }, 0, false); } $scope.$watch('form.collapseInnerSections', function () { var collapse = $scope.form.collapseInnerSections && $scope.form.collapseInnerSections.value; if (loadedFormDetails[formUuid]) { $scope.form.component = renderWithControls(loadedFormDetails[formUuid], formObservations, 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; } } } }); }; return { restrict: 'E', scope: { form: "=", patient: "=", validateForm: "=" }, controller: controller }; }]); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('concept', ['RecursionHelper', 'spinner', '$filter', 'messagingService', function (RecursionHelper, spinner, $filter, messagingService) { var link = function (scope) { var hideAbnormalbuttonConfig = scope.observation && scope.observation.conceptUIConfig && scope.observation.conceptUIConfig['hideAbnormalButton']; scope.now = moment().format("YYYY-MM-DD hh:mm:ss"); scope.showTitle = scope.showTitle === undefined ? true : scope.showTitle; scope.hideAbnormalButton = hideAbnormalbuttonConfig == undefined ? scope.hideAbnormalButton : hideAbnormalbuttonConfig; scope.cloneNew = function (observation, parentObservation) { observation.showAddMoreButton = function () { return false; }; var newObs = observation.cloneNew(); newObs.scrollToElement = true; var index = parentObservation.groupMembers.indexOf(observation); parentObservation.groupMembers.splice(index + 1, 0, newObs); messagingService.showMessage("info", "A new " + observation.label + " section has been added"); scope.$root.$broadcast("event:addMore", newObs); }; scope.removeClonedObs = function (observation, parentObservation) { observation.voided = true; var lastObservationByLabel = _.findLast(parentObservation.groupMembers, function (groupMember) { return groupMember.label === observation.label && !groupMember.voided; }); lastObservationByLabel.showAddMoreButton = function () { return true; }; observation.hidden = true; }; scope.isClone = function (observation, parentObservation) { if (parentObservation && parentObservation.groupMembers) { var index = parentObservation.groupMembers.indexOf(observation); return (index > 0) ? parentObservation.groupMembers[index].label == parentObservation.groupMembers[index - 1].label : false; } return false; }; scope.isRemoveValid = function (observation) { if (observation.getControlType() == 'image') { return !observation.value; } return true; }; scope.getStringValue = function (observations) { return observations.map(function (observation) { return observation.value + ' (' + $filter('bahmniDate')(observation.date) + ")"; }).join(", "); }; scope.toggleSection = function () { scope.collapse = !scope.collapse; }; scope.isCollapsibleSet = function () { return scope.showTitle == true; }; scope.hasPDFAsValue = function () { return scope.observation.value && (scope.observation.value.indexOf(".pdf") > 0); }; scope.$watch('collapseInnerSections', function () { scope.collapse = scope.collapseInnerSections && scope.collapseInnerSections.value; }); scope.handleUpdate = function () { scope.$root.$broadcast("event:observationUpdated-" + scope.conceptSetName, scope.observation.concept.name, scope.rootObservation); }; scope.update = function (value) { if (scope.getBooleanResult(scope.observation.isObservationNode)) { scope.observation.primaryObs.value = value; } else if (scope.getBooleanResult(scope.observation.isFormElement())) { scope.observation.value = value; } scope.handleUpdate(); }; scope.getBooleanResult = function (value) { return !!value; }; }; var compile = function (element) { return RecursionHelper.compile(element, link); }; return { restrict: 'E', compile: compile, scope: { conceptSetName: "=", observation: "=", atLeastOneValueIsSet: "=", showTitle: "=", conceptSetRequired: "=", rootObservation: "=", patient: "=", collapseInnerSections: "=", rootConcept: "&", hideAbnormalButton: "=" }, templateUrl: '../common/concept-set/views/observation.html' }; }]); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('buttonSelect', function () { return { restrict: 'E', scope: { observation: '=', abnormalObs: '=?' }, link: function (scope, element, attrs) { if (attrs.dirtyCheckFlag) { scope.hasDirtyFlag = true; } }, controller: function ($scope) { $scope.isSet = function (answer) { return $scope.observation.hasValueOf(answer); }; $scope.select = function (answer) { $scope.observation.toggleSelection(answer); if ($scope.$parent.observation && typeof $scope.$parent.observation.onValueChanged == 'function') { $scope.$parent.observation.onValueChanged(); } $scope.$parent.handleUpdate(); }; $scope.getAnswerDisplayName = function (answer) { var shortName = answer.names ? _.first(answer.names.filter(function (name) { return name.conceptNameType === 'SHORT'; })) : null; return shortName ? shortName.name : answer.displayString; }; }, templateUrl: '../common/concept-set/views/buttonSelect.html' }; }); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('stepper', function () { return { restrict: 'E', require: 'ngModel', replace: true, scope: { ngModel: '=', obs: '=', ngClass: '=', focusMe: '=' }, template: '
' + '' + '' + '' + '
', link: function (scope, element, attrs, ngModelController) { // Specify how UI should be updated ngModelController.$render = function () { // element.html(ngModelController.$viewValue || ''); }; // when model change, cast to integer ngModelController.$formatters.push(function (value) { return parseInt(value, 10); }); // when view change, cast to integer ngModelController.$parsers.push(function (value) { return parseInt(value, 10); }); scope.increment = function () { if (scope.obs.concept.hiNormal != null) { var currValue = (isNaN(ngModelController.$viewValue) ? 0 : ngModelController.$viewValue); if (currValue < scope.obs.concept.hiNormal) { updateModel(+1); } } else { updateModel(+1); } }; scope.decrement = function () { if (scope.obs.concept.lowNormal != null) { var currValue = (isNaN(ngModelController.$viewValue) ? 0 : ngModelController.$viewValue); if (currValue > scope.obs.concept.lowNormal) { updateModel(-1); } } else { updateModel(-1); } }; function updateModel (offset) { var currValue = 0; if (isNaN(ngModelController.$viewValue)) { if (scope.obs.concept.lowNormal != null) { currValue = scope.obs.concept.lowNormal - offset; // To mention the start point for Plus And Minus // if - or + is pressed on empty field, set them with low value or 0 } } else { currValue = parseInt(ngModelController.$viewValue); } ngModelController.$setViewValue(currValue + offset); } } }; }); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('obsConstraints', function () { var attributesMap = {'Numeric': 'number', 'Date': 'date', 'Datetime': 'datetime'}; var link = function ($scope, element) { var attributes = {}; var obsConcept = $scope.obs.concept; if (obsConcept.conceptClass == Bahmni.Common.Constants.conceptDetailsClassName) { obsConcept = $scope.obs.primaryObs.concept; } attributes['type'] = attributesMap[obsConcept.dataType] || "text"; if (attributes['type'] === 'number') { attributes['step'] = 'any'; } if (obsConcept.hiNormal) { attributes['max'] = obsConcept.hiNormal; } if (obsConcept.lowNormal) { attributes['min'] = obsConcept.lowNormal; } if (attributes['type'] == 'date') { if ($scope.obs.conceptUIConfig == null || !$scope.obs.conceptUIConfig['allowFutureDates']) { attributes['max'] = Bahmni.Common.Util.DateTimeFormatter.getDateWithoutTime(); } } element.attr(attributes); }; return { link: link, scope: { obs: '=' }, require: 'ngModel' }; }); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('duration', ['contextChangeHandler', function (contextChangeHandler) { var link = function ($scope, element, attrs, ngModelController) { var setValue = function () { if ($scope.unitValue && $scope.measureValue) { var value = $scope.unitValue * $scope.measureValue; ngModelController.$setViewValue(value); } else { ngModelController.$setViewValue(undefined); } }; $scope.$watch('measureValue', setValue); $scope.$watch('unitValue', setValue); $scope.$watch('disabled', function (value) { if (value) { $scope.unitValue = undefined; $scope.measureValue = undefined; $scope.hours = undefined; } }); var illegalValueChecker = $scope.$watch('illegalValue', function (value) { $scope.illegalDurationValue = value; var contextChange = function () { return {allow: !$scope.illegalDurationValue}; }; contextChangeHandler.add(contextChange); }); $scope.$on('$destroy', function () { $scope.illegalDurationValue = false; illegalValueChecker(); }); }; var controller = function ($scope) { var valueAndUnit = Bahmni.Common.Util.DateUtil.convertToUnits($scope.hours); $scope.units = valueAndUnit["allUnits"]; $scope.measureValue = valueAndUnit["value"]; $scope.unitValue = valueAndUnit["unitValueInMinutes"]; var durations = Object.keys($scope.units).reverse(); $scope.displayUnits = durations.map(function (duration) { return {"name": duration, "value": $scope.units[duration]}; }); }; return { restrict: 'E', require: 'ngModel', controller: controller, scope: { hours: "=ngModel", illegalValue: "=", disabled: "=" }, link: link, template: '' + '' }; }]); 'use strict'; angular.module('bahmni.common.conceptSet') .directive('latestObs', function () { var controller = function ($scope, observationsService, $q, spinner) { var init = function () { spinner.forPromise(observationsService.fetch($scope.patientUuid, $scope.conceptNames, "latest").then(function (response) { var observations = new Bahmni.Common.Obs.ObservationMapper().map(response.data, []); $scope.observations = _.sortBy(observations, 'sortWeight'); })); }; init(); }; return { restrict: 'E', controller: controller, templateUrl: '../common/concept-set/views/latestObs.html', scope: { patientUuid: "=", conceptNames: "=" } }; }); 'use strict'; Bahmni.ConceptSet.ConceptSetGroupValidationHandler = function (conceptSetSections) { var validations = []; this.add = function (validation) { validations.push(validation); }; this.validate = function () { var errorMessage = ""; var allConceptSetSectionsValid = true; validations.forEach(function (validation) { var validationReturn = validation(); if (_.isEmpty(errorMessage)) { errorMessage = validationReturn["errorMessage"]; } allConceptSetSectionsValid = allConceptSetSectionsValid && validationReturn["allow"]; }); if (!allConceptSetSectionsValid) { conceptSetSections.filter(_.property('isLoaded')).forEach(function (conceptSetSection) { conceptSetSection.show(); }); } return {allow: allConceptSetSectionsValid, errorMessage: errorMessage}; }; }; 'use strict'; Bahmni.ConceptSet.Observation = function (observation, savedObs, conceptUIConfig) { var self = this; angular.extend(this, observation); this.isObservation = true; this.conceptUIConfig = conceptUIConfig[this.concept.name] || []; this.uniqueId = _.uniqueId('observation_'); this.erroneousValue = null; if (savedObs) { this.uuid = savedObs.uuid; this.value = savedObs.value; this.observationDateTime = savedObs.observationDateTime; this.provider = savedObs.provider; } else { this.value = this.conceptUIConfig.defaultValue; } Object.defineProperty(this, 'autocompleteValue', { enumerable: true, get: function () { return (this.value != null && (typeof this.value === "object")) ? this.value.name : this.value; }, set: function (newValue) { this.__prevValue = this.value; this.value = newValue; } }); Object.defineProperty(this, 'value', { enumerable: true, get: function () { if (self._value != null) { return self._value; } if (savedObs) { if (typeof (savedObs.value) === "object" && savedObs.value) { savedObs.value['displayString'] = (savedObs.value.shortName ? savedObs.value.shortName : savedObs.value.name); } } return savedObs ? savedObs.value : undefined; }, set: function (newValue) { self.__prevValue = this.value; self._value = newValue; if (!newValue) { savedObs = null; } self.onValueChanged(); } }); var cloneNonTabularObs = function (oldObs) { var newGroupMembers = []; oldObs.groupMembers.forEach(function (member) { if (member.isTabularObs === undefined) { var clone = member.cloneNew(); clone.hidden = member.hidden; newGroupMembers.push(clone); } }); return newGroupMembers; }; var getTabularObs = function (oldObs) { var tabularObsList = []; oldObs.groupMembers.forEach(function (member) { if (member.isTabularObs !== undefined) { tabularObsList.push(member); } }); return tabularObsList; }; var cloneTabularObs = function (oldObs, tabularObsList) { tabularObsList = _.map(tabularObsList, function (tabularObs) { var matchingObsList = _.filter(oldObs.groupMembers, function (member) { return member.concept.name == tabularObs.concept.name; }); return new Bahmni.ConceptSet.TabularObservations(matchingObsList, oldObs, conceptUIConfig); }); tabularObsList.forEach(function (tabularObs) { oldObs.groupMembers.push(tabularObs); }); return oldObs; }; this.cloneNew = function () { var oldObs = angular.copy(observation); if (oldObs.groupMembers && oldObs.groupMembers.length > 0) { oldObs.groupMembers = _.filter(oldObs.groupMembers, function (member) { return !member.isMultiSelect; }); var newGroupMembers = cloneNonTabularObs(oldObs); var tabularObsList = getTabularObs(oldObs); oldObs.groupMembers = newGroupMembers; if (!_.isEmpty(tabularObsList)) { oldObs = cloneTabularObs(oldObs, tabularObsList); } } new Bahmni.ConceptSet.MultiSelectObservations(conceptUIConfig).map(oldObs.groupMembers); var clone = new Bahmni.ConceptSet.Observation(oldObs, null, conceptUIConfig); clone.comment = undefined; clone.disabled = this.disabled; return clone; }; }; Bahmni.ConceptSet.Observation.prototype = { displayValue: function () { if (this.possibleAnswers.length > 0) { for (var i = 0; i < this.possibleAnswers.length; i++) { if (this.possibleAnswers[i].uuid === this.value) { return this.possibleAnswers[i].display; } } } else { return this.value; } }, isGroup: function () { if (this.groupMembers) { return this.groupMembers.length > 0; } return false; }, isComputed: function () { return this.concept.conceptClass === "Computed"; }, isComputedAndEditable: function () { return this.concept.conceptClass === "Computed/Editable"; }, isNumeric: function () { return this.getDataTypeName() === "Numeric"; }, isValidNumeric: function () { if (!this.isDecimalAllowed()) { if (this.value && this.value.toString().indexOf('.') >= 0) { return false; } } return true; }, isValidNumericValue: function () { var element = document.getElementById(this.uniqueId); if (this.value === "" && element) { return element.checkValidity(); } return true; }, isText: function () { return this.getDataTypeName() === "Text"; }, isCoded: function () { return this.getDataTypeName() === "Coded"; }, isDatetime: function () { return this.getDataTypeName() === "Datetime"; }, isImage: function () { return this.concept.conceptClass == Bahmni.Common.Constants.imageClassName; }, isVideo: function () { return this.concept.conceptClass == Bahmni.Common.Constants.videoClassName; }, getDataTypeName: function () { return this.concept.dataType; }, isDecimalAllowed: function () { return this.concept.allowDecimal; }, isDateDataType: function () { return 'Date'.indexOf(this.getDataTypeName()) != -1; }, isVoided: function () { return this.voided === undefined ? false : this.voided; }, getPossibleAnswers: function () { return this.possibleAnswers; }, getHighAbsolute: function () { return this.concept.hiAbsolute; }, getLowAbsolute: function () { return this.concept.lowAbsolute; }, isHtml5InputDataType: function () { return ['Date', 'Numeric'].indexOf(this.getDataTypeName()) !== -1; }, isGrid: function () { return this.conceptUIConfig.grid; }, isButtonRadio: function () { return this.conceptUIConfig.buttonRadio; }, isComplex: function () { return this.concept.dataType === "Complex"; }, isLocationRef: function () { return this.isComplex() && this.concept.handler === "LocationObsHandler"; }, isProviderRef: function () { return this.isComplex() && this.concept.handler === "ProviderObsHandler"; }, getControlType: function () { if (this.hidden) { return "hidden"; } if (this.conceptUIConfig.freeTextAutocomplete) { return "freeTextAutocomplete"; } if (this.isHtml5InputDataType()) { return "html5InputDataType"; } if (this.isImage()) { return "image"; } if (this.isVideo()) { return "video"; } if (this.isText()) { return "text"; } if (this.isCoded()) { return this._getCodedControlType(); } if (this.isGrid()) { return "grid"; } if (this.isDatetime()) { return "datetime"; } if (this.isLocationRef()) { return "text"; } if (this.isProviderRef()) { return "text"; } return "unknown"; }, canHaveComment: function () { return this.conceptUIConfig.disableAddNotes ? !this.conceptUIConfig.disableAddNotes : (!this.isText() && !this.isImage() && !this.isVideo()); }, canAddMore: function () { return this.conceptUIConfig.allowAddMore == true; }, isStepperControl: function () { if (this.isNumeric()) { return this.conceptUIConfig.stepper == true; } }, isConciseText: function () { return this.conceptUIConfig.conciseText == true; }, _getCodedControlType: function () { var conceptUIConfig = this.conceptUIConfig; if (conceptUIConfig.autocomplete) { return "autocomplete"; } if (conceptUIConfig.dropdown) { return "dropdown"; } return "buttonselect"; }, onValueChanged: function () { if (this.isNumeric()) { this.setErroneousValue(); } }, setErroneousValue: function () { if (this.hasValue()) { var erroneousValue = this.value > (this.concept.hiAbsolute || Infinity) || this.value < (this.concept.lowAbsolute || 0); this.erroneousValue = erroneousValue; } else { this.erroneousValue = undefined; } }, getInputType: function () { return this.getDataTypeName(); }, atLeastOneValueSet: function () { if (this.isGroup()) { return this.groupMembers.some(function (childNode) { return childNode.atLeastOneValueSet(); }); } else { return this.hasValue() && !this.isVoided(); } }, hasValue: function () { var value = this.value; if (value === false) { return true; } if (value === 0) { return true; } //! value ignores 0 if (value === '' || !value) { return false; } if (value instanceof Array) { return value.length > 0; } return true; }, hasValueOf: function (value) { if (!this.value || !value) { return false; } return this.value == value || this.value.uuid == value.uuid; }, toggleSelection: function (answer) { if (this.value && this.value.uuid === answer.uuid) { this.value = null; } else { this.value = answer; } }, isValidDate: function () { if (this.isComputed()) { return true; } if (!this.hasValue()) { return true; } var date = Bahmni.Common.Util.DateUtil.parse(this.value); if (!this.conceptUIConfig.allowFutureDates) { var today = Bahmni.Common.Util.DateUtil.parse(moment().format("YYYY-MM-DD")); if (today < date) { return false; } } return date.getUTCFullYear() && date.getUTCFullYear().toString().length <= 4; }, hasInvalidDateTime: function () { if (this.isComputed()) { return false; } var date = Bahmni.Common.Util.DateUtil.parse(this.value); if (!this.conceptUIConfig.allowFutureDates) { if (moment() < date) { return true; } } return this.value === "Invalid Datetime"; }, isValid: function (checkRequiredFields, conceptSetRequired) { if (this.isNumeric() && !this.isValidNumeric()) { return false; } if (this.error) { return false; } if (this.hidden) { return true; } if (checkRequiredFields) { if (this.isGroup()) { return this._hasValidChildren(checkRequiredFields, conceptSetRequired); } if (conceptSetRequired && this.isRequired() && !this.hasValue()) { return false; } if (this.isRequired() && !this.hasValue()) { return false; } } if (this._isDateDataType()) { return this.isValidDate(); } if (this._isDateTimeDataType()) { return !this.hasInvalidDateTime(); } if (this.erroneousValue) { return false; } if (this.getControlType() === 'autocomplete') { return _.isEmpty(this.value) || _.isObject(this.value); } return true; }, isValueInAbsoluteRange: function () { if (this.erroneousValue) { return false; } if (this.isGroup()) { return this._areChildNodesInAbsoluteRange(); } return true; }, _isDateDataType: function () { return this.getDataTypeName() === 'Date'; }, _isDateTimeDataType: function () { return this.getDataTypeName() === "Datetime"; }, isRequired: function () { this.disabled = this.disabled ? this.disabled : false; return this.conceptUIConfig.required === true && this.disabled === false; }, isFormElement: function () { return (!this.concept.set || this.isGrid()) && !this.isComputed(); }, _hasValidChildren: function (checkRequiredFields, conceptSetRequired) { return this.groupMembers.every(function (member) { return member.isValid(checkRequiredFields, conceptSetRequired); }); }, _areChildNodesInAbsoluteRange: function () { return this.groupMembers.every(function (member) { // Other than Bahmni.ConceptSet.Observation and Bahmni.ConceptSet.ObservationNode, other concepts does not have isValueInAbsoluteRange fn return (typeof member.isValueInAbsoluteRange == 'function') ? member.isValueInAbsoluteRange() : true; }); }, markAsNonCoded: function () { this.markedAsNonCoded = !this.markedAsNonCoded; }, toggleVoidingOfImage: function () { this.voided = !this.voided; }, assignAddMoreButtonID: function () { return this.concept.name.split(' ').join('_').toLowerCase() + '_addmore_' + this.uniqueId; } }; 'use strict'; Bahmni.ConceptSet.BooleanObservation = function (observation, conceptUIConfig) { angular.extend(this, observation); this.isBoolean = true; this.conceptUIConfig = conceptUIConfig[this.concept.name] || {}; this.cloneNew = function () { var clone = new Bahmni.ConceptSet.BooleanObservation(angular.copy(observation), conceptUIConfig); clone.value = undefined; clone.comment = undefined; clone.uuid = null; clone.disabled = this.disabled; return clone; }; var possibleAnswers = [ {displayString: "OBS_BOOLEAN_YES_KEY", value: true}, {displayString: "OBS_BOOLEAN_NO_KEY", value: false} ]; this.getPossibleAnswers = function () { return possibleAnswers; }; this.hasValueOf = function (answer) { return this.value === answer.value; }; this.toggleSelection = function (answer) { if (this.value === answer.value) { this.value = null; } else { this.value = answer.value; } }; this.isFormElement = function () { return true; }; this.getControlType = function () { return "buttonselect"; }; this.isRequired = function () { this.disabled = this.disabled ? this.disabled : false; return this.getConceptUIConfig().required === true && this.disabled === false; }; this.isComputedAndEditable = function () { return this.concept.conceptClass === "Computed/Editable"; }; this.atLeastOneValueSet = function () { return (this.value != undefined); }; this.isValid = function (checkRequiredFields, conceptSetRequired) { if (this.error) { return false; } var notYetSet = function (value) { return (typeof value == 'undefined' || value == null); }; if (checkRequiredFields) { if (conceptSetRequired && this.isRequired() && notYetSet(this.value)) { return false; } if (this.isRequired() && notYetSet(this.value)) { return false; } } return true; }; this.canHaveComment = function () { return this.getConceptUIConfig().disableAddNotes ? !this.getConceptUIConfig().disableAddNotes : true; }; this.getConceptUIConfig = function () { return this.conceptUIConfig; }; this.canAddMore = function () { return this.getConceptUIConfig().allowAddMore == true; }; this.isComputed = function () { return this.concept.conceptClass === "Computed"; }; this.getDataTypeName = function () { return this.concept.dataType; }; this.hasValue = function () { var value = this.value; if (value === false) { return true; } if (value === 0) { return true; } //! value ignores 0 if (value === '' || !value) { return false; } if (value instanceof Array) { return value.length > 0; } return true; }; this.isNumeric = function () { return this.getDataTypeName() === "Numeric"; }; this.isText = function () { return this.getDataTypeName() === "Text"; }; this.isCoded = function () { return this.getDataTypeName() === "Coded"; }; this._isDateTimeDataType = function () { return this.getDataTypeName() === "Datetime"; }; }; 'use strict'; (function () { var findObservationByClassName = function (groupMembers, conceptClassName) { return _.find(groupMembers, function (member) { return (member.concept.conceptClass.name === conceptClassName) || (member.concept.conceptClass === conceptClassName); }); }; var findObservationByConceptName = function (groupMembers, conceptName) { return _.find(groupMembers, {concept: {name: conceptName}}); }; var setNewObservation = function (observation, newValue) { if (observation) { observation.__prevValue = observation.value; observation.value = newValue; observation.voided = false; } }; var voidObservation = function (observation) { if (observation) { if (observation.uuid) { observation.voided = true; } else { observation.value = undefined; } } }; var isFreeTextAutocompleteType = function (conceptUIConfig) { return conceptUIConfig.autocomplete && conceptUIConfig.nonCodedConceptName && conceptUIConfig.codedConceptName; }; Bahmni.ConceptSet.ObservationNode = function (observation, savedObs, conceptUIConfig, concept) { angular.extend(this, observation); this.conceptUIConfig = conceptUIConfig[concept.name.name] || (!_.isEmpty(concept.setMembers) && conceptUIConfig[concept.setMembers[0].name.name]) || {}; this.cloneNew = function () { var oldObs = angular.copy(observation); oldObs.groupMembers = _.map(oldObs.groupMembers, function (member) { return member.cloneNew(); }); var clone = new Bahmni.ConceptSet.ObservationNode(oldObs, null, conceptUIConfig, concept); clone.comment = undefined; return clone; }; var getPrimaryObservationValue = function () { return this.primaryObs && _.get(this, 'primaryObs.value.name') || _.get(this, 'primaryObs.value'); }; var setFreeTextPrimaryObservationValue = function (newValue) { var codedObservation = findObservationByConceptName(this.groupMembers, this.conceptUIConfig.codedConceptName); var nonCodedObservation = findObservationByConceptName(this.groupMembers, this.conceptUIConfig.nonCodedConceptName); if (typeof newValue === "object") { setNewObservation(codedObservation, newValue); voidObservation(nonCodedObservation); this.markedAsNonCoded = false; } else { setNewObservation(nonCodedObservation, newValue); voidObservation(codedObservation); } this.onValueChanged(newValue); }; var setFirstObservationValue = function (newValue) { setNewObservation(this.primaryObs, newValue); this.onValueChanged(newValue); }; Object.defineProperty(this, 'value', { enumerable: true, get: getPrimaryObservationValue, set: isFreeTextAutocompleteType(this.conceptUIConfig) ? setFreeTextPrimaryObservationValue : setFirstObservationValue }); var getFreeTextPrimaryObservation = function () { var isAlreadySavedObservation = function (observation) { return _.isString(_.get(observation, 'value')) && !_.get(observation, 'voided'); }; var codedConceptObservation = findObservationByConceptName(this.groupMembers, this.conceptUIConfig.codedConceptName); var nonCodedConceptObservation = findObservationByConceptName(this.groupMembers, this.conceptUIConfig.nonCodedConceptName); if (isAlreadySavedObservation(nonCodedConceptObservation)) { return nonCodedConceptObservation; } if (!codedConceptObservation) { throw new Error("Configuration Error: Concept '" + this.conceptUIConfig.codedConceptName + "' is not a set member of '" + concept.name.name + "'."); } return codedConceptObservation; }; var getGroupMembersWithoutClass = function (groupMembers, classNames) { return _.filter(groupMembers, function (member) { return !(_.includes(classNames, member.concept.conceptClass.name) || _.includes(classNames, member.concept.conceptClass)); }); }; var getFirstObservation = function () { var observations = getGroupMembersWithoutClass(this.groupMembers, [Bahmni.Common.Constants.abnormalConceptClassName, Bahmni.Common.Constants.unknownConceptClassName, Bahmni.Common.Constants.durationConceptClassName]); if (_.isEmpty(observations)) { return this.groupMembers[0]; } var primaryObs = observations[1] && observations[1].uuid && !observations[1].voided ? observations[1] : observations[0]; if (observations[0].isMultiSelect) { return observations[0]; } if (primaryObs.uuid && !primaryObs.voided) { return primaryObs; } return observations[1] && (observations[1].value || observations[1].value === "") && !observations[1].voided ? observations[1] : observations[0]; }; Object.defineProperty(this, 'primaryObs', { enumerable: true, get: isFreeTextAutocompleteType(this.conceptUIConfig) ? getFreeTextPrimaryObservation : getFirstObservation }); this.isObservationNode = true; this.uniqueId = _.uniqueId('observation_'); this.durationObs = findObservationByClassName(this.groupMembers, Bahmni.Common.Constants.durationConceptClassName); this.abnormalObs = findObservationByClassName(this.groupMembers, Bahmni.Common.Constants.abnormalConceptClassName); this.unknownObs = findObservationByClassName(this.groupMembers, Bahmni.Common.Constants.unknownConceptClassName); this.markedAsNonCoded = this.primaryObs.concept.dataType !== "Coded" && this.primaryObs.uuid; if (savedObs) { this.uuid = savedObs.uuid; this.observationDateTime = savedObs.observationDateTime; } else { this.value = this.conceptUIConfig.defaultValue; } }; Bahmni.ConceptSet.ObservationNode.prototype = { canAddMore: function () { return this.conceptUIConfig.allowAddMore == true; }, isStepperControl: function () { if (this.isNumeric()) { return this.conceptUIConfig.stepper == true; } return false; }, getPossibleAnswers: function () { return this.primaryObs.concept.answers; }, getCodedConcept: function () { return findObservationByConceptName(this.groupMembers, this.conceptUIConfig.codedConceptName).concept; }, onValueChanged: function () { if (!this.primaryObs.hasValue() && this.abnormalObs) { this.abnormalObs.value = undefined; this.abnormalObs.erroneousValue = undefined; } if (this.primaryObs.isNumeric() && this.primaryObs.hasValue() && this.abnormalObs) { this.setAbnormal(); } // TODO: Mihir, D3 : Hacky fix to update the datetime to current datetime on the server side. Ideal would be void the previous observation and create a new one. this.primaryObs.observationDateTime = null; if (this.unknownObs) { this.setUnknown(); } }, setAbnormal: function () { if (this.primaryObs.hasValue()) { var erroneousValue = this.value > (this.primaryObs.concept.hiAbsolute || Infinity) || this.value < (this.primaryObs.concept.lowAbsolute || 0); var valueInRange = this.value <= (this.primaryObs.concept.hiNormal || Infinity) && this.value >= (this.primaryObs.concept.lowNormal || 0); this.abnormalObs.value = !valueInRange; this.abnormalObs.erroneousValue = erroneousValue; } else { this.abnormalObs.value = undefined; this.abnormalObs.erroneousValue = undefined; } }, setUnknown: function () { if (this.primaryObs.atLeastOneValueSet() && this.primaryObs.hasValue()) { this.unknownObs.value = false; } else { if (this.unknownObs.value == false) { this.unknownObs.value = undefined; } } }, displayValue: function () { if (this.possibleAnswers.length > 0) { for (var i = 0; i < this.possibleAnswers.length; i++) { if (this.possibleAnswers[i].uuid === this.value) { return this.possibleAnswers[i].display; } } } else { return this.value; } }, isGroup: function () { return false; }, getControlType: function () { if (isFreeTextAutocompleteType(this.conceptUIConfig)) { return "freeTextAutocomplete"; } if (this.conceptUIConfig.autocomplete) { return "autocomplete"; } if (this.isHtml5InputDataType()) { return "html5InputDataType"; } if (this.primaryObs.isText()) { return "text"; } if (this.conceptUIConfig.dropdown) { return "dropdown"; } return "buttonselect"; }, isHtml5InputDataType: function () { return ['Date', 'Numeric', 'Datetime'].indexOf(this.primaryObs.getDataTypeName()) != -1; }, _isDateTimeDataType: function () { return this.primaryObs.getDataTypeName() === "Datetime"; }, isComputed: function () { return this.primaryObs.isComputed(); }, isConciseText: function () { return this.conceptUIConfig.conciseText === true; }, isComputedAndEditable: function () { return this.concept.conceptClass === "Computed/Editable"; }, atLeastOneValueSet: function () { return this.primaryObs.hasValue(); }, doesNotHaveDuration: function () { if (!this.durationObs || !this.conceptUIConfig.durationRequired) { return false; } else { if (!this.durationObs.value) { return true; } return this.durationObs.value < 0; } }, isValid: function (checkRequiredFields, conceptSetRequired) { if (this.isNumeric() && (!this.isValidNumeric() || !this.isValidNumericValue())) { return false; } if (this.isGroup()) { return this._hasValidChildren(checkRequiredFields, conceptSetRequired); } if (checkRequiredFields) { if (conceptSetRequired && this.isRequired() && !this.primaryObs.hasValue()) { return false; } if (this.isRequired() && !this.primaryObs.hasValue()) { return false; } if (this.getControlType() === "freeTextAutocomplete") { return this.isValidFreeTextAutocomplete(); } } if (this.primaryObs.getDataTypeName() === "Date") { return this.primaryObs.isValidDate(); } if (this.primaryObs.hasValue() && this.doesNotHaveDuration()) { return false; } if (this.abnormalObs && this.abnormalObs.erroneousValue) { return false; } if (this.primaryObs.hasValue() && this.primaryObs._isDateTimeDataType()) { return !this.hasInvalidDateTime(); } if (this.getControlType() === 'autocomplete') { return _.isEmpty(this.primaryObs.value) || _.isObject(this.primaryObs.value); } if (this.primaryObs.hasValue() && this.primaryObs.erroneousValue) { return false; } return true; }, isValueInAbsoluteRange: function () { return !(this.abnormalObs && this.abnormalObs.erroneousValue); }, isValidFreeTextAutocomplete: function () { return !(this.primaryObs.concept.dataType !== "Coded" && !this.markedAsNonCoded && this.primaryObs.value); }, isRequired: function () { this.disabled = this.disabled ? this.disabled : false; return this.conceptUIConfig.required === true && this.disabled === false; }, isDurationRequired: function () { return !!this.conceptUIConfig.durationRequired && !!this.primaryObs.value; }, isNumeric: function () { return this.primaryObs.getDataTypeName() === "Numeric"; }, isDecimalAllowed: function () { return this.primaryObs.concept.allowDecimal; }, isValidNumeric: function () { if (!this.isDecimalAllowed()) { if (this.value && this.value.toString().indexOf('.') >= 0) { return false; } } return true; }, isValidNumericValue: function () { var element = document.getElementById(this.uniqueId); if (this.value === "" && element) { return element.checkValidity(); } return true; }, _hasValidChildren: function (checkRequiredFields, conceptSetRequired) { return this.groupMembers.every(function (member) { return member.isValid(checkRequiredFields, conceptSetRequired); }); }, markAsNonCoded: function () { this.markedAsNonCoded = !this.markedAsNonCoded; }, toggleAbnormal: function () { this.abnormalObs.value = !this.abnormalObs.value; }, toggleUnknown: function () { if (!this.unknownObs.value) { this.unknownObs.value = true; } else { this.unknownObs.value = undefined; } }, assignAddMoreButtonID: function () { return this.concept.name.split(' ').join('_').toLowerCase() + '_addmore_' + this.uniqueId; }, canHaveComment: function () { return this.conceptUIConfig.disableAddNotes ? !this.conceptUIConfig.disableAddNotes : true; }, hasInvalidDateTime: function () { if (this.isComputed()) { return false; } var date = Bahmni.Common.Util.DateUtil.parse(this.value); if (!this.conceptUIConfig.allowFutureDates) { if (moment() < date) { return true; } } return this.value === "Invalid Datetime"; } }; })(); 'use strict'; Bahmni.ConceptSet.TabularObservations = function (obsGroups, parentObs, conceptUIConfig) { this.parentObs = parentObs; this.concept = obsGroups[0] && obsGroups[0].concept; this.label = obsGroups[0] && obsGroups[0].label; this.conceptUIConfig = conceptUIConfig[this.concept.name] || {}; this.isTabularObs = true; this.rows = _.map(obsGroups, function (group) { return new Bahmni.ConceptSet.ObservationRow(group, conceptUIConfig); }); this.columns = _.map(obsGroups[0].groupMembers, function (group) { return group.concept; }); this.cloneNew = function () { var old = this; var clone = new Bahmni.ConceptSet.TabularObservations(angular.copy(obsGroups), parentObs, conceptUIConfig); clone.rows = _.map(old.rows, function (row) { return row.cloneNew(); }); clone.disabled = this.disabled; return clone; }; this.addNew = function (row) { var newRow = row.cloneNew(); this.rows.push(newRow); this.parentObs.groupMembers.push(newRow.obsGroup); }; this.remove = function (row) { row.void(); this.rows.splice(this.rows.indexOf(row), 1); if (this.rows.length == 0) { this.addNew(row); } }; this.isFormElement = function () { return false; }; this.getControlType = function () { return "tabular"; }; this.isValid = function (checkRequiredFields, conceptSetRequired) { return _.every(this.rows, function (observationRow) { return _.every(observationRow.cells, function (conceptSetObservation) { return conceptSetObservation.isValid(checkRequiredFields, conceptSetRequired); }); }); }; this.getConceptUIConfig = function () { return this.conceptUIConfig || {}; }; this.canAddMore = function () { return this.getConceptUIConfig().allowAddMore == true; }; this.atLeastOneValueSet = function () { return this.rows.some(function (childNode) { return childNode.obsGroup.atLeastOneValueSet(); }); }; this.isNumeric = function () { return this.concept.dataType === "Numeric"; }; this.isValidNumericValue = function () { var element = document.getElementById(this.uniqueId); if (this.value === "" && element) { return element.checkValidity(); } return true; }; }; Bahmni.ConceptSet.ObservationRow = function (obsGroup, conceptUIConfig) { this.obsGroup = obsGroup; this.concept = obsGroup.concept; this.cells = obsGroup.groupMembers; this.void = function () { this.obsGroup.voided = true; }; this.cloneNew = function () { var newObsGroup = this.obsGroup.cloneNew(); newObsGroup.hidden = true; var clone = new Bahmni.ConceptSet.ObservationRow(newObsGroup, conceptUIConfig); clone.disabled = this.disabled; return clone; }; }; 'use strict'; Bahmni.ConceptSet.MultiSelectObservations = function (conceptSetConfig) { var self = this; this.multiSelectObservationsMap = {}; this.map = function (memberOfCollection) { memberOfCollection.forEach(function (member) { if (isMultiSelectable(member.concept, conceptSetConfig)) { add(member.concept, member, memberOfCollection); } }); insertMultiSelectObsInExistingOrder(memberOfCollection); }; var isMultiSelectable = function (concept, conceptSetConfig) { return conceptSetConfig[concept.name] && conceptSetConfig[concept.name].multiSelect; }; var insertMultiSelectObsInExistingOrder = function (memberOfCollection) { getAll().forEach(function (multiObs) { var index = _.findIndex(memberOfCollection, function (member) { return member.concept.name === multiObs.concept.name; }); memberOfCollection.splice(index, 0, multiObs); }); }; var add = function (concept, obs, memberOfCollection) { var conceptName = concept.name.name || concept.name; self.multiSelectObservationsMap[conceptName] = self.multiSelectObservationsMap[conceptName] || new Bahmni.ConceptSet.MultiSelectObservation(concept, memberOfCollection, conceptSetConfig); self.multiSelectObservationsMap[conceptName].add(obs); }; var getAll = function () { return _.values(self.multiSelectObservationsMap); }; }; Bahmni.ConceptSet.MultiSelectObservation = function (concept, memberOfCollection, conceptSetConfig) { var self = this; this.label = concept.shortName || concept.name; this.isMultiSelect = true; this.selectedObs = {}; this.concept = concept; this.concept.answers = this.concept.answers || []; this.groupMembers = []; this.provider = null; this.observationDateTime = ""; this.conceptUIConfig = conceptSetConfig[this.concept.name] || {}; this.possibleAnswers = self.concept.answers.map(function (answer) { var cloned = _.cloneDeep(answer); if (answer.name.name) { cloned.name = answer.name.name; } return cloned; }); this.getPossibleAnswers = function () { return this.possibleAnswers; }; this.cloneNew = function () { var clone = new Bahmni.ConceptSet.MultiSelectObservation(concept, memberOfCollection, conceptSetConfig); clone.disabled = this.disabled; return clone; }; this.add = function (obs) { if (obs.value) { self.selectedObs[obs.value.name] = obs; if (!self.provider) { self.provider = self.selectedObs[obs.value.name].provider; } var currentObservationDateTime = self.selectedObs[obs.value.name].observationDateTime; if (self.observationDateTime < currentObservationDateTime) { self.observationDateTime = currentObservationDateTime; } } obs.hidden = true; }; this.isComputedAndEditable = function () { return this.concept.conceptClass === "Computed/Editable"; }; this.hasValueOf = function (answer) { return self.selectedObs[answer.name] && !self.selectedObs[answer.name].voided; }; this.toggleSelection = function (answer) { if (self.hasValueOf(answer)) { unselectAnswer(answer); } else { self.selectAnswer(answer); } }; this.isFormElement = function () { return true; }; this.getControlType = function () { var conceptConfig = this.getConceptUIConfig(); if (this.isCoded() && conceptConfig.autocomplete == true && conceptConfig.multiSelect == true) { return "autocompleteMultiSelect"; } else if (conceptConfig.autocomplete == true) { return "autocomplete"; } return "buttonselect"; }; this.atLeastOneValueSet = function () { var obsValue = _.filter(this.selectedObs, function (obs) { return obs.value; }); return !_.isEmpty(obsValue); }; this.hasValue = function () { return !_.isEmpty(this.selectedObs); }; this.hasNonVoidedValue = function () { var hasNonVoidedValue = false; if (this.hasValue()) { angular.forEach(this.selectedObs, function (obs) { if (!obs.voided) { hasNonVoidedValue = true; } }); } return hasNonVoidedValue; }; this.isValid = function (checkRequiredFields, conceptSetRequired) { if (this.error) { return false; } if (checkRequiredFields) { if (conceptSetRequired && this.isRequired() && !this.hasNonVoidedValue()) { return false; } if (this.isRequired() && !this.hasNonVoidedValue()) { return false; } } return true; }; this.canHaveComment = function () { return false; }; this.getConceptUIConfig = function () { return this.conceptUIConfig || {}; }; this.canAddMore = function () { return this.getConceptUIConfig().allowAddMore == true; }; this.isRequired = function () { this.disabled = this.disabled ? this.disabled : false; return this.getConceptUIConfig().required === true && this.disabled === false; }; var createObsFrom = function (answer) { var obs = newObservation(concept, answer, conceptSetConfig); memberOfCollection.push(obs); return obs; }; var removeObsFrom = function (answer) { var obs = newObservation(concept, answer, conceptSetConfig); _.remove(memberOfCollection, function (member) { if (member.value) { return obs.value.displayString == member.value.displayString; } return false; }); }; this.selectAnswer = function (answer) { var obs = self.selectedObs[answer.name]; if (obs) { obs.value = answer; obs.voided = false; } else { obs = createObsFrom((answer)); self.add(obs); } }; var unselectAnswer = function (answer) { var obs = self.selectedObs[answer.name]; if (obs && obs.uuid) { obs.value = null; obs.voided = true; } else { removeObsFrom(answer); delete self.selectedObs[answer.name]; } }; var newObservation = function (concept, value, conceptSetConfig) { var observation = buildObservation(concept); return new Bahmni.ConceptSet.Observation(observation, {value: value}, conceptSetConfig, []); }; var buildObservation = function (concept) { return { concept: concept, units: concept.units, label: concept.shortName || concept.name, possibleAnswers: self.concept.answers, groupMembers: [], comment: null}; }; this.getValues = function () { var values = []; _.values(self.selectedObs).forEach(function (obs) { if (obs.value) { values.push(obs.value.shortName || obs.value.name); } }); return values; }; this.isComputed = function () { return this.concept.conceptClass === "Computed"; }; this.getDataTypeName = function () { return this.concept.dataType; }; this._isDateTimeDataType = function () { return this.getDataTypeName() === "Datetime"; }; this.isNumeric = function () { return this.getDataTypeName() === "Numeric"; }; this.isText = function () { return this.getDataTypeName() === "Text"; }; this.isCoded = function () { return this.getDataTypeName() === "Coded"; }; }; 'use strict'; Bahmni.ConceptSet.CustomRepresentationBuilder = { build: function (fields, childPropertyName, numberOfLevels) { var childPropertyRep = childPropertyName + ':{{entity_fileds}}'; var singleEntityString = "(" + fields.concat(childPropertyRep).join(',') + ")"; var customRepresentation = singleEntityString; for (var i = 0; i < numberOfLevels; i++) { customRepresentation = customRepresentation.replace("{{entity_fileds}}", singleEntityString); } customRepresentation = customRepresentation.replace("," + childPropertyRep, ''); return customRepresentation; } }; 'use strict'; Bahmni.ConceptSet.ConceptSetSection = function (extensions, user, config, observations, conceptSet) { var self = this; self.clone = function () { var clonedConceptSetSection = new Bahmni.ConceptSet.ConceptSetSection(extensions, user, config, [], conceptSet); clonedConceptSetSection.isAdded = true; return clonedConceptSetSection; }; var init = function () { self.observations = observations; self.options = extensions.extensionParams || {}; self.conceptName = conceptSet.name ? conceptSet.name.name : self.options.conceptName; var conceptName = _.find(conceptSet.names, {conceptNameType: "SHORT"}) || _.find(conceptSet.names, {conceptNameType: "FULLY_SPECIFIED"}); conceptName = conceptName ? conceptName.name : conceptName; self.label = conceptName || self.conceptName || self.options.conceptName; self.isLoaded = self.isOpen; self.collapseInnerSections = {value: false}; self.uuid = conceptSet.uuid; self.alwaysShow = user.isFavouriteObsTemplate(self.conceptName); self.allowAddMore = config.allowAddMore; self.id = "concept-set-" + conceptSet.uuid; }; var getShowIfFunction = function () { if (!self.showIfFunction) { var showIfFunctionStrings = self.options.showIf || ["return true;"]; self.showIfFunction = new Function("context", showIfFunctionStrings.join('\n')); // eslint-disable-line no-new-func } return self.showIfFunction; }; var atLeastOneValueSet = function (observation) { if (observation.groupMembers && observation.groupMembers.length > 0) { return observation.groupMembers.some(function (groupMember) { return atLeastOneValueSet(groupMember); }); } else { return !(_.isUndefined(observation.value) || observation.value === ""); } }; self.isAvailable = function (context) { return getShowIfFunction()(context || {}); }; self.show = function () { self.isOpen = true; self.isLoaded = true; }; self.hide = function () { self.isOpen = false; }; self.getObservationsForConceptSection = function () { return self.observations.filter(function (observation) { return observation.concept.name === self.conceptName; }); }; self.hasSomeValue = function () { var observations = self.getObservationsForConceptSection(); return _.some(observations, function (observation) { return atLeastOneValueSet(observation); }); }; self.showComputeButton = function () { return config.computeDrugs === true; }; self.toggle = function () { self.added = !self.added; if (self.added) { self.show(); } }; self.maximizeInnerSections = function (event) { event.stopPropagation(); self.collapseInnerSections = {value: false}; }; self.minimizeInnerSections = function (event) { event.stopPropagation(); self.collapseInnerSections = {value: true}; }; self.toggleDisplay = function () { if (self.isOpen) { self.hide(); } else { self.show(); } }; self.canToggle = function () { return !self.hasSomeValue(); }; self.canAddMore = function () { return self.allowAddMore == true; }; Object.defineProperty(self, "isOpen", { get: function () { if (self.open === undefined) { self.open = self.hasSomeValue(); } return self.open; }, set: function (value) { self.open = value; } }); self.isDefault = function () { return self.options.default; }; Object.defineProperty(self, "isAdded", { get: function () { if (self.added === undefined) { if (self.options.default) { self.added = true; } else { self.added = self.hasSomeValue(); } } return self.added; }, set: function (value) { self.added = value; } }); init(); }; 'use strict'; Bahmni.ObservationForm = function (formUuid, user, formName, formVersion, observations, extension) { var self = this; var init = function () { self.formUuid = formUuid; self.formVersion = formVersion; self.formName = formName; self.label = formName; self.conceptName = formName; self.collapseInnerSections = {value: false}; self.alwaysShow = user.isFavouriteObsTemplate(self.conceptName); self.observations = []; _.each(observations, function (observation) { var observationFormField = observation.formFieldPath ? (observation.formFieldPath.split("/")[0]).split('.') : null; if (observationFormField && observationFormField[0] === formName && observationFormField[1] === formVersion) { self.observations.push(observation); } }); self.isOpen = self.observations.length > 0; self.id = "concept-set-" + formUuid; self.options = extension ? (extension.extensionParams || {}) : {}; }; self.toggleDisplay = function () { if (self.isOpen) { hide(); } else { show(); } }; function hide () { self.isOpen = false; } function show () { self.isOpen = true; } // parameters added to show in observation page :: START self.clone = function () { var clonedObservationFormSection = new Bahmni.ObservationForm(self.formUuid, user, self.formName, self.formVersion, []); clonedObservationFormSection.isOpen = true; return clonedObservationFormSection; }; self.isAvailable = function (context) { return true; }; self.show = function () { self.isOpen = true; self.isLoaded = true; }; self.toggle = function () { self.added = !self.added; if (self.added) { self.show(); } }; self.hasSomeValue = function () { var observations = self.getObservationsForConceptSection(); return _.some(observations, function (observation) { return atLeastOneValueSet(observation); }); }; self.getObservationsForConceptSection = function () { return self.observations.filter(function (observation) { return observation.formFieldPath.split('.')[0] === self.formName; }); }; var atLeastOneValueSet = function (observation) { if (observation.groupMembers && observation.groupMembers.length > 0) { return observation.groupMembers.some(function (groupMember) { return atLeastOneValueSet(groupMember); }); } else { return !(_.isUndefined(observation.value) || observation.value === ""); } }; self.isDefault = function () { return false; }; Object.defineProperty(self, "isAdded", { get: function () { if (self.hasSomeValue()) { self.added = true; } return self.added; }, set: function (value) { self.added = value; } }); self.maximizeInnerSections = function (event) { event.stopPropagation(); self.collapseInnerSections = {value: false}; }; self.minimizeInnerSections = function (event) { event.stopPropagation(); self.collapseInnerSections = {value: true}; }; // parameters added to show in observation page :: END init(); }; 'use strict'; Bahmni.ConceptSet.ObservationMapper = function () { var conceptMapper = new Bahmni.Common.Domain.ConceptMapper(); var self = this; // TODO : Shouldn't this be in clinical module. Don't see a reason for this to be in concept-set code - Shruthi this.getObservationsForView = function (observations, conceptSetConfig) { return internalMapForDisplay(observations, conceptSetConfig); }; var internalMapForDisplay = function (observations, conceptSetConfig) { var observationsForDisplay = []; _.forEach(observations, function (savedObs) { if (savedObs.concept.conceptClass && (savedObs.concept.conceptClass === Bahmni.Common.Constants.conceptDetailsClassName || savedObs.concept.conceptClass.name === Bahmni.Common.Constants.conceptDetailsClassName)) { var observationNode = new Bahmni.ConceptSet.ObservationNode(savedObs, savedObs, [], savedObs.concept); var obsToDisplay = createObservationForDisplay(observationNode, observationNode.primaryObs.concept); if (obsToDisplay) { observationsForDisplay.push(obsToDisplay); } } else { if (savedObs.concept.set) { if (conceptSetConfig[savedObs.concept.name] && conceptSetConfig[savedObs.concept.name].grid) { savedObs.value = self.getGridObservationDisplayValue(savedObs); observationsForDisplay = observationsForDisplay.concat(createObservationForDisplay(savedObs, savedObs.concept)); } else { var groupMemberObservationsForDisplay = internalMapForDisplay(savedObs.groupMembers, conceptSetConfig); observationsForDisplay = observationsForDisplay.concat(groupMemberObservationsForDisplay); } } else { var obsToDisplay = null; if (savedObs.isMultiSelect) { obsToDisplay = savedObs; } else if (!savedObs.hidden) { var observation = newObservation(savedObs.concept, savedObs, []); obsToDisplay = createObservationForDisplay(observation, observation.concept); } if (obsToDisplay) { observationsForDisplay.push(obsToDisplay); } } } }); return observationsForDisplay; }; this.map = function (observations, rootConcept, conceptSetConfig) { var savedObs = findInSavedObservation(rootConcept, observations)[0]; return mapObservation(rootConcept, savedObs, conceptSetConfig || {}); }; var findInSavedObservation = function (concept, observations) { return _.filter(observations, function (obs) { return obs && obs.concept && concept.uuid === obs.concept.uuid; }); }; var mapObservation = function (concept, savedObs, conceptSetConfig) { var obs = null; if (savedObs && (savedObs.isObservation || savedObs.isObservationNode)) { return savedObs; } var mappedGroupMembers = concept && concept.set ? mapObservationGroupMembers(savedObs ? savedObs.groupMembers : [], concept, conceptSetConfig) : []; if (concept.conceptClass.name === Bahmni.Common.Constants.conceptDetailsClassName) { obs = newObservationNode(concept, savedObs, conceptSetConfig, mappedGroupMembers); } else { obs = newObservation(concept, savedObs, conceptSetConfig, mappedGroupMembers); new Bahmni.ConceptSet.MultiSelectObservations(conceptSetConfig).map(mappedGroupMembers); } mapTabularObs(mappedGroupMembers, concept, obs, conceptSetConfig); return obs; }; function mapTabularObs (mappedGroupMembers, concept, obs, conceptSetConfig) { var tabularObsGroups = _.filter(mappedGroupMembers, function (member) { return conceptSetConfig[member.concept.name] && conceptSetConfig[member.concept.name]['isTabular']; }); if (tabularObsGroups.length > 0) { var array = _.map(concept.setMembers, function (member) { return member.name.name; }); tabularObsGroups.forEach(function (group) { group.hidden = true; }); var groupedObsGroups = _.groupBy(tabularObsGroups, function (group) { return group.concept.name; }); _.values(groupedObsGroups).forEach(function (groups) { var tabularObservations = new Bahmni.ConceptSet.TabularObservations(groups, obs, conceptSetConfig); obs.groupMembers.push(tabularObservations); }); var sortedGroupMembers = _.sortBy(obs.groupMembers, function (observation) { return array.indexOf(observation.concept.name); }); obs.groupMembers.length = 0; obs.groupMembers.push.apply(obs.groupMembers, sortedGroupMembers); } } var mapObservationGroupMembers = function (observations, parentConcept, conceptSetConfig) { var observationGroupMembers = []; var conceptSetMembers = parentConcept.setMembers; conceptSetMembers.forEach(function (memberConcept) { var savedObservations = findInSavedObservation(memberConcept, observations); var configForConcept = conceptSetConfig[memberConcept.name.name] || {}; var numberOfNodes = configForConcept.multiple || 1; for (var i = savedObservations.length - 1; i >= 0; i--) { observationGroupMembers.push(mapObservation(memberConcept, savedObservations[i], conceptSetConfig)); } for (var i = 0; i < numberOfNodes - savedObservations.length; i++) { observationGroupMembers.push(mapObservation(memberConcept, null, conceptSetConfig)); } }); return observationGroupMembers; }; var getDatatype = function (concept) { if (concept.dataType) { return concept.dataType; } return concept.datatype && concept.datatype.name; }; // tODO : remove conceptUIConfig var newObservation = function (concept, savedObs, conceptSetConfig, mappedGroupMembers) { var observation = buildObservation(concept, savedObs, mappedGroupMembers); var obs = new Bahmni.ConceptSet.Observation(observation, savedObs, conceptSetConfig, mappedGroupMembers); if (getDatatype(concept) == "Boolean") { obs = new Bahmni.ConceptSet.BooleanObservation(obs, conceptSetConfig); } return obs; }; // TODO : remove conceptUIConfig var newObservationNode = function (concept, savedObsNode, conceptSetConfig, mappedGroupMembers) { var observation = buildObservation(concept, savedObsNode, mappedGroupMembers); return new Bahmni.ConceptSet.ObservationNode(observation, savedObsNode, conceptSetConfig, concept); }; var showAddMoreButton = function (rootObservation) { var observation = this; var lastObservationByLabel = _.findLast(rootObservation.groupMembers, {label: observation.label}); return lastObservationByLabel.uuid === observation.uuid; }; function buildObservation (concept, savedObs, mappedGroupMembers) { var comment = savedObs ? savedObs.comment : null; return { concept: conceptMapper.map(concept), units: concept.units, label: getLabel(concept), possibleAnswers: concept.answers, groupMembers: mappedGroupMembers, comment: comment, showAddMoreButton: showAddMoreButton }; } var createObservationForDisplay = function (observation, concept) { if (observation.value == null) { return; } var observationValue = getObservationDisplayValue(observation); observationValue = observation.durationObs ? observationValue + " " + getDurationDisplayValue(observation.durationObs) : observationValue; return { "value": observationValue, "abnormalObs": observation.abnormalObs, "duration": observation.durationObs, "provider": observation.provider, "label": getLabel(observation.concept), "observationDateTime": observation.observationDateTime, "concept": concept, "comment": observation.comment, "uuid": observation.uuid }; }; var getObservationDisplayValue = function (observation) { if (observation.isBoolean || observation.type === "Boolean") { return observation.value === true ? "Yes" : "No"; } if (!observation.value) { return ""; } if (typeof observation.value.name === 'object') { var valueConcept = conceptMapper.map(observation.value); return valueConcept.shortName || valueConcept.name; } return observation.value.shortName || observation.value.name || observation.value; }; var getDurationDisplayValue = function (duration) { var durationForDisplay = Bahmni.Common.Util.DateUtil.convertToUnits(duration.value); if (durationForDisplay["value"] && durationForDisplay["unitName"]) { return "since " + durationForDisplay["value"] + " " + durationForDisplay["unitName"]; } return ""; }; this.getGridObservationDisplayValue = function (observation) { var memberValues = _.compact(_.map(observation.groupMembers, function (member) { return getObservationDisplayValue(member); })); return memberValues.join(', '); }; var getLabel = function (concept) { var mappedConcept = conceptMapper.map(concept); return mappedConcept.shortName || mappedConcept.name; }; }; 'use strict'; angular.module('bahmni.common.conceptSet') .factory('conceptService', ['$q', '$http', function ($q, $http) { var conceptMapper = new Bahmni.Common.Domain.ConceptMapper(); var mapConceptOrGetDrug = function (conceptAnswer) { return conceptAnswer.concept && conceptMapper.map(conceptAnswer.concept) || conceptAnswer.drug; }; var getAnswersForConceptName = function (request) { var params = { q: request.term, question: request.answersConceptName, v: "custom:(concept:(uuid,name:(display,uuid,name,conceptNameType),names:(display,uuid,name,conceptNameType)),drug:(uuid,name,display))", s: "byQuestion" }; return $http.get(Bahmni.Common.Constants.bahmniConceptAnswerUrl, {params: params}) .then(_.partial(_.get, _, 'data.results')) .then(function (conceptAnswers) { return _(conceptAnswers) .map(mapConceptOrGetDrug) .uniqBy('uuid') .value(); }); }; var getAnswers = function (defaultConcept) { var deferred = $q.defer(); var response = _(defaultConcept.answers) .uniqBy('uuid') .map(conceptMapper.map) .value(); deferred.resolve(response); return deferred.promise; }; return { getAnswersForConceptName: getAnswersForConceptName, getAnswers: getAnswers }; }]); 'use strict'; angular.module('bahmni.common.conceptSet') .factory('conceptSetUiConfigService', ['$http', '$q', 'appService', function ($http, $q, appService) { var setConceptUuidInsteadOfName = function (config, conceptNameField, uuidField) { var conceptName = config[conceptNameField]; if (conceptName != null) { return $http.get(Bahmni.Common.Constants.conceptSearchByFullNameUrl, { params: {name: conceptName, v: "custom:(uuid,name)"} }).then(function (response) { var concept = response.data.results.filter(function (c) { return c.name.name === conceptName; }); if (concept.length > 0) { config[uuidField] = concept[0].uuid; } }); } }; var setExtraData = function (config) { Object.getOwnPropertyNames(config).forEach(function (conceptConfigKey) { var conceptConfig = config[conceptConfigKey]; if (conceptConfig['freeTextAutocomplete'] instanceof Object) { setConceptUuidInsteadOfName(conceptConfig['freeTextAutocomplete'], 'codedConceptName', 'codedConceptUuid'); setConceptUuidInsteadOfName(conceptConfig['freeTextAutocomplete'], 'conceptSetName', 'conceptSetUuid'); } }); }; var getConfig = function () { var config = appService.getAppDescriptor().getConfigValue("conceptSetUI") || {}; setExtraData(config); return config; }; return { getConfig: getConfig }; }]); 'use strict'; angular.module('bahmni.common.uiHelper') .filter('thumbnail', function () { return function (url, extension) { if (url) { if (extension) { return Bahmni.Common.Constants.documentsPath + '/' + url.replace(/(.*)\.(.*)$/, "$1_thumbnail." + extension) || null; } return Bahmni.Common.Constants.documentsPath + '/' + url.replace(/(.*)\.(.*)$/, "$1_thumbnail.$2") || null; } }; }); 'use strict'; angular.module('bahmni.common.uiHelper') .filter('days', function () { return function (startDate, endDate) { return Bahmni.Common.Util.DateUtil.diffInDays(startDate, endDate); }; }).filter('bahmniDateTime', function () { return function (date) { return Bahmni.Common.Util.DateUtil.formatDateWithTime(date); }; }).filter('bahmniDate', function () { return function (date) { return Bahmni.Common.Util.DateUtil.formatDateWithoutTime(date); }; }).filter('bahmniTime', function () { return function (date) { return Bahmni.Common.Util.DateUtil.formatTime(date); }; }).filter('bahmniDateInStrictMode', function () { return function (date) { return Bahmni.Common.Util.DateUtil.formatDateInStrictMode(date); }; }); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.Logging = Bahmni.Common.Logging || {}; angular.module('bahmni.common.logging', []); 'use strict'; angular.module('bahmni.common.logging') .config(['$provide', function ($provide) { $provide.decorator("$exceptionHandler", function ($delegate, $injector, $window, $log) { var logError = function (exception, cause) { try { var messagingService = $injector.get('messagingService'); var loggingService = $injector.get('loggingService'); var errorMessage = exception.toString(); var stackTrace = printStackTrace({ e: exception }); var errorDetails = { timestamp: new Date(), browser: $window.navigator.userAgent, errorUrl: $window.location.href, errorMessage: errorMessage, stackTrace: stackTrace, cause: (cause || "") }; loggingService.log(errorDetails); messagingService.showMessage('error', errorMessage); exposeException(errorDetails); } catch (loggingError) { $log.warn("Error logging failed"); $log.log(loggingError); } }; var exposeException = function (exceptionDetails) { window.angular_exception = window.angular_exception || []; window.angular_exception.push(exceptionDetails); }; return function (exception, cause) { $delegate(exception, cause); logError(exception, cause); }; }); }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.DisplayControl = Bahmni.Common.DisplayControl || {}; angular.module('bahmni.common.displaycontrol', []); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.DisplayControl = Bahmni.Common.DisplayControl || {}; Bahmni.Common.DisplayControl.Observation = Bahmni.Common.DisplayControl.Observation || {}; angular.module('bahmni.common.displaycontrol.observation', ['bahmni.common.conceptSet', 'pascalprecht.translate']); 'use strict'; angular.module('bahmni.common.conceptSet') .factory('formService', ['$http', function ($http) { var getFormList = function (encounterUuid) { return $http.get(Bahmni.Common.Constants.latestPublishedForms, {params: {encounterUuid: encounterUuid}}); }; var getAllForms = function () { return $http.get(Bahmni.Common.Constants.allFormsUrl, {params: {v: "custom:(version,name,uuid)"}}); }; var getFormDetail = function (formUuid, params) { return $http.get(Bahmni.Common.Constants.formUrl + '/' + formUuid, {params: params}); }; var getFormTranslations = function (url, form) { if (url && url !== Bahmni.Common.Constants.formTranslationsUrl) { return $http.get(url); } return $http.get(Bahmni.Common.Constants.formTranslationsUrl, { params: form}); }; return { getFormList: getFormList, getAllForms: getAllForms, getFormDetail: getFormDetail, getFormTranslations: getFormTranslations }; }]); 'use strict'; Bahmni.Common.DisplayControl.Observation.GroupingFunctions = function () { var self = this; var observationGroupingFunction = function (obs) { return Bahmni.Common.Util.DateUtil.getDateTimeWithoutSeconds(obs.encounterDateTime); }; self.groupByEncounterDate = function (bahmniObservations) { var obsArray = []; bahmniObservations = _.groupBy(bahmniObservations, observationGroupingFunction); var sortWithInAConceptDateCombination = function (anObs, challengerObs) { if (anObs.encounterDateTime < challengerObs.encounterDateTime) { return 1; } if (anObs.encounterDateTime > challengerObs.encounterDateTime) { return -1; } if (anObs.conceptSortWeight < challengerObs.conceptSortWeight) { return -1; } if (anObs.conceptSortWeight > challengerObs.conceptSortWeight) { return 1; } return 0; }; for (var obsKey in bahmniObservations) { var dateTime = obsKey; var anObs = { "key": dateTime, "value": bahmniObservations[dateTime].sort(sortWithInAConceptDateCombination), "date": dateTime }; obsArray.push(anObs); } return _.sortBy(obsArray, 'date').reverse(); }; self.persistOrderOfConceptNames = function (bahmniObservations) { var obsArray = []; for (var obsKey in bahmniObservations) { var anObs = { "key": obsKey, "value": [bahmniObservations[obsKey]], "date": bahmniObservations[obsKey].encounterDateTime }; obsArray.push(anObs); } return obsArray; }; return self; }; 'use strict'; angular.module('bahmni.common.displaycontrol.observation') .service('formHierarchyService', ['formService', function (formService) { var self = this; self.build = function (observations) { var obs = self.preProcessMultipleSelectObsToObs(observations); obs = self.createDummyObsGroupForObservationsForForm(obs); self.createDummyObsGroupForSectionsForForm(obs); }; self.preProcessMultipleSelectObsToObs = function (observations) { _.forEach(observations, function (obs) { _.forEach(obs.value, function (value, index) { if (value.type == "multiSelect") { obs.value.push(value.groupMembers[0]); obs.value.splice(index, 1); } }); }); return observations; }; self.createDummyObsGroupForObservationsForForm = function (observations) { _.forEach(observations, function (obs) { var newValues = []; _.forEach(obs.value, function (value) { if (!value.formFieldPath) { newValues.push(value); return; } var dummyObsGroup = { "groupMembers": [], "concept": { "shortName": "", "conceptClass": null }, "encounterUuid": "" }; dummyObsGroup.concept.shortName = value.formFieldPath.split('.')[0]; dummyObsGroup.encounterUuid = value.encounterUuid; var previousDummyObsGroupFound; _.forEach(newValues, function (newValue) { if (dummyObsGroup.concept.shortName == newValue.concept.shortName) { newValue.groupMembers.push(value); previousDummyObsGroupFound = true; } }); if (previousDummyObsGroupFound) { return; } dummyObsGroup.groupMembers.push(value); newValues.push(dummyObsGroup); }); obs.value = newValues; }); return observations; }; self.getFormVersion = function (members) { var formVersion; _.forEach(members, function (member) { if (member.formFieldPath) { formVersion = member.formFieldPath.split('.')[1].split('/')[0]; return false; } }); return formVersion; }; self.getMemberFromFormByFormFieldPath = function (members, id) { return _.filter(members, function (member) { return member.formFieldPath.split('.')[1].split('/')[1].split('-')[0] == id; }); }; self.getFormByFormName = function (formList, formName, formVersion) { return _.find(formList, function (form) { return form.name == formName && form.version == formVersion; }); }; self.parseSection = function (members, controls, value) { var sectionIsEmpty = true; _.forEach(controls, function (control) { var dummyObsGroup = { "groupMembers": [], "concept": { "shortName": "", "conceptClass": null } }; if (control.type == "section") { dummyObsGroup.concept.shortName = control.label.value; value.groupMembers.push(dummyObsGroup); if (!self.parseSection(members, control.controls, dummyObsGroup)) { value.groupMembers.pop(); } else { sectionIsEmpty = false; } } else { var member = self.getMemberFromFormByFormFieldPath(members, control.id); if (member.length != 0) { if (member[0].formFieldPath.split('-')[1] != 0) { _.reverse(member); } _.map(member, function (m) { value.groupMembers.push(m); }); sectionIsEmpty = false; } } }); if (sectionIsEmpty) { return null; } return value; }; self.createSectionForSingleForm = function (obsFromSameForm, formDetails) { var members = obsFromSameForm.groupMembers.slice(); obsFromSameForm.groupMembers.splice(0, obsFromSameForm.groupMembers.length); return self.parseSection(members, formDetails.controls, obsFromSameForm); }; self.createDummyObsGroupForSectionsForForm = function (bahmniObservations) { if (_.isEmpty(bahmniObservations)) { return; } formService.getAllForms().then(function (response) { var allForms = response.data; _.forEach(bahmniObservations, function (observation) { var forms = []; _.forEach(observation.value, function (form) { if (form.concept.conceptClass) { forms.push(form); return; } var observationForm = self.getFormByFormName(allForms, form.concept.shortName, self.getFormVersion(form.groupMembers)); if (!observationForm) { return; } formService.getFormDetail(observationForm.uuid, { v: "custom:(resources:(value))"}).then(function (response) { var formDetailsAsString = _.get(response, 'data.resources[0].value'); if (formDetailsAsString) { var formDetails = JSON.parse(formDetailsAsString); forms.push(self.createSectionForSingleForm(form, formDetails)); } observation.value = forms; }); }); }); }); }; } ]); 'use strict'; angular.module('bahmni.common.displaycontrol.observation') .directive('bahmniObservation', ['observationsService', 'appService', '$q', 'spinner', '$rootScope', 'formHierarchyService', '$translate', function (observationsService, appService, $q, spinner, $rootScope, formHierarchyService, $translate) { var controller = function ($scope) { $scope.print = $rootScope.isBeingPrinted || false; $scope.showGroupDateTime = $scope.config.showGroupDateTime !== false; var mapObservation = function (observations) { var conceptsConfig = appService.getAppDescriptor().getConfigValue("conceptSetUI") || {}; observations = new Bahmni.Common.Obs.ObservationMapper().map(observations, conceptsConfig); if ($scope.config.conceptNames) { observations = _.filter(observations, function (observation) { return _.some($scope.config.conceptNames, function (conceptName) { return _.toLower(conceptName) === _.toLower(_.get(observation, 'concept.name')); }); }); } if ($scope.config.persistOrderOfConcepts) { $scope.bahmniObservations = new Bahmni.Common.DisplayControl.Observation.GroupingFunctions().persistOrderOfConceptNames(observations); } else { $scope.bahmniObservations = new Bahmni.Common.DisplayControl.Observation.GroupingFunctions().groupByEncounterDate(observations); } if (_.isEmpty($scope.bahmniObservations)) { $scope.noObsMessage = $translate.instant(Bahmni.Common.Constants.messageForNoObservation); $scope.$emit("no-data-present-event"); } else { if (!$scope.showGroupDateTime) { _.forEach($scope.bahmniObservations, function (bahmniObs) { bahmniObs.isOpen = true; }); } else { $scope.bahmniObservations[0].isOpen = true; } } var formObservations = _.filter(observations, function (obs) { return obs.formFieldPath; }); if (formObservations.length > 0) { formHierarchyService.build($scope.bahmniObservations); } }; var fetchObservations = function () { if ($scope.observations) { mapObservation($scope.observations, $scope.config); $scope.isFulfilmentDisplayControl = true; } else { if ($scope.config.observationUuid) { $scope.initialization = observationsService.getByUuid($scope.config.observationUuid).then(function (response) { mapObservation([response.data], $scope.config); }); } else if ($scope.config.encounterUuid) { var fetchForEncounter = observationsService.fetchForEncounter($scope.config.encounterUuid, $scope.config.conceptNames); $scope.initialization = fetchForEncounter.then(function (response) { mapObservation(response.data, $scope.config); }); } else if ($scope.enrollment) { $scope.initialization = observationsService.fetchForPatientProgram($scope.enrollment, $scope.config.conceptNames, $scope.config.scope, $scope.config.obsIgnoreList).then(function (response) { mapObservation(response.data, $scope.config); }); } else { $scope.initialization = observationsService.fetch($scope.patient.uuid, $scope.config.conceptNames, $scope.config.scope, $scope.config.numberOfVisits, $scope.visitUuid, $scope.config.obsIgnoreList, null).then(function (response) { mapObservation(response.data, $scope.config); }); } } }; $scope.toggle = function (element) { element.isOpen = !element.isOpen; }; $scope.isClickable = function () { return $scope.isOnDashboard && $scope.section.expandedViewConfig && ($scope.section.expandedViewConfig.pivotTable || $scope.section.expandedViewConfig.observationGraph); }; fetchObservations(); $scope.dialogData = { "patient": $scope.patient, "section": $scope.section }; }; var link = function ($scope, element) { $scope.initialization && spinner.forPromise($scope.initialization, element); }; return { restrict: 'E', controller: controller, link: link, templateUrl: "../common/displaycontrols/observation/views/observationDisplayControl.html", scope: { patient: "=", visitUuid: "@", section: "=?", config: "=", title: "=sectionTitle", isOnDashboard: "=?", observations: "=?", message: "=?", enrollment: "=?" } }; }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.DisplayControl = Bahmni.Common.DisplayControl || {}; Bahmni.Common.DisplayControl.PivotTable = Bahmni.Common.DisplayControl.PivotTable || {}; angular.module('bahmni.common.displaycontrol', []); angular.module('bahmni.common.displaycontrol.pivottable', []); 'use strict'; angular.module('bahmni.common.displaycontrol.pivottable').directive('pivotTable', ['$rootScope', '$filter', '$stateParams', 'spinner', 'pivotTableService', 'appService', 'conceptSetUiConfigService', '$interval', function ($rootScope, $filter, $stateParams, spinner, pivotTableService, appService, conceptSetUiConfigService, $interval) { return { scope: { patientUuid: "=", diseaseName: "=", displayName: "=", config: "=", visitUuid: "=", status: "=?" }, link: function (scope, element) { var tablescroll; if (!scope.config) { return; } scope.groupBy = scope.config.groupBy || "visits"; scope.groupByEncounters = scope.groupBy === "encounters"; scope.groupByVisits = scope.groupBy === "visits"; scope.getOnlyDate = function (startdate) { return Bahmni.Common.Util.DateUtil.formatDateWithoutTime(startdate); }; scope.getOnlyTime = function (startDate) { return Bahmni.Common.Util.DateUtil.formatTime(startDate); }; scope.isLonger = function (value) { return value ? value.length > 13 : false; }; scope.getColumnValue = function (value, conceptName) { if (conceptName && conceptSetUiConfigService.getConfig()[conceptName] && conceptSetUiConfigService.getConfig()[conceptName].displayMonthAndYear == true) { return Bahmni.Common.Util.DateUtil.getDateInMonthsAndYears(value); } return scope.isLonger(value) ? value.substring(0, 10) + "..." : value; }; scope.scrollLeft = function () { $('table.pivot-table tbody').animate({ scrollLeft: 0}); return false; }; scope.scrollRight = function () { $('table.pivot-table tbody').animate({ scrollLeft: tablescroll}); return false; }; var programConfig = appService.getAppDescriptor().getConfigValue("program") || {}; var startDate = null, endDate = null; if (programConfig.showDetailsWithinDateRange) { startDate = $stateParams.dateEnrolled; endDate = $stateParams.dateCompleted; } var checkIfPivotTableLoaded = $interval(function () { if ($('table.pivot-table tbody tr').length > 11) { $('table.pivot-table tbody').animate({ scrollLeft: '20000px' }, 500); tablescroll = $('table.pivot-table tbody').scrollLeft(); clearInterval(checkIfPivotTableLoaded); } else if ($('table.pivot-table tbody tr').length < 12) { $('.btn-scroll-right, .btn-scroll-left').attr("disabled", true); clearInterval(checkIfPivotTableLoaded); } }, 1000, 2); var pivotDataPromise = pivotTableService.getPivotTableFor(scope.patientUuid, scope.config, scope.visitUuid, startDate, endDate); spinner.forPromise(pivotDataPromise, element); pivotDataPromise.then(function (response) { var concepts = _.map(response.data.conceptDetails, function (conceptDetail) { return { name: conceptDetail.fullName, shortName: conceptDetail.name, lowNormal: conceptDetail.lowNormal, hiNormal: conceptDetail.hiNormal, units: conceptDetail.units }; }); var tabluarDataInAscOrderByDate = _(response.data.tabularData).toPairs().sortBy(0).fromPairs().value(); scope.result = {concepts: concepts, tabularData: tabluarDataInAscOrderByDate}; scope.hasData = !_.isEmpty(scope.result.tabularData); scope.status = scope.status || {}; scope.status.data = scope.hasData; }); scope.showOnPrint = !$rootScope.isBeingPrinted; }, templateUrl: '../common/displaycontrols/pivottable/views/pivotTable.html' }; }]); 'use strict'; angular.module('bahmni.common.displaycontrol.pivottable') .service('pivotTableService', ['$http', function ($http) { this.getPivotTableFor = function (patientUuid, diseaseSummaryConfig, visitUuid, startDate, endDate) { return $http.get(Bahmni.Common.Constants.diseaseSummaryPivotUrl, { params: { patientUuid: patientUuid, visit: visitUuid, numberOfVisits: diseaseSummaryConfig["numberOfVisits"], initialCount: diseaseSummaryConfig["initialCount"], latestCount: diseaseSummaryConfig["latestCount"], obsConcepts: diseaseSummaryConfig["obsConcepts"], drugConcepts: diseaseSummaryConfig["drugConcepts"], labConcepts: diseaseSummaryConfig["labConcepts"], groupBy: diseaseSummaryConfig["groupBy"], startDate: Bahmni.Common.Util.DateUtil.parseLongDateToServerFormat(startDate), endDate: Bahmni.Common.Util.DateUtil.parseLongDateToServerFormat(endDate) } }); }; }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.DisplayControl = Bahmni.Common.DisplayControl || {}; Bahmni.Common.DisplayControl.Custom = Bahmni.Common.DisplayControl.Custom || {}; angular.module('bahmni.common.displaycontrol.custom', []); 'use strict'; angular.module('bahmni.common.displaycontrol.custom') .directive('customDisplayControl', [function () { return { restrict: 'E', template: '
', scope: { patient: "=", visitUuid: "=", section: "=", config: "=", enrollment: "=", params: "=", visitSummary: '=' } }; }]); var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.Obs = Bahmni.Common.Obs || {}; angular.module('bahmni.common.obs', []); 'use strict'; Bahmni.Common.Obs.Observation = (function () { var Observation = function (obs, conceptConfig) { angular.extend(this, obs); this.concept = obs.concept; this.conceptConfig = conceptConfig; }; Observation.prototype = { isFormElement: function () { return this.groupMembers && this.groupMembers.length <= 0; }, isImageConcept: function () { return this.concept.conceptClass === "Image"; }, isVideoConcept: function () { return this.concept.conceptClass === "Video"; }, hasPDFAsValue: function () { return (this.value.indexOf(".pdf") > 0); }, isComplexConcept: function () { return this.concept.dataType === "Complex"; }, getComplexDataType: function () { return this.complexData ? this.complexData.dataType : null; }, isLocationRef: function () { return this.isComplexConcept() && this.getComplexDataType() === "Location"; }, isProviderRef: function () { return this.isComplexConcept() && this.getComplexDataType() === "Provider"; }, getDisplayValue: function () { var value; if (this.type === "Boolean" || this.concept && this.concept.dataType === "Boolean") { return this.value === true ? "OBS_BOOLEAN_YES_KEY" : "OBS_BOOLEAN_NO_KEY"; } if (this.type === "Datetime" || this.concept && this.concept.dataType === "Datetime") { var date = Bahmni.Common.Util.DateUtil.parseDatetime(this.value); return date != null ? Bahmni.Common.Util.DateUtil.formatDateWithTime(date) : ""; } if (this.conceptConfig && this.conceptConfig.displayMonthAndYear) { value = Bahmni.Common.Util.DateUtil.getDateInMonthsAndYears(this.value); if (value != null) { return value; } } if (this.type === "Date" || this.concept && this.concept.dataType === "Date") { return this.value ? Bahmni.Common.Util.DateUtil.formatDateWithoutTime(this.value) : ""; } if (this.isLocationRef()) { return this.complexData.display; } if (this.isProviderRef()) { return this.complexData.display; } value = this.value; var displayValue = value && (value.shortName || (value.name && (value.name.name || value.name)) || value); if (this.duration) { displayValue = displayValue + " " + this.getDurationDisplayValue(); } return displayValue; }, getDurationDisplayValue: function () { var durationForDisplay = Bahmni.Common.Util.DateUtil.convertToUnits(this.duration); return "since " + durationForDisplay["value"] + " " + durationForDisplay["unitName"]; } }; return Observation; })(); 'use strict'; Bahmni.Common.Obs.MultiSelectObservation = (function () { var MultiSelectObservation = function (groupMembers, conceptConfig) { this.type = "multiSelect"; this.concept = groupMembers[0].concept; this.encounterDateTime = groupMembers[0].encounterDateTime; this.groupMembers = groupMembers; this.conceptConfig = conceptConfig; this.observationDateTime = getLatestObservationDateTime(this.groupMembers); this.providers = groupMembers[0].providers; this.creatorName = groupMembers[0].creatorName; }; var getLatestObservationDateTime = function (groupMembers) { var latestObservationDateTime = groupMembers[0].observationDateTime; groupMembers.forEach(function (member) { latestObservationDateTime = latestObservationDateTime < member.observationDateTime ? member.observationDateTime : latestObservationDateTime; }); return latestObservationDateTime; }; MultiSelectObservation.prototype = { isFormElement: function () { return true; }, getDisplayValue: function () { var getName = Bahmni.Common.Domain.ObservationValueMapper.getNameFor["Object"]; return _.map(this.groupMembers, getName).join(", "); } }; return MultiSelectObservation; })(); 'use strict'; Bahmni.Common.Obs.GridObservation = (function () { var conceptMapper = new Bahmni.Common.Domain.ConceptMapper(); var GridObservation = function (obs, conceptConfig) { angular.extend(this, obs); this.type = "grid"; this.conceptConfig = conceptConfig; }; var getObservationDisplayValue = function (observation) { if (observation.isBoolean || observation.type === "Boolean") { return observation.value === true ? "OBS_BOOLEAN_YES_KEY" : "OBS_BOOLEAN_NO_KEY"; } if (!observation.value) { return ""; } if (typeof observation.value.name === 'object') { var valueConcept = conceptMapper.map(observation.value); return valueConcept.shortName || valueConcept.name; } return observation.value.shortName || observation.value.name || observation.value; }; GridObservation.prototype = { isFormElement: function () { return true; }, getDisplayValue: function () { var gridObservationDisplayValue = _.compact(_.map(this.groupMembers, function (member) { return getObservationDisplayValue(member); })).join(', '); return gridObservationDisplayValue || this.value; } }; return GridObservation; })(); 'use strict'; Bahmni.Common.Obs.ImageObservation = function (observation, concept, provider) { this.concept = concept; this.imageObservation = observation; this.dateTime = observation.observationDateTime; this.provider = provider; }; 'use strict'; Bahmni.Common.Obs.ObservationMapper = function () { var conceptMapper = new Bahmni.Common.Domain.ConceptMapper(); this.map = function (bahmniObservations, allConceptsConfig, dontSortByObsDateTime) { var mappedObservations = mapObservations(bahmniObservations, allConceptsConfig, dontSortByObsDateTime); return mapUIObservations(mappedObservations, allConceptsConfig); }; var mapObservations = function (bahmniObservations, allConceptsConfig, dontSortByObsDateTime) { var mappedObservations = []; if (dontSortByObsDateTime) { bahmniObservations = _.flatten(bahmniObservations); } else { bahmniObservations = Bahmni.Common.Obs.ObservationUtil.sortSameConceptsWithObsDateTime(bahmniObservations); } $.each(bahmniObservations, function (i, bahmniObservation) { var conceptConfig = allConceptsConfig[bahmniObservation.concept.name] || []; var observation = new Bahmni.Common.Obs.Observation(bahmniObservation, conceptConfig); if (observation.groupMembers && observation.groupMembers.length >= 0) { observation.groupMembers = mapObservations(observation.groupMembers, allConceptsConfig, dontSortByObsDateTime); } mappedObservations.push(observation); }); return mappedObservations; }; var mapUIObservations = function (observations, allConceptsConfig) { var groupedObservations = _.groupBy(observations, function (observation) { return observation.concept.name; }); var mappedObservations = []; $.each(groupedObservations, function (i, obsGroup) { var conceptConfig = allConceptsConfig[obsGroup[0].concept.name] || []; if (conceptConfig.multiSelect) { var multiSelectObservations = {}; $.each(obsGroup, function (i, observation) { if (multiSelectObservations[observation.encounterDateTime]) { multiSelectObservations[observation.encounterDateTime].push(observation); } else { var observations = []; observations.push(observation); multiSelectObservations[observation.encounterDateTime] = observations; } }); $.each(multiSelectObservations, function (i, observations) { mappedObservations.push(new Bahmni.Common.Obs.MultiSelectObservation(observations, conceptConfig)); }); } else if (conceptConfig.grid) { mappedObservations.push(new Bahmni.Common.Obs.GridObservation(obsGroup[0], conceptConfig)); } else { $.each(obsGroup, function (i, obs) { obs.groupMembers = mapUIObservations(obs.groupMembers, allConceptsConfig); mappedObservations.push(obs); }); } }); return mappedObservations; }; this.getGridObservationDisplayValue = function (observationTemplate) { var memberValues = _.compact(_.map(observationTemplate.bahmniObservations, function (observation) { return getObservationDisplayValue(observation); })); return memberValues.join(', '); }; var getObservationDisplayValue = function (observation) { if (observation.isBoolean || observation.type === "Boolean") { return observation.value === true ? "Yes" : "No"; } if (!observation.value) { return ""; } if (typeof observation.value.name === 'object') { var valueConcept = conceptMapper.map(observation.value); return valueConcept.shortName || valueConcept.name; } return observation.value.shortName || observation.value.name || observation.value; }; }; 'use strict'; angular.module('bahmni.common.obs') .directive('showObservation', ['ngDialog', function (ngDialog) { var controller = function ($scope, $rootScope, $filter) { $scope.toggle = function (observation) { observation.showDetails = !observation.showDetails; }; $scope.print = $rootScope.isBeingPrinted || false; $scope.dateString = function (observation) { var filterName; if ($scope.showDate && $scope.showTime) { filterName = 'bahmniDateTime'; } else if (!$scope.showDate && ($scope.showTime || $scope.showTime === undefined)) { filterName = 'bahmniTime'; } else { return null; } return $filter(filterName)(observation.observationDateTime); }; $scope.openVideoInPopup = function (observation) { ngDialog.open({ template: "../common/obs/views/showVideo.html", closeByDocument: false, className: 'ngdialog-theme-default', showClose: true, data: { observation: observation } }); }; }; return { restrict: 'E', scope: { observation: "=?", patient: "=", showDate: "=?", showTime: "=?", showDetailsButton: "=?" }, controller: controller, template: '' }; }]); 'use strict'; Bahmni.Common.Obs.ObservationUtil = (function () { var sortSameConceptsWithObsDateTime = function (observation) { var sortedObservations = []; for (var i = 0; i < observation.length; i++) { if (i !== observation.length - 1) { if (observation[i].conceptUuid !== observation[i + 1].conceptUuid) { sortedObservations.push(observation[i]); } else { var sameConceptsSubArray = []; var j = i + 1; sameConceptsSubArray.push(observation[i]); while (j < observation.length && observation[i].conceptUuid === observation[j].conceptUuid) { sameConceptsSubArray.push(observation[j++]); } sameConceptsSubArray = _.sortBy(sameConceptsSubArray, 'observationDateTime'); sortedObservations.push(sameConceptsSubArray); i = j - 1; } } else { sortedObservations.push(observation[i]); } } return _.flatten(sortedObservations); }; var getValue = function (observation) { if (observation.selectedObs) { return observation.getValues(); } var obsValue; if (observation.value && observation.value.name && observation.value.name.name) { obsValue = observation.value.name.name; } else if (observation.value && observation.value.name && !observation.value.name.name) { obsValue = observation.value.name; } else { obsValue = observation.value; } return (obsValue === undefined || obsValue === null) ? obsValue : (obsValue.displayString || obsValue); }; var collect = function (flattenedObservations, key, value) { if (value != undefined) { flattenedObservations[key] = flattenedObservations[key] ? _.uniq(_.flatten(_.union([flattenedObservations[key]], [value]))) : value; } }; var findLeafObservations = function (flattenedObservations, observation) { if (!_.isEmpty(observation.groupMembers)) { _.each(observation.groupMembers, function (member) { findLeafObservations(flattenedObservations, member); }); } else { collect(flattenedObservations, observation.concept.name, getValue(observation)); } }; var flatten = function (observation) { var flattenedObservation = {}; if (!_.isEmpty(observation)) { findLeafObservations(flattenedObservation, observation); } return flattenedObservation; }; var flattenObsToArray = function (observations) { var flattened = []; flattened.push.apply(flattened, observations); observations.forEach(function (obs) { if (obs.groupMembers && obs.groupMembers.length > 0) { flattened.push.apply(flattened, flattenObsToArray(obs.groupMembers)); } }); return flattened; }; return { sortSameConceptsWithObsDateTime: sortSameConceptsWithObsDateTime, flatten: flatten, flattenObsToArray: flattenObsToArray }; })(); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.DisplayControl = Bahmni.Common.DisplayControl || {}; Bahmni.Common.DisplayControl.hint = Bahmni.Common.DisplayControl.hint || {}; angular.module('bahmni.common.displaycontrol.hint', []); 'use strict'; angular.module('bahmni.common.displaycontrol.hint') .directive('hint', [ function () { var link = function ($scope) { $scope.hintForNumericConcept = Bahmni.Common.Domain.Helper.getHintForNumericConcept($scope.conceptDetails); }; return { restrict: 'E', link: link, template: '{{::hintForNumericConcept}}', scope: { conceptDetails: "=" } }; }]); 'use strict'; Bahmni.Common.Domain.Diagnosis = function (codedAnswer, order, certainty, existingObsUuid, freeTextAnswer, diagnosisDateTime, voided) { var self = this; self.codedAnswer = codedAnswer; self.order = order; self.certainty = certainty; self.existingObs = existingObsUuid; self.freeTextAnswer = freeTextAnswer; self.diagnosisDateTime = diagnosisDateTime; self.diagnosisStatus = undefined; self.isNonCodedAnswer = false; if (self.codedAnswer) { self.conceptName = self.codedAnswer.name; } self.voided = voided; self.firstDiagnosis = null; self.comments = ""; self.getDisplayName = function () { if (self.freeTextAnswer) { return self.freeTextAnswer; } else { return self.codedAnswer.shortName || self.codedAnswer.name; } }; self.isPrimary = function () { return self.order == "PRIMARY"; }; self.isSecondary = function () { return self.order == "SECONDARY"; }; self.isRuledOut = function () { return self.diagnosisStatus == $rootScope.diagnosisStatus; }; self.answerNotFilled = function () { return !self.codedAnswer.name; }; self.isValidAnswer = function () { return (self.codedAnswer.name && self.codedAnswer.uuid) || (self.codedAnswer.name && !self.codedAnswer.uuid && self.isNonCodedAnswer) || self.answerNotFilled(); }; self.isValidOrder = function () { return self.isEmpty() || self.order !== undefined; }; self.isValidCertainty = function () { return self.isEmpty() || self.certainty !== undefined; }; self.isEmpty = function () { return self.getDisplayName() === undefined || self.getDisplayName().length === 0; }; self.diagnosisStatusValue = null; self.diagnosisStatusConcept = null; Object.defineProperty(this, 'diagnosisStatus', { get: function () { return this.diagnosisStatusValue; }, set: function (newStatus) { if (newStatus) { this.diagnosisStatusValue = newStatus; this.diagnosisStatusConcept = { name: Bahmni.Common.Constants.ruledOutdiagnosisStatus}; } else { this.diagnosisStatusValue = null; this.diagnosisStatusConcept = null; } } }); self.clearCodedAnswerUuid = function () { self.codedAnswer.uuid = undefined; }; self.setAsNonCodedAnswer = function () { self.isNonCodedAnswer = !self.isNonCodedAnswer; }; }; 'use strict'; Bahmni.DiagnosisMapper = function (diagnosisStatus) { var self = this; var mapDiagnosis = function (diagnosis) { if (!diagnosis.codedAnswer) { diagnosis.codedAnswer = { name: undefined, uuid: undefined }; } var mappedDiagnosis = angular.extend(new Bahmni.Common.Domain.Diagnosis(), diagnosis); if (mappedDiagnosis.firstDiagnosis) { mappedDiagnosis.firstDiagnosis = mapDiagnosis(mappedDiagnosis.firstDiagnosis); } if (mappedDiagnosis.latestDiagnosis) { mappedDiagnosis.latestDiagnosis = mapDiagnosis(mappedDiagnosis.latestDiagnosis); } if (diagnosis.diagnosisStatusConcept) { if (Bahmni.Common.Constants.ruledOutdiagnosisStatus === diagnosis.diagnosisStatusConcept.name) { mappedDiagnosis.diagnosisStatus = diagnosisStatus; } } return mappedDiagnosis; }; self.mapDiagnosis = mapDiagnosis; self.mapDiagnoses = function (diagnoses) { var mappedDiagnoses = []; _.each(diagnoses, function (diagnosis) { mappedDiagnoses.push(mapDiagnosis(diagnosis)); }); return mappedDiagnoses; }; self.mapPastDiagnosis = function (diagnoses, currentEncounterUuid) { var pastDiagnosesResponse = []; diagnoses.forEach(function (diagnosis) { if (diagnosis.encounterUuid !== currentEncounterUuid) { diagnosis.previousObs = diagnosis.existingObs; diagnosis.existingObs = null; diagnosis.inCurrentEncounter = undefined; pastDiagnosesResponse.push(diagnosis); } }); return pastDiagnosesResponse; }; self.mapSavedDiagnosesFromCurrentEncounter = function (diagnoses, currentEncounterUuid) { var savedDiagnosesFromCurrentEncounter = []; diagnoses.forEach(function (diagnosis) { if (diagnosis.encounterUuid === currentEncounterUuid) { diagnosis.inCurrentEncounter = true; savedDiagnosesFromCurrentEncounter.push(diagnosis); } }); return savedDiagnosesFromCurrentEncounter; }; }; 'use strict'; angular.module('bahmni.common.domain') .service('diagnosisService', ['$http', '$rootScope', function ($http, $rootScope) { var self = this; this.getAllFor = function (searchTerm) { var url = Bahmni.Common.Constants.emrapiConceptUrl; return $http.get(url, { params: {term: searchTerm, limit: 20} }); }; this.getDiagnoses = function (patientUuid, visitUuid) { var url = Bahmni.Common.Constants.bahmniDiagnosisUrl; return $http.get(url, { params: { patientUuid: patientUuid, visitUuid: visitUuid} }); }; this.deleteDiagnosis = function (obsUuid) { var url = Bahmni.Common.Constants.bahmniDeleteDiagnosisUrl; return $http.get(url, { params: {obsUuid: obsUuid} }); }; this.getDiagnosisConceptSet = function () { return $http.get(Bahmni.Common.Constants.conceptUrl, { method: "GET", params: { v: 'custom:(uuid,name,setMembers)', code: Bahmni.Common.Constants.diagnosisConceptSet, source: Bahmni.Common.Constants.emrapiConceptMappingSource }, withCredentials: true }); }; this.getPastAndCurrentDiagnoses = function (patientUuid, encounterUuid) { return self.getDiagnoses(patientUuid).then(function (response) { var diagnosisMapper = new Bahmni.DiagnosisMapper($rootScope.diagnosisStatus); var allDiagnoses = diagnosisMapper.mapDiagnoses(response.data); var pastDiagnoses = diagnosisMapper.mapPastDiagnosis(allDiagnoses, encounterUuid); var savedDiagnosesFromCurrentEncounter = diagnosisMapper.mapSavedDiagnosesFromCurrentEncounter(allDiagnoses, encounterUuid); return { "pastDiagnoses": pastDiagnoses, "savedDiagnosesFromCurrentEncounter": savedDiagnosesFromCurrentEncounter }; }); }; this.populateDiagnosisInformation = function (patientUuid, consultation) { return this.getPastAndCurrentDiagnoses(patientUuid, consultation.encounterUuid).then(function (diagnosis) { consultation.pastDiagnoses = diagnosis.pastDiagnoses; consultation.savedDiagnosesFromCurrentEncounter = diagnosis.savedDiagnosesFromCurrentEncounter; return consultation; }); }; }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.DisplayControl = Bahmni.Common.DisplayControl || {}; Bahmni.Common.DisplayControl.Diagnosis = Bahmni.Common.DisplayControl.Diagnosis || {}; angular.module('bahmni.common.displaycontrol.diagnosis', []); 'use strict'; angular.module('bahmni.common.displaycontrol.diagnosis') .filter('primaryDiagnosisFirst', function () { return function (diagnoses) { var primaryDiagnoses = _.filter(diagnoses, function (diagnosis) { return diagnosis.isPrimary(); }); var otherDiagnoses = _.filter(diagnoses, function (diagnosis) { return !diagnosis.isPrimary(); }); return primaryDiagnoses.concat(otherDiagnoses); }; }); 'use strict'; angular.module('bahmni.common.displaycontrol.diagnosis') .directive('bahmniDiagnosis', ['diagnosisService', '$q', 'spinner', '$rootScope', '$filter', function (diagnosisService, $q, spinner, $rootScope, $filter) { var controller = function ($scope) { var getAllDiagnosis = function () { return diagnosisService.getDiagnoses($scope.patientUuid, $scope.visitUuid).then(function (response) { var diagnosisMapper = new Bahmni.DiagnosisMapper($rootScope.diagnosisStatus); $scope.allDiagnoses = diagnosisMapper.mapDiagnoses(response.data); if ($scope.showRuledOutDiagnoses == false) { $scope.allDiagnoses = _.filter($scope.allDiagnoses, function (diagnoses) { return diagnoses.diagnosisStatus !== $rootScope.diagnosisStatus; }); } $scope.isDataPresent = function () { if ($scope.allDiagnoses && $scope.allDiagnoses.length == 0) { $scope.$emit("no-data-present-event"); return false; } return true; }; }); }; $scope.title = $scope.config.title; $scope.toggle = function (diagnosis, toggleLatest) { if (toggleLatest) { diagnosis.showDetails = false; diagnosis.showLatestDetails = !diagnosis.showLatestDetails; } else { diagnosis.showLatestDetails = false; diagnosis.showDetails = !diagnosis.showDetails; } }; var getPromises = function () { return [getAllDiagnosis()]; }; $scope.isLatestDiagnosis = function (diagnosis) { return diagnosis.latestDiagnosis ? diagnosis.existingObs == diagnosis.latestDiagnosis.existingObs : false; }; $scope.initialization = $q.all(getPromises()); }; var link = function ($scope, element) { spinner.forPromise($scope.initialization, element); }; return { restrict: 'E', controller: controller, link: link, templateUrl: "../common/displaycontrols/diagnosis/views/diagnosisDisplayControl.html", scope: { patientUuid: "=", config: "=", visitUuid: "=?", showRuledOutDiagnoses: "=?", hideTitle: "=?", showLatestDiagnosis: "@showLatestDiagnosis" } }; }]); 'use strict'; var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.I18n = Bahmni.Common.I18n || {}; angular.module('bahmni.common.i18n', []); 'use strict'; angular.module('bahmni.common.i18n', ['pascalprecht.translate']) .provider('$bahmniTranslate', ['$translateProvider', function ($translateProvider) { this.init = function (options) { var preferredLanguage = window.localStorage["NG_TRANSLATE_LANG_KEY"] || "en"; $translateProvider.useLoader('mergeLocaleFilesService', options); $translateProvider.useSanitizeValueStrategy('escaped'); $translateProvider.preferredLanguage(preferredLanguage); $translateProvider.useLocalStorage(); }; this.$get = [function () { return $translateProvider; }]; } ]) .filter('titleTranslate', ['$translate', function ($translate) { return function (input) { if (!input) { return input; } if (input.translationKey) { return $translate.instant(input.translationKey); } if (input.dashboardName) { return input.dashboardName; } if (input.title) { return input.title; } if (input.label) { return input.label; } if (input.display) { return input.display; } return $translate.instant(input); }; }]); 'use strict'; angular.module('bahmni.common.i18n') .service('mergeLocaleFilesService', ['$http', '$q', 'mergeService', function ($http, $q, mergeService) { return function (options) { var baseLocaleUrl = '../i18n/'; var customLocaleUrl = Bahmni.Common.Constants.rootDir + '/bahmni_config/openmrs/i18n/'; var loadFile = function (url) { return $http.get(url, {withCredentials: true}); }; var mergeLocaleFile = function (options) { var fileURL = options.app + "/locale_" + options.key + ".json"; var loadBahmniTranslations = function () { return loadFile(baseLocaleUrl + fileURL).then(function (result) { return result; }, function () { return; }); }; var loadCustomTranslations = function () { return loadFile(customLocaleUrl + fileURL).then(function (result) { return result; }, function () { return; }); }; var mergeTranslations = function (result) { var baseFileData = result[0] ? result[0].data : undefined; var customFileData = result[1] ? result[1].data : undefined; if (options.shouldMerge || options.shouldMerge === undefined) { return mergeService.merge(baseFileData, customFileData); } return [baseFileData, customFileData]; }; return $q.all([loadBahmniTranslations(), loadCustomTranslations()]) .then(mergeTranslations); }; return mergeLocaleFile(options); }; }]); var Bahmni = Bahmni || {}; Bahmni.Registration = Bahmni.Registration || {}; Bahmni.Registration.AttributesConditions = Bahmni.Registration.AttributesConditions || {}; angular.module('bahmni.registration', ['ui.router', 'bahmni.common.config', 'bahmni.common.domain', 'bahmni.common.util', 'bahmni.common.uiHelper', 'bahmni.common.conceptSet', 'infinite-scroll', 'bahmni.common.patient', 'bahmni.common.logging', 'pascalprecht.translate']); 'use strict'; angular .module('registration', ['ui.router', 'bahmni.registration', 'authentication', 'bahmni.common.config', 'bahmni.common.appFramework', 'httpErrorInterceptor', 'bahmni.common.photoCapture', 'bahmni.common.obs', 'bahmni.common.displaycontrol.observation', 'bahmni.common.i18n', 'bahmni.common.displaycontrol.custom', 'bahmni.common.routeErrorHandler', 'bahmni.common.displaycontrol.pivottable', 'RecursionHelper', 'ngSanitize', 'bahmni.common.uiHelper', 'bahmni.common.domain', 'ngDialog', 'pascalprecht.translate', 'ngCookies', 'monospaced.elastic', 'bahmni.common.displaycontrol.hint', 'bahmni.common.attributeTypes', 'bahmni.common.models', 'bahmni.common.uicontrols', 'bahmni.common.displaycontrol.diagnosis']) .config(['$urlRouterProvider', '$stateProvider', '$httpProvider', '$bahmniTranslateProvider', '$compileProvider', function ($urlRouterProvider, $stateProvider, $httpProvider, $bahmniTranslateProvider, $compileProvider) { $httpProvider.defaults.headers.common['Disable-WWW-Authenticate'] = true; $urlRouterProvider.otherwise('/search'); $compileProvider.debugInfoEnabled(false); $stateProvider .state('search', { url: '/search', reloadOnSearch: false, views: { 'layout': {templateUrl: 'views/layout.html', controller: 'SearchPatientController'}, 'content@search': {templateUrl: 'views/search.html'} }, resolve: { initialize: function (initialization) { return initialization(); } } }) .state('newpatient', { url: '/patient/new', views: { 'layout': {templateUrl: 'views/layout.html', controller: 'CreatePatientController'}, 'content@newpatient': {templateUrl: 'views/newpatient.html'} }, resolve: { initialize: function (initialization) { return initialization(); } } }) .state('patient', { url: '/patient/:patientUuid', abstract: true, views: { 'layout': {template: '
'} }, resolve: { initialize: function (initialization) { return initialization(); } } }) .state('patient.edit', { url: '?serverError', views: { 'layout': {templateUrl: 'views/layout.html', controller: 'EditPatientController'}, 'content@patient.edit': {templateUrl: 'views/editpatient.html'}, 'headerExtension@patient.edit': {} } }) .state('patient.visit', { url: '/visit', views: { 'layout': {templateUrl: 'views/layout.html', controller: 'VisitController'}, 'content@patient.visit': {templateUrl: 'views/visit.html'}, 'headerExtension@patient.visit': {template: '
'} } }) .state('patient.printSticker', { url: '/printSticker', views: { 'layout': {templateUrl: 'views/layout.html'}, 'content@patient.printSticker': {templateUrl: 'views/notimplemented.html'} } }); $bahmniTranslateProvider.init({app: 'registration', shouldMerge: true}); }]).run(['$rootScope', '$templateCache', '$bahmniCookieStore', 'locationService', 'messagingService', 'auditLogService', '$window', function ($rootScope, $templateCache, $bahmniCookieStore, locationService, messagingService, auditLogService, $window) { var getStates = function (toState, fromState) { var states = []; if (fromState === "newpatient" && (toState === "patient.edit" || toState === "patient.visit")) { states.push("newpatient.save"); } if (toState === 'patient.edit') { states.push("patient.view"); } else { states.push(toState); } return states; }; moment.locale($window.localStorage["NG_TRANSLATE_LANG_KEY"] || "en"); var loginLocationUuid = $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName).uuid; locationService.getVisitLocation(loginLocationUuid).then(function (response) { if (response.data) { $rootScope.visitLocation = response.data.uuid; } }); $rootScope.$on('$stateChangeStart', function () { messagingService.hideMessages("error"); }); $rootScope.createAuditLog = function (event, toState, toParams, fromState) { var states = getStates(toState.name, fromState.name); states.forEach(function (state) { auditLogService.log(toParams.patientUuid, Bahmni.Registration.StateNameEvenTypeMap[state], undefined, "MODULE_LABEL_REGISTRATION_KEY"); }); }; $rootScope.$on('$stateChangeSuccess', $rootScope.createAuditLog); } ]); 'use strict'; angular.module('bahmni.registration').factory('initialization', ['$rootScope', '$q', 'configurations', 'authenticator', 'appService', 'spinner', 'preferences', 'locationService', 'mergeService', function ($rootScope, $q, configurations, authenticator, appService, spinner, preferences, locationService, mergeService) { var getConfigs = function () { var configNames = ['encounterConfig', 'patientAttributesConfig', 'identifierTypesConfig', 'addressLevels', 'genderMap', 'relationshipTypeConfig', 'relationshipTypeMap', 'loginLocationToVisitTypeMapping']; return configurations.load(configNames).then(function () { var mandatoryPersonAttributes = appService.getAppDescriptor().getConfigValue("mandatoryPersonAttributes"); var patientAttributeTypes = new Bahmni.Common.Domain.AttributeTypeMapper().mapFromOpenmrsAttributeTypes(configurations.patientAttributesConfig(), mandatoryPersonAttributes); $rootScope.regEncounterConfiguration = angular.extend(new Bahmni.Registration.RegistrationEncounterConfig(), configurations.encounterConfig()); $rootScope.encounterConfig = angular.extend(new EncounterConfig(), configurations.encounterConfig()); $rootScope.patientConfiguration = new Bahmni.Registration.PatientConfig(patientAttributeTypes.attributeTypes, configurations.identifierTypesConfig(), appService.getAppDescriptor().getConfigValue("patientInformation")); $rootScope.regEncounterConfiguration.loginLocationToVisitTypeMap = configurations.loginLocationToVisitTypeMapping(); $rootScope.addressLevels = configurations.addressLevels(); $rootScope.fieldValidation = appService.getAppDescriptor().getConfigValue("fieldValidation"); $rootScope.genderMap = configurations.genderMap(); $rootScope.relationshipTypeMap = configurations.relationshipTypeMap(); $rootScope.relationshipTypes = configurations.relationshipTypes(); }); }; var loadValidators = function (baseUrl, contextPath) { var script = baseUrl + contextPath + '/fieldValidation.js'; Bahmni.Common.Util.DynamicResourceLoader.includeJs(script, false); }; var initApp = function () { return appService.initApp('registration', {'app': true, 'extension': true }); }; var getIdentifierPrefix = function () { preferences.identifierPrefix = appService.getAppDescriptor().getConfigValue("defaultIdentifierPrefix"); }; var initAppConfigs = function () { $rootScope.registration = $rootScope.registration || {}; getIdentifierPrefix(); }; var mapRelationsTypeWithSearch = function () { var relationshipTypeMap = $rootScope.relationshipTypeMap || {}; if (!relationshipTypeMap.provider) { return "patient"; } $rootScope.relationshipTypes.forEach(function (relationshipType) { relationshipType.searchType = (relationshipTypeMap.provider.indexOf(relationshipType.aIsToB) > -1) ? "provider" : "patient"; }); }; var loggedInLocation = function () { return locationService.getLoggedInLocation().then(function (location) { $rootScope.loggedInLocation = location; }); }; var mergeFormConditions = function () { var formConditions = Bahmni.ConceptSet.FormConditions; if (formConditions) { formConditions.rules = mergeService.merge(formConditions.rules, formConditions.rulesOverride); } }; var checkPrivilege = function () { return appService.checkPrivilege("app:registration"); }; return function () { return spinner.forPromise(authenticator.authenticateUser() .then(initApp) .then(checkPrivilege) .then(getConfigs) .then(initAppConfigs) .then(mapRelationsTypeWithSearch) .then(loggedInLocation) .then(loadValidators(appService.configBaseUrl(), "registration")) .then(mergeFormConditions) ); }; }] ); 'use strict'; /* exported defaults */ var defaults = { maxAutocompleteResults: 20 }; var Bahmni = Bahmni || {}; Bahmni.Registration = Bahmni.Registration || {}; var hostUrl = Bahmni.Common.Constants.hostURL; var RESTWS_V1 = hostUrl + "/openmrs/ws/rest/v1"; Bahmni.Registration.Constants = { openmrsUrl: hostUrl + "/openmrs", registrationEncounterType: "REG", baseOpenMRSRESTURL: RESTWS_V1, patientImageUrlByPatientUuid: RESTWS_V1 + "/patientImage?patientUuid=", bahmniRESTBaseURL: hostUrl + "/openmrs/ws/rest/v1/bahmnicore", emrApiRESTBaseURL: hostUrl + "/openmrs/ws/rest/emrapi", emrApiEncounterUrl: hostUrl + "/openmrs/ws/rest/emrapi/encounter", webServiceRestBaseURL: hostUrl + "/openmrs/ws/rest/v1", patientSearchURL: "/search", allAddressFileds: ["uuid", "preferred", "address1", "address2", "address3", "address4", "address5", "address6", "cityVillage", "countyDistrict", "stateProvince", "postalCode", "country", "latitude", "longitude"], nextStepConfigId: "org.bahmni.registration.patient.next" }; Bahmni.Registration.Constants.Errors = { manageIdentifierSequencePrivilege: "You don't have the privilege to create a patient with the given ID." }; 'use strict'; function getWatchers (element) { var elementToWatch = element ? angular.element(element) : angular.element(document.getElementsByTagName('body')); var watchers = []; var f = function (element) { angular.forEach(['$scope', '$isolateScope'], function (scopeProperty) { if (element.data() && element.data().hasOwnProperty(scopeProperty)) { angular.forEach(element.data()[scopeProperty].$$watchers, function (watcher) { watchers.push(watcher); }); } }); angular.forEach(element.children(), function (childElement) { f(angular.element(childElement)); }); }; f(elementToWatch); // Remove duplicate watchers var watchersWithoutDuplicates = []; angular.forEach(watchers, function (item) { if (watchersWithoutDuplicates.indexOf(item) < 0) { watchersWithoutDuplicates.push(item); } }); console.log(watchersWithoutDuplicates); return watchersWithoutDuplicates; } 'use strict'; angular.module('bahmni.common.patient') .directive('fallbackSrc', function () { return { restrict: 'A', link: function (scope, element, attrs) { if (_.isEmpty(attrs.ngSrc)) { element.attr('src', attrs.fallbackSrc); } element.bind('error', function () { element.attr('src', attrs.fallbackSrc); }); } }; }); 'use strict'; angular.module('bahmni.registration') .directive('addressFields', function () { return { restrict: 'AE', templateUrl: ' views/addressFields.html', controller: 'AddressFieldsDirectiveController', scope: { address: '=', addressLevels: '=', fieldValidation: '=', strictAutocompleteFromLevel: '=' } }; }) .controller('AddressFieldsDirectiveController', ['$scope', 'addressHierarchyService', function ($scope, addressHierarchyService) { var addressLevelsCloneInDescendingOrder = $scope.addressLevels.slice(0).reverse(); $scope.addressLevelsChunks = Bahmni.Common.Util.ArrayUtil.chunk(addressLevelsCloneInDescendingOrder, 2); var addressLevelsNamesInDescendingOrder = addressLevelsCloneInDescendingOrder.map(function (addressLevel) { return addressLevel.addressField; }); $scope.addressFieldSelected = function (fieldName) { return function (addressFieldItem) { var parentFields = addressLevelsNamesInDescendingOrder.slice(addressLevelsNamesInDescendingOrder.indexOf(fieldName) + 1); $scope.selectedValue[fieldName] = addressFieldItem.addressField.name; var parent = addressFieldItem.addressField.parent; parentFields.forEach(function (parentField) { if (!parent) { return; } $scope.address[parentField] = parent.name; $scope.selectedValue[parentField] = parent.name; parent = parent.parent; }); }; }; $scope.removeAutoCompleteEntry = function (fieldName) { return function () { $scope.selectedValue[fieldName] = null; }; }; $scope.getAddressEntryList = function (field) { return function (searchAttrs) { return addressHierarchyService.search(field, searchAttrs.term); }; }; $scope.getAddressDataResults = addressHierarchyService.getAddressDataResults; $scope.clearFields = function (fieldName) { var childFields = addressLevelsNamesInDescendingOrder.slice(0, addressLevelsNamesInDescendingOrder.indexOf(fieldName)); childFields.forEach(function (childField) { if (!_.isEmpty($scope.selectedValue[childField])) { $scope.address[childField] = null; $scope.selectedValue[childField] = null; } }); }; var init = function () { $scope.addressLevels.reverse(); var isStrictEntry = false; _.each($scope.addressLevels, function (addressLevel) { addressLevel.isStrictEntry = $scope.strictAutocompleteFromLevel == addressLevel.addressField || isStrictEntry; isStrictEntry = addressLevel.isStrictEntry; }); $scope.addressLevels.reverse(); // wait for address to be resolved in edit patient scenario var addressWatch = $scope.$watch('address', function (newValue) { if (newValue !== undefined) { $scope.selectedValue = _.mapValues($scope.address, function (value, key) { var addressLevel = _.find($scope.addressLevels, {addressField: key}); return addressLevel && addressLevel.isStrictEntry ? value : null; }); addressWatch(); } }); }; init(); }]); 'use strict'; angular.module('bahmni.registration') .directive('topDownAddressFields', function () { return { restrict: 'AE', templateUrl: 'views/topDownAddressFields.html', controller: 'TopDownAddressFieldsDirectiveController', scope: { address: '=', addressLevels: '=', fieldValidation: '=', strictAutocompleteFromLevel: '=' } }; }) .controller('TopDownAddressFieldsDirectiveController', ['$scope', 'addressHierarchyService', function ($scope, addressHierarchyService) { $scope.addressFieldInvalid = false; var selectedAddressUuids = {}; var selectedUserGeneratedIds = {}; var addressLevelsCloneInDescendingOrder = $scope.addressLevels.slice(0).reverse(); var addressLevelUIOrderBasedOnConfig = $scope.addressLevels; $scope.addressLevelsChunks = Bahmni.Common.Util.ArrayUtil.chunk(addressLevelUIOrderBasedOnConfig, 2); var addressLevelsNamesInDescendingOrder = addressLevelsCloneInDescendingOrder.map(function (addressLevel) { return addressLevel.addressField; }); var populateSelectedAddressUuids = function (levelIndex, parentUuid) { if ($scope.addressLevels.length === 0 || !$scope.addressLevels[levelIndex]) { return; } var fieldName = $scope.addressLevels[levelIndex].addressField; var addressValue = $scope.address[fieldName]; if (addressValue) { addressHierarchyService.search(fieldName, addressValue, parentUuid).then(function (response) { var address = response && response.data && response.data[0]; if (address) { selectedAddressUuids[fieldName] = address.uuid; selectedUserGeneratedIds[fieldName] = address.userGeneratedId; populateSelectedAddressUuids(levelIndex + 1, address.uuid); } }); } }; $scope.addressFieldSelected = function (fieldName) { return function (addressFieldItem) { selectedAddressUuids[fieldName] = addressFieldItem.addressField.uuid; selectedUserGeneratedIds[fieldName] = addressFieldItem.addressField.userGeneratedId; $scope.selectedValue[fieldName] = addressFieldItem.addressField.name; var parentFields = addressLevelsNamesInDescendingOrder.slice(addressLevelsNamesInDescendingOrder.indexOf(fieldName) + 1); var parent = addressFieldItem.addressField.parent; parentFields.forEach(function (parentField) { if (!parent) { return; } $scope.address[parentField] = parent.name; $scope.selectedValue[parentField] = parent.name; parent = parent.parent; }); }; }; $scope.findParentField = function (fieldName) { var found = _.find($scope.addressLevels, {addressField: fieldName}); var index = _.findIndex($scope.addressLevels, found); var parentFieldName; var topLevel = 0; if (index !== topLevel) { var parent = $scope.addressLevels[index - 1]; parentFieldName = parent.addressField; } return parentFieldName; }; $scope.isReadOnly = function (addressLevel) { if (!$scope.address) { return false; } if (!addressLevel.isStrictEntry) { return false; } var fieldName = addressLevel.addressField; var parentFieldName = $scope.findParentField(fieldName); var parentValue = $scope.address[parentFieldName]; var parentValueInvalid = isParentValueInvalid(parentFieldName); if (!parentFieldName) { return false; } if (parentFieldName && !parentValue) { return true; } return parentFieldName && parentValue && parentValueInvalid; }; var isParentValueInvalid = function (parentId) { return angular.element($("#" + parentId)).hasClass('illegalValue'); }; var parentUuid = function (field) { return selectedAddressUuids[$scope.findParentField(field)]; }; $scope.getAddressEntryList = function (field) { return function (searchAttrs) { return addressHierarchyService.search(field, searchAttrs.term, parentUuid(field)); }; }; $scope.getAddressDataResults = addressHierarchyService.getAddressDataResults; $scope.clearFields = function (fieldName) { var childFields = addressLevelsNamesInDescendingOrder.slice(0, addressLevelsNamesInDescendingOrder.indexOf(fieldName)); childFields.forEach(function (childField) { if ($scope.selectedValue[childField] !== null) { $scope.address[childField] = null; $scope.selectedValue[childField] = null; selectedAddressUuids[childField] = null; selectedUserGeneratedIds[childField] = null; } }); if (_.isEmpty($scope.address[fieldName])) { $scope.address[fieldName] = null; selectedUserGeneratedIds[fieldName] = null; } }; $scope.removeAutoCompleteEntry = function (fieldName) { return function () { $scope.selectedValue[fieldName] = null; }; }; var init = function () { $scope.addressLevels.reverse(); var isStrictEntry = false; _.each($scope.addressLevels, function (addressLevel) { addressLevel.isStrictEntry = $scope.strictAutocompleteFromLevel == addressLevel.addressField || isStrictEntry; isStrictEntry = addressLevel.isStrictEntry; }); $scope.addressLevels.reverse(); // wait for address to be resolved in edit patient scenario var deregisterAddressWatch = $scope.$watch('address', function (newValue) { if (newValue !== undefined) { populateSelectedAddressUuids(0); $scope.selectedValue = _.mapValues($scope.address, function (value, key) { var addressLevel = _.find($scope.addressLevels, {addressField: key}); return addressLevel && addressLevel.isStrictEntry ? value : null; }); deregisterAddressWatch(); } }); }; init(); }]); 'use strict'; angular.module("bahmni.registration") .directive("printOptions", ["$http", "$q", "$cookies", "$stateParams", "$rootScope", "registrationCardPrinter", "spinner", "appService", "$filter", function ($http, $q, $cookies, $stateParams, $rootScope, registrationCardPrinter, spinner, appService, $filter) { var controller = function ($scope) { $scope.printOptionsAdmission = appService.getAppDescriptor().getConfigValue("printOptions").filter(function (option) { return option.shortcutKey !== "r"; }); $scope.defaultPrintAdmission = $scope.printOptionsAdmission && $scope.printOptionsAdmission[0]; $scope.printOptions = appService.getAppDescriptor().getConfigValue("printOptions").filter(function (option) { return option.shortcutKey !== "i" && option.shortcutKey !== "r"; }); $scope.queueMng = appService.getAppDescriptor().getConfigValue("queueManagement"); $scope.defaultPrint = $scope.printOptions && $scope.printOptions[0]; $scope.printOptionsAdmissionForDev = appService.getAppDescriptor().getConfigValue("printOptions"); $scope.defaultPrintAdmissionForDev = $scope.printOptionsAdmissionForDev && $scope.printOptionsAdmissionForDev[0]; $scope.printOptionsForDev = appService.getAppDescriptor().getConfigValue("printOptions").filter(function (option) { return option.shortcutKey !== "i"; }); $scope.defaultPrintForDev = $scope.printOptionsForDev && $scope.printOptionsForDev[0]; var mapRegistrationObservations = function () { var obs = {}; $scope.observations = $scope.observations || []; var getValue = function (observation) { obs[observation.concept.name] = obs[observation.concept.name] || []; observation.value && obs[observation.concept.name].push(observation.value); observation.groupMembers.forEach(getValue); }; if ($scope.queueMng.willUse === true) { // var identifier = $scope.patient.primaryIdentifier.identifier; // var date = new Date(); // var formatDate = date.toISOString().split("T"); var getSerial = function () { return $http.get("/openmrs/module/queuemanagement/getToken.form?identifier=${identifier}&dateCreated=${formatDate[0]}", { method: "GET", withCredentials: true }); }; $q.all([getSerial()]).then(function (response) { $scope.observations.serial = response[0].data.token; }); } else { console.log("Queue management is not started"); } $scope.observations.forEach(getValue); var value = $cookies.get("bahmni.user.location"); if (JSON.parse(value).name === "Emergency") { $scope.observations = $scope.observations.filter(function (data) { return data.formFieldPath !== "Room To Assign.2/1-0"; }); } else { $scope.observations = $scope.observations.filter(function (data) { return data.formFieldPath !== "Room To Assign Emergency.1/1-0"; }); } var getDispositionProvider = function () { return $http.get("/openmrs/ws/rest/v1/obs?limit=1&concepts=Disposition&patient=${$stateParams.patientUuid}", { method: "GET", withCredentials: true }); }; var getTemporaryCategoryNotes = function () { return $http.get("/openmrs/ws/rest/v1/obs?patient=${$stateParams.patientUuid}&concept=Temporary%20Category", { method: "GET", withCredentials: true }); }; var getProviderDesignation = function (providerUuid) { var params = { q: "bahmni.sqlGet.providerDesignation2", v: "full", providerUuid: providerUuid }; return $http.get("/openmrs/ws/rest/v1/bahmnicore/sql", { method: "GET", params: params, withCredentials: true }); }; var getApiData = function (url) { return $http.get("/openmrs${url}", { method: "GET", withCredentials: true }); }; $q.all([getTemporaryCategoryNotes()]).then(function (response) { if (response[0].data.results.length > 0) { $q.all([getApiData(response[0].data.results[0].links[0].uri.split("/openmrs")[1])]).then(function (response) { $scope.observations.temporaryCategoryNotes = response[0].data.comment; }); } }); $q.all([getDispositionProvider()]).then(function (response) { if (response[0].data.results.length > 0) { $q.all([getApiData(response[0].data.results[0].links[0].uri.split("/openmrs")[1])]).then(function (response) { $q.all([getApiData(response[0].data.encounter.links[0].uri.split("/openmrs")[1])]).then(function (response) { $q.all([getApiData(response[0].data.encounterProviders[0].links[0].uri.split("/openmrs")[1])]).then(function (response) { $q.all([getApiData(response[0].data.provider.links[0].uri.split("/openmrs")[1])]).then(function (response) { $scope.observations.providerName = response[0].data.person.display; }); $q.all([getProviderDesignation(response[0].data.provider.uuid)]).then(function (response) { if (response[0].data.length > 0) { for (var i = 0; i < response[0].data.length; i++) { if (response[0].data[i].name === "Designation") { $scope.observations.providerDesignation = response[0].data[i].value_reference; } } } }); }); }); }); } }); var getDispositionNote = function () { return $http.get("/openmrs/ws/rest/v1/obs?limit=1&patient=${$stateParams.patientUuid}&concept=Disposition%20Set", { method: "GET", withCredentials: true }); }; $q.all([getDispositionNote()]).then(function (response) { if (response[0].data.results.length > 0) { $q.all([getApiData(response[0].data.results[0].links[0].uri.split("/openmrs")[1])]).then(function (response) { $scope.observations.dispositionSet = response[0].data.groupMembers.filter(function (data) { return data.concept.display === "Disposition"; }); $scope.observations.dispositionNote = response[0].data.groupMembers.filter(function (data) { return data.concept.display === "Disposition Note"; }); }); } }); var getRoomData = function (url) { return $http.get("/openmrs${url}", { method: "GET", withCredentials: true }); }; var getRoom = function () { return $http.get("/openmrs/ws/rest/v1/obs?limit=2&concepts=Opd%20Consultation%20Room&patient=${$stateParams.patientUuid}", { method: "GET", withCredentials: true }); }; $q.all([getRoom()]).then(function (response) { if (response[0].data.results.length === 1) { $scope.observations.previousDate = $scope.observations[1].encounterDateTime; } else if (response[0].data.results.length > 1) { $q.all([getRoomData(response[0].data.results[1].links[0].uri.split("/openmrs")[1])]).then(function (response) { $scope.observations.previousDate = response[0].data.obsDatetime; }); } }); return obs; }; $scope.print = function (option) { return registrationCardPrinter.print(option.templateUrl, $scope.patient, mapRegistrationObservations(), $scope.encounterDateTime, $scope.observations); }; $scope.buttonText = function (option, type) { var printHtml = ""; var optionValue = option && $filter('titleTranslate')(option); if (type) { printHtml = ''; } return '' + optionValue + '' + printHtml; }; }; return { restrict: 'A', templateUrl: 'views/printOptions.html', controller: controller }; }]); 'use strict'; angular.module('bahmni.registration') .directive('patientRelationship', function () { return { restrict: 'AE', templateUrl: 'views/patientRelationships.html', controller: 'PatientRelationshipController', scope: { patient: "=" } }; }) .controller('PatientRelationshipController', ['$window', '$scope', '$rootScope', 'spinner', 'patientService', 'providerService', 'appService', '$q', function ($window, $scope, $rootScope, spinner, patientService, providerService, appService, $q) { $scope.addPlaceholderRelationship = function () { $scope.patient.newlyAddedRelationships.push({}); }; $scope.removeRelationship = function (relationship, index) { if (relationship.uuid) { relationship.voided = true; $scope.patient.deletedRelationships.push(relationship); } else { $scope.patient.newlyAddedRelationships.splice(index, 1); } }; $scope.isPatientRelationship = function (relationship) { var relationshipType = getRelationshipType(relationship); return relationshipType && (_.isUndefined(relationshipType.searchType) || relationshipType.searchType === "patient"); }; var getRelationshipType = function (relationship) { if (angular.isUndefined(relationship['relationshipType'])) { return false; } return $scope.getRelationshipType(relationship.relationshipType.uuid); }; $scope.getChosenRelationshipType = function (relation) { if ($scope.isPatientRelationship(relation)) { return "patient"; } else if ($scope.isProviderRelationship(relation)) { return "provider"; } }; $scope.isProviderRelationship = function (relationship) { var relationshipType = getRelationshipType(relationship); return relationshipType && relationshipType.searchType === "provider"; }; $scope.getRelationshipType = function (uuid) { return _.find($scope.relationshipTypes, {uuid: uuid}); }; $scope.getRelationshipTypeForDisplay = function (relationship) { var personUuid = $scope.patient.uuid; var relationshipType = $scope.getRelationshipType(relationship.relationshipType.uuid); if (!relationship.personA) { return ""; } if (relationship.personA.uuid === personUuid) { return relationshipType.aIsToB; } else { return relationshipType.bIsToA; } }; $scope.getRelatedToPersonForDisplay = function (relationship) { var personRelatedTo = getPersonRelatedTo(relationship); return personRelatedTo ? personRelatedTo.display : ""; }; var getName = function (patient) { return patient.givenName + (patient.middleName ? " " + patient.middleName : "") + (patient.familyName ? " " + patient.familyName : ""); }; var getPersonB = function (personName, personUuid) { return {'display': personName, 'uuid': personUuid}; }; $scope.searchByPatientIdentifier = function (relationship) { if (!relationship.patientIdentifier) { relationship.personB = null; relationship.content = null; return; } if (relationship.hasOwnProperty('personB')) { relationship.personB = null; } return patientService.searchByIdentifier(relationship.patientIdentifier).then(function (response) { if (angular.isUndefined(response)) { return; } var patients = response.data.pageOfResults; if (patients.length === 0) { return; } relationship.content = getPatientGenderAndAge(patients[0]); var personUuid = patients[0]['uuid']; var personName = getName(patients[0]); relationship.personB = getPersonB(personName, personUuid); }); }; $scope.showPersonNotFound = function (relationship) { return (relationship.patientIdentifier && !relationship.personB) && $scope.getChosenRelationshipType(relationship) !== 'patient'; }; $scope.isInvalidRelation = function (relation) { return _.isEmpty(_.get(relation, "personB.uuid")) || $scope.duplicateRelationship(relation); }; $scope.duplicateRelationship = function (relationship) { if (_.isEmpty(relationship.relationshipType) || _.isEmpty(relationship.personB)) { return false; } var existingRelatives = getAlreadyAddedRelationshipPersonUuid($scope.patient, relationship.relationshipType.uuid); return _.get(_.countBy(existingRelatives, _.identity), relationship.personB.uuid, 0) > 1; }; var getPersonRelatedTo = function (relationship) { return relationship.personA && relationship.personA.uuid === $scope.patient.uuid ? relationship.personB : relationship.personA; }; $scope.openPatientDashboardInNewTab = function (relationship) { var personRelatedTo = getPersonRelatedTo(relationship); $window.open(getPatientRegistrationUrl(personRelatedTo.uuid), '_blank'); }; var getPatientRegistrationUrl = function (patientUuid) { return '#/patient/' + patientUuid; }; $scope.getProviderList = function () { return function (searchAttrs) { return providerService.search(searchAttrs.term); }; }; $scope.providerSelected = function (relationship) { return function (providerData) { relationship.providerName = providerData.identifier; relationship.personB = getPersonB(providerData.identifier, providerData.uuid); }; }; var clearPersonB = function (relationship, fieldName) { if (!relationship[fieldName]) { delete relationship.personB; } }; var getDeletedRelationshipUuids = function (patient, relationTypeUuid) { return getPersonUuidsForRelationship(patient.deletedRelationships, relationTypeUuid); }; var getNewlyAddedRelationshipPersonUuid = function (patient, relationTypeUuid) { return getPersonUuidsForRelationship(patient.newlyAddedRelationships, relationTypeUuid); }; var getPersonUuidsForRelationship = function (relationships, relationshipTypeUuid) { var uuids = []; _.each(relationships, function (relationship) { if (relationship.personB && relationship.relationshipType.uuid === relationshipTypeUuid) { uuids.push(relationship.personB.uuid); } }); return uuids; }; var getAlreadyAddedRelationshipPersonUuid = function (patient, relationTypeUuid) { var personUuids = _.concat(getPersonUuidsForRelationship(patient.relationships, relationTypeUuid), getNewlyAddedRelationshipPersonUuid(patient, relationTypeUuid)); return _.difference(personUuids, getDeletedRelationshipUuids(patient, relationTypeUuid)); }; $scope.clearProvider = function (relationship) { clearPersonB(relationship, 'providerName'); }; var getLimit = function (configName, defaultValue) { return appService.getAppDescriptor().getConfigValue(configName) || defaultValue; }; $scope.searchByPatientIdentifierOrName = function (searchAttrs) { var term = searchAttrs.term; if (term && term.length >= getLimit("minCharRequireToSearch", 1)) { return patientService.searchByNameOrIdentifier(term, getLimit("possibleRelativeSearchLimit", Bahmni.Common.Constants.defaultPossibleRelativeSearchLimit)); } return $q.when(); }; $scope.clearPatient = function (relationship) { clearPersonB(relationship, 'patientIdentifier'); }; $scope.patientSelected = function (relationship) { return function (patientData) { relationship.patientIdentifier = patientData.identifier; relationship.personB = getPersonB(patientData.value, patientData.uuid); }; }; $scope.getPatientList = function (response) { if (angular.isUndefined(response)) { return; } return response.data.pageOfResults.map(function (patient) { return { value: getName(patient) + " - " + patient.identifier, uuid: patient.uuid, identifier: patient.identifier }; }); }; $scope.getProviderDataResults = function (data) { return data.data.results.filter(function (provider) { return provider.person; }) .map(function (providerDetails) { return { 'value': providerDetails.display || providerDetails.person.display, 'uuid': providerDetails.person.uuid, 'identifier': providerDetails.identifier || providerDetails.person.display }; }); }; $scope.onEdit = function (relationship) { return function () { delete relationship.personB; }; }; $scope.clearRelationshipRow = function (relationship, index) { delete relationship.personB; delete relationship.patientIdentifier; delete relationship.providerName; delete relationship.endDate; delete relationship.content; managePlaceholderRelationshipRows(index); }; var managePlaceholderRelationshipRows = function (index) { var iter; for (iter = 0; iter < $scope.patient.newlyAddedRelationships.length; iter++) { if ($scope.isEmpty($scope.patient.newlyAddedRelationships[iter]) && iter !== index) { $scope.patient.newlyAddedRelationships.splice(iter, 1); } } var emptyRows = _.filter($scope.patient.newlyAddedRelationships, $scope.isEmpty); if (emptyRows.length === 0) { $scope.addPlaceholderRelationship(); } }; $scope.isEmpty = function (relationship) { return !relationship.relationshipType || !relationship.relationshipType.uuid; }; var getPatientGenderAndAge = function (patient) { var patientGenderAndAge = [patient.givenName, patient.age, $rootScope.genderMap[angular.uppercase(patient.gender)]]; return patientGenderAndAge.join(", "); }; var init = function () { $scope.relationshipTypes = $rootScope.relationshipTypes; $scope.patient.relationships = $scope.patient.relationships || []; }; init(); } ]); 'use strict'; angular.module('bahmni.registration') .controller('NavigationController', ['$scope', '$rootScope', '$location', 'sessionService', '$window', 'appService', '$sce', function ($scope, $rootScope, $location, sessionService, $window, appService, $sce) { $scope.extensions = appService.getAppDescriptor().getExtensions("org.bahmni.registration.navigation", "link"); $scope.goTo = function (url) { $location.url(url); }; $scope.htmlLabel = function (label) { return $sce.trustAsHtml(label); }; $scope.logout = function () { $rootScope.errorMessage = null; sessionService.destroy().then( function () { $window.location = "../home/"; } ); }; $scope.sync = function () { }; }]); 'use strict'; angular.module('bahmni.registration') .controller('SearchPatientController', ['$rootScope', '$timeout', '$scope', '$location', '$window', 'spinner', 'patientService', 'appService', 'messagingService', '$translate', '$filter', function ($rootScope, $timeout, $scope, $location, $window, spinner, patientService, appService, messagingService, $translate, $filter) { $scope.results = []; $scope.extraIdentifierTypes = _.filter($rootScope.patientConfiguration.identifierTypes, function (identifierType) { return !identifierType.primary; }); var hostName = $window.location.hostname; var baseUrl = "https://" + hostName; $scope.providerName = localStorage.getItem('providerName'); $scope.providerFacility = localStorage.getItem('providerFacility'); var searching = false; var maxAttributesFromConfig = 5; const healthIDEnable = appService.getAppDescriptor().getConfigValue("healthIdEnable"); var allSearchConfigs = appService.getAppDescriptor().getConfigValue("patientSearch") || {}; var patientSearchResultConfigs = appService.getAppDescriptor().getConfigValue("patientSearchResults") || {}; maxAttributesFromConfig = !_.isEmpty(allSearchConfigs.programAttributes) ? maxAttributesFromConfig - 1 : maxAttributesFromConfig; $window.localStorage.removeItem("healthId"); $scope.getAddressColumnName = function (column) { var columnName = ""; var columnCamelCase = column.replace(/([-_][a-z])/g, function ($1) { return $1.toUpperCase().replace(/[-_]/, ''); }); _.each($scope.addressLevels, function (addressLevel) { if (addressLevel.addressField === columnCamelCase) { columnName = addressLevel.name; } }); return columnName; }; $scope.selectedIdPreference = 'patientID'; $scope.idPreference = function (selectedValue) { $scope.selectedIdPreference = selectedValue; }; var hasSearchParameters = function () { return $scope.searchParameters.name.trim().length > 0 || $scope.searchParameters.addressFieldValue.trim().length > 0 || $scope.searchParameters.customAttribute.trim().length > 0 || $scope.searchParameters.programAttributeFieldValue.trim().length > 0; }; var searchBasedOnQueryParameters = function (offset) { if (!isUserPrivilegedForSearch()) { showInsufficientPrivMessage(); return; } var searchParameters = $location.search(); $scope.searchParameters.addressFieldValue = searchParameters.addressFieldValue || ''; $scope.searchParameters.name = searchParameters.name || ''; $scope.searchParameters.customAttribute = searchParameters.customAttribute || ''; $scope.searchParameters.programAttributeFieldValue = searchParameters.programAttributeFieldValue || ''; $scope.searchParameters.addressSearchResultsConfig = searchParameters.addressSearchResultsConfig || ''; $scope.searchParameters.personSearchResultsConfig = searchParameters.personSearchResultsConfig || ''; $scope.searchParameters.registrationNumber = searchParameters.registrationNumber || searchParameters.healthIDNumber || ""; if (hasSearchParameters()) { searching = true; var searchPromise = patientService.search( $scope.searchParameters.name, undefined, $scope.addressSearchConfig.field, $scope.searchParameters.addressFieldValue, $scope.searchParameters.customAttribute, offset, $scope.customAttributesSearchConfig.fields, $scope.programAttributesSearchConfig.field, $scope.searchParameters.programAttributeFieldValue, $scope.addressSearchResultsConfig.fields, $scope.personSearchResultsConfig.fields ).then(function (response) { mapExtraIdentifiers(response); mapCustomAttributesSearchResults(response); mapAddressAttributesSearchResults(response); mapProgramAttributesSearchResults(response); return response; }); searchPromise['finally'](function () { searching = false; }); return searchPromise; } }; $scope.convertToTableHeader = function (camelCasedText) { return camelCasedText.replace(/[A-Z]|^[a-z]/g, function (str) { return " " + str.toUpperCase() + ""; }).trim(); }; $scope.getProgramAttributeValues = function (result) { var attributeValues = result && result.patientProgramAttributeValue && result.patientProgramAttributeValue[$scope.programAttributesSearchConfig.field]; var commaSeparatedAttributeValues = ""; _.each(attributeValues, function (attr) { commaSeparatedAttributeValues = commaSeparatedAttributeValues + attr + ", "; }); return commaSeparatedAttributeValues.substring(0, commaSeparatedAttributeValues.length - 2); }; var mapExtraIdentifiers = function (data) { if (data !== "Searching") { _.each(data.pageOfResults, function (result) { result.extraIdentifiers = result.extraIdentifiers && JSON.parse(result.extraIdentifiers); }); } }; var mapCustomAttributesSearchResults = function (data) { if (($scope.personSearchResultsConfig.fields) && data !== "Searching") { _.map(data.pageOfResults, function (result) { result.customAttribute = result.customAttribute && JSON.parse(result.customAttribute); }); } }; var mapAddressAttributesSearchResults = function (data) { if (($scope.addressSearchResultsConfig.fields) && data !== "Searching") { _.map(data.pageOfResults, function (result) { try { result.addressFieldValue = JSON.parse(result.addressFieldValue); } catch (e) { } }); } }; var mapProgramAttributesSearchResults = function (data) { if (($scope.programAttributesSearchConfig.field) && data !== "Searching") { _.map(data.pageOfResults, function (result) { var programAttributesObj = {}; var arrayOfStringOfKeysValue = result.patientProgramAttributeValue && result.patientProgramAttributeValue.substring(2, result.patientProgramAttributeValue.length - 2).split('","'); _.each(arrayOfStringOfKeysValue, function (keyValueString) { var keyValueArray = keyValueString.split('":"'); var key = keyValueArray[0]; var value = keyValueArray[1]; if (!_.includes(_.keys(programAttributesObj), key)) { programAttributesObj[key] = []; programAttributesObj[key].push(value); } else { programAttributesObj[key].push(value); } }); result.patientProgramAttributeValue = programAttributesObj; }); } }; $scope.hidRedirect = function (data) { const spinnerToken = spinner.show(); fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByHID.htm?hid=" + data.hid) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { if (res.statusCode === 200) { $timeout(function () { // healthIdPatientAdd(patientAllData.hid, res.content); // spinner.hide(spinnerToken); localStorage.setItem("healthId", res.content); window.location.href = "/bahmni/registration/#/patient/new"; spinner.hide(spinnerToken); }); } }) .catch((error) => { console.error("Error:", error); }); }; // currently not use // var healthIdPatientAdd = function (healthId, patientData) { // fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/patient/download.htm", // { // method: "POST", // body: JSON.stringify(patientData.body), // headers: { // "Content-Type": "application/json" // } // }) // .then((response) => { // console.log(response); // if (!response.ok) { // throw new Error(`Request failed with status: ${response.status}`); // } // return response.json(); // }) // .then((res) => { // console.log(res); // if (res) { // window.location.href = `/bahmni/registration/#/patient/${res.uuid}`; // } // }) // .catch((error) => { // localStorage.setItem("healthId", JSON.stringify(patientData)); // window.location.href = "/bahmni/registration/#/patient/new"; // console.error("Error:", error); // }); // }; $scope.nidPatient = []; var showSearchResults = function (searchPromise) { $scope.nidPatient = []; $scope.noMoreResultsPresent = false; if (searchPromise) { searchPromise.then(function (data) { $scope.results = data.pageOfResults; if ($scope.selectedIdPreference === 'NID' && $scope.results.length === 0) { var nid = $scope.searchParameters.nid; if (nid) { $scope.noResultsMessage = null; searching = true; try { fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByNID.htm?type=nid&nid=" + nid) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((patient) => { let responseData = angular.fromJson(patient.content); searching = false; if (responseData.results.length > 0) { let patientData = responseData.results[0]; fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByHID.htm?hid=" + patientData.hid) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((_res) => { let res = angular.fromJson(_res.content); if (_res.statusCode === 200) { $timeout(function () { const patientAllData = res; localStorage.setItem("healthId", JSON.stringify(patientAllData)); window.location.href = "/bahmni/registration/#/patient/new"; }); } }) .catch((error) => { console.error("Error:", error); }); } else { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': nid}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; }); } }) .catch((error) => { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': nid}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; }); console.error("Error:", error); }); } catch (error) { console.error("Caught an exception:", error); } } else { $scope.patientIdentifier = {'patientIdentifier': nid}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; } } else if ($scope.selectedIdPreference === 'BRN' && $scope.results.length === 0) { var brn = $scope.searchParameters.brn; if (brn) { $scope.noResultsMessage = null; searching = true; try { // fetch(`https://${window.location.hostname}:6062/api/v1/health-id/brn/${brn}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByNID.htm?type=bin_brn&nid=" + brn) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((patient) => { let responseData = angular.fromJson(patient.content); if (responseData.results.length > 0) { let patientData = responseData.results[0]; // fetch(`https://${$window.location.hostname}:6062/api/v1/health-id/${patientData.hid}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByHID.htm?hid=" + patientData.hid) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((_res) => { let res = angular.fromJson(_res.content); if (_res.statusCode === 200) { $timeout(function () { const patientAllData = res; localStorage.setItem("healthId", JSON.stringify(patientAllData)); window.location.href = "/bahmni/registration/#/patient/new"; }); } }) .catch((error) => { console.error("Error:", error); }); } else { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': brn}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; }); } }) .catch((error) => { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': brn}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; }); console.error("Error:", error); }); } catch (error) { console.error("Caught an exception:", error); } } else { $scope.patientIdentifier = {'patientIdentifier': brn}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; } } else if ($scope.selectedIdPreference === 'phoneNumber' && $scope.results.length === 0) { var phoneNumber = $scope.searchParameters.phoneNumber; if (phoneNumber) { $scope.noResultsMessage = null; searching = true; try { // fetch(`https://${window.location.hostname}:6062/api/v1/health-id/mobile/${phoneNumber}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByNID.htm?type=phone_no&nid=" + phoneNumber) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((patient) => { let responseData = angular.fromJson(patient.content); searching = false; if (responseData.results.length > 0) { $timeout(function () { let patientData = responseData.results; $scope.nidPatient = patientData; searching = false; }); } else { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': phoneNumber}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; }); } }) .catch((error) => { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': phoneNumber}; $scope.noResultsMessage = 'REGISTRATION_NO_RESULTS_FOUND'; }); console.error("Error:", error); }); } catch (error) { console.error("Caught an exception:", error); } } } // $scope.noResultsMessage = $scope.results.length === 0 ? 'REGISTRATION_NO_RESULTS_FOUND' : null; }); } }; var setPatientIdentifierSearchConfig = function () { $scope.patientIdentifierSearchConfig = {}; $scope.patientIdentifierSearchConfig.show = allSearchConfigs.searchByPatientIdentifier === undefined ? true : allSearchConfigs.searchByPatientIdentifier; }; var setAddressSearchConfig = function () { $scope.addressSearchConfig = allSearchConfigs.address || {}; $scope.addressSearchConfig.show = !_.isEmpty($scope.addressSearchConfig) && !_.isEmpty($scope.addressSearchConfig.field); if ($scope.addressSearchConfig.label && !$scope.addressSearchConfig.label) { throw new Error("Search Config label is not present!"); } if ($scope.addressSearchConfig.field && !$scope.addressSearchConfig.field) { throw new Error("Search Config field is not present!"); } }; var setCustomAttributesSearchConfig = function () { var customAttributesSearchConfig = allSearchConfigs.customAttributes; $scope.customAttributesSearchConfig = customAttributesSearchConfig || {}; $scope.customAttributesSearchConfig.show = !_.isEmpty(customAttributesSearchConfig) && !_.isEmpty(customAttributesSearchConfig.fields); }; var setProgramAttributesSearchConfig = function () { $scope.programAttributesSearchConfig = allSearchConfigs.programAttributes || {}; $scope.programAttributesSearchConfig.show = !_.isEmpty($scope.programAttributesSearchConfig.field); }; var sliceExtraColumns = function () { var orderedColumns = Object.keys(patientSearchResultConfigs); _.each(orderedColumns, function (column) { if (patientSearchResultConfigs[column].fields && !_.isEmpty(patientSearchResultConfigs[column].fields)) { patientSearchResultConfigs[column].fields = patientSearchResultConfigs[column].fields.slice(patientSearchResultConfigs[column].fields, maxAttributesFromConfig); maxAttributesFromConfig -= patientSearchResultConfigs[column].fields.length; } }); }; var setSearchResultsConfig = function () { var resultsConfigNotFound = false; if (_.isEmpty(patientSearchResultConfigs)) { resultsConfigNotFound = true; patientSearchResultConfigs.address = {"fields": allSearchConfigs.address ? [allSearchConfigs.address.field] : {}}; patientSearchResultConfigs.personAttributes = {fields: allSearchConfigs.customAttributes ? allSearchConfigs.customAttributes.fields : {}}; } else { if (!patientSearchResultConfigs.address) patientSearchResultConfigs.address = {}; if (!patientSearchResultConfigs.personAttributes) patientSearchResultConfigs.personAttributes = {}; } if (patientSearchResultConfigs.address.fields && !_.isEmpty(patientSearchResultConfigs.address.fields)) { patientSearchResultConfigs.address.fields = patientSearchResultConfigs.address.fields.filter(function (item) { return !_.isEmpty($scope.getAddressColumnName(item)); }); } if (!resultsConfigNotFound) sliceExtraColumns(); $scope.personSearchResultsConfig = patientSearchResultConfigs.personAttributes; $scope.addressSearchResultsConfig = patientSearchResultConfigs.address; }; var initialize = function () { $scope.searchParameters = {}; $scope.searchActions = appService.getAppDescriptor().getExtensions("org.bahmni.registration.patient.search.result.action"); setPatientIdentifierSearchConfig(); setAddressSearchConfig(); setCustomAttributesSearchConfig(); setProgramAttributesSearchConfig(); setSearchResultsConfig(); }; var identifyParams = function (querystring) { querystring = querystring.substring(querystring.indexOf('?') + 1).split('&'); var params = {}, pair, d = decodeURIComponent; for (var i = querystring.length - 1; i >= 0; i--) { pair = querystring[i].split('='); params[d(pair[0])] = d(pair[1]); } return params; }; initialize(); $scope.disableSearchButton = function () { return !$scope.searchParameters.name && !$scope.searchParameters.addressFieldValue && !$scope.searchParameters.customAttribute && !$scope.searchParameters.programAttributeFieldValue; }; $scope.$watch(function () { return $location.search(); }, function () { showSearchResults(searchBasedOnQueryParameters(0)); }); var customAttributeSearch = function () { var searchParameters = $location.search(); $scope.searchParameters.addressFieldValue = searchParameters.addressFieldValue || ''; $scope.searchParameters.name = searchParameters.name || ''; $scope.searchParameters.customAttribute = searchParameters.customAttribute || ''; $scope.searchParameters.programAttributeFieldValue = searchParameters.programAttributeFieldValue || ''; $scope.searchParameters.addressSearchResultsConfig = searchParameters.addressSearchResultsConfig || ''; $scope.searchParameters.personSearchResultsConfig = searchParameters.personSearchResultsConfig || ''; $scope.searchParameters.registrationNumber = searchParameters.registrationNumber || searchParameters.healthIDNumber || ""; if (hasSearchParameters()) { searching = true; var searchPromise = patientService.search( $scope.searchParameters.name, undefined, $scope.addressSearchConfig.field, $scope.searchParameters.addressFieldValue, $scope.searchParameters.customAttribute, undefined, $scope.customAttributesSearchConfig.fields, $scope.programAttributesSearchConfig.field, $scope.searchParameters.programAttributeFieldValue, $scope.addressSearchResultsConfig.fields, $scope.personSearchResultsConfig.fields ).then(function (response) { mapExtraIdentifiers(response); mapCustomAttributesSearchResults(response); mapAddressAttributesSearchResults(response); mapProgramAttributesSearchResults(response); return response; }); searchPromise['finally'](function () { searching = false; }); return searchPromise; } }; $scope.searchById = function () { $scope.nidPatient = []; $scope.noResultsMessage = null; if (!isUserPrivilegedForSearch()) { showInsufficientPrivMessage(); return; } if (!$scope.searchParameters.registrationNumber && !$scope.searchParameters.nid && !$scope.searchParameters.brn && !$scope.searchParameters.healthID && !$scope.searchParameters.phoneNumber) { return; } $scope.results = []; if ($scope.selectedIdPreference === 'NID') { $location.search({ customAttribute: $scope.searchParameters.nid }); customAttributeSearch(); } else if ($scope.selectedIdPreference === 'BRN') { $location.search({ customAttribute: $scope.searchParameters.brn }); customAttributeSearch(); } else if ($scope.selectedIdPreference === 'phoneNumber') { $location.search({ customAttribute: $scope.searchParameters.phoneNumber }); customAttributeSearch(); } else if ($scope.selectedIdPreference === 'HID') { $location.search({ registrationNumber: $scope.searchParameters.healthID, programAttributeFieldName: $scope.programAttributesSearchConfig.field, patientAttributes: $scope.customAttributesSearchConfig.fields, programAttributeFieldValue: $scope.searchParameters.programAttributeFieldValue, addressSearchResultsConfig: $scope.addressSearchResultsConfig.fields, personSearchResultsConfig: $scope.personSearchResultsConfig.fields }); healthIDandPatientIDSearch(); } else if ($scope.selectedIdPreference === 'patientID') { $location.search({ registrationNumber: $scope.searchParameters.registrationNumber, programAttributeFieldName: $scope.programAttributesSearchConfig.field, patientAttributes: $scope.customAttributesSearchConfig.fields, programAttributeFieldValue: $scope.searchParameters.programAttributeFieldValue, addressSearchResultsConfig: $scope.addressSearchResultsConfig.fields, personSearchResultsConfig: $scope.personSearchResultsConfig.fields }); healthIDandPatientIDSearch(); } else { $location.search({ registrationNumber: $scope.searchParameters.registrationNumber, programAttributeFieldName: $scope.programAttributesSearchConfig.field, patientAttributes: $scope.customAttributesSearchConfig.fields, programAttributeFieldValue: $scope.searchParameters.programAttributeFieldValue, addressSearchResultsConfig: $scope.addressSearchResultsConfig.fields, personSearchResultsConfig: $scope.personSearchResultsConfig.fields }); healthIDandPatientIDSearch(); } }; var healthIdPatientAdd = function (healthId, patientData) { // fetch(`https://${window.location.hostname}/openmrs/ws/mci/download?hid=${healthId}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/patient/download.htm", { method: "POST", body: JSON.stringify(patientData.body), headers: { "Content-Type": "application/json" } }) .then((response) => { console.log(response); if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { console.log(res); if (res) { window.location.href = `/bahmni/registration/#/patient/${res.uuid}`; } }) .catch((error) => { localStorage.setItem("healthId", JSON.stringify(patientData)); window.location.href = "/bahmni/registration/#/patient/new"; console.error("Error:", error); }); }; var healthIDandPatientIDSearch = function () { var patientIdentifier = $scope.selectedIdPreference === 'HID' ? $scope.searchParameters.healthID : $scope.searchParameters.registrationNumber; var searchPromise = patientService.search(undefined, patientIdentifier, $scope.addressSearchConfig.field, undefined, undefined, undefined, $scope.customAttributesSearchConfig.fields, $scope.programAttributesSearchConfig.field, $scope.searchParameters.programAttributeFieldValue, $scope.addressSearchResultsConfig.fields, $scope.personSearchResultsConfig.fields, $scope.isExtraIdentifierConfigured()) .then(function (data) { mapExtraIdentifiers(data); mapCustomAttributesSearchResults(data); mapAddressAttributesSearchResults(data); mapProgramAttributesSearchResults(data); if (data.pageOfResults.length === 1) { var patient = data.pageOfResults[0]; var forwardUrl = appService.getAppDescriptor().getConfigValue("searchByIdForwardUrl") || "/patient/{{patientUuid}}"; $location.url(appService.getAppDescriptor().formatUrl(forwardUrl, {'patientUuid': patient.uuid})); } else if (data.pageOfResults.length > 1) { $scope.results = data.pageOfResults; $scope.noResultsMessage = null; } else { if (healthIDEnable) { if ($scope.selectedIdPreference === 'HID') { var healthId = $scope.searchParameters.healthID; if (healthId) { searching = true; $scope.noResultsMessage = null; try { // fetch(`https://${window.location.hostname}:6062/api/v1/health-id/${healthId}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByHID.htm?hid=" + healthId) .then((response) => { console.log(response); if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { if (res.statusCode === 200) { // localStorage.setItem("healthId", JSON.stringify(res.content)); localStorage.setItem("healthId", res.content); window.location.href = "/bahmni/registration/#/patient/new"; } }) .catch((error) => { $timeout(function () { searching = false; $scope.patientIdentifier = {'patientIdentifier': patientIdentifier}; $scope.noResultsMessage = 'REGISTRATION_LABEL_COULD_NOT_FIND_PATIENT'; }); console.error("Error:", error); }); } catch (error) { console.error("Caught an exception:", error); } } else { $scope.patientIdentifier = {'patientIdentifier': patientIdentifier}; $scope.noResultsMessage = 'REGISTRATION_LABEL_COULD_NOT_FIND_PATIENT'; } } else { $scope.patientIdentifier = {'patientIdentifier': patientIdentifier}; $scope.noResultsMessage = 'REGISTRATION_LABEL_COULD_NOT_FIND_PATIENT'; } } else { $scope.patientIdentifier = {'patientIdentifier': patientIdentifier}; $scope.noResultsMessage = 'REGISTRATION_LABEL_COULD_NOT_FIND_PATIENT'; } } }); spinner.forPromise(searchPromise); }; var isUserPrivilegedForSearch = function () { var applicablePrivs = [Bahmni.Common.Constants.viewPatientsPrivilege, Bahmni.Common.Constants.editPatientsPrivilege, Bahmni.Common.Constants.addVisitsPrivilege, Bahmni.Common.Constants.deleteVisitsPrivilege]; var userPrivs = _.map($rootScope.currentUser.privileges, function (privilege) { return privilege.name; }); var result = _.some(userPrivs, function (privName) { return _.includes(applicablePrivs, privName); }); return result; }; var showInsufficientPrivMessage = function () { var message = $translate.instant("REGISTRATION_INSUFFICIENT_PRIVILEGE"); messagingService.showMessage('error', message); }; $scope.loadingMoreResults = function () { return searching && !$scope.noMoreResultsPresent; }; $scope.searchPatients = function () { if (!isUserPrivilegedForSearch()) { showInsufficientPrivMessage(); return; } var queryParams = {}; $scope.results = []; if ($scope.searchParameters.name) { queryParams.name = $scope.searchParameters.name; } if ($scope.searchParameters.addressFieldValue) { queryParams.addressFieldValue = $scope.searchParameters.addressFieldValue; } if ($scope.searchParameters.customAttribute && $scope.customAttributesSearchConfig.show) { queryParams.customAttribute = $scope.searchParameters.customAttribute; } if ($scope.searchParameters.programAttributeFieldValue && $scope.programAttributesSearchConfig.show) { queryParams.programAttributeFieldName = $scope.programAttributesSearchConfig.field; queryParams.programAttributeFieldValue = $scope.searchParameters.programAttributeFieldValue; } $location.search(queryParams); }; $scope.resultsPresent = function () { return angular.isDefined($scope.results) && $scope.results.length > 0; }; $scope.editPatientUrl = function (url, options) { var temp = url; for (var key in options) { temp = temp.replace("{{" + key + "}}", options[key]); } return temp; }; $scope.nextPage = function () { if ($scope.nextPageLoading) { return; } $scope.nextPageLoading = true; var promise = searchBasedOnQueryParameters($scope.results.length); if (promise) { promise.then(function (data) { angular.forEach(data.pageOfResults, function (result) { $scope.results.push(result); }); $scope.noMoreResultsPresent = (data.pageOfResults.length === 0); $scope.nextPageLoading = false; }, function () { $scope.nextPageLoading = false; }); } }; $scope.forPatient = function (patient) { $scope.selectedPatient = patient; return $scope; }; $scope.doExtensionAction = function (extension) { var forwardTo = appService.getAppDescriptor().formatUrl(extension.url, {'patientUuid': $scope.selectedPatient.uuid}); if (extension.label === 'Print') { var params = identifyParams(forwardTo); if (params.launch === 'dialog') { var firstChar = forwardTo.charAt(0); var prefix = firstChar === "/" ? "#" : "#/"; var hiddenFrame = $("#printPatientFrame")[0]; hiddenFrame.src = prefix + forwardTo; hiddenFrame.contentWindow.print(); } else { $location.url(forwardTo); } } else { $location.url(forwardTo); } }; $scope.extensionActionText = function (extension) { return $filter('titleTranslate')(extension); }; $scope.isExtraIdentifierConfigured = function () { return !_.isEmpty($scope.extraIdentifierTypes); }; }]); 'use strict'; angular.module('bahmni.registration') .controller('PatientCommonController', ['$scope', '$rootScope', '$http', 'patientAttributeService', 'appService', 'spinner', '$location', 'ngDialog', '$window', '$state', function ($scope, $rootScope, $http, patientAttributeService, appService, spinner, $location, ngDialog, $window, $state) { var autoCompleteFields = appService.getAppDescriptor().getConfigValue("autoCompleteFields", []); var showCasteSameAsLastNameCheckbox = appService.getAppDescriptor().getConfigValue("showCasteSameAsLastNameCheckbox"); var personAttributes = []; var caste; $scope.showMiddleName = appService.getAppDescriptor().getConfigValue("showMiddleName"); $scope.showLastName = appService.getAppDescriptor().getConfigValue("showLastName"); $scope.isLastNameMandatory = $scope.showLastName && appService.getAppDescriptor().getConfigValue("isLastNameMandatory"); $scope.showBirthTime = appService.getAppDescriptor().getConfigValue("showBirthTime") != null ? appService.getAppDescriptor().getConfigValue("showBirthTime") : true; // show birth time by default $scope.genderCodes = Object.keys($rootScope.genderMap); $scope.dobMandatory = appService.getAppDescriptor().getConfigValue("dobMandatory") || false; $scope.readOnlyExtraIdentifiers = appService.getAppDescriptor().getConfigValue("readOnlyExtraIdentifiers"); $scope.showSaveConfirmDialogConfig = appService.getAppDescriptor().getConfigValue("showSaveConfirmDialog"); $scope.showSaveAndContinueButton = false; getDoctorList(); $scope.currentDateTime = new Date(); $scope.currentTime = $scope.currentDateTime.getTime(); $scope.serviceObject = {}; $scope.billingBillableService = {}; $scope.doctrors = []; function getDoctorList() { var baseUrl = location.host; $http({ method: "GET", url: "https://" + baseUrl + '/openmrs/ws/rest/v1/angtcore/evening/evening.htm', headers: { "Content-Type": "application/json", "Authorization": "Basic YWRtaW46dGVzdA==" } }).then(function (response) { $scope.doctrors = response.data; }); } $scope.getBillingService = function (service) { var baseUrl = location.host; $scope.serviceObject = {}; $scope.billingBillableService = {}; $scope.serviceObject = service; $http({ method: "GET", url: "https://" + baseUrl + '/openmrs/ws/rest/v1/angtbilling/billableservice/getServiceInfoByConceptId.htm?conceptId=' + service.conceptId, headers: { "Content-Type": "application/json", "Authorization": "Basic YWRtaW46dGVzdA==" } }).then(function (response) { $scope.billingBillableService = response.data; }); }; var dontSaveButtonClicked = false; var isHref = false; $rootScope.onHomeNavigate = function (event) { if ($scope.showSaveConfirmDialogConfig && $state.current.name != "patient.visit") { event.preventDefault(); $scope.targetUrl = event.currentTarget.getAttribute('href'); isHref = true; $scope.confirmationPrompt(event); } }; var stateChangeListener = $rootScope.$on("$stateChangeStart", function (event, toState, toParams) { if ($scope.showSaveConfirmDialogConfig && (toState.url == "/search" || toState.url == "/patient/new")) { $scope.targetUrl = toState.name; isHref = false; $scope.confirmationPrompt(event, toState, toParams); } }); $scope.confirmationPrompt = function (event, toState) { if (dontSaveButtonClicked === false) { if (event) { event.preventDefault(); } ngDialog.openConfirm({template: "../common/ui-helper/views/saveConfirmation.html", scope: $scope}); } }; $scope.continueWithoutSaving = function () { ngDialog.close(); dontSaveButtonClicked = true; if (isHref === true) { $window.open($scope.targetUrl, '_self'); } else { $state.go($scope.targetUrl); } }; $scope.cancelTransition = function () { ngDialog.close(); delete $scope.targetUrl; }; $scope.$on("$destroy", function () { stateChangeListener(); }); $scope.getDeathConcepts = function () { return $http({ url: Bahmni.Common.Constants.globalPropertyUrl, method: 'GET', params: { property: 'concept.reasonForDeath' }, withCredentials: true, transformResponse: [function (deathConcept) { if (_.isEmpty(deathConcept)) { $scope.deathConceptExists = false; } else { $http.get(Bahmni.Common.Constants.conceptSearchByFullNameUrl, { params: { name: deathConcept, v: "custom:(uuid,name,set,setMembers:(uuid,display,name:(uuid,name),retired))" }, withCredentials: true }).then(function (results) { $scope.deathConceptExists = !!results.data.results.length; $scope.deathConcepts = results.data.results[0] ? results.data.results[0].setMembers : []; $scope.deathConcepts = filterRetireDeathConcepts($scope.deathConcepts); }); } }] }); }; spinner.forPromise($scope.getDeathConcepts()); var filterRetireDeathConcepts = function (deathConcepts) { return _.filter(deathConcepts, function (concept) { return !concept.retired; }); }; $scope.isAutoComplete = function (fieldName) { return !_.isEmpty(autoCompleteFields) ? autoCompleteFields.indexOf(fieldName) > -1 : false; }; $scope.showCasteSameAsLastName = function () { personAttributes = _.map($rootScope.patientConfiguration.attributeTypes, function (attribute) { return attribute.name.toLowerCase(); }); var personAttributeHasCaste = personAttributes.indexOf("caste") !== -1; caste = personAttributeHasCaste ? $rootScope.patientConfiguration.attributeTypes[personAttributes.indexOf("caste")].name : undefined; return showCasteSameAsLastNameCheckbox && personAttributeHasCaste; }; $scope.setCasteAsLastName = function () { if ($scope.patient.sameAsLastName) { $scope.patient[caste] = $scope.patient.familyName; } }; var showSections = function (sectionsToShow, allSections) { _.each(sectionsToShow, function (sectionName) { allSections[sectionName].canShow = true; allSections[sectionName].expand = true; }); }; var hideSections = function (sectionsToHide, allSections) { _.each(sectionsToHide, function (sectionName) { allSections[sectionName].canShow = false; }); }; var executeRule = function (ruleFunction) { var attributesShowOrHideMap = ruleFunction($scope.patient); var patientAttributesSections = $rootScope.patientConfiguration.getPatientAttributesSections(); showSections(attributesShowOrHideMap.show, patientAttributesSections); hideSections(attributesShowOrHideMap.hide, patientAttributesSections); }; $scope.handleUpdate = function (attribute) { var ruleFunction = Bahmni.Registration.AttributesConditions.rules && Bahmni.Registration.AttributesConditions.rules[attribute]; if (ruleFunction) { executeRule(ruleFunction); } }; var executeShowOrHideRules = function () { _.each(Bahmni.Registration.AttributesConditions.rules, function (rule) { executeRule(rule); }); }; $scope.$watch('patientLoaded', function () { if ($scope.patientLoaded) { executeShowOrHideRules(); } }); $scope.getAutoCompleteList = function (attributeName, query, type) { return patientAttributeService.search(attributeName, query, type); }; $scope.getDataResults = function (data) { return data.results; }; $scope.$watch('patient.familyName', function () { if ($scope.patient.sameAsLastName) { $scope.patient[caste] = $scope.patient.familyName; } }); $scope.$watch('patient.caste', function () { if ($scope.patient.sameAsLastName && ($scope.patient.familyName !== $scope.patient[caste])) { $scope.patient.sameAsLastName = false; } }); $scope.selectIsDead = function () { if ($scope.patient.causeOfDeath || $scope.patient.deathDate) { $scope.patient.dead = true; } }; $scope.disableIsDead = function () { return ($scope.patient.causeOfDeath || $scope.patient.deathDate) && $scope.patient.dead; }; }]); 'use strict'; angular.module('bahmni.registration') .controller('CreatePatientController', ['$window', '$scope', '$rootScope', '$state', 'patientService', 'patient', 'spinner', 'appService', 'messagingService', 'ngDialog', '$q', '$http', '$timeout', function ($window, $scope, $rootScope, $state, patientService, patient, spinner, appService, messagingService, ngDialog, $q, $http, $timeout) { var dateUtil = Bahmni.Common.Util.DateUtil; $scope.actions = {}; var errorMessage; $scope.getPatientBtnHide = false; $scope.providerName = localStorage.getItem('providerName'); var configValueForEnterId = appService.getAppDescriptor().getConfigValue('showEnterID'); const healthIDEnable = appService.getAppDescriptor().getConfigValue("healthIdEnable"); $scope.addressHierarchyConfigs = appService.getAppDescriptor().getConfigValue("addressHierarchy"); $scope.disablePhotoCapture = appService.getAppDescriptor().getConfigValue("disablePhotoCapture"); $scope.showEnterID = configValueForEnterId === null ? true : configValueForEnterId; $scope.today = Bahmni.Common.Util.DateTimeFormatter.getDateWithoutTime(dateUtil.now()); window.sessionStorage.removeItem('free'); $window.localStorage.removeItem('refresh'); var hostName = $window.location.hostname; var baseUrl = "https://" + hostName; const convertToYYYYMMDD = (timestamp) => { const date = new Date(timestamp); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // Month is zero-based const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; }; var nidResponseData; const patientNIDData = (data) => { return { performer: $rootScope.currentUser.uuid, nidOrBrn: data.nationalId ? data.nationalId : data.birthRegistrationId, type: data.nationalId ? "nid" : "brn", name: "patient", dob: convertToYYYYMMDD(data.birthdate), mobile: "01762940071" }; }; const resetPatient = () => { $scope.patient.givenName = ''; $scope.patient.givenNameLocal = ''; $scope.patient.primaryRelative = ''; $scope.patient.motherName = ''; $scope.patient.givenFatherNameLocal = ''; $scope.patient.givenMotherNameLocal = ''; $scope.patient.address.address1 = ''; $scope.patient.address.display = ''; $scope.patient.extraIdentifiers[0].identifier = ''; $scope.patient.extraIdentifiers[0].registrationNumber = ''; }; const checkHealthID = (spinnerToken, endPoint) => { return fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByNID.htm?" + endPoint) .then((response) => { if (!response.ok) { $timeout(function () { resetPatient(); messagingService.showMessage("error", "Something went wrong in MCI Server, Please try again."); spinner.hide(spinnerToken); }); // throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }); }; $scope.getPatientInfo = () => { if (!$scope.patient.birthdate && (!$scope.patient.nationalId || !$scope.patient.birthRegistrationId)) { return $timeout(function () { messagingService.showMessage("error", "Please provide birth date and NID/Birth registration number"); }); } const isNationalIdPresent = $scope.patient.nationalId; const endPoint = isNationalIdPresent ? "type=nid&nid=" + $scope.patient.nationalId : "type=bin_brn&nid=" + $scope.patient.birthRegistrationId; const spinnerToken = spinner.show(); checkHealthID(spinnerToken, endPoint).then((_healthIdCheck) => { let healthIdCheck = angular.fromJson(_healthIdCheck.content); if (_healthIdCheck.statusCode === 200 && healthIdCheck.results && healthIdCheck.results.length > 0) { const patientData = healthIdCheck.results[0]; // fetch(`https://${$window.location.hostname}:6062/api/v1/health-id/geo-code?upazillaCode=${patientData.present_address.upazila_id}&districtCode=${patientData.present_address.district_id}&divisionCode=${patientData.present_address.division_id}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/getBbs.htm?upazillaCode=" + patientData.present_address.upazila_id + "&districtCode=" + patientData.present_address.district_id + "&divisionCode=" + patientData.present_address.division_id) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { if (res) { $timeout(function () { resetPatient(); $scope.patient.givenName = patientData.given_name; $scope.patient.familyName = patientData.sur_name; $scope.patient.gender = patientData.gender; $scope.patient.birthdate = new Date( patientData.date_of_birth ); var currentDate = new Date(); var birthDate = new Date(patientData.date_of_birth); var years = currentDate.getFullYear() - birthDate.getFullYear(); var months = currentDate.getMonth() - birthDate.getMonth(); var days = currentDate.getDate() - birthDate.getDate(); if (months < 0 || (months === 0 && days < 0)) { years--; months += 12; } if (days < 0) { var prevMonthDate = new Date( currentDate.getFullYear(), currentDate.getMonth() - 1, 0 ); days = prevMonthDate.getDate() - birthDate.getDate() + currentDate.getDate(); months--; } $scope.patient.age.years = years; $scope.patient.age.months = months; $scope.patient.age.days = days; var obj = { identifier: patientData.hid, registrationNumber: patientData.hid, "preferred": false, "voided": false, identifierType: { description: 'Health Identifier type', uuid: "77aa2e83-2c56-11ea-bfb9-20474797761c", name: "Health Id", format: null, required: false, primary: false, identifierSources: [] } }; $scope.patient.extraIdentifiers.unshift(obj); $scope.patient.extraIdentifiers[0].identifier = patientData.hid; $scope.patient.extraIdentifiers[0].registrationNumber = patientData.hid; $scope.patient.nationalId = patientData.nid; $scope.patient.healthId = patientData.hid; // $scope.patient.address.address1 = patientData.present_address.address_line; // $scope.patient.address.display = patientData.present_address.address_line; // $scope.patient.address.stateProvince = stateProvince; // $scope.patient.address.countyDistrict = countyDistrict; // $scope.patient.address.address5 = upazila; $scope.patient.address.address1 = patientData.present_address.address_line; $scope.patient.address.display = patientData.present_address.address_line; $scope.patient.address.address5 = res.content.upazilla; $scope.patient.address.countyDistrict = res.content.district; $scope.patient.address.stateProvince = res.content.division; // fetch(`https://${$window.location.hostname}:6062/api/v1/health-id/${patientData.hid}`) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByHID.htm?hid=" + patientData.hid) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { if (res.statusCode === 200) { $timeout(function () { const patientData = angular.fromJson(res.content); $scope.patient.givenNameLocal = patientData.name_bangla; $scope.patient.phoneNumber = patientData.phone_number ? patientData.phone_number.number : ''; if (patientData.relations) { const fatherRelation = patientData.relations.find(relation => relation.type === 'FTH'); const motherRelation = patientData.relations.find(relation => relation.type === 'MTH'); if (fatherRelation) { $scope.patient.primaryRelative = fatherRelation.given_name; $scope.patient.givenFatherNameLocal = fatherRelation.name_bangla; } if (motherRelation) { $scope.patient.motherName = motherRelation.given_name; $scope.patient.givenMotherNameLocal = motherRelation.name_bangla; } } $scope.getPatientBtnHide = true; spinner.hide(spinnerToken); messagingService.showMessage("info", "Patient information retrieved successfully"); }); } }) .catch((error) => { console.error("Error:", error); }); }); // return patientCreate($scope.patient, jumpAccepted); } }); } else if (_healthIdCheck.statusCode === 400) { $timeout(function () { resetPatient(); spinner.hide(spinnerToken); messagingService.showMessage("error", "Invalid BRN/NID"); }); } else if (_healthIdCheck.statusCode !== 500) { // fetch(`https://${$window.location.hostname}:6062/api/v1/health-id/nid-verify`, fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/verifyNIDBRN.htm", { method: "POST", body: JSON.stringify(patientNIDData($scope.patient)), headers: { "Content-Type": "application/json" } } ) .then((response) => { console.log(response); if (!response.ok) { $timeout(function () { resetPatient(); messagingService.showMessage("error", "Something went wrong in NID Server, Please try again."); spinner.hide(spinnerToken); }); // throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((_response) => { if (_response.statusCode === 500) { $timeout(function () { messagingService.showMessage("error", "Not Found, Please Try again"); spinner.hide(spinnerToken); }); } let response = angular.fromJson(_response.content); if (response.verifyToken) { $timeout(function () { resetPatient(); const nidData = response.citizenData; nidResponseData = nidData; $scope.patient.givenName = nidData.fullName_English; $scope.patient.givenNameLocal = nidData.fullName_Bangla; $scope.patient.gender = nidData.gender === 1 ? 'M' : nidData.gender === 2 ? 'F' : 'O'; $scope.patient.primaryRelative = nidData.fatherName_English; $scope.patient.motherName = nidData.motherName_English; $scope.patient.givenFatherNameLocal = nidData.fatherName_Bangla; $scope.patient.givenMotherNameLocal = nidData.motherName_Bangla; $scope.patient.birthdate = new Date(nidData.dob); var currentDate = new Date(); var birthDate = new Date(nidData.dob); var years = currentDate.getFullYear() - birthDate.getFullYear(); var months = currentDate.getMonth() - birthDate.getMonth(); var days = currentDate.getDate() - birthDate.getDate(); if (months < 0 || (months === 0 && days < 0)) { years--; months += 12; } if (days < 0) { var prevMonthDate = new Date( currentDate.getFullYear(), currentDate.getMonth() - 1, 0 ); days = prevMonthDate.getDate() - birthDate.getDate() + currentDate.getDate(); months--; } $scope.patient.age.years = years; $scope.patient.age.months = months; $scope.patient.age.days = days; $scope.patient.nationalId = nidData.citizen_nid ? nidData.citizen_nid : $scope.patient.nationalId; $scope.patient.birthRegistrationId = nidData.bin_BRN ? nidData.bin_BRN : $scope.patient.birthRegistrationId; if (nidData.presentHouseholdNoText) { $scope.patient.address.address1 = nidData.presentHouseholdNoText; $scope.patient.address.display = nidData.presentHouseholdNoText; } else { const addressComponents = [ nidData.presentHouseholdNo.houseOrHoldingNo, nidData.presentHouseholdNo.villageOrRoad, nidData.presentHouseholdNo.mouzaOrMoholla, nidData.presentHouseholdNo.unionOrWard, nidData.presentHouseholdNo.upazilla, nidData.presentHouseholdNo.district, nidData.presentHouseholdNo.division ]; const nidAddressData = addressComponents.filter(item => item !== "." && item !== "" && item !== "-" && item !== "--" && item !== "," && item !== null).join(', '); $scope.patient.address.address1 = nidAddressData; $scope.patient.address.display = nidAddressData; } spinner.hide(spinnerToken); messagingService.showMessage("info", "Patient information retrieved successfully"); }); } else if (response.status !== 500) { $timeout(function () { resetPatient(); messagingService.showMessage("error", "Patient information not available."); spinner.hide(spinnerToken); }); } }); } }); }; if (healthIDEnable) { if ($window.localStorage.getItem("healthId")) { let patientData = JSON.parse($window.localStorage.getItem("healthId")); $timeout(function () { $scope.getPatientBtnHide = true; $scope.patient.givenName = patientData.given_name; $scope.patient.givenNameLocal = patientData.name_bangla; $scope.patient.familyName = patientData.sur_name; $scope.patient.phoneNumber = patientData.phone_number ? patientData.phone_number.number : ''; $scope.patient.gender = patientData.gender; if (patientData.relations) { const fatherRelation = patientData.relations.find(relation => relation.type === 'FTH'); const motherRelation = patientData.relations.find(relation => relation.type === 'MTH'); if (fatherRelation) { $scope.patient.primaryRelative = fatherRelation.given_name; $scope.patient.givenFatherNameLocal = fatherRelation.name_bangla; } if (motherRelation) { $scope.patient.motherName = motherRelation.given_name; $scope.patient.givenMotherNameLocal = motherRelation.name_bangla; } } $scope.patient.familyName = patientData.sur_name; $scope.patient.gender = patientData.gender; $scope.patient.birthdate = new Date(patientData.date_of_birth); var currentDate = new Date(); var birthDate = new Date(patientData.date_of_birth); var years = currentDate.getFullYear() - birthDate.getFullYear(); var months = currentDate.getMonth() - birthDate.getMonth(); var days = currentDate.getDate() - birthDate.getDate(); if (months < 0 || (months === 0 && days < 0)) { years--; months += 12; } if (days < 0) { var prevMonthDate = new Date( currentDate.getFullYear(), currentDate.getMonth() - 1, 0 ); days = prevMonthDate.getDate() - birthDate.getDate() + currentDate.getDate(); months--; } $scope.patient.age.years = years; $scope.patient.age.months = months; $scope.patient.age.days = days; var obj = { identifier: patientData.hid, registrationNumber: patientData.hid, "preferred": false, "voided": false, identifierType: { description: 'Health Identifier type', uuid: "77aa2e83-2c56-11ea-bfb9-20474797761c", name: "Health Id", format: null, required: false, primary: false, identifierSources: [] } }; $scope.patient.extraIdentifiers.unshift(obj); $scope.patient.extraIdentifiers[0].identifier = patientData.hid; $scope.patient.extraIdentifiers[0].registrationNumber = patientData.hid; $scope.patient.nationalId = patientData.nid ? patientData.nid : ''; $scope.patient.healthId = patientData.hid ? patientData.hid : ''; $scope.patient.birthRegistrationId = patientData.bin_brn ? patientData.bin_brn : ''; // fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/searchByNID.htm?type=nid&nid=" + nid) fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/common/getBbs.htm?upazillaCode=" + patientData.present_address.upazila_id + "&districtCode=" + patientData.present_address.district_id + "&divisionCode=" + patientData.present_address.division_id) .then((response) => { if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { $scope.patient.address.address1 = patientData.present_address.address_line; $scope.patient.address.display = patientData.present_address.address_line; $scope.patient.address.address5 = res.content.upazilla; $scope.patient.address.countyDistrict = res.content.district; $scope.patient.address.stateProvince = res.content.division; }); }, 100); } } var getPersonAttributeTypes = function () { return $rootScope.patientConfiguration.attributeTypes; }; var prepopulateDefaultsInFields = function () { var personAttributeTypes = getPersonAttributeTypes(); var patientInformation = appService.getAppDescriptor().getConfigValue("patientInformation"); if (!patientInformation || !patientInformation.defaults) { return; } var defaults = patientInformation.defaults; var defaultVariableNames = _.keys(defaults); var hasDefaultAnswer = function (personAttributeType) { return _.includes(defaultVariableNames, personAttributeType.name); }; var isConcept = function (personAttributeType) { return personAttributeType.format === "org.openmrs.Concept"; }; var setDefaultAnswer = function (personAttributeType) { $scope.patient[personAttributeType.name] = defaults[personAttributeType.name]; }; var setDefaultConcept = function (personAttributeType) { var defaultAnswer = defaults[personAttributeType.name]; var isDefaultAnswer = function (answer) { return answer.fullySpecifiedName === defaultAnswer; }; _.chain(personAttributeType.answers).filter(isDefaultAnswer).each(function (answer) { $scope.patient[personAttributeType.name] = { conceptUuid: answer.conceptId, value: answer.fullySpecifiedName }; }).value(); }; _.chain(personAttributeTypes) .filter(hasDefaultAnswer) .each(setDefaultAnswer).filter(isConcept).each(setDefaultConcept).value(); }; var expandSectionsWithDefaultValue = function () { angular.forEach($rootScope.patientConfiguration && $rootScope.patientConfiguration.getPatientAttributesSections(), function (section) { var notNullAttribute = _.find(section && section.attributes, function (attribute) { return $scope.patient[attribute.name] !== undefined; }); section.expand = section.expanded || (notNullAttribute ? true : false); }); }; var init = function () { $scope.patient = patient.create(); prepopulateDefaultsInFields(); expandSectionsWithDefaultValue(); $scope.patientLoaded = true; }; init(); var prepopulateFields = function () { var fieldsToPopulate = appService.getAppDescriptor().getConfigValue("prepopulateFields"); if (fieldsToPopulate) { _.each(fieldsToPopulate, function (field) { var addressLevel = _.find($scope.addressLevels, function (level) { return level.name === field; }); if (addressLevel) { $scope.patient.address[addressLevel.addressField] = $rootScope.loggedInLocation[addressLevel.addressField]; } }); } }; prepopulateFields(); var addNewRelationships = function () { var newRelationships = _.filter($scope.patient.newlyAddedRelationships, function (relationship) { return relationship.relationshipType && relationship.relationshipType.uuid; }); newRelationships = _.each(newRelationships, function (relationship) { delete relationship.patientIdentifier; delete relationship.content; delete relationship.providerName; }); $scope.patient.relationships = newRelationships; }; var getConfirmationViaNgDialog = function (config) { var ngDialogLocalScope = config.scope.$new(); ngDialogLocalScope.yes = function () { ngDialog.close(); config.yesCallback(); }; ngDialogLocalScope.no = function () { ngDialog.close(); }; ngDialog.open({ template: config.template, data: config.data, scope: ngDialogLocalScope }); }; var copyPatientProfileDataToScope = function (response) { var patientProfileData = response.data; $scope.patient.uuid = patientProfileData.patient.uuid; $scope.patient.name = patientProfileData.patient.person.names[0].display; $scope.patient.isNew = true; $scope.patient.registrationDate = dateUtil.now(); $scope.patient.newlyAddedRelationships = [{}]; $scope.actions.followUpAction(patientProfileData); }; function doctorBill(concept, patientUuid) { var baseUrl = location.host; $http({ method: "GET", url: "https://" + baseUrl + '/openmrs/ws/rest/v1/angtbilling/doctorcharge/addDoctorCharge.htm?conceptId=' + concept.conceptId + "&patientUuid=" + patientUuid, headers: { "Content-Type": "application/json", "Authorization": "Basic YWRtaW46dGVzdA==" } }).then(function (response) { console.log(response.data); doctorBillPrint(response.data); $state.go("newpatient"); }); }; function doctorBillPrint(obj) { var baseUrl = location.host; var strWindowFeatures = "location=yes,scrollbars=yes,status=yes,fullscreen=yes"; var URL = ('https://' + baseUrl + '/openmrs/module/angtbilling/doctorServicePrint.htm?billUuid=' + obj.uuid); var win = window.open(URL, '', strWindowFeatures, '_blank'); }; const transformNidVerifyData = (data, nidData) => { const userUuid = $rootScope.currentUser.uuid; const isNationalIdPresent = data.nationalId; const fullName = nidData.fullName_English.trim(); const nameParts = fullName.split(' '); let givenName = ''; let surname = ''; if (nameParts.length === 1) { givenName = nameParts[0]; } else { givenName = nameParts.slice(0, -1).join(' '); surname = nameParts.slice(-1).join(' '); } return { given_name: givenName, sur_name: surname, date_of_birth: data.birthdate ? data.birthdate.toISOString().substring(0, 10) : null, gender: nidData.gender === 1 ? 'M' : nidData.gender === 2 ? 'F' : 'O', nid: isNationalIdPresent ? data.nationalId : '', bin_brn: isNationalIdPresent ? '' : data.birthRegistrationId, verifyToken: userUuid, phone_number: { number: data.phoneNumber }, present_address: { address_line: nidData.presentHouseholdNoText ? nidData.presentHouseholdNoText : data.address.address1, division_id: "30", district_id: "26", upazila_id: "02", country_code: "050" }, name_bangla: nidData.fullName_Bangla, religion: null, blood_group: null, place_of_birth: null, nationality: null, marital_status: null, primary_contact: null, primary_contact_number: { number: null }, relations: [ {type: 'FTH', name_bangla: nidData.fatherName_Bangla, given_name: nidData.fatherName_English}, {type: 'MTH', name_bangla: nidData.motherName_Bangla, given_name: nidData.motherName_English} ], // permanent_address: { // address_line: nidData.permanentHouseholdNoText ? nidData.permanentHouseholdNoText : null, // // division_id: null, // // district_id: null, // // upazila_id: null, // city_corporation_id: null, // union_or_urban_ward_id: null, // rural_ward_id: null, // area_mouja: null, // village: null, // holding_number: null, // street: null, // post_office: null, // post_code: null, // country_code: '050' // }, confidential: 'No', openMRSPatientUuid: data.uuid }; }; var createPatient = function (jumpAccepted) { // let _identifier = $scope.patient.extraIdentifiers[0]; // if (_identifier.identifier === "" || _identifier.identifier === undefined) { // $scope.patient.extraIdentifiers = []; // } return patientService.create($scope.patient, jumpAccepted).then(function (response) { console.log(response); var _data = response.data; copyPatientProfileDataToScope(response); if (response.status === 200) { const HIDPayloadData = transformNidVerifyData($scope.patient, nidResponseData); createPatientMCI(HIDPayloadData); } if (response.status === 200 && $scope.patient.eveningDoctorName != undefined) { doctorBill($scope.patient.eveningDoctorName, _data.patient.uuid); } }, function (response) { if (response.status === 412) { var data = _.map(response.data, function (data) { return { sizeOfTheJump: data.sizeOfJump, identifierName: _.find($rootScope.patientConfiguration.identifierTypes, {uuid: data.identifierType}).name }; }); getConfirmationViaNgDialog({ template: 'views/customIdentifierConfirmation.html', data: data, scope: $scope, yesCallback: function () { return createPatient(true); } }); } if (response.isIdentifierDuplicate) { errorMessage = response.message; } }); }; const createPatientMCI = (HIDPayloadData) => { fetch(baseUrl + "/openmrs/ws/rest/v1/angtcore/hid/create/mciPatientCreate.htm", { method: "POST", body: JSON.stringify(HIDPayloadData), headers: { "Content-Type": "application/json", "Authorization": "Basic YWRtaW46dGVzdA==" } } ) .then((response) => { if (!response.ok) { $timeout(function () { resetPatient(); messagingService.showMessage("error", "Something went wrong in NID Server, Please try again."); }); // throw new Error(`Request failed with status: ${response.status}`); } return response.json(); }) .then((res) => { console.log(res); if (res.statusCode === 201) { return res; } else { $timeout(function () { messagingService.showMessage("error", "Something went wrong in MCI Server, Please try again."); }); // throw new Error(`Request failed with status: ${response.status}`); } }); }; var createPromise = function () { var deferred = $q.defer(); createPatient().finally(function () { return deferred.resolve({}); }); return deferred.promise; }; $scope.create = function () { addNewRelationships(); var errorMessages = Bahmni.Common.Util.ValidationUtil.validate($scope.patient, $scope.patientConfiguration.attributeTypes); if (errorMessages.length > 0) { errorMessages.forEach(function (errorMessage) { messagingService.showMessage('error', errorMessage); }); return $q.when({}); } return spinner.forPromise(createPromise()).then(function (response) { if (errorMessage) { messagingService.showMessage("error", errorMessage); errorMessage = undefined; } }); }; $scope.afterSave = function () { messagingService.showMessage("info", "REGISTRATION_LABEL_SAVED"); $state.go("patient.edit", { patientUuid: $scope.patient.uuid }); _reload(); }; function _reload() { setTimeout(function () { window.location.reload(); }, 1500) } } ]); 'use strict'; angular.module('bahmni.registration') .controller('EditPatientController', ['$scope', '$http', 'patientService', 'encounterService', '$stateParams', 'openmrsPatientMapper', '$window', '$q', 'spinner', 'appService', 'messagingService', '$rootScope', 'auditLogService', function ($scope, $http, patientService, encounterService, $stateParams, openmrsPatientMapper, $window, $q, spinner, appService, messagingService, $rootScope, auditLogService) { var dateUtil = Bahmni.Common.Util.DateUtil; var uuid = $stateParams.patientUuid; $scope.patient = {}; var getUserRole = function () { var params = { v: "full" }; return $http.get('/openmrs/ws/rest/v1/user?limit=500', { method: "GET", params: params, withCredentials: true }); }; $q.all([getUserRole()]).then(function (response) { var result = response[0].data.results; var providerUuid = $rootScope.currentUser.person.uuid; var filterUser = result.filter(function (user) { return user.person.uuid === providerUuid; } ); var roles = filterUser[0].roles; var verify = roles.filter(function (role) { return role.name === "System Developer"; }); if (verify.length === 0) { var refresh = $window.localStorage.getItem('refresh'); if (refresh === null) { location.reload(); $window.localStorage.setItem('refresh', "1"); } $scope.patient.access = true; } else { $scope.patient.access = false; } }); $scope.actions = {}; $scope.addressHierarchyConfigs = appService.getAppDescriptor().getConfigValue("addressHierarchy"); $scope.disablePhotoCapture = appService.getAppDescriptor().getConfigValue("disablePhotoCapture"); $scope.today = dateUtil.getDateWithoutTime(dateUtil.now()); var setReadOnlyFields = function () { $scope.readOnlyFields = {}; var readOnlyFields = appService.getAppDescriptor().getConfigValue("readOnlyFields"); angular.forEach(readOnlyFields, function (readOnlyField) { if ($scope.patient[readOnlyField]) { $scope.readOnlyFields[readOnlyField] = true; } }); }; $rootScope.onHomeNavigate = function (event) { if ($scope.showSaveConfirmDialogConfig && $state.current.name != "patient.visit") { event.preventDefault(); $scope.targetUrl = event.currentTarget.getAttribute('href'); isHref = true; $scope.confirmationPrompt(event); } }; var successCallBack = function (openmrsPatient) { $scope.openMRSPatient = openmrsPatient["patient"]; $scope.patient = openmrsPatientMapper.map(openmrsPatient); setReadOnlyFields(); expandDataFilledSections(); $scope.patientLoaded = true; }; var expandDataFilledSections = function () { angular.forEach($rootScope.patientConfiguration && $rootScope.patientConfiguration.getPatientAttributesSections(), function (section) { var notNullAttribute = _.find(section && section.attributes, function (attribute) { return $scope.patient[attribute.name] !== undefined; }); section.expand = section.expanded || (notNullAttribute ? true : false); }); }; (function () { var getPatientPromise = patientService.get(uuid).then(successCallBack); var isDigitized = encounterService.getDigitized(uuid); isDigitized.then(function (data) { var encountersWithObservations = data.data.results.filter(function (encounter) { return encounter.obs.length > 0; }); $scope.isDigitized = encountersWithObservations.length > 0; }); spinner.forPromise($q.all([getPatientPromise, isDigitized])); })(); // angt code function doctorBill(concept, patientUuid) { var baseUrl = location.host; $http({ method: "GET", url: "https://" + baseUrl + '/openmrs/ws/rest/v1/angtbilling/doctorcharge/addDoctorCharge.htm?conceptId=' + concept.conceptId + "&patientUuid=" + patientUuid, headers: { "Content-Type": "application/json", "Authorization": "Basic YWRtaW46dGVzdA==" } }).then(function (response) { console.log(response.data); doctorBillPrint(response.data); }); }; function doctorBillPrint(obj) { var baseUrl = location.host; var strWindowFeatures = "location=yes,scrollbars=yes,status=yes,fullscreen=yes"; var URL = ('https://' + baseUrl + '/openmrs/module/angtbilling/doctorServicePrint.htm?billUuid=' + obj.uuid); var win = window.open(URL, '', strWindowFeatures, '_blank'); }; // end $scope.update = function () { if ($scope.patient.eveningDoctorName != undefined) { doctorBill($scope.patient.eveningDoctorName, $scope.patient.uuid); } addNewRelationships(); var errorMessages = Bahmni.Common.Util.ValidationUtil.validate($scope.patient, $scope.patientConfiguration.attributeTypes); if (errorMessages.length > 0) { errorMessages.forEach(function (errorMessage) { messagingService.showMessage('error', errorMessage); }); return $q.when({}); } return spinner.forPromise(patientService.update($scope.patient, $scope.openMRSPatient).then(function (result) { var patientProfileData = result.data; if (!patientProfileData.error) { successCallBack(patientProfileData); $scope.actions.followUpAction(patientProfileData); } })); }; var addNewRelationships = function () { var newRelationships = _.filter($scope.patient.newlyAddedRelationships, function (relationship) { return relationship.relationshipType && relationship.relationshipType.uuid; }); newRelationships = _.each(newRelationships, function (relationship) { delete relationship.patientIdentifier; delete relationship.content; delete relationship.providerName; }); $scope.patient.relationships = _.concat(newRelationships, $scope.patient.deletedRelationships); }; $scope.isReadOnly = function (field) { return $scope.readOnlyFields ? ($scope.readOnlyFields[field] ? true : false) : undefined; }; $scope.afterSave = function () { auditLogService.log($scope.patient.uuid, Bahmni.Registration.StateNameEvenTypeMap['patient.edit'], undefined, "MODULE_LABEL_REGISTRATION_KEY"); messagingService.showMessage("info", "REGISTRATION_LABEL_SAVED"); _reload(); }; function _reload() { setTimeout(function () { location.reload(); }, 1000); } }]); 'use strict'; angular.module('bahmni.registration') .directive('patientAction', ['$window', '$location', '$state', 'spinner', '$rootScope', '$stateParams', '$bahmniCookieStore', 'appService', 'visitService', 'sessionService', 'encounterService', 'messagingService', '$translate', 'auditLogService', function ($window, $location, $state, spinner, $rootScope, $stateParams, $bahmniCookieStore, appService, visitService, sessionService, encounterService, messagingService, $translate, auditLogService) { var controller = function ($scope) { var self = this; var uuid = $stateParams.patientUuid; var editActionsConfig = appService.getAppDescriptor().getExtensions(Bahmni.Registration.Constants.nextStepConfigId, "config") || []; var conceptSetExtensions = appService.getAppDescriptor().getExtensions("org.bahmni.registration.conceptSetGroup.observations", "config"); var loginLocationUuid = $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName).uuid; var defaultVisitType = $rootScope.regEncounterConfiguration.getDefaultVisitType(loginLocationUuid); defaultVisitType = defaultVisitType || appService.getAppDescriptor().getConfigValue('defaultVisitType'); var showStartVisitButton = appService.getAppDescriptor().getConfigValue("showStartVisitButton"); var forwardUrlsForVisitTypes = appService.getAppDescriptor().getConfigValue("forwardUrlsForVisitTypes"); showStartVisitButton = (_.isUndefined(showStartVisitButton) || _.isNull(showStartVisitButton)) ? true : showStartVisitButton; var visitLocationUuid = $rootScope.visitLocation; var forwardUrls = forwardUrlsForVisitTypes || false; var getForwardUrlEntryForVisitFromTheConfig = function () { var matchedEntry = _.find(forwardUrls, function (entry) { if (self.hasActiveVisit) { return entry.visitType === self.activeVisit.visitType.name; } return entry.visitType === $scope.visitControl.selectedVisitType.name; }); return matchedEntry; }; var keyForActiveVisitEntry = function () { var matchedEntry = getForwardUrlEntryForVisitFromTheConfig(); if (matchedEntry) { $scope.activeVisitConfig = matchedEntry; if (_.isEmpty(_.get($scope.activeVisitConfig, 'translationKey'))) { $scope.activeVisitConfig.translationKey = "REGISTRATION_LABEL_ENTER_VISIT"; $scope.activeVisitConfig.shortcutKey = "REGISTRATION_ENTER_VISIT_DETAILS_ACCESS_KEY"; } return 'forwardAction'; } }; function setForwardActionKey () { if (editActionsConfig.length === 0) { $scope.forwardActionKey = self.hasActiveVisit ? (getForwardUrlEntryForVisitFromTheConfig() ? keyForActiveVisitEntry() : 'enterVisitDetails') : 'startVisit'; } else { $scope.actionConfig = editActionsConfig[0]; $scope.forwardActionKey = 'configAction'; } } var init = function () { if (_.isEmpty(uuid)) { self.hasActiveVisit = false; setForwardActionKey(); return; } var searchParams = { patient: uuid, includeInactive: false, v: "custom:(uuid,visitType,location:(uuid))" }; spinner.forPromise(visitService.search(searchParams).then(function (response) { var results = response.data.results; var activeVisitForCurrentLoginLocation; if (results) { activeVisitForCurrentLoginLocation = _.filter(results, function (result) { return result.location.uuid === visitLocationUuid; }); } self.hasActiveVisit = activeVisitForCurrentLoginLocation && (activeVisitForCurrentLoginLocation.length > 0); if (self.hasActiveVisit) { self.activeVisit = activeVisitForCurrentLoginLocation[0]; } setForwardActionKey(); })); }; $scope.visitControl = new Bahmni.Common.VisitControl( $rootScope.regEncounterConfiguration.getVisitTypesAsArray(), defaultVisitType, encounterService, $translate, visitService ); $scope.visitControl.onStartVisit = function () { $scope.setSubmitSource('startVisit'); }; $scope.setSubmitSource = function (source) { $scope.actions.submitSource = source; }; $scope.showStartVisitButton = function () { return showStartVisitButton; }; var goToForwardUrlPage = function (patientData) { var forwardUrl = appService.getAppDescriptor().formatUrl($scope.activeVisitConfig.forwardUrl, {'patientUuid': patientData.patient.uuid}); $window.location.href = forwardUrl; }; $scope.actions.followUpAction = function (patientProfileData) { messagingService.clearAll(); switch ($scope.actions.submitSource) { case 'startVisit': var entry = getForwardUrlEntryForVisitFromTheConfig(); var forwardUrl = entry ? entry.forwardUrl : undefined; return createVisit(patientProfileData, forwardUrl); case 'forwardAction': return goToForwardUrlPage(patientProfileData); case 'enterVisitDetails': return goToVisitPage(patientProfileData); case 'configAction': return handleConfigAction(patientProfileData); case 'save': $scope.afterSave(); } }; var handleConfigAction = function (patientProfileData) { var forwardUrl = appService.getAppDescriptor().formatUrl($scope.actionConfig.extensionParams.forwardUrl, {'patientUuid': patientProfileData.patient.uuid}); if (!self.hasActiveVisit) { createVisit(patientProfileData, forwardUrl); } else { $window.location.href = forwardUrl; } }; var goToVisitPage = function (patientData) { $scope.patient.uuid = patientData.patient.uuid; $scope.patient.name = patientData.patient.person.names[0].display; $location.path("/patient/" + patientData.patient.uuid + "/visit"); }; var isEmptyVisitLocation = function () { return _.isEmpty($rootScope.visitLocation); }; var createVisit = function (patientProfileData, forwardUrl) { if (isEmptyVisitLocation()) { $state.go('patient.edit', {patientUuid: $scope.patient.uuid}).then(function () { messagingService.showMessage("error", "NO_LOCATION_TAGGED_TO_VISIT_LOCATION"); }); return; } spinner.forPromise($scope.visitControl.createVisitOnly(patientProfileData.patient.uuid, $rootScope.visitLocation).then(function (response) { auditLogService.log(patientProfileData.patient.uuid, "OPEN_VISIT", {visitUuid: response.data.uuid, visitType: response.data.visitType.display}, 'MODULE_LABEL_REGISTRATION_KEY'); if (forwardUrl) { var updatedForwardUrl = appService.getAppDescriptor().formatUrl(forwardUrl, {'patientUuid': patientProfileData.patient.uuid}); $window.location.href = updatedForwardUrl; } else { goToVisitPage(patientProfileData); } }, function () { $state.go('patient.edit', {patientUuid: $scope.patient.uuid}); })); }; init(); }; return { restrict: 'E', templateUrl: 'views/patientAction.html', controller: controller }; } ]); 'use strict'; angular.module('bahmni.registration') .controller('VisitController', ['$window', '$scope', '$rootScope', '$state', '$bahmniCookieStore', 'patientService', 'encounterService', '$stateParams', 'spinner', '$timeout', '$q', 'appService', 'openmrsPatientMapper', 'contextChangeHandler', 'messagingService', 'sessionService', 'visitService', '$location', '$translate', 'auditLogService', 'formService', 'registrationCardPrinter', '$http', function ($window, $scope, $rootScope, $state, $bahmniCookieStore, patientService, encounterService, $stateParams, spinner, $timeout, $q, appService, openmrsPatientMapper, contextChangeHandler, messagingService, sessionService, visitService, $location, $translate, auditLogService, formService, registrationCardPrinter, $http) { var vm = this; var patientUuid = $stateParams.patientUuid; var extensions = appService.getAppDescriptor().getExtensions("org.bahmni.registration.conceptSetGroup.observations", "config"); var formExtensions = appService.getAppDescriptor().getExtensions("org.bahmni.registration.conceptSetGroup.observations", "forms"); var locationUuid = sessionService.getLoginLocationUuid(); var selectedProvider = $rootScope.currentProvider; var regEncounterTypeUuid = $rootScope.regEncounterConfiguration.encounterTypes[Bahmni.Registration.Constants.registrationEncounterType]; var visitLocationUuid = $rootScope.visitLocation; var getPatient = function () { var deferred = $q.defer(); patientService.get(patientUuid).then(function (openMRSPatient) { deferred.resolve(openMRSPatient); $scope.patient = openmrsPatientMapper.map(openMRSPatient); $scope.patient.name = openMRSPatient.patient.person.names[0].display; $scope.patient.uuid = openMRSPatient.patient.uuid; }); return deferred.promise; }; var getActiveEncounter = function () { var deferred = $q.defer(); encounterService.find({ "patientUuid": patientUuid, "providerUuids": !_.isEmpty($scope.currentProvider.uuid) ? [$scope.currentProvider.uuid] : null, "includeAll": false, locationUuid: locationUuid, encounterTypeUuids: [regEncounterTypeUuid] }).then(function (response) { deferred.resolve(response); $scope.encounterUuid = response.data.encounterUuid; $scope.observations = response.data.observations; }); return deferred.promise; }; var getAllForms = function () { var deferred = $q.defer(); formService.getFormList($scope.encounterUuid) .then(function (response) { $scope.conceptSets = extensions.map(function (extension) { return new Bahmni.ConceptSet.ConceptSetSection(extension, $rootScope.currentUser, {}, [], {}); }); $scope.observationForms = getObservationForms(formExtensions, response.data); $scope.conceptSets = $scope.conceptSets.concat($scope.observationForms); $scope.availableConceptSets = $scope.conceptSets.filter(function (conceptSet) { return conceptSet.isAvailable($scope.context); }); deferred.resolve(response.data); }); return deferred.promise; }; $scope.hideFields = appService.getAppDescriptor().getConfigValue("hideFields"); $scope.back = function () { $state.go('patient.edit'); }; $scope.updatePatientImage = function (image) { var updateImagePromise = patientService.updateImage($scope.patient.uuid, image.replace("data:image/jpeg;base64,", "")); spinner.forPromise(updateImagePromise); return updateImagePromise; }; var save = function () { $scope.encounter = { patientUuid: $scope.patient.uuid, locationUuid: locationUuid, encounterTypeUuid: regEncounterTypeUuid, orders: [], drugOrders: [], extensions: {} }; $bahmniCookieStore.put(Bahmni.Common.Constants.grantProviderAccessDataCookieName, selectedProvider, { path: '/', expires: 1 }); $scope.encounter.observations = $scope.observations; $scope.encounter.observations = new Bahmni.Common.Domain.ObservationFilter().filter($scope.encounter.observations); addFormObservations($scope.encounter.observations); var createPromise = encounterService.create($scope.encounter); spinner.forPromise(createPromise); return createPromise.then(function (response) { var messageParams = { encounterUuid: response.data.encounterUuid, encounterType: response.data.encounterType }; auditLogService.log(patientUuid, 'EDIT_ENCOUNTER', messageParams, 'MODULE_LABEL_REGISTRATION_KEY'); var visitType, visitTypeUuid; visitTypeUuid = response.data.visitTypeUuid; visitService.getVisitType().then(function (response) { visitType = _.find(response.data.results, function (type) { if (type.uuid === visitTypeUuid) { return type; } }); }); }); }; var isUserPrivilegedToCloseVisit = function () { var applicablePrivs = [Bahmni.Common.Constants.closeVisitPrivilege, Bahmni.Common.Constants.deleteVisitsPrivilege]; var userPrivs = _.map($rootScope.currentUser.privileges, function (privilege) { return privilege.name; }); return _.some(userPrivs, function (privName) { return _.includes(applicablePrivs, privName); }); }; var searchActiveVisitsPromise = function () { return visitService.search({ patient: patientUuid, includeInactive: false, v: "custom:(uuid,location:(uuid))" }).then(function (response) { var results = response.data.results; var activeVisitForCurrentLoginLocation; if (results) { activeVisitForCurrentLoginLocation = _.filter(results, function (result) { return result.location.uuid === visitLocationUuid; }); } var hasActiveVisit = activeVisitForCurrentLoginLocation.length > 0; vm.visitUuid = hasActiveVisit ? activeVisitForCurrentLoginLocation[0].uuid : ""; $scope.canCloseVisit = isUserPrivilegedToCloseVisit() && hasActiveVisit; }); }; $scope.closeVisitIfDischarged = function () { visitService.getVisitSummary(vm.visitUuid).then(function (response) { var visitSummary = response.data; if (visitSummary.admissionDetails && !visitSummary.dischargeDetails) { messagingService.showMessage("error", 'REGISTRATION_VISIT_CANNOT_BE_CLOSED'); var messageParams = { visitUuid: vm.visitUuid, visitType: visitSummary.visitType }; auditLogService.log(patientUuid, 'CLOSE_VISIT_FAILED', messageParams, 'MODULE_LABEL_REGISTRATION_KEY'); } else { closeVisit(visitSummary.visitType); } }); }; var closeVisit = function (visitType) { var confirmed = $window.confirm($translate.instant("REGISTRATION_CONFIRM_CLOSE_VISIT")); if (confirmed) { visitService.endVisit(vm.visitUuid).then(function () { $location.url(Bahmni.Registration.Constants.patientSearchURL); var messageParams = { visitUuid: vm.visitUuid, visitType: visitType }; auditLogService.log(patientUuid, 'CLOSE_VISIT', messageParams, 'MODULE_LABEL_REGISTRATION_KEY'); }); } }; $scope.getMessage = function () { return $scope.message; }; var isObservationFormValid = function () { var opdRoomMandatory = appService.getAppDescriptor().getConfigValue("opdRoom"); var valid = true; var isSelectOpd = false; var _value = []; _.each($scope.observationForms, function (observationForm) { _value = observationForm.component.getValue().observations; if (valid && observationForm.component) { var value = observationForm.component.getValue(); if (value.errors) { messagingService.showMessage('error', "{{'REGISTRATION_FORM_ERRORS_MESSAGE_KEY' | translate }}"); valid = false; } } }); _.each(_value, function (t) { if (t.concept.name.includes(opdRoomMandatory.conceptName)) { isSelectOpd = true; } if (t.value === undefined) { isSelectOpd = false; } }); if (opdRoomMandatory.isMandatory) { if (!isSelectOpd) { messagingService.showMessage('error', "{{'Please input Opd Consultation Room'}}"); valid = false; } } return valid; }; var validate = function () { var isFormValidated = mandatoryValidate(); var deferred = $q.defer(); var contxChange = contextChangeHandler.execute(); var allowContextChange = contxChange["allow"]; var errorMessage; if (!isObservationFormValid()) { deferred.reject("Some fields are not valid"); return deferred.promise; } if (!allowContextChange) { errorMessage = contxChange["errorMessage"] ? contxChange["errorMessage"] : 'REGISTRATION_LABEL_CORRECT_ERRORS'; messagingService.showMessage('error', errorMessage); deferred.reject("Some fields are not valid"); return deferred.promise; } else if (!isFormValidated) { // This ELSE IF condition is to be deleted later. errorMessage = "REGISTRATION_LABEL_ENTER_MANDATORY_FIELDS"; messagingService.showMessage('error', errorMessage); deferred.reject("Some fields are not valid"); return deferred.promise; } else { deferred.resolve(); return deferred.promise; } }; // Start :: Registration Page validation // To be deleted later - Hacky fix only for Registration Page var mandatoryConceptGroup = []; var mandatoryValidate = function () { conceptGroupValidation($scope.observations); return isValid(mandatoryConceptGroup); }; var conceptGroupValidation = function (observations) { var concepts = _.filter(observations, function (observationNode) { return isMandatoryConcept(observationNode); }); if (!_.isEmpty(concepts)) { mandatoryConceptGroup = _.union(mandatoryConceptGroup, concepts); } }; var isMandatoryConcept = function (observation) { if (!_.isEmpty(observation.groupMembers)) { conceptGroupValidation(observation.groupMembers); } else { return observation.conceptUIConfig && observation.conceptUIConfig.required; } }; var isValid = function (mandatoryConcepts) { var concept = mandatoryConcepts.filter(function (mandatoryConcept) { if (mandatoryConcept.hasValue()) { return false; } if (mandatoryConcept instanceof Bahmni.ConceptSet.Observation && mandatoryConcept.conceptUIConfig && mandatoryConcept.conceptUIConfig.multiSelect) { return false; } if (mandatoryConcept.isMultiSelect) { return _.isEmpty(mandatoryConcept.getValues()); } return !mandatoryConcept.value; }); return _.isEmpty(concept); }; // End :: Registration Page validation var generateQueue = function (queueData) { console.log("Queue Generated :: " + queueData); return $http({ method: 'POST', url: '/openmrs/module/queuemanagement/generate.form', data: JSON.stringify(queueData), headers: { 'Content-Type': 'application/json' } }); }; var afterSave = function () { var afterSave = appService.getAppDescriptor().getConfigValue("afterSavePrint"); $scope.serial = $scope.serial || []; var queueManagement = appService.getAppDescriptor().getConfigValue("queueManagement"); $state.transitionTo($state.current, $state.params, { reload: true, inherit: false, notify: true }); messagingService.showMessage('info', 'REGISTRATION_LABEL_SAVED'); $timeout(function () { var apiURL = "/openmrs/ws/rest/v1/bahmnicore/observations?" + "concept=Visit+Details&concept=Patient+Visit+Details&" + "concept=Patient+Visit+Type&" + "concept=Opd+Consultation+Room&" + "patientUuid=" + patientUuid + "&scope=latest"; $http({ method: "GET", url: apiURL }).then(function mySuccess (response) { var obsdata = response.data; $scope.obsData = obsdata; patientService.get(patientUuid).then(function (openMRSPatient) { $scope.patient = openmrsPatientMapper.map(openMRSPatient); obsdata.forEach(function (key) { if (key.complexData != null) { let identifier = $scope.patient.primaryIdentifier.identifier; let roomName = key.complexData.data.name; let roomId = key.complexData.data.id; let date = new Date(); let formatDate = date.toISOString().split("T"); let queue = { identifier: identifier, visitroom: roomName, roomId: roomId, dateCreated: formatDate[0] }; if (queueManagement.willUse == true) { generateQueue(queue); console.log(queue); $http({ method: "GET", url: "/openmrs/module/queuemanagement/getToken.form?identifier=" + identifier + "&dateCreated=" + formatDate[0] }).then(function mySuccess(response) { var newData = response.data.token; $scope.serial.push(newData); }); } else { console.log("Queue management module is not being used now"); } } } ); }); if (afterSave.print === true) { $scope.observations = $scope.obsData || $scope.observations; var obs = {}; var getValue = function (observation) { obs[observation.concept.name] = obs[observation.concept.name] || []; observation.value && obs[observation.concept.name].push(observation.value); observation.groupMembers.forEach(getValue); }; $scope.observations.forEach(getValue); $scope.obs = obs; $scope.observations.roomData = $scope.observations.filter(function (data) { return data.conceptNameToDisplay === 'Consultation Room'; }); registrationCardPrinter.print(afterSave.templateUrl, $scope.patient, $scope.obs, $scope.encounterDateTime, $scope.observations); if (afterSave.createNew === true) { $state.go('newpatient'); } window.sessionStorage.removeItem('free'); } }); }, 500); }; $scope.submit = function () { return validate().then(save).then(afterSave); }; $scope.today = function () { return new Date(); }; $scope.disableFormSubmitOnEnter = function () { $('.visit-patient').find('input').keypress(function (e) { if (e.which === 13) { // Enter key = keycode 13 return false; } }); }; var getConceptSet = function () { var visitType = $scope.encounterConfig.getVisitTypeByUuid($scope.visitTypeUuid); $scope.context = { visitType: visitType, patient: $scope.patient }; }; var getObservationForms = function (extensions, observationsForms) { var forms = []; var observations = $scope.observations || []; _.each(extensions, function (ext) { var options = ext.extensionParams || {}; var observationForm = _.find(observationsForms, function (form) { return (form.formName === options.formName || form.name === options.formName); }); if (observationForm) { var formUuid = observationForm.formUuid || observationForm.uuid; var formName = observationForm.name || observationForm.formName; var formVersion = observationForm.version || observationForm.formVersion; forms.push(new Bahmni.ObservationForm(formUuid, $rootScope.currentUser, formName, formVersion, observations, ext)); } }); return forms; }; $scope.isFormTemplate = function (data) { return data.formUuid; }; var addFormObservations = function (observations) { if ($scope.observationForms) { _.remove(observations, function (observation) { return observation.formNamespace; }); _.each($scope.observationForms, function (observationForm) { if (observationForm.component) { var formObservations = observationForm.component.getValue(); _.each(formObservations.observations, function (obs) { observations.push(obs); }); } }); } }; spinner.forPromise($q.all([getPatient(), getActiveEncounter(), searchActiveVisitsPromise()]) .then(function () { getAllForms().then(function () { getConceptSet(); }); })); }]); 'use strict'; angular.module('bahmni.registration') .factory('patientService', ['$http', '$rootScope', '$bahmniCookieStore', '$q', 'patientServiceStrategy', 'sessionService', function ($http, $rootScope, $bahmniCookieStore, $q, patientServiceStrategy, sessionService) { var openmrsUrl = Bahmni.Registration.Constants.openmrsUrl; var baseOpenMRSRESTURL = Bahmni.Registration.Constants.baseOpenMRSRESTURL; var search = function (query, identifier, addressFieldName, addressFieldValue, customAttributeValue, offset, customAttributeFields, programAttributeFieldName, programAttributeFieldValue, addressSearchResultsConfig, patientSearchResultsConfig, filterOnAllIdentifiers) { var config = { params: { q: query, identifier: identifier, s: "byIdOrNameOrVillage", addressFieldName: addressFieldName, addressFieldValue: addressFieldValue, customAttribute: customAttributeValue, startIndex: offset || 0, patientAttributes: customAttributeFields, programAttributeFieldName: programAttributeFieldName, programAttributeFieldValue: programAttributeFieldValue, addressSearchResultsConfig: addressSearchResultsConfig, patientSearchResultsConfig: patientSearchResultsConfig, loginLocationUuid: sessionService.getLoginLocationUuid(), filterOnAllIdentifiers: filterOnAllIdentifiers }, withCredentials: true }; return patientServiceStrategy.search(config); }; var searchByIdentifier = function (identifier) { return $http.get(Bahmni.Common.Constants.bahmniSearchUrl + "/patient", { method: "GET", params: { identifier: identifier, loginLocationUuid: sessionService.getLoginLocationUuid() }, withCredentials: true }); }; var searchByNameOrIdentifier = function (query, limit) { return $http.get(Bahmni.Common.Constants.bahmniSearchUrl + "/patient", { method: "GET", params: { q: query, s: "byIdOrName", limit: limit, loginLocationUuid: sessionService.getLoginLocationUuid() }, withCredentials: true }); }; var get = function (uuid) { return patientServiceStrategy.get(uuid); }; var create = function (patient, jumpAccepted) { return patientServiceStrategy.create(patient, jumpAccepted); }; var update = function (patient, openMRSPatient) { return patientServiceStrategy.update(patient, openMRSPatient, $rootScope.patientConfiguration.attributeTypes); }; var updateImage = function (uuid, image) { var url = baseOpenMRSRESTURL + "/personimage/"; var data = { "person": {"uuid": uuid}, "base64EncodedImage": image }; var config = { withCredentials: true, headers: {"Accept": "application/json", "Content-Type": "application/json"} }; return $http.post(url, data, config); }; return { search: search, searchByIdentifier: searchByIdentifier, create: create, update: update, get: get, updateImage: updateImage, searchByNameOrIdentifier: searchByNameOrIdentifier }; }]); 'use strict'; angular.module('bahmni.registration') .factory('patientAttributeService', ['$http', '$q', function ($http, $q) { var urlMap; var init = function () { urlMap = { "personName": Bahmni.Common.Constants.bahmniSearchUrl + "/personname", "personAttribute": Bahmni.Common.Constants.bahmniSearchUrl + "/personattribute" }; }; init(); var search = function (fieldName, query, type) { var url = urlMap[type]; var queryWithoutTrailingSpaces = query.trimLeft(); return $http.get(url, { method: "GET", params: {q: queryWithoutTrailingSpaces, key: fieldName }, withCredentials: true }); }; return { search: search }; }]); 'use strict'; angular.module('bahmni.registration') .factory('addressHierarchyService', ['$http', function ($http) { var parseSearchString = function (searchString) { searchString = searchString.replace(new RegExp("\\(", "g"), "\\("); searchString = searchString.replace(new RegExp("\\)", "g"), "\\)"); return searchString; }; var search = function (fieldName, query, parentUuid) { var params = {searchString: query, addressField: fieldName, parentUuid: parentUuid, limit: defaults.maxAutocompleteResults}; var url = Bahmni.Registration.Constants.openmrsUrl + "/module/addresshierarchy/ajax/getPossibleAddressHierarchyEntriesWithParents.form"; return $http.get(url, { method: "GET", params: params, withCredentials: true }); }; var getNextAvailableParentName = function (addressField) { var parent = addressField.parent; while (parent) { if (parent.name) { return parent.name; } else { parent = parent.parent; } } return ""; }; var getAddressDataResults = function (data) { return data.data ? data.data.map(function (addressField) { var parentName = getNextAvailableParentName(addressField); return { 'value': addressField.name, 'label': addressField.name + (parentName ? ", " + parentName : ""), addressField: addressField }; }) : []; }; return { search: search, getNextAvailableParentName: getNextAvailableParentName, getAddressDataResults: getAddressDataResults }; }]); 'use strict'; angular.module('bahmni.registration') .factory('registrationCardPrinter', ['printer', function (printer) { var print = function (templatePath, patient, obs, encounterDateTime, observations, serial) { templatePath = templatePath || "views/nolayoutfound.html"; printer.print(templatePath, { patient: patient, today: new Date(), obs: obs || {}, encounterDateTime: encounterDateTime, observations: observations || {}, serial: serial || {} }); }; return { print: print }; }]); 'use strict'; Bahmni.Common.Domain.AttributeTypeMapper = (function () { function AttributeTypeMapper () { } AttributeTypeMapper.prototype.mapFromOpenmrsAttributeTypes = function (mrsAttributeTypes, mandatoryAttributes, attributesConfig) { var attributeTypes = []; angular.forEach(mrsAttributeTypes, function (mrsAttributeType) { var isRequired = function () { var element = _.find(mandatoryAttributes, function (mandatoryAttribute) { return mandatoryAttribute == mrsAttributeType.name; }); return element ? true : false; }; var attributeType = { uuid: mrsAttributeType.uuid, sortWeight: mrsAttributeType.sortWeight, name: mrsAttributeType.name, fullySpecifiedName: mrsAttributeType.name, description: mrsAttributeType.description || mrsAttributeType.name, format: mrsAttributeType.format || mrsAttributeType.datatypeClassname, answers: [], required: isRequired(), concept: mrsAttributeType.concept || {}, excludeFrom: (attributesConfig && attributesConfig[mrsAttributeType.name] && attributesConfig[mrsAttributeType.name].excludeFrom) || [] }; attributeType.concept.dataType = attributeType.concept.datatype && attributeType.concept.datatype.name; if (mrsAttributeType.concept && mrsAttributeType.concept.answers) { angular.forEach(mrsAttributeType.concept.answers, function (mrsAnswer) { var displayName = mrsAnswer.display; var fullySpecifiedName = mrsAnswer.display; if (mrsAnswer.names && mrsAnswer.names.length == 2) { if (mrsAnswer.name.conceptNameType == 'FULLY_SPECIFIED') { if (mrsAnswer.names[0].display == displayName) { displayName = mrsAnswer.names[1].display; fullySpecifiedName = mrsAnswer.names[0].display; } else { displayName = mrsAnswer.names[0].display; fullySpecifiedName = mrsAnswer.names[1].display; } } } attributeType.answers.push({ fullySpecifiedName: fullySpecifiedName, description: displayName, conceptId: mrsAnswer.uuid }); }); } if (attributeType.format == "org.openmrs.customdatatype.datatype.RegexValidatedTextDatatype") { attributeType.pattern = mrsAttributeType.datatypeConfig; } attributeTypes.push(attributeType); }); return { attributeTypes: attributeTypes }; }; return AttributeTypeMapper; })(); 'use strict'; Bahmni.Common.Domain.AttributeFormatter = (function () { function AttributeFormatter () { } AttributeFormatter.prototype.getMrsAttributes = function (model, attributeTypes) { return attributeTypes.map(function (result) { var attribute = { attributeType: { uuid: result.uuid } }; if (!_.isEmpty(model)) { setAttributeValue(result, attribute, model[result.name]); } return attribute; }); }; AttributeFormatter.prototype.getMrsAttributesForUpdate = function (model, attributeTypes, attributes) { return _.filter(AttributeFormatter.prototype.getMrsAttributes(model, attributeTypes), function (mrsAttribute) { var attribute = _.find(attributes, function (attribute) { return mrsAttribute.attributeType.uuid === attribute.attributeType.uuid; }); if (attribute && !attribute.voided) { mrsAttribute.uuid = attribute.uuid; } return isAttributeChanged(mrsAttribute); }); }; AttributeFormatter.prototype.removeUnfilledAttributes = function (formattedAttributes) { return _.filter(formattedAttributes, isAttributeChanged); }; var isAttributeChanged = function (attribute) { return attribute.value || attribute.uuid; }; var setAttributeValue = function setAttributeValue (attributeType, attr, value) { if (value === "" || value === null || value === undefined || value.conceptUuid === null) { attr.voided = true; } else if (attributeType.format === "org.openmrs.Concept") { var attrDescription = _.find(attributeType.answers, function (answer) { if (answer.conceptId === value.conceptUuid) { return true; } }); attr.value = attrDescription != undefined ? attrDescription.description : null; attr.hydratedObject = value.conceptUuid; } else if (attributeType.format == "org.openmrs.util.AttributableDate" || attributeType.format == "org.openmrs.customdatatype.datatype.DateDatatype") { var mnt = moment(value); attr.value = mnt.format('YYYY-MM-DD'); } else { attr.value = value.toString(); } }; return AttributeFormatter; })(); 'use strict'; angular.module('bahmni.registration').factory('openmrsPatientMapper', ['patient', '$rootScope', 'age', 'identifiers', function (patient, $rootScope, age, identifiers) { var patientModel = patient; var whereAttributeTypeExists = function (attribute) { return $rootScope.patientConfiguration.get(attribute.attributeType.uuid); }, addAttributeToPatient = function (patient, attribute) { var attributeType = $rootScope.patientConfiguration.get(attribute.attributeType.uuid); if (attributeType) { if (attributeType.format === "org.openmrs.Concept" && attribute.value) { patient[attributeType.name] = {conceptUuid: attribute.value.uuid, value: attribute.value.display}; } else if (attributeType.format === "org.openmrs.util.AttributableDate") { patient[attributeType.name] = parseDate(attribute.value); } else { patient[attributeType.name] = attribute.value; } } }, mapAttributes = function (patient, attributes) { attributes.filter(whereAttributeTypeExists).forEach(function (attribute) { addAttributeToPatient(patient, attribute); }); }, parseDate = function (dateStr) { return Bahmni.Common.Util.DateUtil.parseServerDateToDate(dateStr); }, mapAddress = function (preferredAddress) { return preferredAddress || {}; }, mapRelationships = function (patient, relationships) { patient.relationships = relationships || []; patient.newlyAddedRelationships = [{}]; patient.hasRelationships = patient.relationships.length > 0; }, map = function (openmrsPatient) { var relationships = openmrsPatient.relationships; openmrsPatient = openmrsPatient.patient; var openmrsPerson = openmrsPatient.person; var patient = patientModel.create(); var birthDate = parseDate(openmrsPerson.birthdate); patient.uuid = openmrsPatient.uuid; patient.givenName = openmrsPerson.preferredName.givenName; patient.middleName = openmrsPerson.preferredName.middleName; patient.familyName = openmrsPerson.preferredName.familyName; patient.birthdate = !birthDate ? null : birthDate; patient.age = birthDate ? age.fromBirthDate(birthDate) : null; patient.gender = openmrsPerson.gender; patient.address = mapAddress(openmrsPerson.preferredAddress); patient.birthtime = parseDate(openmrsPerson.birthtime); patient.image = Bahmni.Registration.Constants.patientImageUrlByPatientUuid + openmrsPatient.uuid + "&q=" + new Date().toISOString(); patient.registrationDate = Bahmni.Common.Util.DateUtil.parse(openmrsPerson.auditInfo.dateCreated); patient.dead = openmrsPerson.dead; patient.isDead = patient.dead; patient.deathDate = parseDate(openmrsPerson.deathDate); patient.causeOfDeath = openmrsPerson.causeOfDeath; patient.birthdateEstimated = openmrsPerson.birthdateEstimated; patient.bloodGroup = openmrsPerson.bloodGroup; mapAttributes(patient, openmrsPerson.attributes); mapRelationships(patient, relationships); _.assign(patient, identifiers.mapIdentifiers(openmrsPatient.identifiers)); return patient; }; return { map: map }; }]); 'use strict'; Bahmni.Registration.CreatePatientRequestMapper = (function () { function CreatePatientRequestMapper (currentDate) { this.currentDate = currentDate; } CreatePatientRequestMapper.prototype.mapFromPatient = function (patientAttributeTypes, patient) { var constants = Bahmni.Registration.Constants; var allIdentifiers = _.concat(patient.extraIdentifiers, patient.primaryIdentifier); var identifiers = _.filter(allIdentifiers, function (identifier) { return !_.isEmpty(identifier.selectedIdentifierSource) || (identifier.identifier !== undefined); }); identifiers = _.map(identifiers, function (identifier) { return { identifier: identifier.identifier, identifierSourceUuid: identifier.selectedIdentifierSource ? identifier.selectedIdentifierSource.uuid : undefined, identifierPrefix: identifier.selectedIdentifierSource ? identifier.selectedIdentifierSource.prefix : undefined, identifierType: identifier.identifierType.uuid, preferred: identifier.preferred, voided: identifier.voided }; }); var openMRSPatient = { patient: { person: { names: [ { givenName: patient.givenName, middleName: patient.middleName, familyName: patient.familyName, display: patient.givenName + (patient.familyName ? " " + patient.familyName : ""), "preferred": false } ], addresses: [_.pick(patient.address, constants.allAddressFileds)], birthdate: this.getBirthdate(patient.birthdate, patient.age), birthdateEstimated: patient.birthdateEstimated, gender: patient.gender, birthtime: Bahmni.Common.Util.DateUtil.parseLongDateToServerFormat(patient.birthtime), personDateCreated: patient.registrationDate, attributes: new Bahmni.Common.Domain.AttributeFormatter().getMrsAttributes(patient, patientAttributeTypes), dead: patient.dead, deathDate: Bahmni.Common.Util.DateUtil.getDateWithoutTime(patient.deathDate), causeOfDeath: patient.causeOfDeath ? patient.causeOfDeath.uuid : '', uuid: patient.uuid }, identifiers: identifiers, uuid: patient.uuid } }; this.setImage(patient, openMRSPatient); openMRSPatient.relationships = patient.relationships; return openMRSPatient; }; CreatePatientRequestMapper.prototype.setImage = function (patient, openMRSPatient) { if (patient.getImageData()) { openMRSPatient.image = patient.getImageData(); } }; CreatePatientRequestMapper.prototype.getBirthdate = function (birthdate, age) { var mnt; if (birthdate) { mnt = moment(birthdate); } else if (age !== undefined) { mnt = moment(this.currentDate).subtract('days', age.days).subtract('months', age.months).subtract('years', age.years); } return mnt.format('YYYY-MM-DDTHH:mm:ss.SSSZZ'); }; return CreatePatientRequestMapper; })(); 'use strict'; Bahmni.Registration.UpdatePatientRequestMapper = (function () { var UpdatePatientRequestMapper = function (currentDate) { this.currentDate = currentDate; }; UpdatePatientRequestMapper.prototype.currentDate = undefined; UpdatePatientRequestMapper.prototype.mapFromPatient = function (patientAttributeTypes, openMRSPatient, patient) { var openMRSPatientProfile = { patient: { person: { names: [ { uuid: openMRSPatient.person.names[0].uuid, givenName: patient.givenName, middleName: patient.middleName, familyName: patient.familyName, display: patient.givenName + (patient.familyName ? " " + patient.familyName : ""), "preferred": true } ], addresses: [_.pick(patient.address, Bahmni.Registration.Constants.allAddressFileds)], birthdate: this.getBirthdate(patient.birthdate, patient.age), birthdateEstimated: patient.birthdateEstimated, birthtime: Bahmni.Common.Util.DateUtil.parseLongDateToServerFormat(patient.birthtime), gender: patient.gender, attributes: this.getMrsAttributes(openMRSPatient, patient, patientAttributeTypes), dead: patient.dead, deathDate: Bahmni.Common.Util.DateUtil.getDateWithoutTime(patient.deathDate), causeOfDeath: patient.causeOfDeath ? patient.causeOfDeath.uuid : '' } } }; var allIdentifiers = _.concat(patient.extraIdentifiers, patient.primaryIdentifier); var nonEmptyIdentifiers = _.filter(allIdentifiers, function (identifier) { return identifier.uuid || identifier.identifier; }); openMRSPatientProfile.patient.identifiers = _.map(nonEmptyIdentifiers, function (identifier) { return { uuid: identifier.uuid, identifier: identifier.identifier, identifierType: identifier.identifierType.uuid, preferred: identifier.preferred, voided: identifier.voided }; }); this.setImage(patient, openMRSPatientProfile); if (patient.relationships) { openMRSPatientProfile.relationships = patient.relationships; } return openMRSPatientProfile; }; UpdatePatientRequestMapper.prototype.setImage = function (patient, openMRSPatient) { if (patient.getImageData()) { openMRSPatient.image = patient.getImageData(); } }; UpdatePatientRequestMapper.prototype.getMrsAttributes = function (openMRSPatient, patient, patientAttributeTypes) { var attributes = []; patientAttributeTypes.forEach(function (attributeType) { var attr = { attributeType: { uuid: attributeType.uuid } }; var savedAttribute = openMRSPatient.person.attributes.filter(function (attribute) { return attributeType.uuid === attribute.attributeType.uuid; })[0]; if (savedAttribute) { attr.uuid = savedAttribute.uuid; setAttributeValue(attributeType, attr, patient[savedAttribute.attributeType.display]); } else { setAttributeValue(attributeType, attr, patient[attributeType.name]); } attributes.push(attr); }); return attributes; }; var setAttributeValue = function (attributeType, attr, value) { if (value === "" || value === null || value === undefined || value.conceptUuid === null) { attr.voided = true; } else if (attributeType.format === "org.openmrs.Concept") { attr.hydratedObject = value.conceptUuid; } else if (attributeType.format === "org.openmrs.util.AttributableDate") { var mnt = moment(value); attr.value = mnt.format('YYYY-MM-DDTHH:mm:ss.SSSZZ'); } else { attr.value = value.toString(); } }; UpdatePatientRequestMapper.prototype.getBirthdate = function (birthdate, age) { var mnt; if (birthdate) { mnt = moment(birthdate); } else if (age !== undefined) { mnt = moment(this.currentDate).subtract('days', age.days).subtract('months', age.months).subtract('years', age.years); } return mnt.format('YYYY-MM-DDTHH:mm:ss.SSSZZ'); }; return UpdatePatientRequestMapper; })(); 'use strict'; angular.module('bahmni.registration') .factory('patient', ['age', 'identifiers', function (age, identifiers) { var create = function () { var calculateAge = function () { if (this.birthdate) { this.age = age.fromBirthDate(this.birthdate); } else { this.age = age.create(null, null, null); } }; var calculateBirthDate = function () { this.birthdate = age.calculateBirthDate(this.age); }; var fullNameLocal = function () { var givenNameLocal = this.givenNameLocal || this.givenName || ""; var middleNameLocal = this.middleNameLocal || this.middleName || ""; var familyNameLocal = this.familyNameLocal || this.familyName || ""; return (givenNameLocal.trim() + " " + (middleNameLocal ? middleNameLocal + " " : "") + familyNameLocal.trim()).trim(); }; var getImageData = function () { return this.image && this.image.indexOf('data') === 0 ? this.image.replace("data:image/jpeg;base64,", "") : null; }; var identifierDetails = identifiers.create(); var patient = { address: {}, age: age.create(), birthdate: null, calculateAge: calculateAge, image: '../images/blank-user.gif', fullNameLocal: fullNameLocal, getImageData: getImageData, relationships: [], newlyAddedRelationships: [{}], deletedRelationships: [], calculateBirthDate: calculateBirthDate }; return _.assign(patient, identifierDetails); }; return { create: create }; }]); 'use strict'; Bahmni.Registration.Identifier = function (identifierType) { this.identifierType = identifierType; this.preferred = identifierType.primary; this.voided = false; return this; }; var prototype = Bahmni.Registration.Identifier.prototype; prototype.hasIdentifierSources = function () { return this.identifierType.identifierSources.length > 0; }; prototype.isPrimary = function () { return this.identifierType.primary; }; prototype.map = function (identifiers) { var savedIdentifier = _.find(identifiers, {identifierType: {uuid: this.identifierType.uuid}}); if (savedIdentifier) { this.registrationNumber = savedIdentifier.identifier; this.identifier = savedIdentifier.identifier; this.preferred = savedIdentifier.preferred; this.voided = savedIdentifier.voided; this.uuid = savedIdentifier.uuid; } return this; }; prototype.hasIdentifierSourceWithEmptyPrefix = function () { var identifierSources = this.identifierType.identifierSources; return identifierSources.length === 1 && _.isEmpty(identifierSources[0].prefix); }; prototype.isIdentifierRequired = function () { if (this.hasOldIdentifier) { return true; } else if (this.identifierType.required) { return !this.hasIdentifierSources(); } return false; }; prototype.generate = function () { if (this.registrationNumber && this.registrationNumber.length > 0) { this.identifier = this.selectedIdentifierSource ? this.selectedIdentifierSource.prefix + this.registrationNumber : this.registrationNumber; this.voided = false; } else if (this.uuid) { this.voided = true; } }; prototype.clearRegistrationNumber = function () { this.registrationNumber = null; this.identifier = null; }; 'use strict'; angular.module('bahmni.registration') .factory('identifiers', ['$rootScope', 'preferences', function ($rootScope, preferences) { var create = function () { var identifiers = []; _.each($rootScope.patientConfiguration.identifierTypes, function (identifierType) { var identifier = new Bahmni.Registration.Identifier(identifierType); if (identifier.isPrimary()) { identifier.selectedIdentifierSource = _.find(identifier.identifierType.identifierSources, {prefix: preferences.identifierPrefix}); identifier.hasOldIdentifier = preferences.hasOldIdentifier; } identifier.selectedIdentifierSource = identifier.selectedIdentifierSource || identifier.identifierType.identifierSources[0]; identifiers.push(identifier); }); return { primaryIdentifier: getPrimaryIdentifier(identifiers), extraIdentifiers: getExtraIdentifiers(identifiers) }; }; var mapIdentifiers = function (identifiers) { var mappedIdentifiers = []; _.each($rootScope.patientConfiguration.identifierTypes, function (identifierType) { var mappedIdentifier = new Bahmni.Registration.Identifier(identifierType).map(identifiers); mappedIdentifiers.push(mappedIdentifier); }); return { primaryIdentifier: getPrimaryIdentifier(mappedIdentifiers), extraIdentifiers: getExtraIdentifiers(mappedIdentifiers) }; }; var getPrimaryIdentifier = function (identifiers) { return _.find(identifiers, {identifierType: {primary: true}}); }; var getExtraIdentifiers = function (identifiers) { return _.filter(identifiers, {identifierType: {primary: false}}); }; return { create: create, mapIdentifiers: mapIdentifiers }; }]); 'use strict'; angular.module('bahmni.registration') .factory('preferences', [function () { return { hasOldIdentifier: false }; }]); 'use strict'; Bahmni.Registration.RegistrationEncounterConfig = (function () { function RegistrationEncounterConfig (conceptData, encounterTypes, visitTypes) { this.conceptData = conceptData; this.encounterTypes = encounterTypes; this.visitTypes = visitTypes; } RegistrationEncounterConfig.prototype = { getVisitTypesAsArray: function () { var visitTypesArray = []; for (var name in this.visitTypes) { visitTypesArray.push({name: name, uuid: this.visitTypes[name]}); } return visitTypesArray; }, getDefaultVisitType: function (locationUuid) { var visitType = null; _.each(this.loginLocationToVisitTypeMap.results, function (result) { if (result.entity.uuid === locationUuid) { visitType = result.mappings[0].name; } }); return visitType; } }; return RegistrationEncounterConfig; })(); 'use strict'; Bahmni.Registration.PatientConfig = (function () { function PatientConfig (patientAttributeTypes, identifierTypes, patientInformation) { this.attributeTypes = patientAttributeTypes; this.identifierTypes = identifierTypes; var patientAttributesSections = {}; // Avoiding multiple calls from angular code. Side effect of the way angular does dirty check. [Shruti/ Sush] if (!this.attributeRows && this.attributeTypes) { if (!patientInformation) { this.attributeRows = this.splitAsRows(this.attributeTypes); return; } var hiddenAttributes = patientInformation["hidden"] && patientInformation["hidden"].attributes; delete patientInformation["hidden"]; var otherInformationAttributes = this.attributeTypes.filter(function (item) { return !isHiddenPatientAttribute(hiddenAttributes, item) && !isItemAMandatoryField(item) && !isAttributeInOtherSection(patientInformation, patientAttributesSections, item); }); this.attributeRows = this.splitAsRows(otherInformationAttributes); this.patientAttributesSections = patientAttributesSections; } } function isHiddenPatientAttribute (hiddenAttributes, item) { // Ignore hidden fields from patientInformation configuration return hiddenAttributes && hiddenAttributes.indexOf(item.name) > -1; } function isAttributeInOtherSection (patientInformation, patientAttributesSections, item) { return _.find(patientInformation, function (section, key) { return _.find(section.attributes, function (attribute) { if (attribute === item.name) { var sectionObject = patientAttributesSections[key]; if (!sectionObject) { sectionObject = { attributes: [], title: section.title, expanded: section.expanded, translationKey: section.translationKey, shortcutKey: section.shortcutKey, order: section.order, canShow: true }; } sectionObject.attributes.push(item); patientAttributesSections[key] = sectionObject; return true; } return false; }); }); } function isItemAMandatoryField (item) { var mandatoryPatientAttributes = ["healthCenter", "givenNameLocal", "middleNameLocal", "familyNameLocal"]; return mandatoryPatientAttributes.indexOf(item.name) > -1; } PatientConfig.prototype = { get: function (attributeUuid) { return this.attributeTypes.filter(function (item) { return item.uuid === attributeUuid; })[0]; }, customAttributeRows: function () { return this.attributeRows; }, getPatientAttributesSections: function () { return this.patientAttributesSections; }, getOrderedPatientAttributesSections: function () { return _.sortBy(this.patientAttributesSections, 'order'); }, splitAsRows: function (attributes) { var attributeRows = []; var row = []; for (var i in attributes) { row.push(attributes[i]); if (i !== 0 && (i % 2) !== 0) { attributeRows.push(row); row = []; } } if (row.length > 0) { attributeRows.push(row); } return attributeRows; }, heathCentreAttribute: function () { return this.attributeTypes.filter(function (item) { return item.name === "healthCenter"; })[0]; }, local: function () { var givenName = this.attributeTypes.filter(function (item) { return item.name === "givenNameLocal"; })[0]; var middleName = this.attributeTypes.filter(function (item) { return item.name === "middleNameLocal"; })[0]; var familyName = this.attributeTypes.filter(function (item) { return item.name === "familyNameLocal"; })[0]; if (givenName && middleName && familyName) { return { "showNameField": true, "labelForNameField": givenName.description, "placeholderForGivenName": givenName.description, "placeholderForMiddleName": middleName.description, "placeholderForFamilyName": familyName.description}; } return {"showNameField": false}; } }; return PatientConfig; })(); var Bahmni = Bahmni || {}; Bahmni.Common = Bahmni.Common || {}; Bahmni.Common.PatientSearch = Bahmni.Common.PatientSearch || {}; Bahmni.Common.PatientSearch.Constants = { searchExtensionTileViewType: "tile", searchExtensionTabularViewType: "tabular", tabularViewIgnoreHeadingsList: ["display", "uuid", "image", "$$hashKey", "activeVisitUuid", "hasBeenAdmitted", "forwardUrl", "programUuid", "enrollment"], identifierHeading: ["ID", "Id", "id", "identifier", "DQ_COLUMN_TITLE_ACTION"], nameHeading: ["NAME", "Name", "name"], patientTileHeight: 100, patientTileWidth: 100, printIgnoreHeadingsList: ["DQ_COLUMN_TITLE_ACTION"], tileLoadRatio: 1 / 2 }; 'use strict'; Bahmni.Common.PatientSearch.Search = function (searchTypes) { var self = this; self.searchTypes = searchTypes || []; self.searchType = this.searchTypes[0]; self.searchParameter = ''; self.noResultsMessage = null; self.searchResults = []; self.activePatients = []; self.navigated = false; self.links = self.searchType && self.searchType.links ? self.searchType.links : []; self.searchColumns = self.searchType && self.searchType.searchColumns ? self.searchType.searchColumns : ["identifier", "name"]; angular.forEach(searchTypes, function (searchType) { searchType.patientCount = "..."; }); self.switchSearchType = function (searchType) { self.noResultsMessage = null; if (!self.isSelectedSearch(searchType)) { self.searchParameter = ''; self.navigated = true; self.searchType = searchType; self.activePatients = []; self.searchResults = []; self.links = self.searchType && self.searchType.links ? self.searchType.links : []; self.searchColumns = self.searchType && self.searchType.searchColumns ? self.searchType.searchColumns : ["identifier", "name"]; } self.markPatientEntry(); }; self.markPatientEntry = function () { self.startPatientSearch = true; window.setTimeout(function () { // eslint-disable-line angular/timeout-service self.startPatientSearch = false; }); }; self.patientsCount = function () { return self.activePatients.length; }; self.updatePatientList = function (patientList) { self.activePatients = patientList.map(mapPatient); self.searchResults = self.activePatients; }; self.updateSearchResults = function (patientList) { self.updatePatientList(patientList); if (self.activePatients.length === 0 && self.searchParameter != '') { self.noResultsMessage = "NO_RESULTS_FOUND"; } else { self.noResultsMessage = null; } }; self.hasSingleActivePatient = function () { return self.activePatients.length === 1; }; self.filterPatients = function (matchingCriteria) { matchingCriteria = matchingCriteria ? matchingCriteria : matchesNameOrId; self.searchResults = self.searchParameter ? self.activePatients.filter(matchingCriteria) : self.activePatients; }; self.filterPatientsByIdentifier = function () { self.filterPatients(matchesId); }; self.isSelectedSearch = function (searchType) { return self.searchType && self.searchType.id == searchType.id; }; self.isCurrentSearchLookUp = function () { return self.searchType && self.searchType.handler; }; self.isTileView = function () { return self.searchType && self.searchType.view === Bahmni.Common.PatientSearch.Constants.searchExtensionTileViewType; }; self.isTabularView = function () { return self.searchType && self.searchType.view === Bahmni.Common.PatientSearch.Constants.searchExtensionTabularViewType; }; self.showPatientCountOnSearchParameter = function (searchType) { return showPatientCount(searchType) && self.searchParameter; }; function mapPatient (patient) { if (patient.name || patient.givenName || patient.familyName) { patient.name = patient.name || (patient.givenName + (patient.familyName ? ' ' + patient.familyName : "")); } patient.display = _.map(self.searchColumns, function (column) { return patient[column]; }).join(" - "); patient.image = Bahmni.Common.Constants.patientImageUrlByPatientUuid + patient.uuid; return patient; } var matchesNameOrId = function (patient) { return patient.display.toLowerCase().indexOf(self.searchParameter.toLowerCase()) !== -1; }; var matchesId = function (patient) { return patient.identifier.toLowerCase().indexOf(self.searchParameter.toLowerCase()) !== -1; }; var showPatientCount = function (searchType) { return self.isSelectedSearch(searchType) && self.isCurrentSearchLookUp(); }; }; angular.module('bahmni.common.patientSearch', ['bahmni.common.patient', 'infinite-scroll']); 'use strict'; angular.module('bahmni.common.patientSearch') .controller('PatientsListController', ['$scope', '$http', '$window', 'patientService', '$rootScope', 'appService', 'spinner', '$stateParams', '$bahmniCookieStore', 'printer', 'configurationService', function ($scope, $http, $window, patientService, $rootScope, appService, spinner, $stateParams, $bahmniCookieStore, printer, configurationService) { const DEFAULT_FETCH_DELAY = 2000; var patientSearchConfig = appService.getAppDescriptor().getConfigValue("patientSearch"); var patientListSpinner; var initialize = function () { var searchTypes = appService.getAppDescriptor().getExtensions("org.bahmni.patient.search", "config").map(mapExtensionToSearchType); $scope.search = new Bahmni.Common.PatientSearch.Search(_.without(searchTypes, undefined)); $scope.search.markPatientEntry(); $scope.$watch('search.searchType', function (currentSearchType) { _.isEmpty(currentSearchType) || fetchPatients(currentSearchType); }); $scope.$watch('search.activePatients', function (activePatientsList) { if (activePatientsList.length > 0 && patientListSpinner) { hideSpinner(spinner, patientListSpinner, $(".tab-content")); } }); if (patientSearchConfig && patientSearchConfig.serializeSearch) { getPatientCountSeriallyBySearchIndex(0); } else { _.each($scope.search.searchTypes, function (searchType) { _.isEmpty(searchType) || ($scope.search.searchType != searchType && getPatientCount(searchType, null)); }); } if ($rootScope.currentSearchType != null) { $scope.search.switchSearchType($rootScope.currentSearchType); } configurationService.getConfigurations(['identifierTypesConfig']).then(function (response) { $scope.primaryIdentifier = _.find(response.identifierTypesConfig, { primary: true }).name; }); }; $scope.searchPatients = function () { return spinner.forPromise(patientService.search($scope.search.searchParameter)).then(function (response) { $scope.search.updateSearchResults(response.data.pageOfResults); if ($scope.search.hasSingleActivePatient()) { $scope.forwardPatient($scope.search.activePatients[0]); } }); }; $scope.filterPatientsAndSubmit = function () { if ($scope.search.searchResults.length == 1) { $scope.forwardPatient($scope.search.searchResults[0]); } }; var getPatientCount = function (searchType, patientListSpinner) { if (searchType.handler) { var params = { q: searchType.handler, v: "full", location_uuid: $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName).uuid, provider_uuid: $rootScope.currentProvider.uuid }; if (searchType.additionalParams) { params["additionalParams"] = searchType.additionalParams; } patientService.findPatients(params).then(function (response) { searchType.patientCount = response.data.length; if ($scope.search.isSelectedSearch(searchType)) { $scope.search.updatePatientList(response.data); } if (patientListSpinner) { hideSpinner(spinner, patientListSpinner, $(".tab-content")); } }); } }; var hideSpinner = function (spinnerObj, data, container) { spinnerObj.hide(data, container); $(container).children('patient-list-spinner').hide(); }; $scope.getHeadings = function (patients) { if (patients && patients.length > 0) { var headings = _.chain(patients[0]) .keys() .filter(function (heading) { return _.indexOf(Bahmni.Common.PatientSearch.Constants.tabularViewIgnoreHeadingsList, heading) === -1; }) .value(); return headings; } return []; }; $scope.isHeadingOfLinkColumn = function (heading) { var identifierHeading = _.includes(Bahmni.Common.PatientSearch.Constants.identifierHeading, heading); if (identifierHeading) { return identifierHeading; } else if ($scope.search.searchType && $scope.search.searchType.links) { return _.find($scope.search.searchType.links, { linkColumn: heading }); } else if ($scope.search.searchType && $scope.search.searchType.linkColumn) { return _.includes([$scope.search.searchType.linkColumn], heading); } }; $scope.isHeadingOfName = function (heading) { return _.includes(Bahmni.Common.PatientSearch.Constants.nameHeading, heading); }; $scope.getPrintableHeadings = function (patients) { var headings = $scope.getHeadings(patients); var printableHeadings = headings.filter(function (heading) { return _.indexOf(Bahmni.Common.PatientSearch.Constants.printIgnoreHeadingsList, heading) === -1; }); return printableHeadings; }; $scope.printPage = function () { if ($scope.search.searchType.printHtmlLocation != null) { printer.printFromScope($scope.search.searchType.printHtmlLocation, $scope); } }; var mapExtensionToSearchType = function (appExtn) { return { name: appExtn.label, display: appExtn.extensionParams.display, handler: appExtn.extensionParams.searchHandler, forwardUrl: appExtn.extensionParams.forwardUrl, id: appExtn.id, params: appExtn.extensionParams.searchParams, refreshTime: appExtn.extensionParams.refreshTime || 0, view: appExtn.extensionParams.view || Bahmni.Common.PatientSearch.Constants.searchExtensionTileViewType, showPrint: appExtn.extensionParams.showPrint || false, printHtmlLocation: appExtn.extensionParams.printHtmlLocation || null, additionalParams: appExtn.extensionParams.additionalParams, searchColumns: appExtn.extensionParams.searchColumns, translationKey: appExtn.extensionParams.translationKey, linkColumn: appExtn.extensionParams.linkColumn, links: appExtn.extensionParams.links }; }; var debounceGetPatientCount = _.debounce(function (currentSearchType, patientListSpinner) { getPatientCount(currentSearchType, patientListSpinner); }, (patientSearchConfig && patientSearchConfig.fetchDelay) || DEFAULT_FETCH_DELAY, {}); var showSpinner = function (spinnerObj, container) { $(container).children('patient-list-spinner').show(); return spinnerObj.show(container); }; var fetchPatients = function (currentSearchType) { if (patientListSpinner !== undefined) { hideSpinner(spinner, patientListSpinner, $(".tab-content")); } $rootScope.currentSearchType = currentSearchType; if ($scope.search.isCurrentSearchLookUp()) { patientListSpinner = showSpinner(spinner, $(".tab-content")); if (patientSearchConfig && patientSearchConfig.debounceSearch) { debounceGetPatientCount(currentSearchType, patientListSpinner); } else { getPatientCount(currentSearchType, patientListSpinner); } } }; $scope.forwardPatient = function (patient, heading) { var options = $.extend({}, $stateParams); $rootScope.patientAdmitLocationStatus = patient.Status; $.extend(options, { patientUuid: patient.uuid, visitUuid: patient.activeVisitUuid || null, encounterUuid: $stateParams.encounterUuid || 'active', programUuid: patient.programUuid || null, enrollment: patient.enrollment || null, forwardUrl: patient.forwardUrl || null, dateEnrolled: patient.dateEnrolled || null }); var link = options.forwardUrl ? { url: options.forwardUrl, newTab: true } : { url: $scope.search.searchType.forwardUrl, newTab: false }; if ($scope.search.searchType.links) { link = _.find($scope.search.searchType.links, { linkColumn: heading }) || link; } if (link.url === "#/default/patient/{{patientUuid}}/dashboard?encounterUuid=active") { $http({ method: "GET", url: "/openmrs/ws/rest/v1/visit?includeInactive=true&patient=" + patient.uuid + "&v=custom:(uuid,visitType,startDatetime,stopDatetime,location,encounters:(uuid))" }).then(function mySuccess (response) { var result = response.data.results; if (result.length > 1) { $window.open(appService.getAppDescriptor().formatUrl(link.url, options, true), link.newTab ? "_blank" : "_self"); } else { // $window.location.href = ("https://${$window.location.hostname}:6061/prescription/${patient.uuid}"); $window.location.href = "https://" + $window.location.hostname + ":6060/patientDashboard/" + patient.uuid; } }); } else { $window.open(appService.getAppDescriptor().formatUrl(link.url, options, true), link.newTab ? "_blank" : "_self"); } // if (link.url === "#/default/patient/{{patientUuid}}/dashboard?encounterUuid=active") { // link.url = "#/default/patient/{{patientUuid}}/dashboard/concept-set-group/observations?encounterUuid=active"; // } // $window.open(appService.getAppDescriptor().formatUrl(link.url, options, true), link.newTab ? "_blank" : "_self"); }; var getPatientCountSeriallyBySearchIndex = function (index) { if (index === $scope.search.searchTypes.length) { return; } var searchType = $scope.search.searchTypes[index]; if (searchType.handler) { var params = { q: searchType.handler, v: "full", location_uuid: $bahmniCookieStore.get(Bahmni.Common.Constants.locationCookieName).uuid, provider_uuid: $rootScope.currentProvider.uuid }; if (searchType.additionalParams) { params["additionalParams"] = searchType.additionalParams; } patientService.findPatients(params).then(function (response) { searchType.patientCount = response.data.length; if ($scope.search.isSelectedSearch(searchType)) { $scope.search.updatePatientList(response.data); } return getPatientCountSeriallyBySearchIndex(index + 1); }); } }; initialize(); } ]);