From 48d80d2e3665b6bd3d8a3a9c58eeda824534f402 Mon Sep 17 00:00:00 2001 From: Binal Date: Mon, 6 Jul 2020 12:56:08 -0700 Subject: [PATCH 01/39] Merge from wnprc18.3 svn r.64261-64312 --- .../api/EHR_ComplianceService.java | 22 + EHR_ComplianceDB/resources/module.xml | 7 + .../SOPDateLastRead.query.xml | 20 - .../ehr_compliancedb/SOPDateLastRead.sql | 26 - .../SOPDateLastRead/.qview.xml | 2 +- .../SOPrequirements.query.xml | 20 - .../ehr_compliancedb/SOPrequirements.sql | 53 - .../SOPrequirements/To Read.qview.xml | 2 +- .../employees/Active Employees.qview.xml | 30 + .../recentlyActivatedSOPs.sql | 42 - .../resources/views/SOPadmin.html | 5 +- .../EHR_ComplianceDBModule.java | 3 + .../EHR_ComplianceServiceImpl.java | 34 + Viral_Load_Assay/resources/module.xml | 6 +- .../Viral_Load_Assay-12.25-12.26.sql | 18 + .../Viral_Load_Assay-12.25-12.26.sql | 18 + .../resources/schemas/viral_load_assay.xml | 28 + .../web/Viral_Load_Assay/SampleData/lc96.txt | 31 + .../web/Viral_Load_Assay/vl_utils.js | 89 + .../Viral_Load_AssayModule.java | 2 +- .../assay/AbstractWNPRCImportMethod.java | 172 ++ .../assay/LC96ImportMethod.java | 431 ++++ .../assay/ViralLoadAssayDataProvider.java | 12 + ehr/resources/credits/scripts.txt | 9 - ehr/resources/data/lookup_sets.tsv | 6 +- ehr/resources/queries/ehr/protocol_title.sql | 2 + ehr/resources/queries/ehr/tasks.query.xml | 6 + .../queries/study/colonyPopulationChange.sql | 10 +- .../dbscripts/postgresql/ehr-17.20-17.21.sql | 43 + .../dbscripts/sqlserver/ehr-17.20-17.21.sql | 22 + ehr/resources/scripts/ehr/ScriptHelper.js | 7 +- ehr/resources/scripts/ehr/triggers.js | 11 +- ehr/resources/scripts/ehr/validation.js | 2 +- ehr/resources/views/animalHistory.html | 32 +- ehr/resources/views/manageRequest.html | 24 + ehr/resources/views/manageTask.html | 30 + ehr/resources/views/participantView.html | 43 +- ehr/resources/views/populateInitialData.html | 4 +- ehr/resources/web/ehr/DataEntryUtils.js | 32 +- .../web/ehr/HousingAndAssignmentHistory.css | 34 - .../HousingAndAssignmentHistoryTemplate.html | 61 - ehr/resources/web/ehr/d3-graph-template.html | 24 - .../web/ehr/data/DataEntryServerStore.js | 4 +- .../web/ehr/data/RequestStoreCollection.js | 38 + ehr/resources/web/ehr/data/StoreCollection.js | 3 +- ehr/resources/web/ehr/ehr_api.lib.xml | 6 + ehr/resources/web/ehr/ext3/ExtContainers.js | 25 +- .../web/ehr/ext3/ehrGridFormPanel.js | 351 +++ ehr/resources/web/ehr/ext3/navMenu.js | 7 +- .../web/ehr/form/field/ProjectEntryField.js | 11 +- ehr/resources/web/ehr/grid/Panel.js | 16 +- ehr/resources/web/ehr/lib/classify.js | 98 - ehr/resources/web/ehr/lib/knockout-mapping.js | 809 ------- ehr/resources/web/ehr/lib/knockout.js | 115 - ehr/resources/web/ehr/lib/require-text.js | 391 --- ehr/resources/web/ehr/lib/require.js | 2103 ----------------- ehr/resources/web/ehr/lib/supersqlstore.js | 117 - ehr/resources/web/ehr/lib/text.js | 391 --- .../web/ehr/lib/underscore-string.js | 3 - ehr/resources/web/ehr/lib/underscore.js | 6 - ehr/resources/web/ehr/metadata/Default.js | 14 +- ehr/resources/web/ehr/metadata/Metadata.js | 22 +- .../web/ehr/panel/AnimalHistoryPanel.js | 45 +- ehr/resources/web/ehr/panel/SnapshotPanel.js | 10 +- ehr/resources/web/ehr/plugin/RowEditor.js | 3 +- ehr/resources/web/ehr/reports.js | 49 - .../web/ehr/requirements-participantView.js | 33 - ehr/src/org/labkey/ehr/EHRManager.java | 3 +- ehr/src/org/labkey/ehr/EHRModule.java | 5 + .../BasicDemographicsProvider.java | 3 +- .../labkey/ehr/security/EHRDataAdminRole.java | 6 +- .../ehr/security/EHRFullUpdaterRole.java | 6 +- .../labkey/ehr/security/EHRRequestorRole.java | 1 + .../ehr/security/EHRSecurityManager.java | 5 + .../labkey/ehr/table/AgeDisplayColumn.java | 2 +- .../ehr/table/AgeMonthsDisplayColumn.java | 2 +- .../ehr/table/AgeYearMonthsDisplayColumn.java | 2 +- .../AgeYearsMonthsDaysDisplayColumn.java | 2 +- .../labkey/ehr/utils/TriggerScriptHelper.java | 5 +- 79 files changed, 1638 insertions(+), 4549 deletions(-) create mode 100644 EHR_ComplianceDB/api-src/org/labkey/ehr_compliancedb/api/EHR_ComplianceService.java delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.query.xml delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.sql delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.query.xml delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.sql delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/recentlyActivatedSOPs.sql create mode 100644 EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceServiceImpl.java create mode 100644 Viral_Load_Assay/resources/schemas/dbscripts/postgresql/Viral_Load_Assay-12.25-12.26.sql create mode 100644 Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.25-12.26.sql create mode 100644 Viral_Load_Assay/resources/web/Viral_Load_Assay/SampleData/lc96.txt create mode 100644 Viral_Load_Assay/resources/web/Viral_Load_Assay/vl_utils.js create mode 100644 Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/AbstractWNPRCImportMethod.java create mode 100644 Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LC96ImportMethod.java delete mode 100644 ehr/resources/credits/scripts.txt create mode 100644 ehr/resources/queries/ehr/protocol_title.sql create mode 100644 ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql create mode 100644 ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql delete mode 100644 ehr/resources/web/ehr/HousingAndAssignmentHistory.css delete mode 100644 ehr/resources/web/ehr/HousingAndAssignmentHistoryTemplate.html delete mode 100644 ehr/resources/web/ehr/d3-graph-template.html delete mode 100644 ehr/resources/web/ehr/lib/classify.js delete mode 100644 ehr/resources/web/ehr/lib/knockout-mapping.js delete mode 100644 ehr/resources/web/ehr/lib/knockout.js delete mode 100644 ehr/resources/web/ehr/lib/require-text.js delete mode 100644 ehr/resources/web/ehr/lib/require.js delete mode 100644 ehr/resources/web/ehr/lib/supersqlstore.js delete mode 100644 ehr/resources/web/ehr/lib/text.js delete mode 100644 ehr/resources/web/ehr/lib/underscore-string.js delete mode 100644 ehr/resources/web/ehr/lib/underscore.js delete mode 100644 ehr/resources/web/ehr/requirements-participantView.js diff --git a/EHR_ComplianceDB/api-src/org/labkey/ehr_compliancedb/api/EHR_ComplianceService.java b/EHR_ComplianceDB/api-src/org/labkey/ehr_compliancedb/api/EHR_ComplianceService.java new file mode 100644 index 000000000..163762e73 --- /dev/null +++ b/EHR_ComplianceDB/api-src/org/labkey/ehr_compliancedb/api/EHR_ComplianceService.java @@ -0,0 +1,22 @@ +package org.labkey.ehr_compliancedb.api; + +import org.labkey.api.data.Container; + +/** + * Created by jon on 3/22/16. + */ +public abstract class EHR_ComplianceService { + static private EHR_ComplianceService _service = null; + + static public EHR_ComplianceService get() { + return _service; + } + + public static void setInstance(EHR_ComplianceService instance) { + _service = instance; + } + + public abstract String getComplianceModuleName(); + + public abstract Container getEmployeeContainer(Container c); +} diff --git a/EHR_ComplianceDB/resources/module.xml b/EHR_ComplianceDB/resources/module.xml index 8d95f5b68..ec54c55ca 100644 --- a/EHR_ComplianceDB/resources/module.xml +++ b/EHR_ComplianceDB/resources/module.xml @@ -14,6 +14,13 @@ This is the default view to show on the employees table + + true + + ADMIN + + This is the containerPath to the folder holding the list of PDFs shared between public and private folder. The PDF list has a Linked schema between both folders, the actual files have to reside in the public folder Use of slashes is very important - it should be in the format '/myProject/compliance' + diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.query.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.query.xml deleted file mode 100644 index e253428a4..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.query.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - true - - lists - sops - id - - - - SOP_ID -
-
-
-
diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.sql b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.sql deleted file mode 100644 index 9961edf49..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead.sql +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2012-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -SELECT - -e.employeeId, -sop.id as SOP_ID, -sop.name, -sop.pdf, -sop.Spanish_PDF, -sop.video, -T1.LastRead, -sop.activeDate - - -FROM ehr_compliancedb.employees e - - -JOIN -( SELECT max(t.date) as LastRead, t.SOPID, t.EmployeeId from ehr_compliancedb.SOPdates t group by t.employeeid, t.sopid) T1 - ON (T1.employeeId = e.employeeId ) - -LEFT JOIN lists.SOPs sop - ON (T1.SOPID = sop.id) \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead/.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead/.qview.xml index cc4f75c8a..493cbd4c2 100644 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead/.qview.xml +++ b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPDateLastRead/.qview.xml @@ -6,7 +6,7 @@ - + diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.query.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.query.xml deleted file mode 100644 index 643c6a89a..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.query.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - true - - lists - sops - id - - - - SOP_ID -
-
-
-
diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.sql b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.sql deleted file mode 100644 index 947aba466..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements.sql +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -SELECT - e.employeeid, - sop.id as SOP_ID, - sop.name, - sop.pdf, - sop.Spanish_PDF, - e.email, - T1.LastRead, - - --we calculate the time until renewal - --this subquery was written before I changed this to use joins - --it is no longer needed, but i kept it b/c is uses age_in_months and is working - CONVERT( - CASE - WHEN (T1.LastRead IS NULL) THEN - 0 - ELSE - COALESCE( - --(12 - age_in_months(T1.MostRecentDate, curdate())) , 0) - - (SELECT (12 - age_in_months(sq1.MostRecentDate, curdate())) AS TimeUntilRenewal - FROM - (SELECT max(t.date) AS MostRecentDate, t.SOPID, t.EmployeeId FROM ehr_compliancedb.SOPdates t GROUP BY t.EmployeeId, t.SOPID) sq1 - WHERE sq1.SOPID = sc.SOP_ID AND e.employeeid = sq1.EmployeeId), 0) - END, double) - AS MonthsUntilRenewal, - - CASE - WHEN sc.sop_id IS NULL then FALSE - ELSE TRUE - END as required - -FROM ehr_compliancedb.Employees e - -CROSS JOIN lists.SOPs sop - --ON (e.category = sc.category) - -LEFT JOIN ehr_compliancedb.SOPbyCategory sc - ON (e.category = sc.category AND sop.id = sc.sop_id) - -LEFT JOIN - (SELECT max(t.date) AS LastRead, t.SOPID, t.EmployeeId FROM ehr_compliancedb.SOPdates t GROUP BY t.EmployeeId, t.SOPID) T1 - ON (T1.SOPID = sc.SOP_ID AND T1.EmployeeId = e.employeeid) - -WHERE - ---active employees only -e.EndDateCoalesced >= curdate() \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml index 71ba14e17..3698b0b67 100644 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml +++ b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml @@ -6,7 +6,7 @@
- + diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/employees/Active Employees.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/employees/Active Employees.qview.xml index a6c0a4b9a..5a75ffe12 100644 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/employees/Active Employees.qview.xml +++ b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/employees/Active Employees.qview.xml @@ -1,4 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/recentlyActivatedSOPs.sql b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/recentlyActivatedSOPs.sql deleted file mode 100644 index 418f79d1a..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/recentlyActivatedSOPs.sql +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -SELECT -e.employeeId, -sc.sop_id, -sop.name, -sop.pdf, -sop.Spanish_PDF, -sop.video, -T1.LastRead, - -sop.activeDate, -CONVERT( - CASE - WHEN (T1.LastRead is NULL) Then - 0 - ELSE - COALESCE( (SELECT (12-age_in_months(sq1.MostRecentDate, curdate())) as TimeUntilRenewal - FROM - (SELECT max(t.date) as MostRecentDate, t.sopid, t.employeeid from ehr_compliancedb.sopdates t group by t.employeeid, t.sopid) sq1 - where sq1.sopid = sc.sop_id and e.employeeid = sq1.employeeid), 0) - END, double) AS -MonthsUntilRenewal, - - CASE - WHEN sc.sop_id is null then false - else true - end as -required - -from ehr_compliancedb.employees e - -cross join lists.SOPs sop - -LEFT JOIN ehr_compliancedb.SOPbyCategory sc ON (e.category = sc.category and sop.id = sc.sop_id) - -LEFT JOIN (SELECT max(t.date) as lastRead, t.sopid, t.employeeid from ehr_compliancedb.sopdates t group by t.employeeid, t.sopid) t1 on (e.employeeid = t1.employeeid and sc.sop_id = t1.sopid) - -where e.employeeid is not null \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/views/SOPadmin.html b/EHR_ComplianceDB/resources/views/SOPadmin.html index aee194544..2ec8d7f6b 100644 --- a/EHR_ComplianceDB/resources/views/SOPadmin.html +++ b/EHR_ComplianceDB/resources/views/SOPadmin.html @@ -3,6 +3,7 @@ Ext4.onReady(function(){ var webpart = <%=webpartContext%>; var container = LABKEY.getModuleProperty('ehr_compliancedb', 'EmployeeContainer'); + var pdfs= LABKEY.getModuleProperty('ehr_compliancedb', 'PDFContainer') if (!container){ Ext4.get(webpart.wrapperDivId).update('Error: the containerPath to the folder holding compliance data has not been set. Please contact your administrator.') return; @@ -13,8 +14,8 @@ sections: [ {header: 'SOPs', items: [ - {name: 'SOP Issue Tracker', url: '<%=contextPath%>/issues/WNPRC/WNPRC_Units/Animal_Services/Compliance_Training/Public/SOPs/list.view?Issues.Status~eq=open'}, - {name: 'View/Edit SOPs', url: '<%=contextPath%>/list' + container + '/grid.view?name=SOPs'}, + {name: 'SOP Issue Tracker', url: '<%=contextPath%>/issues/WNPRC/WNPRC_Units/Animal_Services/Compliance_Training/Private/SOP_DB/list.view?Issues.Status~eq=open'}, + {name: 'View/Edit SOPs', url: '<%=contextPath%>/list/'+pdfs +'/grid.view?name=SOPs'}, {name: 'View/Edit SOPs Required For Each Employee Category', url: '<%=contextPath%>/query' + container + '/executeQuery.view?schemaName=ehr_compliancedb&query.queryName=sopbycategory'}, {name: 'View/Edit Dates Employees Read Their SOPs', url: '<%=contextPath%>/query' + container + '/executeQuery.view?schemaName=ehr_compliancedb&query.queryName=SOPDates'}, {name: 'View The Most Recent Date Employees Read Each SOPs', url: '<%=contextPath%>/query' + container + '/executeQuery.view?schemaName=ehr_compliancedb&query.queryName=SOPrequirements'} diff --git a/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java b/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java index eac6434f0..766116000 100644 --- a/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java +++ b/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java @@ -24,6 +24,7 @@ import org.labkey.api.ldk.notification.NotificationService; import org.labkey.ehr_compliancedb.notification.EmployeeComplianceNotification; import org.labkey.api.module.ModuleContext; +import org.labkey.ehr_compliancedb.api.EHR_ComplianceService; import java.util.Collections; import java.util.Set; @@ -61,6 +62,8 @@ public boolean hasScripts() protected void init() { addController(CONTROLLER_NAME, EHR_ComplianceDBController.class); + + EHR_ComplianceService.setInstance(new EHR_ComplianceServiceImpl()); } @Override diff --git a/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceServiceImpl.java b/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceServiceImpl.java new file mode 100644 index 000000000..3cd204cb9 --- /dev/null +++ b/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceServiceImpl.java @@ -0,0 +1,34 @@ +package org.labkey.ehr_compliancedb; + +import org.labkey.api.data.Container; +import org.labkey.api.data.ContainerManager; +import org.labkey.api.data.PropertyManager; +import org.labkey.api.module.ModuleLoader; +import org.labkey.api.module.ModuleProperty; +import org.labkey.ehr_compliancedb.api.EHR_ComplianceService; + +/** + * Created by jon on 3/22/16. + */ +public class EHR_ComplianceServiceImpl extends EHR_ComplianceService { + static public String EmployeeContainerPropertyName = "EmployeeContainer"; + + @Override + public String getComplianceModuleName() { + return EHR_ComplianceDBModule.SCHEMA_NAME; + } + + @Override + public Container getEmployeeContainer(Container c) { + EHR_ComplianceDBModule ehrCompliance = getModule(); + ModuleProperty prop = ehrCompliance.getModuleProperties().get(EmployeeContainerPropertyName); + + String containerPath = PropertyManager.getCoalescedProperty(PropertyManager.SHARED_USER, c, prop.getCategory(), EmployeeContainerPropertyName); + + return ContainerManager.getForPath(containerPath); + } + + public EHR_ComplianceDBModule getModule() { + return ModuleLoader.getInstance().getModule(EHR_ComplianceDBModule.class); + } +} diff --git a/Viral_Load_Assay/resources/module.xml b/Viral_Load_Assay/resources/module.xml index fa63f23f5..bb4eaf10e 100644 --- a/Viral_Load_Assay/resources/module.xml +++ b/Viral_Load_Assay/resources/module.xml @@ -1,5 +1,5 @@ - - - + + + diff --git a/Viral_Load_Assay/resources/schemas/dbscripts/postgresql/Viral_Load_Assay-12.25-12.26.sql b/Viral_Load_Assay/resources/schemas/dbscripts/postgresql/Viral_Load_Assay-12.25-12.26.sql new file mode 100644 index 000000000..f374dc3df --- /dev/null +++ b/Viral_Load_Assay/resources/schemas/dbscripts/postgresql/Viral_Load_Assay-12.25-12.26.sql @@ -0,0 +1,18 @@ +CREATE TABLE viral_load_assay.nucleic_acid +( + type CHARACTER VARYING(200) NOT NULL, + container entityid NOT NULL, + rowid SERIAL NOT NULL, + + CONSTRAINT pk_nucleic_acid PRIMARY KEY (rowid) +); + +CREATE TABLE viral_load_assay.source_material +( + type CHARACTER VARYING(200) NOT NULL, + liquid BOOLEAN NOT NULL, + container entityid NOT NULL, + rowid SERIAL NOT NULL, + + CONSTRAINT pk_source_material PRIMARY KEY (rowid) +); \ No newline at end of file diff --git a/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.25-12.26.sql b/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.25-12.26.sql new file mode 100644 index 000000000..98f877233 --- /dev/null +++ b/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.25-12.26.sql @@ -0,0 +1,18 @@ +CREATE TABLE viral_load_assay.nucleic_acid +( + type NVARCHAR(200) NOT NULL, + container entityid NOT NULL, + rowid INT IDENTITY(1, 1), + + CONSTRAINT pk_nucleic_acid PRIMARY KEY (rowid) +); + +CREATE TABLE viral_load_assay.source_material +( + type NVARCHAR(200) NOT NULL, + liquid BIT NOT NULL, + container entityid NOT NULL, + rowid INT IDENTITY(1, 1), + + CONSTRAINT pk_source_material PRIMARY KEY (rowid) +); \ No newline at end of file diff --git a/Viral_Load_Assay/resources/schemas/viral_load_assay.xml b/Viral_Load_Assay/resources/schemas/viral_load_assay.xml index 0c4e4b682..d8961bf87 100644 --- a/Viral_Load_Assay/resources/schemas/viral_load_assay.xml +++ b/Viral_Load_Assay/resources/schemas/viral_load_assay.xml @@ -150,4 +150,32 @@ + + org.labkey.ldk.query.DefaultTableCustomizer + DETAILED + Nucleic Acid + + + + + + + + +
+ + org.labkey.ldk.query.DefaultTableCustomizer + DETAILED + Source Material + + + + + + + + + + +
diff --git a/Viral_Load_Assay/resources/web/Viral_Load_Assay/SampleData/lc96.txt b/Viral_Load_Assay/resources/web/Viral_Load_Assay/SampleData/lc96.txt new file mode 100644 index 000000000..285dfd9f0 --- /dev/null +++ b/Viral_Load_Assay/resources/web/Viral_Load_Assay/SampleData/lc96.txt @@ -0,0 +1,31 @@ +Color Position Sample Name Gene Name Cq Concentration Call Excluded Sample Type Standard Cq Mean Cq Error Concentration Mean Concentration Error Replicate Group Dye Edited Call Slope EPF Failure Notes Sample Prep Notes Number +255;132;197;238 A1 STD_500000000 None 14.61 3.81E+08 Positive Unchecked Standard 5.00E+08 14.57 0.06 3.93E+08 1.64E+07 A1 FAM 0.32 3.27 None 1 +255;103;103;103 A2 STD_50000000 None 17.56 5.47E+07 Positive Unchecked Standard 5.00E+07 17.63 0.1 5.23E+07 3.40E+06 A2 FAM 0.31 3.19 None 2 +255;242;138;21 A3 STD_5000000 None 20.83 6.35E+06 Positive Unchecked Standard 5.00E+06 20.84 0.01 6.33E+06 2.95E+04 A3 FAM 0.32 3.22 None 3 +255;250;215;15 A4 STD_500000 None 24.54 5.53E+05 Positive Unchecked Standard 5.00E+05 24.54 0.01 5.55E+05 2.58E+03 A4 FAM 0.31 3.07 None 4 +255;103;154;47 A5 STD_50000 None 28.12 5.24E+04 Positive Unchecked Standard 5.00E+04 28.27 0.21 4.79E+04 6.44E+03 A5 FAM 0.3 2.96 None 5 +255;180;73;149 A6 STD_5000 None 31.71 4.94E+03 Positive Unchecked Standard 5.00E+03 31.56 0.21 5.48E+03 7.62E+02 A6 FAM 0.31 2.89 None 6 +255;95;103;174 A7 STD_500 None 35.02 5.59E+02 Positive Unchecked Standard 5.00E+02 35.47 0.64 4.34E+02 1.77E+02 A7 FAM 0.31 2.74 None 7 +255;205;18;55 A8 STD_50 None - - Negative Unchecked Standard - - - - - A8 FAM 0 0 Standard is negative, Replicate group contains positives and negatives. 8 +255;34;176;146 A9 STD_0 None - - Negative Unchecked Unknown - - - - - A9 FAM 0 -0.01 None 9 +255;132;197;238 B1 STD_500000000 None 14.52 4.04E+08 Positive Unchecked Standard 5.00E+08 14.57 0.06 3.93E+08 1.64E+07 A1 FAM 0.34 3.38 None 10 +255;103;103;103 B2 STD_50000000 None 17.7 4.98E+07 Positive Unchecked Standard 5.00E+07 17.63 0.1 5.23E+07 3.40E+06 A2 FAM 0.32 3.21 None 11 +255;242;138;21 B3 STD_5000000 None 20.84 6.31E+06 Positive Unchecked Standard 5.00E+06 20.84 0.01 6.33E+06 2.95E+04 A3 FAM 0.31 3.18 None 12 +255;250;215;15 B4 STD_500000 None 24.53 5.57E+05 Positive Unchecked Standard 5.00E+05 24.54 0.01 5.55E+05 2.58E+03 A4 FAM 0.31 3.06 None 13 +255;103;154;47 B5 STD_50000 None 28.41 4.33E+04 Positive Unchecked Standard 5.00E+04 28.27 0.21 4.79E+04 6.44E+03 A5 FAM 0.3 2.91 None 14 +255;180;73;149 B6 STD_5000 None 31.41 6.01E+03 Positive Unchecked Standard 5.00E+03 31.56 0.21 5.48E+03 7.62E+02 A6 FAM 0.31 2.87 None 15 +255;95;103;174 B7 STD_500 None 35.92 3.09E+02 Positive Unchecked Standard 5.00E+02 35.47 0.64 4.34E+02 1.77E+02 A7 FAM 0.3 2.35 None 16 +255;205;18;55 B8 STD_50 None 38.67 5.06E+01 Positive Unchecked Standard 5.00E+01 38.67 0 5.06E+01 0.00E+00 A8 FAM 0.24 1.68 Replicate group contains positives and negatives. 17 +255;34;176;146 B9 STD_0 None - - Negative Unchecked Unknown - - - - - A9 FAM 0 0.01 None 18 +255;234;79;79 C1 rh2503_2014.06.05_.3 None 30.99 7.93E+03 Positive Unchecked Unknown - 30.85 0.2 8.73E+03 1.13E+03 C1 FAM 0.3 2.53 None 19 +255;66;41;24 C2 rh2503_2014.06.11_.3 None 32.9 2.26E+03 Positive Unchecked Unknown - 32.8 0.15 2.42E+03 2.36E+02 C2 FAM 0.24 2.13 None 20 +255;132;197;238 C3 rh2503_2014.06.13_.3 None - - Negative Unchecked Unknown - - - - - C3 FAM 0.01 0.14 Replicate group contains positives and negatives. 21 +255;103;103;103 C4 rh2499_2014.06.07 None 35.21 4.93E+02 Positive Unchecked Unknown - 36.08 1.23 3.25E+02 2.38E+02 C4 FAM 0.15 1.3 None 22 +255;242;138;21 C5 rh2486_2017.06.13_.3 None 36.32 2.38E+02 Positive Unchecked Unknown - 36.08 0.34 2.82E+02 6.24E+01 C5 FAM 0.11 1.13 None 23 +255;250;215;15 C6 rh2484_2014.06.15_.3 None 37.54 1.07E+02 Positive Unchecked Unknown - 37.54 0 1.07E+02 0.00E+00 C6 FAM 0.22 1.71 Replicate group contains positives and negatives. 24 +255;234;79;79 D1 rh2503_2014.06.05_.3 None 30.71 9.53E+03 Positive Unchecked Unknown - 30.85 0.2 8.73E+03 1.13E+03 C1 FAM 0.29 2.62 None 25 +255;66;41;24 D2 rh2503_2014.06.11_.3 None 32.69 2.59E+03 Positive Unchecked Unknown - 32.8 0.15 2.42E+03 2.36E+02 C2 FAM 0.25 2.25 None 26 +255;132;197;238 D3 rh2503_2014.06.13_.3 None 35.76 3.44E+02 Positive Unchecked Unknown - 35.76 0 3.44E+02 0.00E+00 C3 FAM 0.04 0.41 Replicate group contains positives and negatives. 27 +255;103;103;103 D4 rh2499_2014.06.07 None 36.95 1.57E+02 Positive Unchecked Unknown - 36.08 1.23 3.25E+02 2.38E+02 C4 FAM 0.09 0.78 None 28 +255;242;138;21 D5 rh2486_2017.06.13_.3 None 35.84 3.26E+02 Positive Unchecked Unknown - 36.08 0.34 2.82E+02 6.24E+01 C5 FAM 0.18 1.62 None 29 +255;250;215;15 D6 rh2484_2014.06.15_.3 None - - Negative Unchecked Unknown - - - - - C6 FAM 0 0.03 Replicate group contains positives and negatives. 30 \ No newline at end of file diff --git a/Viral_Load_Assay/resources/web/Viral_Load_Assay/vl_utils.js b/Viral_Load_Assay/resources/web/Viral_Load_Assay/vl_utils.js new file mode 100644 index 000000000..9a407b21e --- /dev/null +++ b/Viral_Load_Assay/resources/web/Viral_Load_Assay/vl_utils.js @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2010-2012 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +Ext4.namespace('ViralLoad.Utils'); + +ViralLoad.Utils = new function(){ + var lookup = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.".split(""); + + return { + compressUUID: function (uuid) { + // Remove any hyphens + uuid = uuid.replace(/-/g, ""); + + var base16Triples = uuid.match(/.{1,3}/g); + + var base64Duples = base16Triples.map(function (base16Number) { + var integer = parseInt(base16Number, 16); + + var firstPart = Math.floor(integer / 64); + var secondPart = integer % 64; + + return "" + lookup[firstPart] + lookup[secondPart]; + }); + + return base64Duples.join(""); + }, + + uncompressUUID: function (compressedUUID) { + var base64Duples = compressedUUID.match(/.{1,2}/g); + var lastIndex = base64Duples.length - 1; + + var base16Duples = base64Duples.map(function (base64Set, curIndex) { + var firstPart = lookup.indexOf(base64Set.substr(0, 1)); + var secondPart = lookup.indexOf(base64Set.substr(1, 1)); + + var integer = (firstPart * 64) + secondPart; + + var hexString = integer.toString(16); + + if (hexString.length == 1) { + hexString = "00" + hexString; + } + else if (hexString.length == 2) { + hexString = "0" + hexString; + } + else if (hexString.length == 0) { + hexString = "000"; + } + + // The last piece is only 2 characters long. + if (curIndex == lastIndex) { + hexString = hexString.substr(1); + } + + return hexString.toLowerCase(); + }); + + var hexString = base16Duples.join(""); + + hexString = [hexString.substr(0, 8), hexString.substr(8, 4), hexString.substr(12, 4), hexString.substr(16, 4), hexString.substr(20, 12)].join("-"); + + return hexString; + }, + + testCompressUUID: function () { + var testUUID = function (UUID) { + if (!UUID) { + UUID = LABKEY.Utils.generateUUID(); + } + + return ( UUID == returnObj.uncompressUUID(returnObj.compressUUID(UUID)) ); + }; + + for (var i = 0; i < 100; i++) { + if (!testUUID()) { + return false; + } + } + + if (!testUUID("00000000-0000-0000-0000-000000000000")) { return false; } + if (!testUUID("ffffffff-ffff-ffff-ffff-ffffffffffff")) { return false; } + + return true; + } + } +} \ No newline at end of file diff --git a/Viral_Load_Assay/src/org/labkey/viral_load_assay/Viral_Load_AssayModule.java b/Viral_Load_Assay/src/org/labkey/viral_load_assay/Viral_Load_AssayModule.java index 3f22c6264..738aa648a 100644 --- a/Viral_Load_Assay/src/org/labkey/viral_load_assay/Viral_Load_AssayModule.java +++ b/Viral_Load_Assay/src/org/labkey/viral_load_assay/Viral_Load_AssayModule.java @@ -49,7 +49,7 @@ public String getName() @Override public @Nullable Double getSchemaVersion() { - return 12.25; + return 12.26; } @Override diff --git a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/AbstractWNPRCImportMethod.java b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/AbstractWNPRCImportMethod.java new file mode 100644 index 000000000..3fe101496 --- /dev/null +++ b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/AbstractWNPRCImportMethod.java @@ -0,0 +1,172 @@ +package org.labkey.viral_load_assay.assay; + +import org.json.JSONObject; +import org.labkey.api.exp.api.ExpProtocol; +import org.labkey.api.view.ViewContext; + +import java.util.Map; + +public class AbstractWNPRCImportMethod extends DefaultVLImportMethod +{ + public AbstractWNPRCImportMethod(String providerName) + { + super(providerName); + } + + @Override + public JSONObject getMetadata(ViewContext ctx, ExpProtocol protocol) + { + JSONObject meta = super.getMetadata(ctx, protocol); + + //Add WNPRC-specific global changes here. + + JSONObject resultsMeta = meta.getJSONObject("Results"); + + JSONObject eluateMap = getJsonObject(resultsMeta, "eluateVol"); + eluateMap.put("defaultValue", 50); + eluateMap.put("setGlobally", true); + + JSONObject sourceMaterial = getJsonObject(resultsMeta, "sourceMaterial"); + sourceMaterial.put("setGlobally", false); + + resultsMeta.put("eluateVol", eluateMap); + resultsMeta.put("sourceMaterial", sourceMaterial); + + meta.put("Results", resultsMeta); + + return meta; + } + + @Override + public JSONObject getSupplementalTemplateMetadata() + { + JSONObject ret = new JSONObject(); + JSONObject domainMeta = new JSONObject(); + JSONObject resultsMeta = new JSONObject(); + + JSONObject sourceMaterial = getJsonObject(resultsMeta, "sourceMaterial"); + sourceMaterial.put("defaultValue", "Plasma"); + sourceMaterial.put("setGlobally", false); + sourceMaterial.put("hidden", false); + sourceMaterial.put("required", true); + resultsMeta.put("sourceMaterial", sourceMaterial); + + JSONObject sampleId = getJsonObject(resultsMeta, "sampleId"); + sampleId.put("hidden", true); + resultsMeta.put("sampleId", sampleId); + + JSONObject sampleType = getJsonObject(resultsMeta, "sampleType"); + sampleType.put("setGlobally", true); + sampleType.put("hidden", false); + sampleType.put("required", true); + resultsMeta.put("sampleType", sampleType); + + JSONObject uniqueSample = getJsonObject(resultsMeta, "uniqueSample"); + uniqueSample.put("getInitialValue", "function(val) { return val || ViralLoad.Utils.compressUUID(LABKEY.Utils.generateUUID().toUpperCase()); }"); + resultsMeta.put("uniqueSample", uniqueSample); + + JSONObject units = getJsonObject(resultsMeta, "sourceMaterial/liquid"); + units.put("hidden", true); + units.put("required", false); + resultsMeta.put("sourceMaterial/liquid", units); + + /********************************************* + * Hide all of the new assay columns - Start * + *********************************************/ + + JSONObject color = getJsonObject(resultsMeta, "color"); + JSONObject geneName = getJsonObject(resultsMeta, "geneName"); + JSONObject call = getJsonObject(resultsMeta, "call"); + JSONObject excluded = getJsonObject(resultsMeta, "excluded"); + JSONObject cqMean = getJsonObject(resultsMeta, "cqMean"); + JSONObject cqError = getJsonObject(resultsMeta, "cqError"); + JSONObject concentrationMean = getJsonObject(resultsMeta, "concentrationMean"); + JSONObject concentrationError = getJsonObject(resultsMeta, "concentrationError"); + JSONObject replicateGroup = getJsonObject(resultsMeta, "replicateGroup"); + JSONObject dye = getJsonObject(resultsMeta, "dye"); + JSONObject editedCall = getJsonObject(resultsMeta, "editedCall"); + JSONObject slope = getJsonObject(resultsMeta, "slope"); + JSONObject epf = getJsonObject(resultsMeta, "epf"); + JSONObject failure = getJsonObject(resultsMeta, "failure"); + JSONObject notes = getJsonObject(resultsMeta, "notes"); + JSONObject samplePrepNotes = getJsonObject(resultsMeta, "samplePrepNotes"); + JSONObject number = getJsonObject(resultsMeta, "number"); + JSONObject qcstate = getJsonObject(resultsMeta, "qcstate"); + JSONObject qcresults = getJsonObject(resultsMeta, "qcresults"); + + color.put("hidden", true); + geneName.put("hidden", true); + call.put("hidden", true); + excluded.put("hidden", true); + cqMean.put("hidden", true); + cqError.put("hidden", true); + concentrationMean.put("hidden", true); + concentrationError.put("hidden", true); + replicateGroup.put("hidden", true); + dye.put("hidden", true); + editedCall.put("hidden", true); + slope.put("hidden", true); + epf.put("hidden", true); + failure.put("hidden", true); + notes.put("hidden", true); + samplePrepNotes.put("hidden", true); + number.put("hidden", true); + qcstate.put("hidden", true); + qcresults.put("hidden", true); + + resultsMeta.put("color", color); + resultsMeta.put("geneName", geneName); + resultsMeta.put("call", call); + resultsMeta.put("excluded", excluded); + resultsMeta.put("cqMean", cqMean); + resultsMeta.put("cqError", cqError); + resultsMeta.put("concentrationMean", concentrationMean); + resultsMeta.put("concentrationError", concentrationError); + resultsMeta.put("replicateGroup", replicateGroup); + resultsMeta.put("dye", dye); + resultsMeta.put("editedCall", editedCall); + resultsMeta.put("slope", slope); + resultsMeta.put("epf", epf); + resultsMeta.put("failure", failure); + resultsMeta.put("notes", notes); + resultsMeta.put("samplePrepNotes", samplePrepNotes); + resultsMeta.put("number", number); + resultsMeta.put("qcstate", qcstate); + resultsMeta.put("qcresults", qcresults); + + /******************************************* + * Hide all of the new assay columns - End * + *******************************************/ + + domainMeta.put("Results", resultsMeta); + ret.put("domains", domainMeta); + + return ret; + } + + protected void calculateViralLoadForRoche(Map map) + { + //calculate VL + Double copiesPerRxn = map.get("Concentration") == null ? null : ((Number)map.get("Concentration")).doubleValue(); + map.put("copiesPerRxn", copiesPerRxn); + + Double eluateVol = new Double((Integer)map.get("eluateVol")); + Double volPerRxn = new Double((Integer)map.get("volPerRxn")); + if (!map.containsKey("sampleVol")) + map.put("sampleVol", 0.0); + + Double sampleVol = Double.parseDouble(map.get("sampleVol").toString()); + + Double viralLoad = 0.0; + Double dilutionFactor = 0.0; + if (copiesPerRxn != null && sampleVol > 0) + { + dilutionFactor = (1.0 / sampleVol) * (eluateVol / volPerRxn); + viralLoad = dilutionFactor * copiesPerRxn; + } + map.put("dilutionfactor", dilutionFactor); + map.put("viralLoad", viralLoad); + map.remove("Standard"); + map.remove("Concentration"); + } +} \ No newline at end of file diff --git a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LC96ImportMethod.java b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LC96ImportMethod.java new file mode 100644 index 000000000..95d0651a3 --- /dev/null +++ b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LC96ImportMethod.java @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2012 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.labkey.viral_load_assay.assay; + +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Level; +import org.jetbrains.annotations.Nullable; +import org.json.JSONArray; +import org.json.JSONObject; +import org.labkey.api.collections.CaseInsensitiveHashMap; +import org.labkey.api.data.Container; +import org.labkey.api.data.ConvertHelper; +import org.labkey.api.data.Results; +import org.labkey.api.data.SimpleFilter; +import org.labkey.api.exp.api.ExpExperiment; +import org.labkey.api.exp.api.ExpProtocol; +import org.labkey.api.exp.api.ExpRun; +import org.labkey.api.laboratory.assay.AssayImportMethod; +import org.labkey.api.laboratory.assay.AssayParser; +import org.labkey.api.laboratory.assay.DefaultAssayParser; +import org.labkey.api.laboratory.assay.ImportContext; +import org.labkey.api.laboratory.assay.ParserErrors; +import org.labkey.api.query.BatchValidationException; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryHelper; +import org.labkey.api.query.ValidationException; +import org.labkey.api.reader.ColumnDescriptor; +import org.labkey.api.reader.TabLoader; +import org.labkey.api.security.User; +import org.labkey.api.settings.AppProps; +import org.labkey.api.util.Pair; +import org.labkey.api.util.ResultSetUtil; +import org.labkey.api.view.ViewContext; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.sql.SQLException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +public class LC96ImportMethod extends AbstractWNPRCImportMethod { + public static final String NAME = "LC96"; + private static final String UNIQUE_FIELD = "uniqueSample"; + private static final String DATE_FIELD = "date"; + + protected final static SimpleDateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + public LC96ImportMethod(String providerName) { + super(providerName); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getLabel() { + return NAME; + } + + @Override + public boolean hideTemplateDownload() { + return true; + } + + @Override + public boolean supportsRunTemplates() { + return true; + } + + @Override + public String getTooltip() { + return "Choose this option to upload data directly from the output of a Roche LC96. NOTE: this expects the sample names to be formatted in a specific manner. Please see instructions above the results section"; + } + + @Override + public String getTemplateInstructions() { + return "This is designed to accept the output directly from a Roche96 Light Cycler. If using the Copy/Paste method please copy all data, including the column headers."; + } + + public AssayParser getFileParser(Container c, User u, int assayId) { + return new Parser(this, c, u, assayId); + } + + @Override + public String getExampleDataUrl(ViewContext ctx) { + return AppProps.getInstance().getContextPath() + "/Viral_Load_Assay/SampleData/lc96.txt"; + } + + @Override + public List getTemplateDownloadColumns() { + + ArrayList exportColumns = new ArrayList<>(); + exportColumns.add("uniqueSample"); + exportColumns.add("well"); + exportColumns.add("subjectId"); + exportColumns.add("date"); + + return exportColumns; + } + + @Override + public JSONObject getMetadata(ViewContext ctx, ExpProtocol protocol) { + JSONObject meta = super.getMetadata(ctx, protocol); + + JSONObject runMeta = meta.getJSONObject("Run"); + runMeta.put("slope", new JSONObject().put("hidden", true)); + runMeta.put("intercept", new JSONObject().put("hidden", true)); + runMeta.put("rSquared", new JSONObject().put("hidden", true)); + runMeta.put("instrument", new JSONObject().put("defaultValue", "LC96")); + meta.put("Run", runMeta); + + JSONObject resultsMeta = meta.getJSONObject("Results"); + + JSONObject objectId = getJsonObject(resultsMeta, "objectid"); + objectId.put("hidden", true); + resultsMeta.put("objectid", objectId); + + meta.put("Results", resultsMeta); + + return meta; + } + + @Override + public void validateTemplate(User u, Container c, ExpProtocol protocol, @Nullable Integer templateId, String title, JSONObject json, BatchValidationException errors) throws BatchValidationException { + //ensure each subject/date has at least 2 neg controls + JSONObject resultDefaults = json.optJSONObject("Results"); + JSONArray rawResults = json.getJSONArray("ResultRows"); + Set distinctWells = new HashSet<>(); + Map wellMap = getWellMap96("well_96", "addressbyrow_96"); + + String[] requiredFields = new String[]{"well", "uniqueSample", "subjectId", "date", "sourceMaterial"}; + List validSourceMaterials = new ArrayList<>(); + + Results rs = null; + List column = new ArrayList<>(); + column.add(FieldKey.fromString("type")); + try { + while (c.isWorkbook()) { + c = c.getParent(); + } + QueryHelper qh = new QueryHelper(c, u, "viral_load_assay", "source_material"); + rs = qh.select(column, new SimpleFilter()); + + while (rs.next()) { + validSourceMaterials.add(rs.getString("type")); + } + } catch (SQLException e) { + //do nothing + } finally { + ResultSetUtil.close(rs); + } + + int rowIdx = 0; + for (JSONObject row : rawResults.toJSONObjectArray()) { + rowIdx++; + + for (String prop : resultDefaults.keySet()) { + row.put(prop, resultDefaults.get(prop)); + } + + boolean missingRequired = false; + for (String field : requiredFields) { + if (row.get(field) == null || StringUtils.isEmpty(row.getString(field))) { + if (field.equals("date") && "Standard".equals(row.get("category"))) { + //There is no error in this case + } else { + errors.addRowError(new ValidationException("Row " + rowIdx + ": missing required field: " + field)); + missingRequired = true; + continue; + } + } + } + + if (missingRequired) { + continue; + } + + String sourceMaterial = row.getString("sourceMaterial"); + boolean foundValidSourceMaterial = false; + for(String validSourceMaterial : validSourceMaterials) { + if(validSourceMaterial.equalsIgnoreCase(sourceMaterial)) { + row.put("sourceMaterial", validSourceMaterial); + foundValidSourceMaterial = true; + break; + } + } + if (!foundValidSourceMaterial) { + errors.addRowError(new ValidationException("Row " + rowIdx + ": " + sourceMaterial + " is not a valid source material")); + continue; + } + + String well = row.getString("well"); + if (well == null) { + errors.addRowError(new ValidationException("Row " + rowIdx + ": sample is missing well")); + continue; + } + + if (!wellMap.containsKey(well)) { + errors.addRowError(new ValidationException("Row " + rowIdx + ": unknown well: " + well)); + continue; + } + + if (distinctWells.contains(well)) { + errors.addRowError(new ValidationException("Row " + rowIdx + ": another sample is already present in well: " + well)); + continue; + } + distinctWells.add(well); + + String uniqueSample = row.getString("uniqueSample"); + if (uniqueSample == null) { + errors.addRowError(new ValidationException("Row " + rowIdx + ": sample is missing uniqueSample")); + continue; + } + + //validate the row's date + if (row.get(DATE_FIELD) != null) { + try { + Date date = ConvertHelper.convert(row.get(DATE_FIELD), Date.class); + _dateFormat.format(date); + } + catch (ConversionException | IllegalArgumentException e) { + errors.addRowError(new ValidationException("Row " + rowIdx + ": Invalid sample date")); + } + } + } + + super.validateTemplate(u, c, protocol, templateId, title, json, errors); + + if (errors.hasErrors()) { + throw errors; + } + } + + + private class Parser extends DefaultAssayParser { + private String HAS_RESULT = "__hasResult__"; + private int _assayId; + final String[] lookup = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.".split(""); + + public Parser(AssayImportMethod method, Container c, User u, int assayId) { + super(method, c, u, assayId); + _assayId = assayId; + } + + @Override + public Pair saveBatch(JSONObject json, File file, String fileName, ViewContext ctx) throws BatchValidationException { + int templateId = json.getInt("TemplateId"); + + Pair result = super.saveBatch(json, file, fileName, ctx); + + saveTemplate(ctx, templateId, result.second.getRowId()); + return result; + } + + protected TabLoader getTabLoader(String contents) throws IOException { + TabLoader loader = new TabLoader(new StringReader(contents), false); + ColumnDescriptor[] cols = new ColumnDescriptor[]{ + new ColumnDescriptor("color", String.class), //not shown by default + new ColumnDescriptor("well", String.class), + new ColumnDescriptor("uniqueSample", String.class), + new ColumnDescriptor("geneName", String.class), //not shown by default + new ColumnDescriptor("Cp", Double.class), + new ColumnDescriptor("Concentration", Double.class), + new ColumnDescriptor("call", String.class), //not shown by default + new ColumnDescriptor("excluded", String.class), //not shown by default + new ColumnDescriptor("category", String.class), + new ColumnDescriptor("Standard", Integer.class), + new ColumnDescriptor("cqMean", Double.class), //not shown by default + new ColumnDescriptor("cqError", Double.class), //not shown by default + new ColumnDescriptor("concentrationMean", Double.class), //not shown by default + new ColumnDescriptor("concentrationError", Double.class), //not shown by default + new ColumnDescriptor("replicateGroup", String.class), //not shown by default + new ColumnDescriptor("dye", String.class), //not shown by default + new ColumnDescriptor("editedCall", String.class), //not shown by default + new ColumnDescriptor("slope", Double.class), //not shown by default + new ColumnDescriptor("epf", Double.class), //not shown by default + new ColumnDescriptor("failure", String.class), //not shown by default + new ColumnDescriptor("notes", String.class), //not shown by default + new ColumnDescriptor("samplePrepNotes", String.class), //not shown by default + new ColumnDescriptor("number", Integer.class) //not shown by default + }; + + loader.setColumns(cols); + return loader; + } + + public int getAssayId() { + return _assayId; + } + + @Override + protected List> processRowsFromFile(List> rows, ImportContext context) throws BatchValidationException { + ParserErrors errors = context.getErrors(); + + String keyProperty = "uniqueSample"; + Map> templateRows = getTemplateRowMap(context, keyProperty); + + List> newRows = new ArrayList<>(); + ListIterator> rowsIter = rows.listIterator(); + int rowIdx = 0; + + if(templateRows.size() + 1 == rows.size()) { + if (rowsIter.hasNext()) { + rowsIter.next(); + } + } + while (rowsIter.hasNext()) { + rowIdx++; + Map row = rowsIter.next(); + Map map = new CaseInsensitiveHashMap<>(row); + + if (row.size() < 6) { + errors.addError("Improperly formatted row on line " + rowIdx + ", excepted 6 cells"); + continue; + } + + appendPromotedResultFields(map, context); + + if (!map.containsKey(UNIQUE_FIELD) || map.get(UNIQUE_FIELD) == null || StringUtils.isEmpty((String) map.get(UNIQUE_FIELD))) { + errors.addError("Missing sample name for row: " + rowIdx); + continue; + } + if (map.get("well") != null) { + map.put("well", ((String) map.get("well")).toUpperCase()); + } + + if (!mergeTemplateRow(keyProperty, templateRows, map, context)) + continue; + + //these are not used + map.remove("Include"); + map.remove("Status"); + + if (map.get("uniqueSample") != null) { + map.put("objectid", uncompressUUID((String) map.get("uniqueSample"))); + } + + calculateViralLoadForRoche(map); + newRows.add(map); + } + ensureTemplateRowsHaveResults(templateRows, context); + errors.confirmNoErrors(); + + return newRows; + } + + protected void ensureTemplateRowsHaveResults(Map> templateRows, ImportContext context) throws BatchValidationException { + for (String key : templateRows.keySet()) { + Map row = templateRows.get(key); + if (!row.containsKey(HAS_RESULT)) { + context.getErrors().addError("Template row with key " + key + " does not have a result", Level.WARN); + } + } + + context.getErrors().confirmNoErrors(); + } + + private String uncompressUUID(String compressObjectId) { + String reg = "(?<=\\G..)"; + String[] base64Duples = compressObjectId.split(reg); + int lastIndex = base64Duples.length - 1; + StringBuilder base16Duples = new StringBuilder(); + int position = 0; + for (String base64set : base64Duples) { + int firstPart = Arrays.asList(lookup).indexOf(base64set.substring(0, 1)); + int secondPart = Arrays.asList(lookup).indexOf(base64set.substring(1, 2)); + + int integer = (firstPart * 64) + secondPart; + + String hexString = Integer.toString(integer, 16); + + if (hexString.length() == 1) { + hexString = "00" + hexString; + } + else if (hexString.length() == 2) { + hexString = "0" + hexString; + } + else if (hexString.length() == 0) { + hexString = "000" + hexString; + } + + if (position == lastIndex) { + hexString = hexString.substring(1); + + } + base16Duples.append(hexString.toLowerCase()); + position++; + + } + char[] objectId = base16Duples.toString().toCharArray(); + + StringBuilder returnObjectId = new StringBuilder(); + + returnObjectId.append(objectId, 0, 8); + returnObjectId.append("-"); + returnObjectId.append(objectId, 8, 4); + returnObjectId.append("-"); + returnObjectId.append(objectId, 12, 4); + returnObjectId.append("-"); + returnObjectId.append(objectId, 16, 4); + returnObjectId.append("-"); + returnObjectId.append(objectId, 20, 12); + + return returnObjectId.toString(); + } + } +} diff --git a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java index e747f27ec..e750ea2c2 100644 --- a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java +++ b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java @@ -24,12 +24,15 @@ import org.labkey.api.module.Module; import org.labkey.api.security.User; import org.labkey.api.view.ViewContext; +import org.labkey.api.view.template.ClientDependency; import org.labkey.viral_load_assay.Viral_Load_AssayModule; import org.labkey.viral_load_assay.Viral_Load_Manager; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; /** * Created with IntelliJ IDEA. @@ -48,6 +51,7 @@ public ViralLoadAssayDataProvider(Module m) _importMethods.add(new LC480ImportMethod(_providerName)); _importMethods.add(new LightCyclerImportMethod(_providerName)); _importMethods.add(new ABI7500ImportMethod(_providerName)); + _importMethods.add(new LC96ImportMethod(_providerName)); } @Override @@ -120,4 +124,12 @@ public List getSettingsItems(Container c, User u) return items; } + + @Override + public Set getClientDependencies() + { + LinkedHashSet resources = new LinkedHashSet<>(); + resources.add(ClientDependency.fromPath("Viral_Load_Assay/vl_utils.js")); + return resources; + } } diff --git a/ehr/resources/credits/scripts.txt b/ehr/resources/credits/scripts.txt deleted file mode 100644 index 1a38b43f8..000000000 --- a/ehr/resources/credits/scripts.txt +++ /dev/null @@ -1,9 +0,0 @@ -{table} -Library|Version|Source|License|LabKey Dev|Purpose -Knockout|3.3.0|{link:Knockout.js|http://knockoutjs.com}|{link:MIT|http://opensource.org/licenses/mit-license.php}|jrichardson|Lightweight, Responsive Components and Observables -Knockout-Mapping|2.4.1|{link:Knockout.js/Mapping Plugin|http://knockoutjs.com/documentation/plugins-mapping.html}|{link:MIT|http://opensource.org/licenses/mit-license.php}|jrichardson|Mapping Plugin for Mapping Objects to Observables -Underscore|1.8.3|{link:Underscore.js|http://underscorejs.org/}|{link:MIT|http://opensource.org/licenses/mit-license.php}|jrichardson|Lightweight Object/Array Utilities -Underscore-String|3.2.2|{link:Underscore.String.js|https://github.com/epeli/underscore.string}|{link:MIT|http://opensource.org/licenses/mit-license.php}|jrichardson|Lightweight String Utilities -Classify|0.0.1|{link:ClassifyJS|https://github.com/JonathonRichardson/ClassifyJS}|{link:Apache 2.0|https://github.com/JonathonRichardson/ClassifyJS/blob/master/LICENSE}|jrichardson|Class Structures -SuperSQLStore|0.0.1|{link:SuperSQLStore|https://github.com/JonathonRichardson/SuperSQLStoreJS}|{link:Apache 2.0|https://github.com/JonathonRichardson/SuperSQLStoreJS/blob/master/LICENSE}|jrichardson|Observable Tables to Bind to Knockout -{table} \ No newline at end of file diff --git a/ehr/resources/data/lookup_sets.tsv b/ehr/resources/data/lookup_sets.tsv index 61ee557e0..a3f1df29d 100644 --- a/ehr/resources/data/lookup_sets.tsv +++ b/ehr/resources/data/lookup_sets.tsv @@ -37,7 +37,8 @@ histology_stain Histology Stain Field Values value hold_codes Hold Codes Field Values value title housing_condition_codes Housing Condition Code Field Values value title housing_reason Housing Reason Field Values value -immunology_method Immunology Method Field Values value +immunology_method Immunology Method Field Values value +location_water Location Water Field Values value microchip_comments Microchip Comments Field Values value necropsy_condition Necropsy Condition Field Values value necropsy_perfusion Necropsy Perfusion Field Values value @@ -56,7 +57,8 @@ parasitology_method Parasitology Method Field Values value pe_region PE Region Field Values value pe_remarks PE Remarks Field Values value preservation_solutions Preservation Solution Field Values value -problem_list_category Problem List Category Field Values value +problem_list_category Problem List Category Field Values value +reason_food_deprive Reason For Deprive Field Values value restraint_duration Restraint Duration Field Values value sample_types Sample Type Field Values value snomed_qualifiers SNOMED Qualifiers Field Values value diff --git a/ehr/resources/queries/ehr/protocol_title.sql b/ehr/resources/queries/ehr/protocol_title.sql new file mode 100644 index 000000000..dcc39c067 --- /dev/null +++ b/ehr/resources/queries/ehr/protocol_title.sql @@ -0,0 +1,2 @@ +SELECT protocol, title , protocol || '-' || coalesce (title,'No Title') as protocolTitle +FROM ehr.protocol \ No newline at end of file diff --git a/ehr/resources/queries/ehr/tasks.query.xml b/ehr/resources/queries/ehr/tasks.query.xml index 2cc725020..176a9e0d9 100644 --- a/ehr/resources/queries/ehr/tasks.query.xml +++ b/ehr/resources/queries/ehr/tasks.query.xml @@ -127,6 +127,12 @@ FBEC5D + + + + + FBEC5D +
diff --git a/ehr/resources/queries/study/colonyPopulationChange.sql b/ehr/resources/queries/study/colonyPopulationChange.sql index 1378540f9..a83267499 100644 --- a/ehr/resources/queries/study/colonyPopulationChange.sql +++ b/ehr/resources/queries/study/colonyPopulationChange.sql @@ -22,14 +22,13 @@ SELECT T2.id, -- T2.id.dataset.demographics.species, 'Arrivals' AS Category, - max(T2.date), - convert(year(max(T2.date)), INTEGER) AS Year, + T2.date, + convert(year(T2.date), INTEGER) AS Year, FROM study.Arrival T2 WHERE T2.date IS NOT NULL AND T2.qcstate.publicdata = true and cast(COALESCE(STARTDATE, '1900-01-01') as date) <= T2.date and cast(COALESCE(ENDDATE, curdate()) as date) >= cast(T2.date as date) -group by id UNION ALL @@ -37,14 +36,13 @@ SELECT T3.id, -- T3.id.dataset.demographics.species, 'Departures' AS Category, - max(T3.Date), - convert(year(max(T3.date)), INTEGER) AS Year, + T3.date, + convert(year(T3.date), INTEGER) AS Year, FROM study.Departure T3 WHERE T3.date IS NOT NULL AND T3.qcstate.publicdata = true and cast(COALESCE(STARTDATE, '1900-01-01') as date) <= T3.date and cast(COALESCE(ENDDATE, curdate()) as date) >= cast(T3.date as date) -group by id UNION ALL diff --git a/ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql b/ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql new file mode 100644 index 000000000..9aa32daa3 --- /dev/null +++ b/ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +--Merged script from conflicting ehr-12.425-12.426.sql scripts authored in different branches, trunk and modules15.2 + +-- Ensure column length is changed as expected +ALTER TABLE ehr.project ALTER COLUMN Title TYPE VARCHAR(400); + +-- Make sure the ehr.protocol table has a contact column +CREATE FUNCTION ehr.handleAddContactToProtocol() RETURNS VOID AS $$ +DECLARE + BEGIN + IF NOT EXISTS ( + SELECT column_name + FROM information_schema.columns + WHERE table_name='protocol' and table_schema='ehr' and column_name='contacts' + ) + THEN + ALTER TABLE ehr.protocol ADD contacts VARCHAR; + END IF; + END; +$$ LANGUAGE plpgsql; + +SELECT ehr.handleAddContactToProtocol(); + +DROP FUNCTION ehr.handleAddContactToProtocol(); + + +-- Merging upgrade scripts, ensure that we end up with rows for 'Started' in both tables +DELETE FROM ehr.qcStateMetadata WHERE QCStateLabel = 'Started'; +DELETE FROM ehr.status WHERE Label = 'Started'; + +INSERT INTO ehr.qcStateMetadata +(QCStateLabel,draftData,isDeleted,isRequest) +VALUES +('Started', TRUE, FALSE, FALSE); +INSERT INTO ehr.status +(label,Description,PublicData,DraftData,isDeleted,isRequest,allowFutureDates) +VALUES +('Started', 'Record has started, but not completed',TRUE,FALSE,FALSE,FALSE,FALSE); \ No newline at end of file diff --git a/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql b/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql new file mode 100644 index 000000000..c5a8e4184 --- /dev/null +++ b/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +--Merged script from conflicting ehr-12.425-12.426.sql scripts authored in different branches, trunk and modules15.2 + +ALTER TABLE ehr.protocol ADD contacts VARCHAR(200); + +-- Merging upgrade scripts, ensure that we end up with rows for 'Started' in both tables +DELETE FROM ehr.qcStateMetadata WHERE QCStateLabel = 'Started'; +DELETE FROM ehr.status WHERE Label = 'Started'; + +INSERT INTO ehr.qcStateMetadata +(QCStateLabel,draftData,isDeleted,isRequest) +VALUES +('Started', 1, 0, 0); +INSERT INTO ehr.status +(label,Description,PublicData,DraftData,isDeleted,isRequest,allowFutureDates) +VALUES +('Started', 'Record has started, but not completed',1,0,0,0,0); \ No newline at end of file diff --git a/ehr/resources/scripts/ehr/ScriptHelper.js b/ehr/resources/scripts/ehr/ScriptHelper.js index dd4d8a851..e8973cf4f 100644 --- a/ehr/resources/scripts/ehr/ScriptHelper.js +++ b/ehr/resources/scripts/ehr/ScriptHelper.js @@ -89,6 +89,7 @@ EHR.Server.ScriptHelper = function(extraContext, event, EHR){ removeTimeFromDate: false, removeTimeFromEndDate: false, allowRequestsInPast: false, + allowRequestsInDistantFuture: false, allowDeadIds: false, allowAnyId: false, skipIdFormatCheck: false, @@ -137,7 +138,7 @@ EHR.Server.ScriptHelper = function(extraContext, event, EHR){ //we allow the client to pass limited options using extraContext //this function is where all processing of client JSON -> server options should reside function setScriptOptionsFromExtraContext(){ - LABKEY.ExtAdapter.each(['skipIdFormatCheck', 'allowAnyId', 'allowDatesInDistantPast'], function(name){ + LABKEY.ExtAdapter.each(['skipIdFormatCheck', 'allowAnyId', 'allowDatesInDistantPast', 'allowRequestsInDistantFuture'], function(name){ if (extraContext[name]) scriptOptions[name] = extraContext[name]; }, this); @@ -167,6 +168,10 @@ EHR.Server.ScriptHelper = function(extraContext, event, EHR){ return scriptOptions.allowRequestsInPast; }, + shouldAllowRequestsInDistantFuture: function() { + return scriptOptions.allowRequestsInDistantFuture + }, + shouldRemoveTimeFromEndDate: function(){ return scriptOptions.removeTimeFromEndDate; }, diff --git a/ehr/resources/scripts/ehr/triggers.js b/ehr/resources/scripts/ehr/triggers.js index 8ae36dc79..700cb8512 100644 --- a/ehr/resources/scripts/ehr/triggers.js +++ b/ehr/resources/scripts/ehr/triggers.js @@ -628,15 +628,20 @@ EHR.Server.Triggers.rowInit = function(helper, scriptErrors, row, oldRow){ EHR.Server.Utils.addError(scriptErrors, 'project', 'Project must be numeric: ' + row.project, 'ERROR'); delete row.project; } + //Make sure that the project is a number validateAssignment method is expecting a integer. + var intProject; + if (row.project){ + intProject = parseInt(row.project); + } //skip if doing assignments if (!helper.isQuickValidation() && !helper.isETL() && - row.project && row.Id && row.date && - !helper.getJavaHelper().isDefaultProject(row.project) && + intProject && row.Id && row.date && + !helper.getJavaHelper().isDefaultProject(intProject) && !helper.isSkipAssignmentCheck() ){ - var assignmentErrors = helper.getJavaHelper().validateAssignment(row.Id, row.project, row.date); + var assignmentErrors = helper.getJavaHelper().validateAssignment(row.Id, intProject, row.date); if (assignmentErrors){ EHR.Server.Utils.addError(scriptErrors, 'project', assignmentErrors, helper.getErrorSeverityForImproperAssignment()); } diff --git a/ehr/resources/scripts/ehr/validation.js b/ehr/resources/scripts/ehr/validation.js index 5c16625ef..e2ecbaab6 100644 --- a/ehr/resources/scripts/ehr/validation.js +++ b/ehr/resources/scripts/ehr/validation.js @@ -26,7 +26,7 @@ EHR.Server.Validation = { */ checkRestraint: function(row, scriptErrors){ if (row.restraint && !LABKEY.ExtAdapter.isDefined(row.restraintDuration)) - EHR.Server.Utils.scriptErrors(errors, 'restraintDuration', 'Must enter time restrained', 'INFO'); + EHR.Server.Utils.addError(scriptErrors, 'restraintDuration', 'Must enter time restrained', 'INFO'); }, diff --git a/ehr/resources/views/animalHistory.html b/ehr/resources/views/animalHistory.html index a36ef1f50..2372b7598 100644 --- a/ehr/resources/views/animalHistory.html +++ b/ehr/resources/views/animalHistory.html @@ -1,18 +1,16 @@ - - - - - - \ No newline at end of file + Ext4.onReady(function (){ + var webpart = <%=webpartContext%>; + var ctx = EHR.Utils.getEHRContext(webpart.wrapperDivId, ['DefaultAnimalHistoryReport']); + if(!ctx) + return; + + Ext4.create('EHR.panel.AnimalHistoryPanel', { + defaultReport: ctx.DefaultAnimalHistoryReport, + defaultTab: 'General', + renderTo: webpart.wrapperDivId + }); + }); + + \ No newline at end of file diff --git a/ehr/resources/views/manageRequest.html b/ehr/resources/views/manageRequest.html index d3c2a1c0a..68ec48d35 100644 --- a/ehr/resources/views/manageRequest.html +++ b/ehr/resources/views/manageRequest.html @@ -1,3 +1,27 @@ + + + + - - - - - \ No newline at end of file + /* get the participant id from the request URL: this parameter is required. */ + var participantId = LABKEY.ActionURL.getParameter('participantId'); + + if (!participantId){ + alert('Must Provide Id'); + return; + } + + var title = 'Animal Details: ' + participantId; + document.title = title; + LABKEY.Utils.setWebpartTitle(title, webpart.id); + + Ext4.create('EHR.panel.ParticipantDetailsPanel', { + participantId: participantId, + defaultReport: ctx.DefaultAnimalHistoryReport, + defaultTab: 'General', + autoLoadDefaultTab: true + }).render(webpart.wrapperDivId); + }); + \ No newline at end of file diff --git a/ehr/resources/views/populateInitialData.html b/ehr/resources/views/populateInitialData.html index f2dcefffc..26774777d 100644 --- a/ehr/resources/views/populateInitialData.html +++ b/ehr/resources/views/populateInitialData.html @@ -429,7 +429,7 @@ ['Clinpath', 'formSections', 'ehr-abstractpanel', '1', '', '', '', '', '', '', '' ], ['Clinpath', 'formHeaders', 'ehr-gridformpanel', '2', 'Clinpath Runs', 'study', '', 'Task,Assay', '', '', '' ], ['Clinpath', 'formSections', 'ehr-gridformpanel', '3', 'Bacteriology Results', 'study', '', 'Task,Assay', '', '', 'add,copyfromclinpath,requestdelete,selectall,duplicate,bulk_edit,sortany,apply_template,save_template' ], - ['Clinpath', 'formSections', 'ehr-gridformpanel', '4', 'Chemistry Results', 'study', '', 'Task,Assay', '', '', 'add,addchemexcel,copyfromclinpath,requestdelete,selectall,duplicate,bulk_edit,sortany,apply_template,save_template' ], + ['Clinpath', 'formSections', 'ehr-gridformpanel', '4', 'Chemistry Results', 'study', '', 'Task,Assay', '', '', 'add,addchemexcel,addchemvetaxcel,copyfromclinpath,requestdelete,selectall,duplicate,bulk_edit,sortany,apply_template,save_template' ], ['Clinpath', 'formSections', 'ehr-gridformpanel', '5', 'Hematology Results', 'study', '', 'Task,Assay', '', '', 'add,addhematologyexcel,requestdelete,copyfromclinpath,selectall,duplicate,bulk_edit,sortany,apply_template,save_template' ], ['Clinpath', 'formSections', 'ehr-gridformpanel', '6', 'Hematology Morphology', 'study', '', 'Task,Assay', '', '', 'add,requestdelete,copyfromclinpath,selectall,duplicate,bulk_edit,sortany,apply_template,save_template' ], ['Clinpath', 'formSections', 'ehr-gridformpanel', '7', 'Immunology Results', 'study', '', 'Task,Assay', '', '', 'add,requestdelete,copyfromclinpath,selectall,duplicate,bulk_edit,sortany,apply_template,save_template' ], @@ -604,7 +604,7 @@ ['abstractClin' ,'Clinical' ,'js' ,'Abstract' ,'true' ,'' ,'study' ,'abstract', '', '', 'date', 'false', 'false', '', 'qcstate/publicdata', 'This report contains a summary of the animal, including demographics, assignments and weight'], ['encounters' ,'Clinical' ,'query' ,'Clinical Encounters' ,'true' ,'' ,'study' ,'Clinical Encounters', '', '', 'date', 'false', 'false', '', 'qcstate/publicdata', 'This report contains one record for each encounter with each animal, including surergies, exams, procedures, etc.'], ['clinremarks' ,'Clinical' ,'query' ,'Clinical Remarks' ,'true' ,'' ,'study' ,'Clinical Remarks', '', '', 'date', 'false', 'false', '', 'qcstate/publicdata', 'This report contains the clinical remarks entered about each animal'], - ['diarrheaCalendar' ,'Clinical' ,'query' ,'Diarrhea Calendar' ,'TRUE' ,'' ,'study' ,'diarrheaCalendar', '', '', '', 'FALSE', 'FALSE', '', 'qcstate/publicdata', 'This report shows a calendar view of the diarrhea observations entered by daily obs.'], + ['diarrheaCalendar' ,'Clinical' ,'js' ,'Diarrhea Calendar' ,'TRUE' ,'' ,'study' ,'diarrheaCalendar', '', '', '', 'FALSE', 'FALSE', '', 'qcstate/publicdata', 'This report shows a calendar view of the diarrhea observations entered by daily obs.'], ['fullHistory' ,'Clinical' ,'query' ,'Full History' ,'true' ,'' ,'study' ,'StudyData', 'Full History', '', 'date', 'false', 'false', '', 'qcstate/publicdata', 'Contains all clinical data on the animal'], ['fullHistoryPlusObs' ,'Clinical' ,'query' ,'Full History Plus Obs' ,'true' ,'' ,'study' ,'StudyData', 'Full History Plus Obs', '', 'date', 'false', 'false', '', 'qcstate/publicdata', 'Similar to Full History, but also contains irregular observations'], ['allObs' ,'Clinical' ,'js' ,'Irregular Obs' ,'true' ,'' ,'study' ,'irregularObs', '', '', 'date', 'false', 'true', '', '', 'This report displays irregular observations, including cage observations'], diff --git a/ehr/resources/web/ehr/DataEntryUtils.js b/ehr/resources/web/ehr/DataEntryUtils.js index d08f4a284..d838a6473 100644 --- a/ehr/resources/web/ehr/DataEntryUtils.js +++ b/ehr/resources/web/ehr/DataEntryUtils.js @@ -814,7 +814,7 @@ EHR.DataEntryUtils = new function(){ containerPath: ctx ? ctx['EHRStudyContainer'] : null, schemaName: 'ehr', queryName: 'project', - columns: 'project,displayName,account,name,protocol,protocol/displayName,title,investigatorId/lastName', + columns: 'project,displayName,account,name,protocol,protocol/displayName,protocol/inves,protocol/investigatorId,title,investigatorId/lastName', //filterArray: [LABKEY.Filter.create('enddate', null, LABKEY.Filter.Types.ISBLANK)], sort: 'displayName', storeId: storeId, @@ -989,23 +989,27 @@ EHR.DataEntryUtils = new function(){ } } else { - Ext4.Object.each(permMap, function(schemaName, queries) { - // minor improvement. non-study tables cannot have per-table permissions, so instead we check - // for the container-level DataEntryPermission + // Check each query to test in turn + Ext4.each(queriesToTest, function(queryObject) { + var schemaPermissions = permMap[queryObject.schemaName]; + var queryPermissions = (schemaPermissions || {})[queryObject.queryName]; + var permissionToTest = permissionName; - if (schemaName.toLowerCase() != 'study'){ + if (queryObject.schemaName.toLowerCase() != 'study'){ + // minor improvement. non-study tables cannot have per-table permissions, so instead we check + // for the container-level DataEntryPermission permissionToTest = 'org.labkey.api.ehr.security.EHRDataEntryPermission'; } - Ext4.Object.each(queries, function(queryName, permissions) { - if (!permissions[permissionToTest]){ - hasPermission = false; - return false; - } - }, this); - if (!hasPermission) - return false; - }, this); + if (Ext4.isDefined(schemaPermissions) && Ext4.isDefined(queryPermissions) && permissionToTest in queryPermissions) { + // Do nothing: we have security + } + else { + // If we don't have any permissions defined for the query, assume we don't have access + hasPermission = false; + return false; // short circuit out of jQuery.each + } + }); } return hasPermission; diff --git a/ehr/resources/web/ehr/HousingAndAssignmentHistory.css b/ehr/resources/web/ehr/HousingAndAssignmentHistory.css deleted file mode 100644 index 233febbee..000000000 --- a/ehr/resources/web/ehr/HousingAndAssignmentHistory.css +++ /dev/null @@ -1,34 +0,0 @@ -.x-axis path, .x-axis line { - fill: none; - stroke: black; - shape-rendering: crispEdges; -} - -.x-axis text { - font-family: sans-serif; - font-size: 11px; -} - -.animal-assignments-tooltip, .animal-housing-tooltip { - position: absolute; - text-align: center; - font: 12px sans-serif; - background: lightsteelblue; - border: 2px solid black; - border-radius: 8px; -} -.animal-assignments-tooltip p, .animal-housing-tooltip p { - margin-bottom: 0; - margin-top: 0; - color: #333; - padding: 2px; -} - -.animal-assignments-tooltip .animal-housingassignments-tooltip-header, .animal-housing-tooltip .animal-housingassignments-tooltip-header { - background: #0094ff; - color: white; - padding: 6px; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - font-weight: bold; -} \ No newline at end of file diff --git a/ehr/resources/web/ehr/HousingAndAssignmentHistoryTemplate.html b/ehr/resources/web/ehr/HousingAndAssignmentHistoryTemplate.html deleted file mode 100644 index fbda61a96..000000000 --- a/ehr/resources/web/ehr/HousingAndAssignmentHistoryTemplate.html +++ /dev/null @@ -1,61 +0,0 @@ - -

- -

-
- - - - - - - - - - - - - - - - - - - -
-

-

-

-

-

-
- -

- - -

(no reason specified)

- -
- -
-

- - - - - (Unrecognized assignment code: "") - -

-

-

-
-

Project:

-

-
- diff --git a/ehr/resources/web/ehr/d3-graph-template.html b/ehr/resources/web/ehr/d3-graph-template.html deleted file mode 100644 index 1680719f7..000000000 --- a/ehr/resources/web/ehr/d3-graph-template.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ehr/resources/web/ehr/data/DataEntryServerStore.js b/ehr/resources/web/ehr/data/DataEntryServerStore.js index e480d093a..dd94b72c4 100644 --- a/ehr/resources/web/ehr/data/DataEntryServerStore.js +++ b/ehr/resources/web/ehr/data/DataEntryServerStore.js @@ -264,9 +264,9 @@ Ext4.define('EHR.data.DataEntryServerStore', { // The code below is being left in place for now, but may be unnecessary. if there are no changes to apply, no edits should be made this.callParent(arguments); - if (command.command != 'delete'){ + if (!command || command.command != 'delete'){ var idProp = this.proxy.reader.getIdProperty(); - Ext4.Array.forEach(command.rows, function(row){ + Ext4.Array.forEach(records, function(row){ var record; if (row.oldKeys){ //NOTE: always test both upper and lower case. somewhat ugly, but the DB can alter the case of GUIDs diff --git a/ehr/resources/web/ehr/data/RequestStoreCollection.js b/ehr/resources/web/ehr/data/RequestStoreCollection.js index 74bbc1035..642698abd 100644 --- a/ehr/resources/web/ehr/data/RequestStoreCollection.js +++ b/ehr/resources/web/ehr/data/RequestStoreCollection.js @@ -20,5 +20,43 @@ Ext4.define('EHR.data.RequestStoreCollection', { } return this.callParent([model]); + }, + + commitChanges: function(){ + // ensure all records are using this requestid and alert if not + var requestid = this.getRequestId(); + if (requestid){ + this.clientStores.each(function(cs){ + if (cs.getFields().get('requestid') != null){ + cs.each(function(r){ + if (requestid != r.get('requestid')){ + LDK.Assert.assertEquality('Incorrect requestid for client store:' + cs.storeId, requestid, r.get('requestid')); + r.beginEdit(); + r.set('requestid', this.getRequestId()); + r.endEdit(true); + } + }, this); + } + }, this); + + this.serverStores.each(function(cs){ + if (cs.getFields().get('requestid') != null){ + cs.each(function(r){ + if (r.isRemovedRequest){ + return; //do not check these records. they have deliberately been separated. + } + + if (requestid != r.get('requestid')){ + LDK.Assert.assertEquality('Incorrect requestid for server store:' + cs.storeId, requestid, r.get('requestid')); + r.beginEdit(); + r.set('requestid', this.getRequestId()); + r.endEdit(true); + } + }, this); + } + }, this); + } + + return this.callParent(arguments); } }); \ No newline at end of file diff --git a/ehr/resources/web/ehr/data/StoreCollection.js b/ehr/resources/web/ehr/data/StoreCollection.js index ac87f8290..dbf0697d9 100644 --- a/ehr/resources/web/ehr/data/StoreCollection.js +++ b/ehr/resources/web/ehr/data/StoreCollection.js @@ -386,7 +386,8 @@ Ext4.define('EHR.data.StoreCollection', { storeId: this.collectionId + '-' + section.name, model: modelName, sectionCfg: section, - loaded: false + loaded: false, + slaveFieldsToInclude: section.slaveFieldsToInclude }); this.addClientStore(store); diff --git a/ehr/resources/web/ehr/ehr_api.lib.xml b/ehr/resources/web/ehr/ehr_api.lib.xml index dad53ba1a..b4effed4c 100644 --- a/ehr/resources/web/ehr/ehr_api.lib.xml +++ b/ehr/resources/web/ehr/ehr_api.lib.xml @@ -64,6 +64,7 @@ \ No newline at end of file diff --git a/ehr/resources/web/ehr/plugin/DataBind.js b/ehr/resources/web/ehr/plugin/DataBind.js index 102e22960..e28c3e6df 100644 --- a/ehr/resources/web/ehr/plugin/DataBind.js +++ b/ehr/resources/web/ehr/plugin/DataBind.js @@ -165,6 +165,15 @@ Ext4.define('EHR.plugin.Databind', { this.unbindRecord(); } + // Split multi-values into arrays before it's bound into the field + for (var fieldName in record.data) { + var value = record.data[fieldName]; + var field = form.findField(fieldName); + if (value && field && field.multiSelect) { + record.data[fieldName] = value.split(','); + } + } + form.suspendEvents(); form.loadRecord(record); form.resumeEvents(); @@ -289,8 +298,10 @@ Ext4.define('EHR.plugin.Databind', { var fieldVal = field.getValue(); if (!field.isEqual(fieldVal, val)) { - if (Ext4.isObject(fieldVal) || Ext4.isArray(fieldVal)){ + if (Ext4.isObject(fieldVal)) { console.error(fieldVal); + } else if (Ext4.isArray(fieldVal)) { + val = fieldVal; } //TODO: combos and other multi-valued fields represent data differently in the store vs the field. need to reconcile here diff --git a/ehr/resources/web/ehr/plugin/RowEditor.js b/ehr/resources/web/ehr/plugin/RowEditor.js index 344dfd841..d8977d5a2 100644 --- a/ehr/resources/web/ehr/plugin/RowEditor.js +++ b/ehr/resources/web/ehr/plugin/RowEditor.js @@ -88,7 +88,7 @@ Ext4.define('EHR.plugin.RowEditor', { getWindowCfg: function(){ return { modal: true, - width: 800, + width: 900, border: false, items: [{ items: [this.getDetailsPanelCfg(), this.getFormPanelCfg()] diff --git a/ehr/resources/web/ehr/reports.js b/ehr/resources/web/ehr/reports.js index 0e4df1284..3cbd7e79f 100644 --- a/ehr/resources/web/ehr/reports.js +++ b/ehr/resources/web/ehr/reports.js @@ -16,17 +16,6 @@ Ext4.namespace('EHR.reports'); * the UI should be rendered. * */ - -//function to directly add qwp to dom see ticket 38440 -addQueryWebPart = function(parentElement, config) { - var targetElement = parentElement.getEl().createChild({tag: 'div'}); - config.renderTo = Ext4.id(targetElement, "queryWebPart"); - - new LABKEY.QueryWebPart(config); - -}; - - EHR.reports['abstract'] = function(panel, tab){ var filterArray = panel.getFilterArray(tab); var title = panel.getTitleSuffix(); @@ -58,7 +47,11 @@ EHR.reports['abstract'] = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab,config) + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); config = panel.getQWPConfig({ title: 'Active Assignments' + title, @@ -70,8 +63,11 @@ EHR.reports['abstract'] = function(panel, tab){ removeableFilters: filterArray.removable }); - - addQueryWebPart(tab,config) + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); addQueryWebPart(tab,config) @@ -86,7 +82,11 @@ EHR.reports['abstract'] = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab,config) + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); EHR.reports.weightGraph(panel, tab); }; @@ -95,25 +95,31 @@ EHR.reports.arrivalDeparture = function(panel, tab){ var filterArray = panel.getFilterArray(tab); var title = panel.getTitleSuffix(); - var config = panel.getQWPConfig({ - title: 'Arrivals' + title, - schemaName: 'study', - queryName: 'arrival', - filters: filterArray.nonRemovable, - removeableFilters: filterArray.removable, - frame: true + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: panel.getQWPConfig({ + title: 'Arrivals' + title, + schemaName: 'study', + queryName: 'arrival', + filters: filterArray.nonRemovable, + removeableFilters: filterArray.removable, + frame: true + }) }); - addQueryWebPart(tab,config); - var config = panel.getQWPConfig({ - title: 'Departures' + title, - schemaName: 'study', - queryName: 'departure', - filters: filterArray.nonRemovable, - removeableFilters: filterArray.removable, - frame: true + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: panel.getQWPConfig({ + title: 'Departures' + title, + schemaName: 'study', + queryName: 'departure', + filters: filterArray.nonRemovable, + removeableFilters: filterArray.removable, + frame: true + }) }); - addQueryWebPart(tab, config); }; EHR.reports.pedigree = function(panel, tab){ @@ -201,7 +207,7 @@ EHR.reports.weightGraph = function(panel, tab){ var filterArray = panel.getFilterArray(tab); var title = panel.getTitleSuffix(); toAdd.push({ - xtype: 'ldk-querypanel', + xtype: 'ldk-querycmp', style: 'margin-bottom:20px;', queryConfig: { title: 'Overview' + title, @@ -251,7 +257,11 @@ EHR.reports.bloodChemistry = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab, config); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); config = panel.getQWPConfig({ schemaName: 'study', @@ -263,7 +273,11 @@ EHR.reports.bloodChemistry = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab, config); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); config = panel.getQWPConfig({ schemaName: 'study', @@ -276,7 +290,11 @@ EHR.reports.bloodChemistry = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab, config); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); } EHR.reports.urinalysisResults = function(panel, tab){ @@ -295,7 +313,11 @@ EHR.reports.urinalysisResults = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab, config); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); config = panel.getQWPConfig({ schemaName: 'study', @@ -307,7 +329,11 @@ EHR.reports.urinalysisResults = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab, config); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); config = panel.getQWPConfig({ schemaName: 'study', @@ -320,7 +346,11 @@ EHR.reports.urinalysisResults = function(panel, tab){ removeableFilters: filterArray.removable }); - addQueryWebPart(tab, config); + tab.add({ + xtype: 'ldk-querycmp', + style: 'margin-bottom:20px;', + queryConfig: config + }); } EHR.reports.treatmentSchedule = function(panel, tab){ @@ -340,7 +370,7 @@ EHR.reports.treatmentSchedule = function(panel, tab){ }); tab.add({ - xtype: 'ldk-querypanel', + xtype: 'ldk-querycmp', style: 'margin-bottom:20px;', queryConfig: config }); @@ -355,7 +385,7 @@ EHR.reports.treatmentSchedule = function(panel, tab){ }); tab.add({ - xtype: 'ldk-querypanel', + xtype: 'ldk-querycmp', style: 'margin-bottom:20px;', queryConfig: config }); @@ -370,7 +400,7 @@ EHR.reports.treatmentSchedule = function(panel, tab){ }); tab.add({ - xtype: 'ldk-querypanel', + xtype: 'ldk-querycmp', style: 'margin-bottom:20px;', queryConfig: config }); @@ -426,7 +456,7 @@ EHR.reports.snapshot = function(panel, tab, showActionsBtn){ var filterArray = panel.getFilterArray(tab); var title = panel.getTitleSuffix(); toAdd.push({ - xtype: 'ldk-querypanel', + xtype: 'ldk-querycmp', style: 'margin-bottom:20px;', queryConfig: { title: 'Overview' + title, @@ -471,7 +501,7 @@ EHR.reports.clinicalHistory = function(panel, tab, showActionsBtn, includeAll){ var filterArray = panel.getFilterArray(tab); var title = panel.getTitleSuffix(); tab.add({ - xtype: 'ldk-querypanel', + xtype: 'ldk-querycmp', style: 'margin-bottom:20px;', queryConfig: { title: 'Overview' + title, diff --git a/ehr_billing/resources/schemas/ehr_billing.xml b/ehr_billing/resources/schemas/ehr_billing.xml index fb0839c4a..6fbbfea30 100644 --- a/ehr_billing/resources/schemas/ehr_billing.xml +++ b/ehr_billing/resources/schemas/ehr_billing.xml @@ -393,6 +393,7 @@
+ Item @@ -678,7 +679,7 @@ DETAILED Charge Units - + Name diff --git a/ehr_billing/resources/web/ehr_billing/data/sources/EHR_BillingDefault.js b/ehr_billing/resources/web/ehr_billing/data/sources/EHR_BillingDefault.js index 470776cea..14966ece7 100644 --- a/ehr_billing/resources/web/ehr_billing/data/sources/EHR_BillingDefault.js +++ b/ehr_billing/resources/web/ehr_billing/data/sources/EHR_BillingDefault.js @@ -20,7 +20,7 @@ EHR.model.DataModelManager.registerMetadata('Default', { columns: 'project' } }, - chargetype: { + chargeGroup: { shownInGrid: true, isAutoExpandColumn: true, useNull: true diff --git a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingContainerListener.java b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingContainerListener.java index 19839efc6..7341e4513 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingContainerListener.java +++ b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingContainerListener.java @@ -89,6 +89,10 @@ public void containerDeleted(Container c, User user) if (dataAccessTable.getTableType() == DatabaseTableType.TABLE) Table.delete(dataAccessTable, containerFilter); + TableInfo chargeableItemCategoriesTable = EHR_BillingSchema.getInstance().getChargeableItemCategories(); + if (chargeableItemCategoriesTable.getTableType() == DatabaseTableType.TABLE) + Table.delete(chargeableItemCategoriesTable, containerFilter); + transaction.commit(); } } diff --git a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java index 0dc729f8e..950f4e905 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java +++ b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java @@ -93,6 +93,11 @@ public TableInfo getChargeableItems() return getSchema().getTable(TABLE_CHARGEABLE_ITEMS); } + public TableInfo getChargeableItemCategories() + { + return getSchema().getTable(TABLE_CHARGEABLE_ITEM_CATEGORIES); + } + public TableInfo getChargeUnits() { return getSchema().getTable(TABLE_CHARGE_UNITS); diff --git a/ehr_billing/src/org/labkey/ehr_billing/notification/BillingNotification.java b/ehr_billing/src/org/labkey/ehr_billing/notification/BillingNotification.java index b9b4e228d..1c45ea940 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/notification/BillingNotification.java +++ b/ehr_billing/src/org/labkey/ehr_billing/notification/BillingNotification.java @@ -342,7 +342,7 @@ public void exec(ResultSet object) throws SQLException projectDisplay = "None"; } - String financialAnalyst = rs.getString(FieldKey.fromString("investigatorLastName")); + String financialAnalyst = rs.getString(FieldKey.fromString("investigator")); if (financialAnalyst == null) { financialAnalyst = "Not Assigned"; From 170bc6c0cb6b87b73c7bb97376e0fbdcc05d0dc7 Mon Sep 17 00:00:00 2001 From: Binal Date: Mon, 6 Jul 2020 16:04:26 -0700 Subject: [PATCH 05/39] Merge from wnprc18.3 svn r.65197 to 65647 (skipping r.65166 since its a backport) --- .../security/EHR_BillingAdminPermission.java | 11 ++++ ehr/src/org/labkey/ehr/EHRController.java | 50 ++++++++++++++++++- ehr/src/org/labkey/ehr/EHRProperties.java | 1 + .../ehr/query/EHRCustomPermissionsTable.java | 16 ------ .../org/labkey/ehr/query/EHRUserSchema.java | 1 + ehr/test/sampledata/ehrTestStudyPolicy.xml | 6 +++ .../security/EHR_BillingAdminPermission.java | 26 ---------- ehr_billing/resources/schemas/ehr_billing.xml | 6 ++- .../form/field/EHRBillingProjectEntryField.js | 8 +-- .../web/ehr_billing/model/sources/Charges.js | 6 --- .../ehr_billing/EHR_BillingController.java | 2 +- .../query/EHRBillingTriggerHelper.java | 2 +- .../ehr_billing/security/EHR_BillingRole.java | 2 +- 13 files changed, 80 insertions(+), 57 deletions(-) create mode 100644 ehr/api-src/org/labkey/api/ehr/security/EHR_BillingAdminPermission.java delete mode 100644 ehr_billing/api-src/org/labkey/api/ehr_billing/security/EHR_BillingAdminPermission.java diff --git a/ehr/api-src/org/labkey/api/ehr/security/EHR_BillingAdminPermission.java b/ehr/api-src/org/labkey/api/ehr/security/EHR_BillingAdminPermission.java new file mode 100644 index 000000000..4c0469007 --- /dev/null +++ b/ehr/api-src/org/labkey/api/ehr/security/EHR_BillingAdminPermission.java @@ -0,0 +1,11 @@ +package org.labkey.api.ehr.security; + +import org.labkey.api.security.permissions.AbstractPermission; + +public class EHR_BillingAdminPermission extends AbstractPermission +{ + public EHR_BillingAdminPermission() + { + super("EHR_BillingAdminPermission", "Can insert and update data in the EHR Billing tables"); + } +} \ No newline at end of file diff --git a/ehr/src/org/labkey/ehr/EHRController.java b/ehr/src/org/labkey/ehr/EHRController.java index d2135d333..565a06dcf 100644 --- a/ehr/src/org/labkey/ehr/EHRController.java +++ b/ehr/src/org/labkey/ehr/EHRController.java @@ -353,7 +353,7 @@ public ModelAndView getView(EHRQueryForm form, BindException errors) { String detailsStr; String importStr; - if (EHRServiceImpl.get().isUseLegagyExt3EditUI(getContainer()) && !isExt4Form(form.getSchemaName(), form.getQueryName())) + if (EHRServiceImpl.get().isUseLegagyExt3EditUI(getContainer()) && !isExt4Form(form.getSchemaName(), form.getQueryName()) && !isReactForm(form.getSchemaName(), form.getQueryName())) { // Because the Ext3-based UI can rely on loading JS-based metadata that is keyed // off table name, and because when this was originally written LK preferentially used label over title for @@ -376,8 +376,32 @@ public ModelAndView getView(EHRQueryForm form, BindException errors) url.addParameter("importURL", importUrl.toString()); } } - else + //TODO implement this after view is set up for editable react form + else if (isReactForm(form.getSchemaName(), form.getQueryName())) { + //weight is custom since it was introduced in its own controller + if ("weight".equals(form.getQueryName())){ + detailsStr = "/enterweights/app.view?"; + }else{ + detailsStr = "/wnprc_ehr/" + queryName + ".view?"; + } + importStr = ""; + for (String pkCol : ti.getPkColumnNames()) + { + detailsStr += "&" + pkCol + "=${" + pkCol + "}"; + importStr += "&" + pkCol + "="; + } + detailsStr += "&" + "formtype=" + queryName; + + if (form.isShowImport()) + { + DetailsURL importUrl = DetailsURL.fromString("/ehr/test.view?schemaName=" + schemaName + "&queryName=" + queryName + importStr); + importUrl.setContainerContext(getContainer()); + + url.addParameter("importURL", importUrl.toString()); + } + } + else { detailsStr = "/ehr/dataEntryFormForQuery.view?schemaName=" + schemaName + "&queryName=" + queryName; importStr = ""; for (String pkCol : ti.getPkColumnNames()) @@ -493,6 +517,28 @@ protected boolean isExt4Form(String schemaName, String queryName) return isExt4Form; } + + //Checks the form_framework_types table to see if there are any forms that should be rendered using react controller + // Currently just enterweights as of March 2020 + protected boolean isReactForm(String schemaName, String queryName) + { + boolean isReactForm = false; + UserSchema us = QueryService.get().getUserSchema(getUser(), getContainer(), EHRSchema.EHR_SCHEMANAME); + if (us == null) { return false; } + + TableInfo ti = us.getTable(EHRSchema.TABLE_FORM_FRAMEWORK_TYPES); + if (ti == null) { return false; } + + TableSelector ts = new TableSelector(ti, Collections.singleton("framework"), new SimpleFilter(FieldKey.fromString("schemaname"), schemaName).addCondition(FieldKey.fromString("queryname"), queryName), null); + String[] ret = ts.getArray(String.class); + + if (ret.length > 0 && "reactjs".equalsIgnoreCase(ret[0])) + { + isReactForm = true; + } + + return isReactForm; + } } public static class GetDemographicsForm diff --git a/ehr/src/org/labkey/ehr/EHRProperties.java b/ehr/src/org/labkey/ehr/EHRProperties.java index 789959e44..084fe4f32 100644 --- a/ehr/src/org/labkey/ehr/EHRProperties.java +++ b/ehr/src/org/labkey/ehr/EHRProperties.java @@ -37,6 +37,7 @@ protected PropertyDescriptor constructPropertyDescriptor() pd.setName("remark"); pd.setStorageColumnName("remark"); pd.setInputType("textarea"); + pd.setScale(-1); return pd; } }; diff --git a/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java b/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java index ac7267204..688bca456 100644 --- a/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java +++ b/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java @@ -1,18 +1,3 @@ -/* - * Copyright (c) 2017-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package org.labkey.ehr.query; import org.labkey.api.data.Container; @@ -49,7 +34,6 @@ protected Container getDomainContainer() return EHRDomainKind.getDomainContainer(getContainer()); } - @Override public QueryUpdateService getUpdateService() { TableInfo table = getRealTable(); diff --git a/ehr/src/org/labkey/ehr/query/EHRUserSchema.java b/ehr/src/org/labkey/ehr/query/EHRUserSchema.java index 357cc48f2..2ca42f205 100644 --- a/ehr/src/org/labkey/ehr/query/EHRUserSchema.java +++ b/ehr/src/org/labkey/ehr/query/EHRUserSchema.java @@ -24,6 +24,7 @@ import org.labkey.api.ehr.security.EHRDataAdminPermission; import org.labkey.api.ehr.security.EHRProjectEditPermission; import org.labkey.api.ehr.security.EHRProtocolEditPermission; +import org.labkey.api.ehr.security.EHR_BillingAdminPermission; import org.labkey.api.query.SimpleUserSchema; import org.labkey.api.security.User; import org.labkey.api.security.permissions.DeletePermission; diff --git a/ehr/test/sampledata/ehrTestStudyPolicy.xml b/ehr/test/sampledata/ehrTestStudyPolicy.xml index 9689235e5..9717953f3 100644 --- a/ehr/test/sampledata/ehrTestStudyPolicy.xml +++ b/ehr/test/sampledata/ehrTestStudyPolicy.xml @@ -340,5 +340,11 @@ + + + + + + \ No newline at end of file diff --git a/ehr_billing/api-src/org/labkey/api/ehr_billing/security/EHR_BillingAdminPermission.java b/ehr_billing/api-src/org/labkey/api/ehr_billing/security/EHR_BillingAdminPermission.java deleted file mode 100644 index f541fd78c..000000000 --- a/ehr_billing/api-src/org/labkey/api/ehr_billing/security/EHR_BillingAdminPermission.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2018-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.api.ehr_billing.security; - -import org.labkey.api.security.permissions.AbstractPermission; - -public class EHR_BillingAdminPermission extends AbstractPermission -{ - public EHR_BillingAdminPermission() - { - super("EHR_BillingAdminPermission", "Can insert and update data in the EHR Billing tables"); - } -} \ No newline at end of file diff --git a/ehr_billing/resources/schemas/ehr_billing.xml b/ehr_billing/resources/schemas/ehr_billing.xml index 6fbbfea30..8a350d514 100644 --- a/ehr_billing/resources/schemas/ehr_billing.xml +++ b/ehr_billing/resources/schemas/ehr_billing.xml @@ -359,7 +359,7 @@ - + @@ -406,6 +406,10 @@ Unit Cost $###,##0.00 + + Total Cost + $###,##0.00 + Credit Account true diff --git a/ehr_billing/resources/web/ehr_billing/form/field/EHRBillingProjectEntryField.js b/ehr_billing/resources/web/ehr_billing/form/field/EHRBillingProjectEntryField.js index ad1a5753b..04a160c3e 100644 --- a/ehr_billing/resources/web/ehr_billing/form/field/EHRBillingProjectEntryField.js +++ b/ehr_billing/resources/web/ehr_billing/form/field/EHRBillingProjectEntryField.js @@ -139,7 +139,7 @@ Ext4.define('EHR_Billing.form.field.EHRBillingProjectEntryField', { } this.loadedKey = key; - var sql = "SELECT DISTINCT t.project, t.investigator, t.title, " + + var sql = "SELECT DISTINCT t.project, t.investigator, t.title, t.account, " + "false as fromClient, min(sort_order) as sort_order, max(isAssigned) as isAssigned FROM ("; if (id){ @@ -148,6 +148,7 @@ Ext4.define('EHR_Billing.form.field.EHRBillingProjectEntryField', { "p.inves as investigator, " + "p.title, " + "1 as sort_order, " + + "p.account, " + "CASE WHEN (a.project = p.project) THEN 1 ELSE 0 END as isAssigned " + " FROM ehr.project p JOIN study.assignment a ON (a.project = p.project) " + " WHERE a.id='"+id+"' AND (a.project = p.project) "; @@ -170,9 +171,10 @@ Ext4.define('EHR_Billing.form.field.EHRBillingProjectEntryField', { sql += ' UNION ALL '; sql += " SELECT p.project," + - "p.inves as investigator," + "p.title, " + + "p.inves as investigator," + "3 as sort_order, " + + "p.account, " + "0 as isAssigned " + "FROM ehr.project p "; @@ -181,7 +183,7 @@ Ext4.define('EHR_Billing.form.field.EHRBillingProjectEntryField', { } } - sql+= " ) t GROUP BY t.project,t.investigator, t.title"; + sql+= " ) t GROUP BY t.project,t.investigator, t.title, t.account"; return sql; }, diff --git a/ehr_billing/resources/web/ehr_billing/model/sources/Charges.js b/ehr_billing/resources/web/ehr_billing/model/sources/Charges.js index 43edda862..78055d0d8 100644 --- a/ehr_billing/resources/web/ehr_billing/model/sources/Charges.js +++ b/ehr_billing/resources/web/ehr_billing/model/sources/Charges.js @@ -13,12 +13,6 @@ EHR.model.DataModelManager.registerMetadata('Charges', { allowBlank: true, nullable: true }, - unitcost: { - hidden: false, - editorConfig: { - decimalPrecision: 2 - } - }, date: { hidden: false, columnConfig: { diff --git a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java index 41a943281..4be85b17a 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java +++ b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java @@ -28,7 +28,7 @@ import org.labkey.api.data.DataRegionSelection; import org.labkey.api.data.TableInfo; import org.labkey.api.ehr_billing.pipeline.InvoicedItemsProcessingService; -import org.labkey.api.ehr_billing.security.EHR_BillingAdminPermission; +import org.labkey.api.ehr.security.EHR_BillingAdminPermission; import org.labkey.api.pipeline.PipeRoot; import org.labkey.api.pipeline.PipelineJobException; import org.labkey.api.pipeline.PipelineService; diff --git a/ehr_billing/src/org/labkey/ehr_billing/query/EHRBillingTriggerHelper.java b/ehr_billing/src/org/labkey/ehr_billing/query/EHRBillingTriggerHelper.java index 4853ed69c..64f71cca7 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/query/EHRBillingTriggerHelper.java +++ b/ehr_billing/src/org/labkey/ehr_billing/query/EHRBillingTriggerHelper.java @@ -24,7 +24,7 @@ import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; import org.labkey.api.ehr.security.EHRDataAdminPermission; -import org.labkey.api.ehr_billing.security.EHR_BillingAdminPermission; +import org.labkey.api.ehr.security.EHR_BillingAdminPermission; import org.labkey.api.query.FieldKey; import org.labkey.api.security.User; import org.labkey.api.security.UserManager; diff --git a/ehr_billing/src/org/labkey/ehr_billing/security/EHR_BillingRole.java b/ehr_billing/src/org/labkey/ehr_billing/security/EHR_BillingRole.java index b087cfc58..98414add0 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/security/EHR_BillingRole.java +++ b/ehr_billing/src/org/labkey/ehr_billing/security/EHR_BillingRole.java @@ -15,7 +15,7 @@ */ package org.labkey.ehr_billing.security; -import org.labkey.api.ehr_billing.security.EHR_BillingAdminPermission; +import org.labkey.api.ehr.security.EHR_BillingAdminPermission; import org.labkey.api.security.permissions.DeletePermission; import org.labkey.api.security.permissions.InsertPermission; import org.labkey.api.security.permissions.ReadPermission; From 201757481cdf299a3541c58e9a7f42b4380bf489 Mon Sep 17 00:00:00 2001 From: Binal Date: Mon, 6 Jul 2020 16:30:56 -0700 Subject: [PATCH 06/39] Remove duplicates happened during merge. --- .../src/org/labkey/ehr_billing/EHR_BillingSchema.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java index 950f4e905..c17a2dff7 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java +++ b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingSchema.java @@ -117,9 +117,4 @@ public TableInfo getDataAccessTable() { return getSchema().getTable(TABLE_DATA_ACCESS); } - - public TableInfo getChargeableItemCategories() - { - return getSchema().getTable(TABLE_CHARGEABLE_ITEM_CATEGORIES); - } } From 5f49850026eec6321891debb227f691a78fbcfc2 Mon Sep 17 00:00:00 2001 From: Binal Date: Tue, 7 Jul 2020 19:16:10 -0700 Subject: [PATCH 07/39] Fix merge inconsistencies. -Delete folders/files that should have been deleted. -Cleanup/add comments to ehr upgrade scripts. --- .../SOPrequirements/.qview.xml | 2 +- .../dbscripts/postgresql/ehr-17.20-17.21.sql | 43 - .../dbscripts/postgresql/ehr-17.21-17.22.sql | 16 - .../postgresql/ehr-20.000-20.001.sql | 18 +- .../dbscripts/sqlserver/ehr-17.20-17.21.sql | 22 - .../dbscripts/sqlserver/ehr-17.21-17.22.sql | 15 - .../dbscripts/sqlserver/ehr-20.000-20.001.sql | 10 +- .../web/ehr/form/field/ProjectEntryField.js | 50 +- ehr/resources/web/ehr/metadata/Assay.js | 78 - ehr/resources/web/ehr/metadata/Biopsy.js | 112 - ehr/resources/web/ehr/metadata/Default.js | 2808 ----------------- ehr/resources/web/ehr/metadata/Necropsy.js | 189 -- ehr/resources/web/ehr/metadata/Request.js | 200 -- ehr/resources/web/ehr/metadata/Surgery.js | 28 - 14 files changed, 30 insertions(+), 3561 deletions(-) delete mode 100644 ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql delete mode 100644 ehr/resources/schemas/dbscripts/postgresql/ehr-17.21-17.22.sql delete mode 100644 ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql delete mode 100644 ehr/resources/schemas/dbscripts/sqlserver/ehr-17.21-17.22.sql delete mode 100644 ehr/resources/web/ehr/metadata/Assay.js delete mode 100644 ehr/resources/web/ehr/metadata/Biopsy.js delete mode 100644 ehr/resources/web/ehr/metadata/Default.js delete mode 100644 ehr/resources/web/ehr/metadata/Necropsy.js delete mode 100644 ehr/resources/web/ehr/metadata/Request.js delete mode 100644 ehr/resources/web/ehr/metadata/Surgery.js diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml index a84f602df..5a6c2cd59 100644 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml +++ b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml @@ -1,7 +1,7 @@ - + diff --git a/ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql b/ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql deleted file mode 100644 index 9aa32daa3..000000000 --- a/ehr/resources/schemas/dbscripts/postgresql/ehr-17.20-17.21.sql +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ - ---Merged script from conflicting ehr-12.425-12.426.sql scripts authored in different branches, trunk and modules15.2 - --- Ensure column length is changed as expected -ALTER TABLE ehr.project ALTER COLUMN Title TYPE VARCHAR(400); - --- Make sure the ehr.protocol table has a contact column -CREATE FUNCTION ehr.handleAddContactToProtocol() RETURNS VOID AS $$ -DECLARE - BEGIN - IF NOT EXISTS ( - SELECT column_name - FROM information_schema.columns - WHERE table_name='protocol' and table_schema='ehr' and column_name='contacts' - ) - THEN - ALTER TABLE ehr.protocol ADD contacts VARCHAR; - END IF; - END; -$$ LANGUAGE plpgsql; - -SELECT ehr.handleAddContactToProtocol(); - -DROP FUNCTION ehr.handleAddContactToProtocol(); - - --- Merging upgrade scripts, ensure that we end up with rows for 'Started' in both tables -DELETE FROM ehr.qcStateMetadata WHERE QCStateLabel = 'Started'; -DELETE FROM ehr.status WHERE Label = 'Started'; - -INSERT INTO ehr.qcStateMetadata -(QCStateLabel,draftData,isDeleted,isRequest) -VALUES -('Started', TRUE, FALSE, FALSE); -INSERT INTO ehr.status -(label,Description,PublicData,DraftData,isDeleted,isRequest,allowFutureDates) -VALUES -('Started', 'Record has started, but not completed',TRUE,FALSE,FALSE,FALSE,FALSE); \ No newline at end of file diff --git a/ehr/resources/schemas/dbscripts/postgresql/ehr-17.21-17.22.sql b/ehr/resources/schemas/dbscripts/postgresql/ehr-17.21-17.22.sql deleted file mode 100644 index 229f18a32..000000000 --- a/ehr/resources/schemas/dbscripts/postgresql/ehr-17.21-17.22.sql +++ /dev/null @@ -1,16 +0,0 @@ -DROP TABLE IF EXISTS ehr.form_framework_types; -CREATE TABLE ehr.form_framework_types ( - RowId SERIAL NOT NULL, - - schemaname varchar(255) DEFAULT NULL, - queryname varchar(255) DEFAULT NULL, - framework varchar(255) DEFAULT NULL, - - Container ENTITYID NOT NULL, - CreatedBy USERID, - Created TIMESTAMP, - ModifiedBy USERID, - Modified TIMESTAMP, - - CONSTRAINT PK_form_framework_types PRIMARY KEY (schemaname, queryname) -); \ No newline at end of file diff --git a/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql b/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql index c28e433ae..eca994592 100644 --- a/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql +++ b/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql @@ -1,17 +1,14 @@ /* - * Copyright (c) 2019 LabKey Corporation + * Copyright (c) 2020 LabKey Corporation * * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 */ --- ehr-17.20-17.21.sql script is getting skipped on teamcity since it got merged to this (wnprc18.3) branch after rolled up scripts ehr-17.20-17.30, and its siblings ehr-17.21-17.30 & ehr-17.22-17.30 were created. --- So adding the contents of ehr-17.20-17.21.sql script below: ---Merged script from conflicting ehr-12.425-12.426.sql scripts authored in different branches, trunk and modules15.2 - --- Ensure column length is changed as expected +-- ehr-17.20-17.21.sql +-- contents of ehr-17.20-17.21.sql script are not in rolled up ehr-0.00-18.10.sql, since they got added and merged after the rollup. +-- So, including it below with a slight variation - add cols only if it doesn't exist since it probably exists on wnprc's postgres db ALTER TABLE ehr.project ALTER COLUMN Title TYPE VARCHAR(400); --- Make sure the ehr.protocol table has a contact column CREATE FUNCTION ehr.handleAddContactToProtocol() RETURNS VOID AS $$ DECLARE BEGIN @@ -30,7 +27,6 @@ SELECT ehr.handleAddContactToProtocol(); DROP FUNCTION ehr.handleAddContactToProtocol(); --- Merging upgrade scripts, ensure that we end up with rows for 'Started' in both tables DELETE FROM ehr.qcStateMetadata WHERE QCStateLabel = 'Started'; DELETE FROM ehr.status WHERE Label = 'Started'; @@ -44,9 +40,9 @@ VALUES ('Started', 'Record has started, but not completed',TRUE,FALSE,FALSE,FALSE,FALSE); --- ehr-17.21-17.22.sql script is getting skipped on teamcity (same reason as mentioned above). --- So adding the contents of ehr-17.21-17.22.sql script below with a slight variation - i.e. create table only if it doesn't exist: - +-- ehr-17.21-17.22.sql +-- contents of ehr-17.21-17.22.sql script are not in rolled up ehr-0.00-18.10.sql, since they got added and merged after the rollup. +-- So, including it below with a slight variation - create table only if it doesn't exist since it probably exists on wnprc's postgres db CREATE FUNCTION ehr.createTable_form_framework_types() RETURNS VOID AS $$ DECLARE BEGIN diff --git a/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql b/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql deleted file mode 100644 index c5a8e4184..000000000 --- a/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.20-17.21.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2018 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ - ---Merged script from conflicting ehr-12.425-12.426.sql scripts authored in different branches, trunk and modules15.2 - -ALTER TABLE ehr.protocol ADD contacts VARCHAR(200); - --- Merging upgrade scripts, ensure that we end up with rows for 'Started' in both tables -DELETE FROM ehr.qcStateMetadata WHERE QCStateLabel = 'Started'; -DELETE FROM ehr.status WHERE Label = 'Started'; - -INSERT INTO ehr.qcStateMetadata -(QCStateLabel,draftData,isDeleted,isRequest) -VALUES -('Started', 1, 0, 0); -INSERT INTO ehr.status -(label,Description,PublicData,DraftData,isDeleted,isRequest,allowFutureDates) -VALUES -('Started', 'Record has started, but not completed',1,0,0,0,0); \ No newline at end of file diff --git a/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.21-17.22.sql b/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.21-17.22.sql deleted file mode 100644 index 5b84fc4f2..000000000 --- a/ehr/resources/schemas/dbscripts/sqlserver/ehr-17.21-17.22.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE TABLE ehr.form_framework_types ( - RowId INT IDENTITY(1,1) NOT NULL, - - schemaname varchar(255) DEFAULT NULL, - queryname varchar(255) DEFAULT NULL, - framework varchar(255) DEFAULT NULL, - - Container ENTITYID NOT NULL, - CreatedBy USERID, - Created datetime, - ModifiedBy USERID, - Modified datetime, - - CONSTRAINT PK_form_framework_types PRIMARY KEY (schemaname, queryname) -); \ No newline at end of file diff --git a/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql b/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql index 2c96db671..a23fd9a12 100644 --- a/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql +++ b/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql @@ -1,7 +1,5 @@ ---ehr-17.20-17.21.sql script is getting skipped on teamcity, so adding the contents of this script below: - ---Merged script from conflicting ehr-12.425-12.426.sql scripts authored in different branches, trunk and modules15.2 - +--ehr-17.20-17.21.sql +-- contents of ehr-17.20-17.21.sql script are not in rolled up ehr-0.00-18.10.sql, since they got added and merged after the rollup, so including it below ALTER TABLE ehr.protocol ADD contacts VARCHAR(200); -- Merging upgrade scripts, ensure that we end up with rows for 'Started' in both tables @@ -17,8 +15,8 @@ INSERT INTO ehr.status VALUES ('Started', 'Record has started, but not completed',1,0,0,0,0); --- ehr-17.21-17.22.sql script is getting skipped on teamcity, so adding the contents of this script below: - +-- ehr-17.21-17.22.sql +-- contents of ehr-17.21-17.22.sql script are not in rolled up ehr-0.00-18.10.sql, since they got added and merged after the rollup, so including it below CREATE TABLE ehr.form_framework_types ( RowId INT IDENTITY(1,1) NOT NULL, diff --git a/ehr/resources/web/ehr/form/field/ProjectEntryField.js b/ehr/resources/web/ehr/form/field/ProjectEntryField.js index 4fdd2d9d0..7f52de79b 100644 --- a/ehr/resources/web/ehr/form/field/ProjectEntryField.js +++ b/ehr/resources/web/ehr/form/field/ProjectEntryField.js @@ -87,34 +87,8 @@ Ext4.define('EHR.form.field.ProjectEntryField', { win.close(); } - })], - validationDelay: 500, - //NOTE: unless i have this empty store an error is thrown - store: { - type: 'labkey-store', - schemaName: 'study', - sql: this.makeSql(), - sort: 'sort_order,project', - autoLoad: false, - loading: true, - listeners: { - scope: this, - delay: 50, - load: function(store){ - // allow for auto-select of the project, if not already selected, for quick data entry - if (this.autoSelectFirstProjectOnLoad && !this.getValue()) { - var storeProjects = Ext4.Array.filter(store.collect('project'), function(proj) { - return LABKEY.Utils.isNumber(proj); - }); - - if (storeProjects.length > 0) { - this.setValue(storeProjects[0]); - } - } - - this.resolveProjectFromStore(); - this.getPicker().refresh(); - } + else { + Ext4.Msg.alert('Error', 'Unknown Project'); } } },{ @@ -149,6 +123,14 @@ Ext4.define('EHR.form.field.ProjectEntryField', { scope: this, delay: 50, load: function(store){ + if (this.autoSelectFirstProjectOnLoad && !this.getValue()) { + var storeProjects = Ext4.Array.filter(store.collect('project'), function(proj) { + return LABKEY.Utils.isNumber(proj); + }); + if (storeProjects.length > 0) { + this.setValue(storeProjects[0]); + } + } this.resolveProjectFromStore(); this.getPicker().refresh(); } @@ -193,12 +175,16 @@ Ext4.define('EHR.form.field.ProjectEntryField', { this.fireEvent('projectchange', val); }, this, {buffer: 200}); - getInnerTpl: function(){ - return ['{[LABKEY.Utils.encodeHtml(values["displayName"] + " " + (values["shortname"] ? ("(" + values["shortname"] + ")") : (values["investigator"] ? "(" + (values["investigator"] ? values["investigator"] : "") : "") + (values["account"] ? ": " + values["account"] : "") + (values["investigator"] ? ")" : "")))]} ']; - }, + this.on('render', function(){ + Ext4.QuickTips.register({ + target: this.triggerEl.elements[0], + text: 'Click to recalculate allowable projects' + }); + }, this); + }, getInnerTpl: function(){ - return ['{[values["displayName"] + " " + (values["shortname"] ? ("(" + values["shortname"] + ")") : (values["investigator"] ? "(" + (values["investigator"] ? values["investigator"] : "") : "") + (values["account"] ? ": " + values["account"] : "") + (values["investigator"] ? ")" : ""))]} ']; + return ['{[LABKEY.Utils.encodeHtml(values["displayName"] + " " + (values["shortname"] ? ("(" + values["shortname"] + ")") : (values["investigator"] ? "(" + (values["investigator"] ? values["investigator"] : "") : "") + (values["account"] ? ": " + values["account"] : "") + (values["investigator"] ? ")" : "")))]} ']; }, trigger1Cls: 'x4-form-search-trigger', diff --git a/ehr/resources/web/ehr/metadata/Assay.js b/ehr/resources/web/ehr/metadata/Assay.js deleted file mode 100644 index cbdd000ac..000000000 --- a/ehr/resources/web/ehr/metadata/Assay.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2013-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -/** - * This is the default metadata applied to records in the context of an assay, which currently is used by the ClinPath task. - */ -EHR.Metadata.registerMetadata('Assay', { - allQueries: { - project: { -// parentConfig: { -// storeIdentifier: {queryName: 'Clinpath Runs', schemaName: 'study'}, -// recordIdentifier: function(parentRecord, childRecord){ -// console.log(parentRecord); -// console.log(childRecord); -// if(!childRecord || !parentRecord){ -// return; -// } -// if(childRecord.get('Id') && childRecord.get('Id') == parentRecord.get('Id')){ -// return true; -// } -// }, -// dataIndex: 'project' -// } - hidden: true - ,shownInGrid: false - } - ,account: { -// parentConfig: { -// storeIdentifier: {queryName: 'Clinpath Runs', schemaName: 'study'}, -// recordIdentifier: function(parentRecord, childRecord){ -// console.log(parentRecord); -// console.log(childRecord); -// if(!childRecord || !parentRecord){ -// return; -// } -// if(childRecord.get('Id') && childRecord.get('Id') == parentRecord.get('Id')){ -// return true; -// } -// }, -// dataIndex: 'account' -// } - hidden: true - ,shownInGrid: false - } - ,performedby: { - hidden: true - } -// ,serviceRequested: { -// xtype: 'displayfield' -// } - }, - byQuery: { - 'Clinpath Runs': { - parentid: { - parentConfig: false, - allowBlank: true - }, - Id: { - parentConfig: null, - hidden: false - }, - date: { - parentConfig: null, - hidden: false - }, - project: { - parentConfig: null, - hidden: false - }, - account: { - parentConfig: null, - hidden: false - } - } - } -}); \ No newline at end of file diff --git a/ehr/resources/web/ehr/metadata/Biopsy.js b/ehr/resources/web/ehr/metadata/Biopsy.js deleted file mode 100644 index 231c12d94..000000000 --- a/ehr/resources/web/ehr/metadata/Biopsy.js +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2013-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -/** - * This is the default metadata applied to records in the context of a biopsy task. Among other things, it configured a parent/child relationship - * between the study.biopsies record and other dataset records. It is similar to Encounter, except the parent record is from study.biopsies. - */ -EHR.Metadata.registerMetadata('Biopsy', { - allQueries: { - Id: { - parentConfig: { - storeIdentifier: {queryName: 'Biopsies', schemaName: 'study'}, - dataIndex: 'Id' - } - ,hidden: true - ,shownInGrid: false - } - ,date: { - parentConfig: { - storeIdentifier: {queryName: 'Biopsies', schemaName: 'study'}, - dataIndex: 'date' - } - ,hidden: true - ,shownInGrid: false - } - ,begindate: { - setInitialValue: function(v, rec){ - var field = rec.fields.get('begindate'); - var store = Ext.StoreMgr.get('study||Biopsies||||'); - if(store) - var record = store.getAt(0); - if(record) - var date = record.get('date'); - if(date) - date = new Date(date.getFullYear(), date.getMonth(), date.getDate()); - - return v || date; - } - ,hidden: false - ,allowBlank: false - } - ,parentid: { - parentConfig: { - storeIdentifier: {queryName: 'Biopsies', schemaName: 'study'}, - dataIndex: 'objectid' - } - ,hidden: true - ,shownInGrid: false - ,allowBlank: false - } - ,project: { - parentConfig: { - storeIdentifier: {queryName: 'Biopsies', schemaName: 'study'}, - dataIndex: 'project' - } - ,hidden: true - ,shownInGrid: false - } - ,account: { - parentConfig: { - storeIdentifier: {queryName: 'Biopsies', schemaName: 'study'}, - dataIndex: 'account' - } - ,hidden: true - ,shownInGrid: false - } - }, - byQuery: { - Biopsies: { - parentid: { - parentConfig: false, - allowBlank: true - }, - Id: { - parentConfig: null, - hidden: false - }, - date: { - parentConfig: null, - hidden: false - }, - project: { - parentConfig: null, - allowBlank: true, - hidden: false - }, - account: { - parentConfig: null, - allowBlank: false, - hidden: false - }, - title: { - parentConfig: { - storeIdentifier: {queryName: 'tasks', schemaName: 'ehr'} - ,dataIndex: 'title' - } - } - }, - tasks: { - duedate: { - parentConfig: { - storeIdentifier: {queryName: 'Biopsies', schemaName: 'study'}, - dataIndex: 'date' - } - ,hidden: true - ,shownInGrid: false - } - } - } -}); diff --git a/ehr/resources/web/ehr/metadata/Default.js b/ehr/resources/web/ehr/metadata/Default.js deleted file mode 100644 index 7e7203ea3..000000000 --- a/ehr/resources/web/ehr/metadata/Default.js +++ /dev/null @@ -1,2808 +0,0 @@ -/* - * Copyright (c) 2013-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -/** - * The default metadata applied to all queries when using getTableMetadata(). - * This is the default metadata applied to all queries when using getTableMetadata(). If adding attributes designed to be applied - * to a given query in all contexts, they should be added here - */ -EHR.Metadata.registerMetadata('Default', { - allQueries: { - fieldDefaults: { - //lazyCreateStore: false, - ignoreColWidths: true -// colModel: { -// showLink: false -// } - }, - Id: { - xtype: 'ehr-participant', - dataIndex: 'Id', - nullable: false, - allowBlank: false, - lookups: false, - colModel: { - width: 65 - ,showLink: false - } - //noDuplicateByDefault: true - }, - 'id/curlocation/location': { - hidden: true, - updateValueFromServer: true, - allowBlank: true, - nullable: true, - shownInGrid: true, - caption: 'Location', - header: 'Location', - lookups: false, - allowDuplicateValue: false, - colModel: { - width: 75, - showLink: false - } - } - ,'id/numroommates/cagemates': { - hidden: true, - updateValueFromServer: true, - allowBlank: true, - nullable: true, - shownInGrid: true, - caption: 'Animals In Cage', - header: 'Animals In Cage', - lookups: false, - allowDuplicateValue: false, - colModel: { - width: 120, - showLink: false - } - } - ,daterequested: { - xtype: 'xdatetime', - noDuplicateByDefault: true, - extFormat: LABKEY.extDefaultDateTimeFormat - } - ,date: { - allowBlank: false, - nullable: false, - //noDuplicateByDefault: true, - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - otherToNow: true, - timeFormat: 'H:i', - plugins: ['ehr-participantfield-events'] - }, - xtype: 'xdatetime', - colModel: { - fixed: true, - width: 130 - }, - setInitialValue: function(v, rec) - { - return v ? v : new Date() - } - } - ,room: { - editorConfig: {listWidth: 200} - } - ,testid: { - colModel: { - showLink: false - } - } - ,begindate: { - xtype: 'xdatetime', - hidden: true, - noSaveInTemplateByDefault: true, - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - }, - colModel: { - fixed: true, - width: 130 - } - } - ,restraint: { - shownInGrid: false, - editorConfig: { - listeners: { - change: function(field, val){ - var theForm = this.ownerCt.getForm(); - if(theForm){ - var restraintDuration = theForm.findField('restraintDuration'); - - if(val) - restraintDuration.setValue('<30 min'); - else - restraintDuration.setValue(null); - - restraintDuration.fireEvent('change', restraintDuration.getValue()) - } - } - } - } - } - ,restraintDuration: { - shownInGrid: false - ,lookup: { - sort: 'sort_order' - } - } - ,enddate: { - xtype: 'xdatetime', - shownInInsertView: true, - colModel: { - fixed: true, - width: 130 - }, - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - } - } - ,cage: { - editorConfig: { - listeners: { - change: function(field, val){ - if(val && !isNaN(val)){ - var newVal = EHR.Utils.padDigits(val, 4); - if(val != newVal) - field.setValue(newVal); - } - } - } - } - } - ,code: { - xtype: 'ehr-snomedcombo' - //,lookups: false - ,colModel: { - width: 150 - ,showLink: false - } -// ,getRenderer: function(col, meta){ -// return function(data, cellMetaData, record, rowIndex, colIndex, store) { -// var storeId = ['ehr_lookups', 'snomed', 'code', 'meaning', store.queryName, (meta.dataIndex || meta.name)].join('||'); -// var lookupStore = Ext.StoreMgr.get(storeId); -// -// if(!lookupStore) -// return ''; -// -// var idx = lookupStore.find('code', data); -// var lookupRecord; -// if(idx != -1) -// lookupRecord = lookupStore.getAt(idx); -// -// if (lookupRecord) -// return lookupRecord.data['meaning'] || lookupRecord.data['code/meaning']; -// else if (data) -// return "[" + data + "]"; -// else -// return meta.lookupNullCaption || "[none]"; -// } -// } - } - ,tissue: { - xtype: 'ehr-snomedcombo', - editorConfig: { - defaultSubset: 'Organ/Tissue' - }, - colModel: { - width: 150, - showLink: false - } - } - ,performedby: { - colModel: { - width: 65 - } - ,shownInGrid: false - } - ,userid: { - lookup: { - schemaName: 'core', - queryName: 'users', - displayColumn: 'name', - keyColumn: 'name', - sort: 'Email' - } - ,formEditorConfig:{readOnly: true} - ,editorConfig: {listWidth: 200} - ,defaultValue: LABKEY.Security.currentUser.displayName - ,shownInGrid: false - } - ,CreatedBy: { - hidden: false - ,shownInInsertView: true - ,xtype: 'displayfield' - ,shownInGrid: false - } - ,ModifiedBy: { - hidden: false - ,shownInInsertView: true - ,xtype: 'displayfield' - ,shownInGrid: false - } - ,AnimalVisit: {hidden: true} - //,CreatedBy: {hidden: true, shownInGrid: false} - //,ModifiedBy: {hidden: true, shownInGrid: false, useNull: true} - ,SequenceNum: {hidden: true} - ,description: {hidden: true} - ,Dataset: {hidden: true} - //,category: {hidden: true} - ,QCState: { - allowBlank: false, - noDuplicateByDefault: true, - allowDuplicateValue: false, - noSaveInTemplateByDefault: true, - setInitialValue: function(v){ - var qc; - if(!v && EHR.Security.getQCStateByLabel('In Progress')) - qc = EHR.Security.getQCStateByLabel('In Progress').RowId; - return v || qc; - }, - shownInGrid: false, - hidden: false, - editorConfig: { - editable: false, - listWidth: 200, - disabled: true - }, - colModel: { - width: 70 - } - } - ,parentid: { - hidden: true, - lookups: false - } - ,taskid: { - lookups: false, - hidden: true - } - ,requestid: { - lookups: false, - hidden: true - } - ,AgeAtTime: {hidden: true} - ,Notes: {hidden: true} - ,DateOnly: {hidden: true} - ,Survivorship: {hidden: true} - ,remark: { - xtype: 'ehr-remark', - isAutoExpandColumn: true, - printWidth: 150, - editorConfig: { - resizeDirections: 's' - } - } - ,so: { - xtype: 'ehr-remark', - isAutoExpandColumn: true, - printWidth: 150, - editorConfig: { - resizeDirections: 's' - } - } - ,a: { - xtype: 'ehr-remark', - isAutoExpandColumn: true, - printWidth: 150, - editorConfig: { - resizeDirections: 's' - } - } - ,p: { - xtype: 'ehr-remark', - isAutoExpandColumn: true, - printWidth: 150, - editorConfig: { - resizeDirections: 's' - } - } - ,project: { - xtype: 'ehr-project' - ,editorConfig: { - defaultProjects: [300901,400901] - } - ,shownInGrid: false - ,useNull: true - ,lookup: { - columns: 'project,account', - displayColumn: 'project' - } - } - ,account: { - shownInGrid: false - }, - performing_lab: { - lookup: { - schemaName: 'wnprc', - queryName: 'external_labs', - displayColumn: 'lab_name', - keyColumn: 'code', - sort: 'lab_name' - } - } - }, - byQuery: { - tasks: { - taskid: { - setInitialValue: function(v, rec) - { - v = v || this.importPanel.formUUID || LABKEY.Utils.generateUUID(); - this.importPanel.formUUID = v; - this.formUUID = v; - return v; - }, - parentConfig: false, - hidden: true - }, - //NOTE: the case is different on hard tables than studies. - //i tried to force hard tables to use QCState, but they kept reverting in odd places - qcstate: { - allowBlank: false, - allowDuplicateValue: false, - setInitialValue: function(v){ - var qc; - if(EHR.Security.getQCStateByLabel('In Progress')) - qc = EHR.Security.getQCStateByLabel('In Progress').RowId; - return v || qc; - }, - shownInGrid: false, - parentConfig: false, - hidden: false, - editorConfig: { - disabled: true, - editorConfig: {listWidth: 200} - } - }, - assignedto: { - useNull: true, - setInitialValue: function(val){ - return val || LABKEY.Security.currentUser.id - }, - lookup: { - sort: 'type,displayname' - }, - editorConfig: {listWidth: 200} - }, - duedate: { - xtype: 'xdatetime', - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - }, - setInitialValue: function(val){ - return val || new Date(); - } - }, - category: { - hidden: true - }, - rowid: { - xtype: 'displayfield' - }, - formtype: { - xtype: 'displayfield', - hidden: true, - setInitialValue: function(val, rec){ - return val || this.importPanel.formType; - } - }, - title: { - setInitialValue: function(val, rec){ - return val || this.importPanel.title || this.importPanel.formType; - } - } - }, - 'Final Reports': { - remark: { - height: 400, - width: 600 - } - }, - requests: { - requestid: { - setInitialValue: function(v, rec) - { - v = v || this.importPanel.formUUID || LABKEY.Utils.generateUUID(); - this.importPanel.formUUID = v; - this.formUUID = v; - return v; - }, - parentConfig: false, - hidden: true - }, - notify1: { - defaultValue: LABKEY.Security.currentUser.id, - lookup: { - sort: 'Type,DisplayName' - }, - listWidth: 250 - }, - notify2: { - lookup: { - sort: 'Type,DisplayName' - }, - listWidth: 250 - }, - notify3: { - lookup: { - sort: 'Type,DisplayName' - }, - listWidth: 250 - }, - daterequested: { - xtype: 'xdatetime', - hidden: true - }, - priority: { - defaultValue: 'Routine' - }, - rowid: { - xtype: 'displayfield' - }, - formtype: { - xtype: 'displayfield', - hidden: true, - setInitialValue: function(val, rec){ - return val || this.importPanel.formType; - } - }, - title: { - setInitialValue: function(val, rec){ - return val || this.importPanel.formType; - } - }, - //NOTE: the case is different on hard tables than studies. - //i tried to force hard tables to use QCState, but they kept reverting in odd places - qcstate: { - allowBlank: false, - setInitialValue: function(v){ - var qc; - if(!v && EHR.Security.getQCStateByLabel('In Progress')) - qc = EHR.Security.getQCStateByLabel('In Progress').RowId; - return v || qc; - }, - shownInGrid: false, - parentConfig: false, - hidden: false, - editorConfig: { - disabled: true - } - } - }, - 'Bacteriology Results': { - source: { - xtype: 'ehr-snomedcombo', - editorConfig: { - defaultSubset: 'Culture Source' - } - }, -// result: { -// xtype: 'ehr-snomedcombo', -// editorConfig: { -// defaultSubset: 'Bacteriology Results' -// } -// }, - organism: { - xtype: 'ehr-snomedcombo', - editorConfig: { - defaultSubset: 'Organisms' - } - }, - antibiotic: { - xtype: 'ehr-snomedcombo', - shownInGrid: false, - editorConfig: { - defaultSubset: 'Antibiotic' - } - }, - sensitivity: { - shownInGrid: false - }, - result: { - shownInGrid: false - }, - units: { - shownInGrid: false - }, - date: { - xtype: 'datefield' - ,extFormat: LABKEY.extDefaultDateFormat - }, - method: { - shownInGrid: false - }, - remark: { - shownInGrid: false - } - }, - Demographics: { - Id: { -// xtype: 'trigger' - allowBlank: false - ,editorConfig: { -// triggerClass: 'x-form-search-trigger', - allowAnyId: true -// ,onTriggerClick: function (){ -// var prefix = this.getValue(); -// -// if(!prefix){ -// Ext.Msg.alert('Error', "Must enter prefix"); -// return -// } -// var sql = "SELECT max(cast(regexp_replace(SUBSTRING(Id, "+(prefix.length+1)+", 6), '[a-z\-]+', '') as integer)) as maxNumber FROM study.Demographics WHERE Id LIKE '" + prefix + "%' AND lcase(SUBSTRING(Id, "+(prefix.length+1)+", 6)) = ucase(SUBSTRING(Id, "+(prefix.length+1)+", 6))"; -// -// LABKEY.Query.executeSql({ -// schemaName: 'study', -// sql: sql, -// scope: this, -// success: function(data){ -// var number; -// if(data.rows && data.rows.length==1){ -// number = Number(data.rows[0].maxNumber)+1; -// } -// else { -// console.log('no mstching IDs found'); -// number = 1; -// } -// -// number = EHR.Utils.padDigits(number, (6-prefix.length)); -// var id = prefix + number; -// this.setValue(id.toLowerCase()); -// }, -// failure: EHR.Utils.onError -// }); -// } - } - }, - project: {hidden: true}, - performedby: {hidden: true}, - account: {hidden: true}, - species: {allowBlank: false}, - gender: {allowBlank: false} - }, - 'Prenatal Deaths': { - conception: { - extFormat: LABKEY.extDefaultDateFormat - } - ,weight: { - useNull: true - ,editorConfig: { - allowNegative: false - ,decimalPrecision: 4 - } - } - ,Id: { - xtype: 'trigger', - editorConfig: { - triggerClass: 'x-form-search-trigger' - ,onTriggerClick: function (){ - var prefix = 'pd'; - var year = new Date().getFullYear().toString().slice(2); - var sql = "SELECT cast(SUBSTRING(MAX(id), 5, 6) AS INTEGER) as num FROM study.prenatal WHERE Id LIKE '" + prefix + year + "%'"; - LABKEY.Query.executeSql({ - schemaName: 'study', - sql: sql, - scope: this, - success: function(data){ - var caseno; - if(data.rows && data.rows.length==1){ - caseno = data.rows[0].num; - caseno++; - } - else { - //console.log('no existing IDs found'); - caseno = 1; - } - - caseno = EHR.Utils.padDigits(caseno, 2); - var val = prefix + year + caseno; - this.setValue(val); - this.fireEvent('change', val) - }, - failure: EHR.Utils.onError - }); - } - ,allowAnyId: true - } - } - ,sire: {lookups: false} - ,dam: { - lookups: false - ,allowBlank: false - } - ,project: {hidden: true} - ,performedby: {hidden: true} - ,account: {hidden: true} - ,room: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - }, - 'Parasitology Results': { - organism: { - xtype: 'ehr-snomedcombo', - editorConfig: { - defaultSubset: 'Parasitology Results' - } - } - ,date: { - xtype: 'datefield' - ,extFormat: LABKEY.extDefaultDateFormat - } - ,method: { - shownInGrid: false - } - ,remark: { - shownInGrid: false - } - }, - 'Tissue Samples': { - diagnosis: { - xtype: 'ehr-snomedcombo' - }, - performedby: { - hidden: true - }, - preservation: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - }, - qualifier: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - }, - shownInGrid: false - }, - quantity: { - shownInGrid: false - }, - ship_to : { - shownInGrid: false - }, - tissueRemarks : { - shownInGrid: false - }, - stain: { - defaultValue: 'Hematoxylin & Eosin', - editorConfig: { - plugins: ['ehr-usereditablecombo'] - }, - shownInGrid: false - }, - recipient: { - shownInGrid: false - }, - trimdate: { - shownInGrid: false - }, - trim_remarks: { - shownInGrid: false - }, - trimmed_by: { - shownInGrid: false - }, - remark: { - hidden: true - - }, - - container_type: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - }, - shownInGrid: false - } - }, - Histology: { - diagnosis: { - xtype: 'ehr-snomedcombo' - }, - slideNum: { -// setInitialValue: function(v, rec){ -// var idx = Ext.StoreMgr.get('study||Histology||||').getCount()+1; -// return v || idx; -// } - }, - performedby: { - hidden: true - }, - stain: { - defaultValue: 'Hematoxylin & Eosin', - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - }, - pathologist: { - shownInGrid: false - }, - pathology: { - shownInGrid: false - }, - trimdate: { - shownInGrid: false - }, - trim_remark: { - shownInGrid: false - }, - trimmed_by: { - shownInGrid: false - }, - qualifier: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - }, - Housing: { - date: { - editorConfig: { - allowNegative: false -// ,listeners: { -// change: function(field, val){ -// var form = this.ownerCt.getForm(); -// var rec = this.ownerCt.boundRecord; -// if(rec && rec.store){ -// -// } -// } -// } - } - } - ,objectid: { setInitialValue: function (v, rec){ - return v || LABKEY.Utils.generateUUID(); - }, - parentConfig:false, - hidden :true - } - ,enddate: { - //hidden: true - xtype: 'xdatetime', - extFormat: LABKEY.extDefaultDateTimeFormat, - shownInGrid: true - } - ,remark: { - shownInGrid: false - } - ,performedby: { - shownInGrid: false - //,allowBlank: false - } - ,cage: { - allowBlank: false - } - ,cond: { - allowBlank: false - ,shownInGrid: false - ,lookup:{ schemaName: 'ehr_lookups', queryName: 'housing_condition_codes', displayColumn: 'value', keyColumn: 'value'} - } - ,reason: { - shownInGrid: false, - lookup:{ - filterArray: [LABKEY.Filter.create('date_disabled', null, LABKEY.Filter.Types.ISBLANK)] - } - } - ,restraintType: { - shownInGrid: false - } - ,cagesJoined: { - shownInGrid: false - } - ,isTemp: { - shownInGrid: false - } - ,project: { - hidden: true - } - ,room: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - }, - 'Clinical Encounters': { - objectid: { - setInitialValue: function(v, rec) - { - return v || LABKEY.Utils.generateUUID(); - } - } - ,serviceRequested: { - xtype: 'displayfield' - ,editorConfig: { - height: 100 - } - } - ,performedby: { - allowBlank: false - } - ,type: { - allowBlank: false - } - }, - 'Clinical Remarks': { - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.displayName - }, - remark: { - hidden: true - }, - date: { - setInitialValue: function(v, rec) - { - return v ? v : (new Date((new Date().toDateString()))); - } - ,noDuplicateByDefault: false - }, - account: { - hidden: true - }, - so: { - shownInGrid: false, - //width: 300, - height: 150 - }, - a: { - shownInGrid: false, - height: 150 - }, - p: { - shownInGrid: false, - height: 150 - } -// userid: { -// defaultValue: LABKEY.Security.currentUser.displayName -// } - - }, - 'Clinpath Runs': { - date: { - xtype: 'xdatetime', - //xtype: 'datefield', - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - } - //extFormat: 'Y-m-d' - }, - collectionMethod : { - shownInGrid: false - }, - sampleType : { - //shownInGrid: false - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - }, - sampleId : {shownInGrid: false}, - sampleQuantity: {shownInGrid: false}, - quantityUnits : {shownInGrid: false}, - servicerequested: { - allowBlank: false, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - theForm.findField('type').setValue(rec.get('dataset')); - } - } - }, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'filtered_labwork_services', - displayColumn: 'servicename', - keyColumn: 'servicename', - sort: 'servicename', - columns: '*' - } - }, - project: { - allowBlank: true, - nullable: true - }, - account: { - allowBlank: false - }, - source: { - xtype: 'ehr-snomedcombo', - editorConfig: { - defaultSubset: 'Organisms' - } - }, - type: { - showInGrid: false, - updateValueFromServer: true, - xtype: 'displayfield' - }, - objectid: { - setInitialValue: function(v, rec) - { - return v || LABKEY.Utils.generateUUID(); - } - } - }, - 'Dental Status': { - gingivitis: {allowBlank: false, includeNullRecord: false}, - tartar: {allowBlank: false, includeNullRecord: false}, - performedby: { - hidden: true - } - }, - 'Treatment Orders': { - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat, - allowBlank: false, - setInitialValue: function(v, rec) - { - return v ? v : new Date() - }, - colModel: { - //fixed: true, - width: 100 - }, - shownInGrid: true - } - ,enddate: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat, - colModel: { - //fixed: true, - width: 100 - } - //shownInGrid: false - } - ,project: { - allowBlank: false - } - ,CurrentRoom: {lookups: false} - ,CurrentCage: {lookups: false} - ,volume: { - compositeField: 'Volume', - xtype: 'ehr-triggernumberfield', - noDuplicateByDefault: true, - noSaveInTemplateByDefault: true, - editorConfig: { - triggerClass: 'x-form-search-trigger' - ,onTriggerClick: function (){ - //recalculate amount if needed: - var theForm = this.findParentByType('ehr-formpanel').getForm(); - var conc = theForm.findField('concentration').getValue(); - var val = this.getValue(); - - if(!val || !conc){ - alert('Must supply volume and concentration'); - return; - } - - if(val && conc){ - var amount = conc * val; - var amountField = theForm.findField('amount'); - amountField.setValue(amount); - amountField.fireEvent('change', amount, amountField.startValue); - } - } - ,decimalPrecision: 3 - }, - header: 'Vol', - colModel: { - width: 50 - } - } - ,vol_units: { - compositeField: 'Volume', -// editorConfig: { -// fieldLabel: null -// } - header: 'Vol Units', - colModel: { - width: 50 - } - } - ,concentration: { - shownInGrid: false, - compositeField: 'Drug Conc', - editorConfig: { - decimalPrecision: 10 - } - } - ,conc_units: { - shownInGrid: false - ,lookup: {columns: '*'} - ,compositeField: 'Drug Conc' - ,editorConfig: { - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - theForm.findField('amount_units').setValue(rec.get('numerator')); - theForm.findField('conc_units').setValue(rec.get('unit')); - theForm.findField('vol_units').setValue(rec.get('denominator')); - - var doseField = theForm.findField('dosage_units'); - if(rec.get('numerator')) - doseField.setValue(rec.get('numerator')+'/kg'); - else - doseField.setValue(''); - - doseField.fireEvent('change', doseField.getValue(), doseField.startValue); - - } - } - } - } - ,amount: { - compositeField: 'Amount' - ,noDuplicateByDefault: true - ,noSaveInTemplateByDefault: true - //,allowBlank: false - ,shownInGrid: false - ,colModel: { - width: 40 - } - ,editorConfig: { - decimalPrecision: 3 - } - } - ,amount_units: { - shownInGrid: false - ,compositeField: 'Amount' - ,colModel: { - width: 70 - } - } - ,route: {shownInGrid: false} - ,frequency: { - allowBlank: false - ,lookup: { - sort: 'sort_order' - ,columns: '*' - - } - } - ,dosage: { - xtype: 'ehr-drugdosefield', - shownInGrid: false, - compositeField: 'Dosage', - editorConfig: { - decimalPrecision: 3 - } - } - ,dosage_units: { - shownInGrid: false, - compositeField: 'Dosage' - } - ,code: { - //shownInGrid: false, - editorConfig: { - defaultSubset: 'Drugs and Procedures' - } - } - ,qualifier: { - shownInGrid: false - } - ,meaning: { - shownInGrid: false, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'treatment_codes', - displayColumn: 'meaning', - keyColumn: 'meaning', - sort: 'category,meaning', - columns: '*' - } - ,editorConfig: { - tpl : function() - { - var tpl = new Ext.XTemplate( - '' + - '
{[ values["category"] ? ""+values["category"]+": " : "" ]}{[ values["meaning"] ]}' + - ' 
' - ); - return tpl.compile() - }(), - listeners: { - select: function(combo, rec){ - var theForm = this.findParentByType('ehr-formpanel').getForm(); - - theForm.findField('route').setValue(rec.get('route')); - theForm.findField('qualifier').setValue(rec.get('qualifier')); - theForm.findField('code').setValue(rec.get('code')); - theForm.findField('frequency').setValue(rec.get('frequency')); - - theForm.findField('amount_units').setValue(rec.get('amount_units')); - theForm.findField('conc_units').setValue(rec.get('conc_units')); - theForm.findField('vol_units').setValue(rec.get('vol_units')); - theForm.findField('dosage_units').setValue(rec.get('dosage_units')); - - theForm.findField('amount').setValue(rec.get('amount')); - theForm.findField('concentration').setValue(rec.get('concentration')); - theForm.findField('volume').setValue(rec.get('volume')); - - var doseField = theForm.findField('dosage'); - doseField.setValue(rec.get('dosage')); - doseField.fireEvent('change', doseField.getValue(), doseField.startValue); - } - } - } - } - ,remark: { - shownInGrid: false - } - ,performedby: { - defaultValue: LABKEY.Security.currentUser.displayName - } - }, - Project: { - project: { - xtype: 'textfield', - lookups: false - } - }, - Assignment: { - project: { - shownInGrid: true, - allowBlank: false, - xtype: 'combo', - lookup: { - filterArray: [LABKEY.Filter.create('protocol/protocol', null, LABKEY.Filter.Types.NONBLANK)], - columns: 'project,protocol,account', - displayColumn: 'project' - - }, - editorConfig: { - plugins: ['ehr-participantfield-events'] - } - }, - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - }, - enddate: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - } - }, - Necropsies: { - remark: { - height: 200, - width: 600 - }, -// perfusion_soln1: { -//// xtype: 'lovcombo', -// editorConfig: { -// plugins: ['ehr-usereditablecombo'] -// }, -// lookup: { -// schemaName: 'ehr_lookups', -// queryName: 'necropsy_perfusion', -// keyColumn: 'perfusion', -// displayColumn: 'perfusion' -// } -// }, -// perfusion_soln2: { -//// xtype: 'lovcombo', -// editorConfig: { -// plugins: ['ehr-usereditablecombo'] -// }, -// lookup: { -// schemaName: 'ehr_lookups', -// queryName: 'necropsy_perfusion', -// keyColumn: 'perfusion', -// displayColumn: 'perfusion' -// } -// }, -// perfusion_time1: { -// xtype: 'xdatetime', -// extFormat: 'Y-m-d H:i', -// editorConfig: { -// dateFormat: 'Y-m-d', -// timeFormat: 'H:i' -// } -// }, -// perfusion_time2: { -// xtype: 'xdatetime', -// extFormat: 'Y-m-d H:i', -// editorConfig: { -// dateFormat: 'Y-m-d', -// timeFormat: 'H:i' -// } -// }, - timeofdeath: { - xtype: 'xdatetime', - extFormat: LABKEY.extDefaultDateTimeFormat, - allowBlank: false, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - } - }, - tissue_distribution: { - xtype: 'lovcombo', - hasOwnTpl: true, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'tissue_distribution', - displayColumn: 'value', - keyColumn: 'value' - } - }, - grossdescription: { - height: 200, - width: 600, - defaultValue: 'A ___ kg rhesus macaque is presented for necropsy in excellent post mortem condition.\n\nA ___ kg cynomolgus macaque is presented for necropsy in excellent post mortem condition.\n\nA ___ kg common marmoset is presented for necropsy in excellent post mortem condition.\n\nA ____ kg cynomolgus macaque is presented for perfusion and necropsy in excellent post mortem condition.\n\nA ____ kg rhesus macaque is presented for perfusion and necropsy in excellent post mortem condition.' - }, - histologicalDescription: { - height: 200, - width: 600 - }, - patho_notes: { - height: 200, - width: 600 - }, - caseno: { - xtype: 'trigger' - ,allowBlank: false - ,editorConfig: { - triggerClass: 'x-form-search-trigger' - ,onTriggerClick: function(){ - var theWin = new Ext.Window({ - layout: 'form' - ,title: 'Case Number' - ,bodyBorder: true - ,border: true - ,theField: this - //,frame: true - ,bodyStyle: 'padding:5px' - ,width: 350 - ,defaults: { - width: 200, - border: false, - bodyBorder: false - } - ,items: [ - { - xtype: 'textfield', - ref: 'prefix', - fieldLabel: 'Prefix', - allowBlank: false, - value: 'c' - },{ - xtype: 'numberfield', - ref: 'year', - fieldLabel: 'Year', - allowBlank: false, - value: (new Date()).getFullYear() - } - ], - buttons: [{ - text:'Submit', - disabled:false, - ref: '../submit', - //scope: this, - handler: function(p){ - getCaseNo(p.ownerCt.ownerCt); - this.ownerCt.ownerCt.hide(); - } - },{ - text: 'Close', - //scope: this, - handler: function(){ - this.ownerCt.ownerCt.hide(); - } - }] - }); - theWin.show(); - - function getCaseNo(panel){ - var year = panel.year.getValue(); - var prefix = panel.prefix.getValue(); - - if(!year || !prefix){ - Ext.Msg.alert('Error', "Must supply both year and prefix"); - return - } - - LABKEY.Query.executeSql({ - schemaName: 'study', - sql: "SELECT cast(SUBSTRING(MAX(caseno), 6, 8) AS INTEGER) as caseno FROM study.Necropsies WHERE caseno LIKE '" + year + prefix + "%'", - scope: this, - success: function(data){ - var caseno; - if(data.rows && data.rows.length==1){ - caseno = data.rows[0].caseno; - caseno++; - } - else { - console.log('no existing cases found'); - caseno = 1; - } - - caseno = EHR.Utils.padDigits(caseno, 3); - var val = year + prefix + caseno; - panel.theField.setValue(val); - panel.theField.fireEvent('change', val) - }, - failure: EHR.Utils.onError - }); - }; - } - } - }, - /*contact_person: { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'PrincipalInvestigators', - displayColumn: 'UserId', - keyColumn: 'UserId' - } - },*/ - performedby: { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'pathologists', - displayColumn: 'UserId', - keyColumn: 'UserId' - } - }, - assistant: { - xtype: 'lovcombo', - hasOwnTpl: true, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'pathologists', - displayColumn: 'UserId', - keyColumn: 'UserId' - } - }, - objectid: { - setInitialValue: function(v, rec) - { - return v || LABKEY.Utils.generateUUID(); - } - }, - causeofdeath: { - allowBlank: false - } - }, - Biopsies: { - remark: { - height: 200, - width: 600 - }, - grossdescription: { - height: 200, - width: 600 - }, - histologicalDescription: { - height: 200, - width: 600 - }, - patho_notes: { - height: 200, - width: 600 - }, - caseno: { - xtype: 'trigger' - ,allowBlank: false - ,editorConfig: { - triggerClass: 'x-form-search-trigger' - ,onTriggerClick: function(){ - var theWin = new Ext.Window({ - layout: 'form' - ,title: 'Case Number' - ,bodyBorder: true - ,border: true - ,theField: this - //,frame: true - ,bodyStyle: 'padding:5px' - ,width: 350 - ,defaults: { - width: 200, - border: false, - bodyBorder: false - } - ,items: [ - { - xtype: 'textfield', - ref: 'prefix', - fieldLabel: 'Prefix', - allowBlank: false, - value: 'b' - },{ - xtype: 'numberfield', - ref: 'year', - fieldLabel: 'Year', - allowBlank: false, - value: (new Date()).getFullYear() - } - ], - buttons: [{ - text:'Submit', - disabled:false, - ref: '../submit', - //scope: this, - handler: function(p){ - getCaseNo(p.ownerCt.ownerCt); - this.ownerCt.ownerCt.hide(); - } - },{ - text: 'Close', - //scope: this, - handler: function(){ - this.ownerCt.ownerCt.hide(); - } - }] - }); - theWin.show(); - - function getCaseNo(panel){ - var year = panel.year.getValue(); - var prefix = panel.prefix.getValue(); - - if(!year || !prefix){ - Ext.Msg.alert('Error', "Must supply both year and prefix"); - return - } - - LABKEY.Query.executeSql({ - schemaName: 'study', - sql: "SELECT cast(SUBSTRING(MAX(caseno), 6, 8) AS INTEGER) as caseno FROM study.biopsies WHERE caseno LIKE '" + year + prefix + "%'", - scope: this, - success: function(data){ - var caseno; - if(data.rows && data.rows.length==1){ - caseno = data.rows[0].caseno; - caseno++; - } - else { - console.log('no existing cases found'); - caseno = 1; - } - - caseno = EHR.Utils.padDigits(caseno, 3); - var val = year + prefix + caseno; - panel.theField.setValue(val); - panel.theField.fireEvent('change', val) - }, - failure: EHR.Utils.onError - }); - }; - } - } - }, - performedby: { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'pathologists', - displayColumn: 'UserId', - keyColumn: 'UserId' - } - }, - objectid: { - setInitialValue: function(v, rec) - { - return v || LABKEY.Utils.generateUUID(); - } - } - }, - 'Morphologic Diagnosis': { - duration: { - xtype: 'lovcombo', - shownInGrid: false, - hasOwnTpl: true, - lookup: { - schemaName:'ehr_lookups', - queryName:'durationSnomed', - displayColumn:'durationVal', - keyColumn:'durationVal' - }, - editorConfig: { - tpl:null, - separator: '!' - } - }, - severity: { - xtype: 'lovcombo', - shownInGrid: false, - hasOwnTpl: true, - lookup: { - schemaName:'ehr_lookups', - queryName:'severitySnomed', - displayColumn:'severityVal', - keyColumn:'severityVal' - }, - editorConfig: { - tpl:null, - separator: '!' - } - }, - etiology: { - xtype: 'lovcombo', - hasOwnTpl: true, - includeNullRecord: false, - shownInGrid: false, - lookup: { - schemaName:'ehr_lookups', - queryName: 'etiologySnomed', - displayColumn:'etiologyVal', - keyColumn:'etiologyVal' - }, - editorConfig: { - tpl:null, - separator: '!' - } - - }, - distribution2: { - xtype: 'ehr-snomedcombo', - shownInGrid: false, - editorConfig: { - defaultSubset: 'Distribution' - } - }, - inflammation: { - xtype: 'lovcombo', - hasOwnTpl: true, - shownInGrid: false, - lookup: { - schemaName:'ehr_lookups', - queryName: 'inflammationSnomed', - displayColumn:'inflammationVal', - keyColumn:'inflammationVal' - }, - editorConfig: { - tpl:null, - separator: '!' - } - }, - inflammation2: { - xtype: 'ehr-snomedcombo', - shownInGrid: false, - editorConfig: { - defaultSubset: 'Inflammation' - } - }, - distribution: { - xtype: 'lovcombo', - shownInGrid: false, - hasOwnTpl: true, - lookup : { - schemaName:'ehr_lookups', - queryName:'distributionSnomed', - displayColumn:'distributionVal', - keyColumn:'distributionVal' - }, - editorConfig: { - tpl:null, - separator: '!' - } - }, - process: { - xtype: 'lovcombo', - shownInGrid: false, - hasOwnTpl: true, - lookup : { - schemaName:'ehr_lookups', - queryName: 'processSnomed', - displayColumn:'processVal', - keyColumn:'processVal' - }, - editorConfig: { - tpl:null, - separator: '!' - } - }, - process2: { - xtype: 'ehr-snomedcombo', - editorConfig: { - defaultSubset: 'Process/Disorder' - } - }, - performedby: { - hidden: true - }, - remark: { - shownInGrid: true - }, - tissue_qualifier: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - }, - 'Organ Weights': { - performedby: { - hidden: true - }, - qualifier: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - }, - weight: { - allowBlank: false, - editorConfig: { - decimalPrecision: 3 - } - } - }, - 'Body Condition': { - performedby: {hidden: true}, - weightStatus: { - xtype: 'ehr-booleancombo', - defaultValue: false -// setInitialValue: function(v){ -// return v || false; -// } - }, - score:{lookup:{ schemaName: 'ehr_lookups', queryName: 'bcs_score', displayColumn: 'value', keyColumn: 'value'}} - }, - Alopecia: { - head: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - dorsum: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - rump: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - shoulders: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - upperArms: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - lowerArms: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - hips: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - upperLegs: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - lowerLegs: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - other: {xtype: 'ehr-remoteradiogroup', includeNullRecord: false, defaultValue: 'No', formEditorConfig: {columns: 3}}, - score: {lookupNullCaption: '', useNull: true, editorConfig: {useNull: true}}, - performedby: {hidden: true} - }, - Restraint: { -// enddate: { -// hidden: true -// }, - type: { - formEditorConfig: {xtype: 'ehr-remoteradiogroup', columns: 2}, - defaultValue: '' - } - }, - cage_observations: { - date: { - parentConfig: false, - hidden: false, - allowBlank: false, - setInitialValue: function(v, rec) - { - return v ? v : new Date() - } - }, - remark: { - allowBlank: true, - formEditorConfig: { - storeCfg: { - schemaName: 'ehr_lookups', - queryName: 'obs_remarks', - valueField: 'description', - displayField: 'value' - } - } - }, - feces: { - shownInGrid: true, - xtype: 'ehr-remotecheckboxgroup', includeNullRecord: false, - formEditorConfig: {columns: 1}, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_feces', displayColumn: 'title', keyColumn: 'value'} - }, - no_observations: { - shownInGrid: false, - formEditorConfig: { - listeners: { - check: function(field, val){ - var theForm = this.ownerCt.getForm(); - if(theForm){ - var rfield = theForm.findField('remark'); - - if(val) - rfield.setValue('ok'); - else if (rfield.getValue()=='ok') - rfield.setValue(''); - - theForm.findField('feces').setValue(); - } - } - } - } - } - }, - Charges: { - type: { - includeNullRecord: false, - allowBlank: false, - lookup: { - columns: 'category,description,cost', - sort: 'category,description', - displayColumn: 'description' - }, - editorConfig: { - tpl : function() - { - var tpl = new Ext.XTemplate( - '' + - '
{[ values["category"] ? ""+values["category"]+": " : "" ]}{[ values["description"] ]}' + - ' 
' - ); - return tpl.compile() - }(), - listeners: { - select: function(combo, rec) - { - var theForm = this.ownerCt.getForm(); - if(theForm){ - theForm.findField('unitCost').setValue(rec.get('cost')); - } - } - } - } - - }, - unitCost: { - xtype: 'displayfield' - }, - quantity: { - allowBlank: false, - defaultValue: 1 - }, - performedby: { - hidden: true - }, - remark: { - shownInGrid: false - }, - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - } - }, - 'Chemistry Results': { - resultOORIndicator: { - label: 'Result', - shownInGrid: false, - compositeField: 'Result', - width: 80, - includeNullRecord: false, - nullCaption: '', - lookup: { - schemaName: 'ehr_lookups', - queryName: 'oor_indicators', - keyColumn: 'indicator', - displayColumn: 'indicator' - } - } - ,result: { - compositeField: 'Result', - editorConfig: { - decimalPrecision: 4 - } - } - ,testid: { - lookup: { - columns: '*', - displayColumn: 'testid', - filterArray: [LABKEY.Filter.create('categories', 'chemistry', LABKEY.Filter.Types.CONTAINS)] - - }, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - var unitField = theForm.findField('units'); - unitField.setValue(rec.get('units')); - unitField.fireEvent('change', unitField.getValue(), unitField.startValue); - } - } - } - } - ,date: { - xtype: 'xdatetime', - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - /* listeners: { - click: function(){ - console.log ('testing chemitry date'); - } - }*/ - } - //setValue: null - //defaultValue: 1 - //,extFormat: 'Y-m-d' - } - ,method: { - shownInGrid: false - } - ,remark: { - shownInGrid: false - } - }, - 'Cytology Automated Evaluation': { - sampleType: { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'clinpath_sampletype', - keyColumn: 'value', - displayColumn: 'value' - }, - editorConfig: { - tpl: null, - plugins: ['ehr-usereditablecombo'] - - } - }, - collectionMethod: { - lookup : { - schemaName: 'ehr_lookups', - queryName: 'clinpath_collection_method', - keyColumn: 'value', - displayColumn: 'value' - }, - editorConfig: { - tpl: null, - plugins: ['ehr-usereditablecombo'] - } - }, - testid: { - lookup: { - schemaName: 'ehr_lookups', - query_Name: 'cytology_tests', - keyColumn: 'testid', - displayColumn: 'testid', - unitColumn: 'units' - - }, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-panel').getForm(); - var unitField = theForm.findField('units'); - unitField.setValue(rec.get('units')); - unitField.fireEvent('change', unitField.getValue(), unitField.startValue); - } - } - } - }, - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - }, - remark: { - shownInGrid: false - } - }, - 'Cytology Manual Evaluation': { - - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - }, - sampleType: { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'clinpath_sampletype', - keyColumn: 'value', - displayColumn: 'value' - }, - editorConfig: { - tpl: null, - plugins: ['ehr-usereditablecombo'] - - } - }, - collectionMethod: { - lookup : { - schemaName: 'ehr_lookups', - queryName: 'clinpath_collection_method', - keyColumn: 'value', - displayColumn: 'value' - }, - editorConfig: { - tpl: null, - plugins: ['ehr-usereditablecombo'] - } - }, - sampleAppearance: { - showInGrid: false - }, - stainType: { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'stain_types', - keyColumn: 'value', - displayColumn: 'value' - }, - editorConfig: { - tpl: null, - plugins: ['ehr-usereditablecombo'] - } - }, - slidesMade: { - showInGrid: false - }, - slidesSubmitted: { - showInGrid: false - }, - results: { - showInGrid: false - } - - }, - 'Immunology Results': { - testid: { - lookup: { - columns: '*', - filterArray: [LABKEY.Filter.create('categories', 'immunology', LABKEY.Filter.Types.CONTAINS)] - }, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - var unitField = theForm.findField('units'); - unitField.setValue(rec.get('units')); - unitField.fireEvent('change', unitField.getValue(), unitField.startValue); - } - } - } - } - ,date: { - xtype: 'datefield' - ,extFormat: LABKEY.extDefaultDateFormat - } - ,method: { - shownInGrid: false - } - ,remark: { - shownInGrid: false - } - }, - 'Hematology Results': { - testid: { - lookup: { - columns: '*', - displayColumn: 'testid', - filterArray: [LABKEY.Filter.create('categories', 'hematology', LABKEY.Filter.Types.CONTAINS)] - }, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - var unitField = theForm.findField('units'); - unitField.setValue(rec.get('units')); - unitField.fireEvent('change', unitField.getValue(), unitField.startValue); - } - } - } - } - ,date: { - xtype: 'xdatetime', - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i', - defaultValue: '00:00' - } - //defaultValue: null - //,extFormat: 'Y-m-d' - } - ,method: { - shownInGrid: false - } - ,remark: { - shownInGrid: false - } - }, - 'Urinalysis Results': { - resultOORIndicator: { - label: 'Result', - shownInGrid: false, - compositeField: 'Result', - width: 80, - includeNullRecord: false, - nullCaption: '', - lookup: { - schemaName: 'ehr_lookups', - queryName: 'oor_indicators', - keyColumn: 'indicator', - displayColumn: 'indicator' - } - } - ,result: { - compositeField: 'Result' - ,editorConfig: { - decimalPrecision: 4 - } - } - ,testid: { - lookup: { - columns: '*', - filterArray: [LABKEY.Filter.create('categories', 'urinalysis', LABKEY.Filter.Types.CONTAINS)], - displayColumn: 'testid', - keyColumn: 'testid' - }, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - var unitField = theForm.findField('units'); - unitField.setValue(rec.get('units')); - unitField.fireEvent('change', unitField.getValue(), unitField.startValue); - } - } - } - } - ,date: { - xtype: 'datefield' - ,extFormat: LABKEY.extDefaultDateFormat - } - ,method: { - shownInGrid: false - } - ,remark: { - shownInGrid: false - } - }, - 'Virology Results': { - date: { - xtype: 'datefield' - ,extFormat: LABKEY.extDefaultDateFormat - }, - virus: { - lookup: {schemaName: 'ehr_lookups', queryName: 'virology_tests', displayColumn: 'testid', keyColumn: 'testid'} - }, - method: { - shownInGrid: false - }, - remark: { - shownInGrid: false - } - }, - 'Hematology Morphology': { - date: { - xtype: 'xdatetime', - extFormat: LABKEY.extDefaultDateTimeFormat, - editorConfig: { - dateFormat: LABKEY.extDefaultDateFormat, - timeFormat: 'H:i' - // defaultValue: '00:00' - } - //xtype: 'datefield' - //,extFormat: 'Y-m-d' - } - }, - 'Irregular Observations': { - RoomAtTime: {hidden: true} - ,date: { - editorConfig: { - minValue: new Date(), - dateConfig: { - minValue: new Date() - } - } - } - ,CageAtTime: { - hidden: true, - editorConfig: { - listeners: { - change: function(field, val){ - if(val && !isNaN(val)){ - var newVal = EHR.Utils.padDigits(val, 4); - if(val != newVal) - field.setValue(newVal); - } - } - } - } - } - ,feces: { - shownInGrid: true, - xtype: 'ehr-remotecheckboxgroup', includeNullRecord: false, - formEditorConfig: {columns: 1}, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_feces', displayColumn: 'title', keyColumn: 'value'} - } - ,menses: { - shownInGrid: true, - xtype: 'ehr-remoteradiogroup', - defaultValue: null, - value: null, - includeNullRecord: true, - formEditorConfig: {columns: 1}, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_mens', displayColumn: 'title', keyColumn: 'value'} - } - ,other: { - shownInGrid: true, - xtype: 'ehr-remotecheckboxgroup', - includeNullRecord: false, - formEditorConfig: {columns: 1}, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_other', displayColumn: 'title', keyColumn: 'value'} - } - ,tlocation: { - shownInGrid: false, - xtype: 'lovcombo', - hasOwnTpl: true, - includeNullRecord: false, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_tlocation', displayColumn: 'value', keyColumn: 'value', sort: 'sort_order'}, - editorConfig: { - tpl: null -// height: 200 - } - } - ,breeding: { - shownInGrid: false, - xtype: 'ehr-remotecheckboxgroup', - includeNullRecord: false, - formEditorConfig: {columns: 1}, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_breeding', displayColumn: 'title', keyColumn: 'value'} - } - ,project: {hidden: true} - ,account: {hidden: true} - ,performedby: { - allowBlank: true, - hidden: false, - defaultValue: LABKEY.Security.currentUser.displayName - } - ,remark: { - shownInGrid: false, - formEditorConfig: { - storeCfg: { - schemaName: 'ehr_lookups', - queryName: 'obs_remarks', - valueField: 'description', - displayField: 'value' - } - } - } - ,behavior: { - shownInGrid: false, - xtype: 'ehr-remotecheckboxgroup', - includeNullRecord: false, - formEditorConfig: {columns: 1}, - lookup: {schemaName: 'ehr_lookups', queryName: 'obs_behavior', displayColumn: 'title', keyColumn: 'value'} - } - ,otherbehavior: {shownInGrid: false} -// ,certified: { -// xtype: 'ehr-approveradio', -// isAutoExpandColumn: true, -// colModel: { -// width: 30 -// }, -// //we allow either true or null, so it works with client-side 'allowBlank' -// convert: function(v){ -// return (v===true ? true : null); -// }, -// allowDuplicateValue: false -// } - }, -// 'Clinpath Requests': { -// dateCompleted: {hidden: true} -// ,status: {hidden: true} -// ,requestor: {defaultValue: LABKEY.Security.currentUser.email} -// ,notify1: {shownInGrid: false} -// ,notify2: {shownInGrid: false} -// -// }, - Menses: { - performedby: {hidden: true}, - project: {hidden: true}, - account: {hidden: true}, - interval: {hidden: true} - }, - 'Pair Tests': { - performedby: {hidden: true}, - project: {hidden: true}, - account: {hidden: true} - }, - 'Behavior Remarks': { - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.displayName - }, - project: {hidden: true}, - account: {hidden: true}, - remark: { - hidden: true - }, - so: { - shownInGrid: false - }, - a: { - shownInGrid: false - }, - p: { - shownInGrid: false - } - /* behatype :{ - xtype: 'ehr-behaviorcombo', - editorConfig: { - defaultSubset: 'SIB' - }, - colModel: { - width: 150, - showLink: false - } - - }*/ - /*category : { - lookup: { - schemaName: 'ehr_lookups', - queryName: 'behavior_category', - keyColumn: 'value', - displayColumn: 'value' - }, - editorConfig: { - tpl: null, - plugins: ['ehr-usereditablecombo'] - } - }*/ - }, - Arrival: { - Id: { - editorConfig: {allowAnyId: true} - }, - project: {hidden: true}, - account: {hidden: true}, - source: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - }, - allowBlank: false - }, - performedby: {hidden: true}, - remark: {shownInGrid: false}, - dam: {shownInGrid: false}, - sire: {shownInGrid: false}, - initialRoom: { - hidden: false, - allowBlank: false - }, - initialCage: { - hidden: false, - allowBlank: false, - editorConfig: { - listeners: { - change: function(field, val){ - if(val && !isNaN(val)){ - var newVal = EHR.Utils.padDigits(val, 4); - if(val != newVal) - field.setValue(newVal); - } - } - } - } - }, - initialCond: {hidden: false} - }, - Departure: { - performedby: {hidden: true}, - project: {hidden: true}, - account: {hidden: true}, - authorized_by: {allowBlank: false}, - destination: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - }, - allowBlank: false - } - }, - Vitals: { - performedby: {hidden: true} - }, - Teeth: { - performedby: {hidden: true}, - tooth: { - lookup: { - columns: '*', - sort: 'sort_order' - } - } - }, - Deaths: { - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.displayName - }, - project: { - hidden: false, - allowBlank: false - }, - account: {hidden: true}, - necropsy: {lookups: false}, - cause: {allowBlank: false}, - gender: {includeNullRecord: false, allowBlank: false}, - tattoo: { - editorConfig: { - helpPopup: 'Please enter the color and number of the tag and/or all visible tattoos' - } - } - //manner: {allowBlank: false} - }, - 'Error Reports': { - performedby: {hidden: true}, - project: {hidden: true}, - account: {hidden: true} - }, - Birth: { - performedby: {hidden: true}, - project: {hidden: true}, - account: {hidden: true}, - dam: {shownInGrid: false, lookups: false}, - sire: {shownInGrid: false, lookups: false}, - gender: {includeNullRecord: false, allowBlank: false}, - weight: {shownInGrid: false ,editorConfig: { forcePrecision: true, decimalPrecision : 3 }}, - wdate: {shownInGrid: false}, - room: {shownInGrid: false}, - cage: {shownInGrid: false}, - cond: { - shownInGrid: false - ,lookup:{ schemaName: 'ehr_lookups', queryName: 'housing_condition_codes', displayColumn: 'value', keyColumn: 'value'} - }, - origin: {shownInGrid: false}, - estimated: {shownInGrid: false}, - conception: {shownInGrid: false} - }, - 'Blood Draws' : { - billedby: {shownInGrid: false} - ,remark: {shownInGrid: false} - ,project: {shownInGrid: true, allowBlank: false} - ,requestor: {shownInGrid: false, hidden: true, formEditorConfig:{readOnly: true}} - ,performedby: {shownInGrid: false} - ,instructions: {shownInGrid: false} - ,objectid: { setInitialValue: function (v, rec){ - return v || LABKEY.Utils.generateUUID(); - }, - parentConfig:false, - hidden :true - } - ,assayCode: { - xtype: 'trigger' - ,shownInGrid: false - ,editorConfig: { - triggerClass: 'x-form-search-trigger', - allowAnyId: true - ,onTriggerClick: function (){ - var prefix = this.getValue(); - - if(!prefix){ - Ext.Msg.alert('Error', "Must enter prefix"); - return - } - var sql = "SELECT max(cast(regexp_replace(SUBSTRING(assayCode, "+(prefix.length+1)+"), '[a-z,\-]+', '') as integer)) as maxNumber FROM study.blood WHERE assayCode LIKE '" + prefix + "%' AND lcase(SUBSTRING(assayCode, "+(prefix.length+1)+")) = ucase(SUBSTRING(assayCode, "+(prefix.length+1)+"))"; - //console.log(sql) - LABKEY.Query.executeSql({ - schemaName: 'study', - sql: sql, - scope: this, - success: function(data){ - var number; - if(data.rows && data.rows.length==1){ - number = Number(data.rows[0].maxNumber)+1; - } - else { - console.log('no matching IDs found'); - number = 1; - } - - //number = EHR.Utils.padDigits(number, (6-prefix.length)); - var id = prefix + number; - this.setValue(id.toLowerCase()); - this.fireEvent('change', this.getValue()); - }, - failure: EHR.Utils.onError - }); - } - } - } - ,additionalServices: { - xtype: 'lovcombo', - hasOwnTpl: true, - includeNullRecord: false, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'blood_draw_services', - displayColumn: 'service', - keyColumn: 'service' - }, - editorConfig: { - tpl: null, - separator: ';' - } - } - ,tube_type: { - xtype: 'combo', - lookup: { - schemaName: 'ehr_lookups', - queryName: 'blood_draw_tube_type', - displayColumn: 'type', - keyColumn: 'type', - columns: 'type,volume' - }, - editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(field, rec){ - var theForm = this.ownerCt.getForm(); - var tube_vol = theForm.findField('tube_vol'); - - tube_vol.store.baseParams['query.tube_types~contains'] = rec.get('type'); - tube_vol.store.load(); - } - } - }, - colModel: { - width: 60, - showLink: false - } - } - ,quantity: { - //xtype: 'displayfield', - shownInGrid: false, - allowBlank: false, - editorConfig: { - allowNegative: false, - calculateQuantity: function(){ - var form = this.ownerCt.getForm(); - var numTubes = form.findField('num_tubes').getValue(); - var tube_vol = form.findField('tube_vol').getValue(); - - var quantity = numTubes*tube_vol; - this.setValue(quantity); - this.fireEvent('change', quantity, this.startValue); - } - } - } - ,num_tubes: { - xtype: 'ehr-triggernumberfield' - ,editorConfig: { - allowNegative: false - ,triggerClass: 'x-form-search-trigger' - ,onTriggerClick: function(){ - var parent = this.findParentByType('ehr-formpanel'); - var theForm = parent.getForm(); - - var tube_vol = theForm.findField('tube_vol'); - - if(!tube_vol.getValue() || !this.getValue()){ - Ext.Msg.alert('Error', 'Must enter tube volume and number of tubes'); - return; - } - - var quantity = tube_vol.getValue() * this.getValue(); - var quantityField = theForm.findField('quantity'); - quantityField.setValue(quantity); - quantityField.fireEvent('change', quantity, quantityField.startValue); - } - } - ,allowBlank: true - ,colModel: { - width: 55, - header: '# Tubes', - showLink: false - } - - } - ,tube_vol: { - shownInGrid: true - ,editorConfig: { - plugins: ['ehr-usereditablecombo'] -// ,listeners: { -// select: function(field, rec){ -// var theForm = this.ownerCt.getForm(); -// } -// } - } - ,includeNullRecord: false - ,lookup: { - schemaName: 'ehr_lookups', - queryName: 'blood_tube_volumes', - displayColumn: 'volume', - keyColumn: 'volume', - columns: '*', - sort: 'volume' - } - ,colModel: { - width: 75, - header: 'Tube Vol (mL)', - showLink: false - } - } - }, - 'Procedure Codes': { - code: { - editorConfig: { - defaultSubset: 'Procedures' - } - }, - performedby: { - hidden: true - } - }, - 'Drug Administration': { - enddate: { - shownInGrid: false, - hidden: false, - shownInInsertView: true, - label: 'End Time' - } - ,category: { - hidden: true - } - ,code: { - editorConfig: { - defaultSubset: 'Drugs and Procedures' - } - } - ,date: { - header: 'Start Time' - ,label: 'Start Time' - ,hidden: false - } - ,HeaderDate: { - xtype: 'xdatetime' - ,hidden: true - ,shownInGrid: false - } - ,remark: {shownInGrid: false} - ,dosage: { - xtype: 'ehr-drugdosefield', - shownInGrid: false, - compositeField: 'Dosage', - editorConfig: { - decimalPrecision: 3 - } - } - ,dosage_units: { - shownInGrid: false, - compositeField: 'Dosage', - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - ,concentration: { - shownInGrid: false, - compositeField: 'Drug Conc', - editorConfig: { - decimalPrecision: 10 - } - } - ,conc_units: { - shownInGrid: false - ,lookup: {columns: '*'} - ,compositeField: 'Drug Conc' - ,editorConfig: { - plugins: ['ehr-usereditablecombo'], - listeners: { - select: function(combo, rec) - { - var theForm = this.findParentByType('ehr-formpanel').getForm(); - theForm.findField('amount_units').setValue(rec.get('numerator')); - theForm.findField('conc_units').setValue(rec.get('unit')); - theForm.findField('vol_units').setValue(rec.get('denominator')); - - var doseField = theForm.findField('dosage_units'); - if(rec.get('numerator')) - doseField.setValue(rec.get('numerator')+'/kg'); - else - doseField.setValue(''); - - doseField.fireEvent('change', doseField.getValue(), doseField.startValue); - } - } - } - } - ,route: { - shownInGrid: false, - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - ,volume: { - compositeField: 'Volume', - xtype: 'ehr-triggernumberfield', - noDuplicateByDefault: true, - noSaveInTemplateByDefault: true, - editorConfig: { - triggerClass: 'x-form-search-trigger' - ,onTriggerClick: function (){ - //recalculate amount if needed: - var theForm = this.findParentByType('ehr-formpanel').getForm(); - var conc = theForm.findField('concentration').getValue(); - var val = this.getValue(); - - if(!val || !conc){ - alert('Must supply volume and concentration'); - return; - } - - if(val && conc){ - var amount = conc * val; - var amountField = theForm.findField('amount'); - amountField.setValue(amount); - amountField.fireEvent('change', amount, amountField.startValue); - } - } - ,decimalPrecision: 3 - } - } - ,vol_units: { - compositeField: 'Volume' - ,header: 'Units' - ,editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - ,amount: { - compositeField: 'Amount Given' - ,noDuplicateByDefault: true - ,noSaveInTemplateByDefault: true - //,allowBlank: false - ,shownInGrid: false - ,colModel: { - width: 40 - } - ,editorConfig: { - decimalPrecision: 10 - } - } - ,amount_units: { - shownInGrid: false - ,compositeField: 'Amount Given' - ,colModel: { - width: 70 - } - ,editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - ,performedby: { - allowBlank: false - } - ,project: { - allowBlank: false - } - ,restraint: { - shownInGrid: false - } - ,restraintDuration: { - shownInGrid: false - } - ,qualifier: { - shownInGrid: false - } - }, - Notes: { - performedby: {hidden: true}, - project: {hidden: true}, - account: {hidden: true} - }, - 'Problem List': { - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - }, - enddate: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - }, - project: {hidden: true}, - account: {hidden: true}, - performedby: {hidden: true}, - code: {hidden: true}, - problem_no: {shownInInsertView: false} - }, - 'Clinical Observations': { - observation: { - xtype: 'ehr-remoteradiogroup', - //defaultValue: 'Normal', - //allowBlank: false, - includeNullRecord: false, - editorConfig: {columns: 2}, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'normal_abnormal', - displayColumn: 'state', - keyColumn: 'state', - sort: '-state' - } - }, - date: { - label: 'Time' - }, - performedby: {hidden: true} - }, - 'TB Tests': { - lot: { - shownInGrid: false - }, - project: { - hidden: true - }, - account: { - hidden: true - }, - dilution: { - shownInGrid: false - }, - remark: { - shownInGrid: false - }, - eye: { - colModel: { - width: 40 - } - }, - result1: { - colModel: { - width: 40 - } - }, - result2: { - colModel: { - width: 40 - } - }, - result3: { - colModel: { - width: 40 - } - }, - date: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - } - }, - Weight: { - project: { - hidden: true - } - ,account: { - hidden: true - } - ,performedby: { - hidden: true - } - ,'id/curlocation/location': { - shownInGrid: true - } - ,remark: { - shownInGrid: false - } - ,weight: { - allowBlank: false - ,useNull: true - ,editorConfig: { - allowNegative: false - ,decimalPrecision: 4 - } - } - //,performedby: {allowBlank: true} - } - } -}); \ No newline at end of file diff --git a/ehr/resources/web/ehr/metadata/Necropsy.js b/ehr/resources/web/ehr/metadata/Necropsy.js deleted file mode 100644 index b87a5f466..000000000 --- a/ehr/resources/web/ehr/metadata/Necropsy.js +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2013-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -/** - * This is the default metadata applied to records in the context of a necropsy task. Among other things, it configured a parent/child relationship - * between the study.necropsies record and other dataset records. It is similar to Encounter, except the parent record is from study.Necropsies. - */ -EHR.Metadata.registerMetadata('Necropsy', { - allQueries: { - Id: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'Id' - } - ,hidden: true - ,shownInGrid: false - } - ,date: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'date' - } - ,hidden: true - ,shownInGrid: false - } - ,begindate: { - setInitialValue: null - ,hidden: false - ,allowBlank: false - } - ,parentid: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'objectid' - } - ,hidden: true - ,shownInGrid: false - ,allowBlank: false - } - ,project: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'project' - } - ,hidden: true - ,shownInGrid: false - } - ,account: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'account' - } - ,hidden: true - ,shownInGrid: false - } - }, - byQuery: { - Necropsies: { - parentid: { - parentConfig: false, - allowBlank: true - }, - Id: { - parentConfig: null, - hidden: false, - allowAnyId: true, - xtype: 'trigger', - editorConfig: { - plugins: ['ehr-participantfield'], - triggerClass: 'x-form-search-trigger', - onTriggerClick: function (){ - Ext.Msg.confirm('Find Next PD Number In Series', 'Clicking OK will find the next available PD number for infant deaths.', function(v){ - if(v == 'yes'){ - var prefix = 'pd'; - var year = new Date().getFullYear().toString().slice(2); - var sql = "SELECT cast(SUBSTRING(MAX(id), 5, 6) AS INTEGER) as num FROM study.prenatal WHERE Id LIKE '" + prefix + year + "%'"; - LABKEY.Query.executeSql({ - schemaName: 'study', - sql: sql, - scope: this, - success: function(data){ - var caseno; - if(data.rows && data.rows.length==1){ - caseno = data.rows[0].num; - caseno++; - } - else { - //console.log('no existing IDs found'); - caseno = 1; - } - - caseno = EHR.Utils.padDigits(caseno, 2); - var val = prefix + year + caseno; - this.setValue(val); - this.fireEvent('change', val) - }, - failure: EHR.Utils.onError - }); - } - }, this); - } - } - }, - date: { - parentConfig: null, - hidden: false - //label: 'Start Time' - }, - project: { - parentConfig: null, - allowBlank: true, - hidden: false - }, - account: { - parentConfig: null, - allowBlank: false, - hidden: false - }, - title: { - parentConfig: { - storeIdentifier: {queryName: 'tasks', schemaName: 'ehr'} - ,dataIndex: 'title' - } - }, - mannerofdeath: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - } - }, - Deaths: { - date: { - parentConfig: null, - hidden: false - }, - caseno: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'caseno' - }, - xtype: 'displayfield' - } - }, - 'Drug Administration': { - begindate: { - hidden: false - } - ,performedby: { - allowBlank: true, - hidden: true - } - }, - Alopecia: { - head: {defaultValue: 'NA', hiddden: true}, - dorsum: {defaultValue: 'NA', hiddden: true}, - rump: {defaultValue: 'NA', hiddden: true}, - shoulders: {defaultValue: 'NA', hiddden: true}, - upperArms: {defaultValue: 'NA', hiddden: true}, - lowerArms: {defaultValue: 'NA', hiddden: true}, - hips: {defaultValue: 'NA', hiddden: true}, - upperLegs: {defaultValue: 'NA', hiddden: true}, - lowerLegs: {defaultValue: 'NA', hiddden: true}, - other: {defaultValue: 'NA', hiddden: true} - - }, - tasks: { - duedate: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'date' - } - ,hidden: true - ,shownInGrid: false - } - }, - Weight: { - date: { - parentConfig: { - storeIdentifier: {queryName: 'Necropsies', schemaName: 'study'}, - dataIndex: 'timeofdeath' - } - ,hidden: false - ,shownInGrid: false - } - } - } -}); \ No newline at end of file diff --git a/ehr/resources/web/ehr/metadata/Request.js b/ehr/resources/web/ehr/metadata/Request.js deleted file mode 100644 index b0daa3de0..000000000 --- a/ehr/resources/web/ehr/metadata/Request.js +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2013-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -/** - * @name EHR.Metadata.Sources.Request - * This is the default metadata applied any record when displayed in the context of a request. Metadata placed here - * can be used to hide fields not editable at time of request. It also configured a parent/child relationship between the ehr.reqeusts record and dataset records. - */ -EHR.Metadata.registerMetadata('Request', { - allQueries: { - requestid: { - parentConfig: { - storeIdentifier: {queryName: 'requests', schemaName: 'ehr'} - ,dataIndex: 'requestid' - } - }, - date: { -// parentConfig: { -// storeIdentifier: {queryName: 'requests', schemaName: 'ehr'} -// ,dataIndex: 'daterequested' -// }, -// hidden: true, - editorConfig: { - minValue: (new Date()).add(Date.DAY, 2), - dateConfig: { - minValue: (new Date()).add(Date.DAY, 2) - } - } - }, - performedby: { - hidden: true, - allowBlank: true - }, - remark: { - hidden: true - }, -// daterequested: { -// editorConfig: { -// minValue: (new Date()).add(Date.DAY, 2) -// } -// }, - QCState: { - //defaultValue: 5, - setInitialValue: function(v){ - var qc; - if(!v && EHR.Security.getQCStateByLabel('Request: Pending')) - qc = EHR.Security.getQCStateByLabel('Request: Pending').RowId; - return v || qc; - } - }, - restraint: { - hidden: true - }, - restraintDuration: { - hidden: true - }, - 'id/curlocation/location': { - shownInGrid: false - } - }, - byQuery: { - project: { - protocol: { - hidden: true - }, - avail: { - hidden: true - } - }, - requests: { - daterequested: { - xtype: 'datefield', - extFormat: LABKEY.extDefaultDateFormat - //nullable: false - } - }, - 'Blood Draws': { - requestor: { - defaultValue: LABKEY.Security.currentUser.displayName - }, - daterequested: { - hidden: true - }, - billedby: { - hidden: true - }, - assayCode: { - hidden: true - }, - performedby: { - allowBlank: true - }, - quantity : { - xtype: 'displayfield' - }, - num_tubes: { - xtype: 'ehr-triggernumberfield', - editorConfig: { - allowNegative: false, - listeners: { - change: function(field, val){ - if(this.ownerCt.getForm) - this.ownerCt.getForm().findField('quantity').calculateQuantity(); - } - } - } - ,nullable: false - }, - tube_vol: { - nullable: false, - editorConfig: { - allowNegative: false, - listeners: { - change: function(field, val){ - if(this.ownerCt.getForm) - this.ownerCt.getForm().findField('quantity').calculateQuantity(); - } - } - } - }, - date: { - nullable: false, - editorConfig: { - timeConfig: { - minValue: '8:30', - maxValue: '12:00', - increment: 30 - } - }, - setInitialValue: function(v){ - var date = (new Date()).add(Date.DAY, 2); - date.setHours(9); - date.setMinutes(30); - return v || date; - } - }, - tube_type: { - nullable: false - }, - project: { - nullable: false - }, - instructions: { - hidden: false, - xtype: 'textarea', - formEditorConfig:{xtype: 'textarea', readOnly: false} - } - }, - 'Clinical Encounters': { - title: { - hidden: true - }, - performedby: { - allowBlank: true - }, - enddate: { - hidden: true - }, - major: { - hidden: true - }, - restraint: { - hidden: true - }, - restraintDuration: { - hidden: true - }, - serviceRequested: { - xtype: 'ehr-remark', - isAutoExpandColumn: true, - printWidth: 150, - editorConfig: { - resizeDirections: 's' - } - } - }, - 'Clinpath Runs': { - date: { - editorConfig: { - minValue: null - } - }, - servicerequested: { - editorConfig: { - plugins: ['ehr-usereditablecombo'] - } - }, - remark: { - hidden: false - } - }, - 'Drug Administration': { - performedby: { - allowBlank: true - } - } - } -}); \ No newline at end of file diff --git a/ehr/resources/web/ehr/metadata/Surgery.js b/ehr/resources/web/ehr/metadata/Surgery.js deleted file mode 100644 index b20aa2b63..000000000 --- a/ehr/resources/web/ehr/metadata/Surgery.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2013-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 - */ -/** - * This is the default metadata applied to records in the context of a Surgery task. - */ -EHR.Metadata.registerMetadata('Surgery', { - allQueries: { - - }, - byQuery: { - 'Clinical Encounters': { - type: { - defaultValue: 'Surgery' - }, - major: { - allowBlank: false - } - }, - 'Drug Administration': { - category: { - hidden: false - } - } - } -}); \ No newline at end of file From 6afa5fa1845a83452a01c78ff305acf4fd5071fa Mon Sep 17 00:00:00 2001 From: Binal Date: Wed, 15 Jul 2020 16:13:09 -0700 Subject: [PATCH 08/39] Restore deleted files during merge. --- ehr/resources/web/ehr/model/sources/Biopsy.js | 64 ++++++++++ .../web/ehr/model/sources/Necropsy.js | 35 ++++++ .../web/ehr/model/sources/Surgery.js | 117 ++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 ehr/resources/web/ehr/model/sources/Biopsy.js create mode 100644 ehr/resources/web/ehr/model/sources/Necropsy.js create mode 100644 ehr/resources/web/ehr/model/sources/Surgery.js diff --git a/ehr/resources/web/ehr/model/sources/Biopsy.js b/ehr/resources/web/ehr/model/sources/Biopsy.js new file mode 100644 index 000000000..619c85639 --- /dev/null +++ b/ehr/resources/web/ehr/model/sources/Biopsy.js @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014-2019 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Biopsy', { + allQueries: { + + }, + byQuery: { + 'study.encounters': { + type: { + defaultValue: 'Biopsy' + }, + chargetype: { + allowBlank: true + }, + assistingstaff: { + allowBlank: true, + hidden: true + }, + procedureid: { + getInitialValue: function(val, record){ + if (val){ + return val; + } + + var procedureStore = EHR.DataEntryUtils.getProceduresStore(); + LDK.Assert.assertNotEmpty('Unable to find procedureStore from Biopsy.js', procedureStore); + + if (LABKEY.ext4.Util.hasStoreLoaded(procedureStore)){ + var procRecIdx = procedureStore.findExact('name', 'Biopsy'); + var procedureRec = procedureStore.getAt(procRecIdx); + LDK.Assert.assertNotEmpty('Unable to find procedure record with name Biopsy from Biopsy.js', procedureRec); + + return procedureRec ? procedureRec.get('rowid') : null; + } + else { + console.log('procedure store not loaded'); + procedureStore.on('load', function(store){ + var procRecIdx = store.findExact('name', 'Biopsy'); + var procedureRec = store.getAt(procRecIdx); + LDK.Assert.assertNotEmpty('Unable to find procedure record with name Biopsy after load from Biopsy.js', procedureRec); + + if (procedureRec){ + record.set('procedureid', procedureRec.get('rowid')); + } + }, this, {single: true}); + } + + return null; + } + }, + caseno: { + xtype: 'ehr-pathologycasenofield', + hidden: false, + editorConfig: { + casePrefix: 'B', + encounterType: 'Biopsy' + } + } + } + } +}); \ No newline at end of file diff --git a/ehr/resources/web/ehr/model/sources/Necropsy.js b/ehr/resources/web/ehr/model/sources/Necropsy.js new file mode 100644 index 000000000..cc4bbb2a7 --- /dev/null +++ b/ehr/resources/web/ehr/model/sources/Necropsy.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013-2019 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Necropsy', { + allQueries: { + }, + byQuery: { + 'study.encounters': { + type: { + defaultValue: 'Necropsy', + hidden: true + }, + chargetype: { + allowBlank: true + }, + assistingstaff: { + allowBlank: true, + hidden: true + }, + caseno: { + xtype: 'ehr-pathologycasenofield', + hidden: false, + editorConfig: { + casePrefix: 'A', + encounterType: 'Necropsy' + } + }, + remark: { + hidden: true + } + } + } +}); \ No newline at end of file diff --git a/ehr/resources/web/ehr/model/sources/Surgery.js b/ehr/resources/web/ehr/model/sources/Surgery.js new file mode 100644 index 000000000..8978f8f94 --- /dev/null +++ b/ehr/resources/web/ehr/model/sources/Surgery.js @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013-2019 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Surgery', { + allQueries: { + performedby: { + allowBlank: true + } + }, + byQuery: { + 'onprc_billing.miscCharges': { + chargeId: { + lookup: { + filterArray: [ + LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL), + LABKEY.Filter.create('category', 'Lease Fee', LABKEY.Filter.Types.NEQ), + LABKEY.Filter.create('category', 'Animal Per Diem', LABKEY.Filter.Types.NEQ), + LABKEY.Filter.create('category', 'Small Animal Per Diem', LABKEY.Filter.Types.NEQ), + LABKEY.Filter.create('category', 'Timed Mated Breeders', LABKEY.Filter.Types.NEQ) + ] + } + }, + chargetype: { + //NOTE: this will be inherited from the encounters record, so we dont want a default + //defaultValue: 'DCM: Surgery Services', + allowBlank: false + } + }, + 'study.treatment_order': { + category: { + defaultValue: 'Surgical' + } + }, + 'study.drug': { + enddate: { + hidden: false + }, + category: { + defaultValue: 'Surgical' + }, + reason: { + defaultValue: 'Procedure' + }, + chargetype: { + //NOTE: this will be inherited from the encounters record, so we dont want a default + //defaultValue: 'DCM: Surgery Services', + allowBlank: false + } + }, + 'study.encounters': { + type: { + defaultValue: 'Surgery', + hidden: true + }, + title: { + hidden: true + }, + caseno: { + hidden: true + }, + procedureid: { + lookup: { + filterArray: [ + LABKEY.Filter.create('category', 'Surgery', LABKEY.Filter.Types.EQUAL), + LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL) + ] + } + }, + performedby: { + hidden: true + }, + remark: { + hidden: true + }, + chargetype: { + allowBlank: false + }, + assistingstaff: { + hidden: false, + allowBlank: true //will be handled in trigger script + }, + enddate: { + editorConfig: { + getDefaultDate: function(){ + var rec = EHR.DataEntryUtils.getBoundRecord(this); + if (rec){ + if (rec.get('date')){ + return rec.get('date'); + } + } + } + } + } + }, + 'ehr.snomed_tags': { + code: { + editorConfig: { + xtype: 'ehr-snomedcombo', + defaultSubset: 'Diagnostic Codes' + } + }, + set_number: { + hidden: true + }, + sort: { + hidden: true + } + }, + 'ehr.encounter_summaries': { + category: { + defaultValue: 'Narrative' + } + } + } +}); \ No newline at end of file From 6cdd5cb87a4f997340ea3c64af914a746083f466 Mon Sep 17 00:00:00 2001 From: Binal Date: Wed, 15 Jul 2020 17:00:50 -0700 Subject: [PATCH 09/39] Code review changes: - Cleanup, optimize imports, fix bad merge - Restore 'invesLastNameCol' in ProjectEntryField.js. - Remove unused class LightCycleImportMethod.java --- .../assay/LightCyclerImportMethod.java | 206 ------------------ .../web/ehr/form/field/ProjectEntryField.js | 14 +- ehr/resources/web/ehr/grid/Panel.js | 10 +- .../ehr/query/EHRCustomPermissionsTable.java | 1 + .../org/labkey/ehr/query/EHRUserSchema.java | 1 - .../labkey/ehr/security/EHRRequestorRole.java | 1 - 6 files changed, 15 insertions(+), 218 deletions(-) delete mode 100644 Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LightCyclerImportMethod.java diff --git a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LightCyclerImportMethod.java b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LightCyclerImportMethod.java deleted file mode 100644 index 12da08c3b..000000000 --- a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/LightCyclerImportMethod.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2012 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.viral_load_assay.assay; - -import org.apache.commons.lang3.StringUtils; -import org.json.JSONObject; -import org.labkey.api.collections.CaseInsensitiveHashMap; -import org.labkey.api.data.Container; -import org.labkey.api.exp.api.ExpProtocol; -import org.labkey.api.laboratory.assay.AssayImportMethod; -import org.labkey.api.laboratory.assay.AssayParser; -import org.labkey.api.laboratory.assay.DefaultAssayParser; -import org.labkey.api.laboratory.assay.ImportContext; -import org.labkey.api.laboratory.assay.ParserErrors; -import org.labkey.api.query.BatchValidationException; -import org.labkey.api.query.ValidationException; -import org.labkey.api.reader.ColumnDescriptor; -import org.labkey.api.reader.TabLoader; -import org.labkey.api.security.User; -import org.labkey.api.settings.AppProps; -import org.labkey.api.view.ViewContext; - -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -/** - * Created with IntelliJ IDEA. - * User: bimber - * Date: 9/26/12 - * Time: 3:52 PM - */ -public class LightCyclerImportMethod extends LC480ImportMethod -{ - public static final String NAME = "Light Cycler"; - - public LightCyclerImportMethod(String providerName) - { - super(providerName); - } - - @Override - public String getName() - { - return NAME; - } - - @Override - public String getLabel() - { - return NAME; - } - - @Override - public boolean hideTemplateDownload() - { - return true; - } - - @Override - public String getTooltip() - { - return "Choose this option to upload data directly from the output of a Roche Light Cycle. NOTE: this expects the sample names to be formatted in a specific manner. Please see instructions above the results section"; - } - - @Override - public String getTemplateInstructions() - { - return "This is designed to accept the output directly from a Roche Light Cycler. However, in order for the results to be recognized by the system, the sample names must be formatted in a specific manner. This is: subject Id, undescore, sample date, underscore, plasma volume, underscore, comments. An example is: 'patient123_2010-03-04_1_Sample Run for Jim'. The comments and/or plasma volume can be ommited: 'patient123_2010-03-04'. If no plasma volume is provided, it will assume 1mL was used."; - } - - @Override - public AssayParser getFileParser(Container c, User u, int assayId) - { - return new Parser(this, c, u, assayId); - } - - @Override - public String getExampleDataUrl(ViewContext ctx) - { - return AppProps.getInstance().getContextPath() + "/Viral_Load_Assay/SampleData/LC_data.txt"; - } - - @Override - public JSONObject getMetadata(ViewContext ctx, ExpProtocol protocol) - { - JSONObject meta = super.getMetadata(ctx, protocol); - - JSONObject runMeta = meta.getJSONObject("Run"); - runMeta.put("instrument", new JSONObject().put("defaultValue", "Light Cycler")); - meta.put("Run", runMeta); - - return meta; - } - - private class Parser extends DefaultAssayParser - { - private static final String NAME_FIELD = "Name"; - - public Parser(AssayImportMethod method, Container c, User u, int assayId) - { - super(method, c, u, assayId); - } - - @Override - protected TabLoader getTabLoader(String contents) throws IOException - { - TabLoader loader = new TabLoader(new StringReader(contents), false); - ColumnDescriptor[] cols = new ColumnDescriptor[]{ - new ColumnDescriptor("Include", String.class), - new ColumnDescriptor("Pos", String.class), - new ColumnDescriptor("Name", String.class), - new ColumnDescriptor("Cp", Double.class), - new ColumnDescriptor("Concentration", Double.class), - new ColumnDescriptor("Standard", Integer.class), - new ColumnDescriptor("Status", String.class) - }; - - loader.setColumns(cols); - return loader; - } - - @Override - protected List> processRowsFromFile(List> rows, ImportContext context) throws BatchValidationException - { - ParserErrors errors = context.getErrors(); - - List> newRows = new ArrayList<>(); - ListIterator> rowsIter = rows.listIterator(); - int rowIdx = 0; - while (rowsIter.hasNext()) - { - rowIdx++; - Map row = rowsIter.next(); - Map map = new CaseInsensitiveHashMap<>(row); - - if (row.size() < 6) - { - errors.addError("Improperly formatted row on line " + rowIdx + ", expected 6 cells"); - continue; - } - - appendPromotedResultFields(map, context); - - if (!map.containsKey("Name") || map.get("Name") == null || StringUtils.isEmpty((String)map.get("Name"))) - { - errors.addError("Missing sample name for row: " + rowIdx); - continue; - } - - //these are not used - map.remove("Include"); - map.remove("Status"); - - //this is a slightly funny way to pass sample info, but it needs to be supported for legacy installs - //they name the samples using a specific format, which gets parsed here. If first token either matches the enum, - //then it is a standard or control otherwise we treat it as a general experimental sample. - String[] nameParts = StringUtils.split((String) map.get("Name"), "_"); - Category cat; - try - { - try - { - cat = Category.valueOf(nameParts[0]); - cat.parseSampleName(map, NAME_FIELD); - } - catch (IllegalArgumentException e) - { - Category.Unknown.parseSampleName(map, NAME_FIELD); - } - } - catch (ValidationException e) - { - errors.addError(e.getMessage()); - } - - map.put("well", map.get("Pos")); - map.remove("Pos"); - - calculateViralLoadForRoche(map); - - newRows.add(map); - } - - errors.confirmNoErrors(); - - return newRows; - } - } -} diff --git a/ehr/resources/web/ehr/form/field/ProjectEntryField.js b/ehr/resources/web/ehr/form/field/ProjectEntryField.js index 7f52de79b..ad40602d6 100644 --- a/ehr/resources/web/ehr/form/field/ProjectEntryField.js +++ b/ehr/resources/web/ehr/form/field/ProjectEntryField.js @@ -20,7 +20,8 @@ Ext4.define('EHR.form.field.ProjectEntryField', { disabled: false, matchFieldWidth: false, includeDefaultProjects: true, - autoSelectFirstProjectOnLoad: false, + invesLastNameCol: 'lastName', + autoSelectFirstProjectOnLoad: false, initComponent: function(){ this.allProjectStore = EHR.DataEntryUtils.getProjectStore(); @@ -82,7 +83,7 @@ Ext4.define('EHR.form.field.ProjectEntryField', { protocol: rec.get('protocol'), title: rec.get('title'), shortname: rec.get('shortname'), - investigator: rec.get('investigatorId/lastName') + investigator: rec.get('investigatorId/' + this.invesLastNameCol) }); win.close(); @@ -224,7 +225,9 @@ Ext4.define('EHR.form.field.ProjectEntryField', { if (id){ //NOTE: show any actively assigned projects, or projects under the same protocol. we also only show projects if either the animal is assigned, or that project is active - sql += "SELECT p.project as project, p.displayName as displayName, p.account as account, p.protocol.displayName as protocolDisplayName, p.protocol as protocol, p.title, p.shortname, CASE WHEN (a.project = p.project AND p.use_category = 'Research') THEN 0 WHEN (a.project = p.project) THEN 1 ELSE 2 END as sort_order, CASE WHEN (a.project = p.project) THEN 1 ELSE 0 END as isAssigned " + + sql += "SELECT p.project as project, p.displayName as displayName, p.account as account, p.protocol.displayName as protocolDisplayName, " + + "p.protocol as protocol, p.title, p.shortname, p.investigatorId." + this.invesLastNameCol + "as investigator, " + + "CASE WHEN (a.project = p.project AND p.use_category = 'Research') THEN 0 WHEN (a.project = p.project) THEN 1 ELSE 2 END as sort_order, CASE WHEN (a.project = p.project) THEN 1 ELSE 0 END as isAssigned " + " FROM ehr.project p JOIN study.assignment a ON (a.project.protocol = p.protocol) " + " WHERE a.id='"+id+"' AND (a.project = p.project) "; //TODO: restore this OR p.enddate IS NULL OR p.enddate >= curdate() @@ -245,7 +248,8 @@ Ext4.define('EHR.form.field.ProjectEntryField', { if (id) sql += ' UNION ALL '; - sql += " SELECT p.project, p.displayName, p.account, p.protocol.displayName as protocolDisplayName, p.protocol as protocol, p.title, p.shortname, 3 as sort_order, 0 as isAssigned FROM ehr.project p WHERE p.alwaysavailable = true"; //TODO: restore this: and p.enddateCoalesced >= curdate() + sql += " SELECT p.project, p.displayName, p.account, p.protocol.displayName as protocolDisplayName, p.protocol as protocol, " + + "p.title, p.shortname, p.investigatorId." + this.invesLastNameCol + " as investigator, 3 as sort_order, 0 as isAssigned FROM ehr.project p WHERE p.alwaysavailable = true"; //TODO: restore this: and p.enddateCoalesced >= curdate() } sql+= " ) t GROUP BY t.project, t.displayName, t.account, t.protocolDisplayName, t.protocol, t.title, t.shortname"; @@ -335,7 +339,7 @@ Ext4.define('EHR.form.field.ProjectEntryField', { protocolDisplayName: rec.data['protocol/displayName'], protocol: rec.data.protocol, title: rec.data.title, - // investigator: rec.data['investigatorId/lastName'], + investigator: rec.data['investigatorId/' + this.invesLastNameCol], isAssigned: 0, fromClient: true }); diff --git a/ehr/resources/web/ehr/grid/Panel.js b/ehr/resources/web/ehr/grid/Panel.js index be7982e60..0b43418f7 100644 --- a/ehr/resources/web/ehr/grid/Panel.js +++ b/ehr/resources/web/ehr/grid/Panel.js @@ -51,11 +51,6 @@ Ext4.define('EHR.grid.Panel', { this.getSelectionModel().on('selectionchange', this.handleSectionChangeEvent, this); - //checks the extra property for a non dataset that does not have Id column - var byPassId = models[0].store.sectionCfg.extraProperties.BY_PASS_ANIMAL_ID; - if (byPassId || byPassId === 'true') - return; - // the intention of the following is to avoid redrawing the entire grid, which is expensive, when we have // single row changes, or more importantly single row changes that only involve validation/tooltip error message differences this.on('storevalidationcomplete', this.onStoreValidationComplete, this, {buffer: 100, delay: 20}); @@ -89,6 +84,11 @@ Ext4.define('EHR.grid.Panel', { if (models.length != 1) return; + //checks the extra property for a non dataset that does not have Id column + var byPassId = models[0].store.sectionCfg.extraProperties.BY_PASS_ANIMAL_ID; + if (byPassId || byPassId === 'true') + return; + var id = models[0].get('Id'); this.fireEvent('animalchange', id); }, diff --git a/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java b/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java index 688bca456..63bdde464 100644 --- a/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java +++ b/ehr/src/org/labkey/ehr/query/EHRCustomPermissionsTable.java @@ -34,6 +34,7 @@ protected Container getDomainContainer() return EHRDomainKind.getDomainContainer(getContainer()); } + @Override public QueryUpdateService getUpdateService() { TableInfo table = getRealTable(); diff --git a/ehr/src/org/labkey/ehr/query/EHRUserSchema.java b/ehr/src/org/labkey/ehr/query/EHRUserSchema.java index 2ca42f205..357cc48f2 100644 --- a/ehr/src/org/labkey/ehr/query/EHRUserSchema.java +++ b/ehr/src/org/labkey/ehr/query/EHRUserSchema.java @@ -24,7 +24,6 @@ import org.labkey.api.ehr.security.EHRDataAdminPermission; import org.labkey.api.ehr.security.EHRProjectEditPermission; import org.labkey.api.ehr.security.EHRProtocolEditPermission; -import org.labkey.api.ehr.security.EHR_BillingAdminPermission; import org.labkey.api.query.SimpleUserSchema; import org.labkey.api.security.User; import org.labkey.api.security.permissions.DeletePermission; diff --git a/ehr/src/org/labkey/ehr/security/EHRRequestorRole.java b/ehr/src/org/labkey/ehr/security/EHRRequestorRole.java index 8068888b4..59ce1ecad 100644 --- a/ehr/src/org/labkey/ehr/security/EHRRequestorRole.java +++ b/ehr/src/org/labkey/ehr/security/EHRRequestorRole.java @@ -26,7 +26,6 @@ import org.labkey.api.ehr.security.EHRRequestPermission; import org.labkey.api.ehr.security.EHRRequestSampleDeliveredInsertPermission; import org.labkey.api.ehr.security.EHRRequestSampleDeliveredUpdatePermission; -import org.labkey.api.ehr.security.EHRScheduledInsertPermission; import org.labkey.api.module.ModuleLoader; import org.labkey.api.security.Group; import org.labkey.api.security.SecurableResource; From 45c972f1c45baaa8c863bc62c0bbce9bb7d2ab10 Mon Sep 17 00:00:00 2001 From: Binal Date: Wed, 15 Jul 2020 17:02:42 -0700 Subject: [PATCH 10/39] Add space. --- ehr/resources/web/ehr/form/field/ProjectEntryField.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ehr/resources/web/ehr/form/field/ProjectEntryField.js b/ehr/resources/web/ehr/form/field/ProjectEntryField.js index ad40602d6..cf67b4931 100644 --- a/ehr/resources/web/ehr/form/field/ProjectEntryField.js +++ b/ehr/resources/web/ehr/form/field/ProjectEntryField.js @@ -226,7 +226,7 @@ Ext4.define('EHR.form.field.ProjectEntryField', { if (id){ //NOTE: show any actively assigned projects, or projects under the same protocol. we also only show projects if either the animal is assigned, or that project is active sql += "SELECT p.project as project, p.displayName as displayName, p.account as account, p.protocol.displayName as protocolDisplayName, " + - "p.protocol as protocol, p.title, p.shortname, p.investigatorId." + this.invesLastNameCol + "as investigator, " + + "p.protocol as protocol, p.title, p.shortname, p.investigatorId." + this.invesLastNameCol + " as investigator, " + "CASE WHEN (a.project = p.project AND p.use_category = 'Research') THEN 0 WHEN (a.project = p.project) THEN 1 ELSE 2 END as sort_order, CASE WHEN (a.project = p.project) THEN 1 ELSE 0 END as isAssigned " + " FROM ehr.project p JOIN study.assignment a ON (a.project.protocol = p.protocol) " + " WHERE a.id='"+id+"' AND (a.project = p.project) "; //TODO: restore this OR p.enddate IS NULL OR p.enddate >= curdate() From 0d499b0d18939b78e40b64e19dc2558e6035f11c Mon Sep 17 00:00:00 2001 From: Binal Date: Wed, 15 Jul 2020 18:19:07 -0700 Subject: [PATCH 11/39] Remove 'SOPRequirements' metadata from ehr_compliancedb module, and add to wnprc-modules. --- .../SOPrequirements/.qview.xml | 32 ---------------- .../SOPrequirements/All SOPs.qview.xml | 27 -------------- .../To Read Standard.qview.xml | 37 ------------------- .../SOPrequirements/To Read.qview.xml | 37 ------------------- 4 files changed, 133 deletions(-) delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/All SOPs.qview.xml delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read Standard.qview.xml delete mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml deleted file mode 100644 index 5a6c2cd59..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/.qview.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/All SOPs.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/All SOPs.qview.xml deleted file mode 100644 index 90619d6fa..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/All SOPs.qview.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read Standard.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read Standard.qview.xml deleted file mode 100644 index 7d295302f..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read Standard.qview.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml deleted file mode 100644 index ca0dc3593..000000000 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/SOPrequirements/To Read.qview.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 43271757dfd6762f14c3589489c9095ec8978177 Mon Sep 17 00:00:00 2001 From: Binal Date: Wed, 15 Jul 2020 18:28:48 -0700 Subject: [PATCH 12/39] Remove 'SOPAdmin' view from ehr_compliancedb module, and add to wnprc-modules. --- .../resources/views/SOPadmin.html | 27 ------------------- .../resources/views/SOPadmin.view.xml | 6 ----- .../resources/views/SOPadmin.webpart.xml | 7 ----- 3 files changed, 40 deletions(-) delete mode 100644 EHR_ComplianceDB/resources/views/SOPadmin.html delete mode 100644 EHR_ComplianceDB/resources/views/SOPadmin.view.xml delete mode 100644 EHR_ComplianceDB/resources/views/SOPadmin.webpart.xml diff --git a/EHR_ComplianceDB/resources/views/SOPadmin.html b/EHR_ComplianceDB/resources/views/SOPadmin.html deleted file mode 100644 index 2ec8d7f6b..000000000 --- a/EHR_ComplianceDB/resources/views/SOPadmin.html +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/views/SOPadmin.view.xml b/EHR_ComplianceDB/resources/views/SOPadmin.view.xml deleted file mode 100644 index bfe464d68..000000000 --- a/EHR_ComplianceDB/resources/views/SOPadmin.view.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/EHR_ComplianceDB/resources/views/SOPadmin.webpart.xml b/EHR_ComplianceDB/resources/views/SOPadmin.webpart.xml deleted file mode 100644 index a99864a2a..000000000 --- a/EHR_ComplianceDB/resources/views/SOPadmin.webpart.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file From f3a28e7a1c90d142be3e31124c2f8e6a134aa9af Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Fri, 14 Aug 2020 17:23:33 -0700 Subject: [PATCH 13/39] Stop hard-coding form URLs and rely on content of metadata table --- ehr/src/org/labkey/ehr/EHRController.java | 41 ++++++++++------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/ehr/src/org/labkey/ehr/EHRController.java b/ehr/src/org/labkey/ehr/EHRController.java index 565a06dcf..57b9e23c8 100644 --- a/ehr/src/org/labkey/ehr/EHRController.java +++ b/ehr/src/org/labkey/ehr/EHRController.java @@ -376,30 +376,9 @@ public ModelAndView getView(EHRQueryForm form, BindException errors) url.addParameter("importURL", importUrl.toString()); } } - //TODO implement this after view is set up for editable react form else if (isReactForm(form.getSchemaName(), form.getQueryName())) { - //weight is custom since it was introduced in its own controller - if ("weight".equals(form.getQueryName())){ - detailsStr = "/enterweights/app.view?"; - }else{ - detailsStr = "/wnprc_ehr/" + queryName + ".view?"; - } - importStr = ""; - for (String pkCol : ti.getPkColumnNames()) - { - detailsStr += "&" + pkCol + "=${" + pkCol + "}"; - importStr += "&" + pkCol + "="; - } - detailsStr += "&" + "formtype=" + queryName; - - if (form.isShowImport()) - { - DetailsURL importUrl = DetailsURL.fromString("/ehr/test.view?schemaName=" + schemaName + "&queryName=" + queryName + importStr); - importUrl.setContainerContext(getContainer()); - - url.addParameter("importURL", importUrl.toString()); - } + detailsStr = getReactFormFrameworkURL(form.getSchemaName(), form.getQueryName()); } else { detailsStr = "/ehr/dataEntryFormForQuery.view?schemaName=" + schemaName + "&queryName=" + queryName; @@ -518,8 +497,7 @@ protected boolean isExt4Form(String schemaName, String queryName) return isExt4Form; } - //Checks the form_framework_types table to see if there are any forms that should be rendered using react controller - // Currently just enterweights as of March 2020 + //Checks the TABLE_FORM_FRAMEWORK_TYPES table to see if there are any forms that should be rendered using react view protected boolean isReactForm(String schemaName, String queryName) { boolean isReactForm = false; @@ -539,6 +517,21 @@ protected boolean isReactForm(String schemaName, String queryName) return isReactForm; } + + protected String getReactFormFrameworkURL(String schemaName, String queryName) + { + String reactFormURL = null; + UserSchema us = QueryService.get().getUserSchema(getUser(), getContainer(), EHRSchema.EHR_SCHEMANAME); + if (us == null) { return null; } + + TableInfo ti = us.getTable(EHRSchema.TABLE_FORM_FRAMEWORK_TYPES); + if (ti == null) { return null; } + + TableSelector ts = new TableSelector(ti, Collections.singleton("url"), new SimpleFilter(FieldKey.fromString("schemaname"), schemaName).addCondition(FieldKey.fromString("queryname"), queryName), null); + Map mp = ts.getMap(); + return (String) mp.get("url"); + + } } public static class GetDemographicsForm From 6b1c76bc01607b1b792f8f19eddbcf3d9f5dcc78 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sat, 15 Aug 2020 08:52:40 -0700 Subject: [PATCH 14/39] Point at new package for permission class --- ehr_billing/resources/web/ehr_billing/BillingUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ehr_billing/resources/web/ehr_billing/BillingUtils.js b/ehr_billing/resources/web/ehr_billing/BillingUtils.js index 4d9c59922..3a07ebf87 100644 --- a/ehr_billing/resources/web/ehr_billing/BillingUtils.js +++ b/ehr_billing/resources/web/ehr_billing/BillingUtils.js @@ -65,7 +65,7 @@ EHR_Billing.BillingUtils = new function(){ if (!ctx || !ctx.EHR_BillingContainerInfo || !ctx.EHR_BillingContainerInfo.effectivePermissions || ctx.EHR_BillingContainerInfo.effectivePermissions.length == 0) return false; - return ctx.EHR_BillingContainerInfo.effectivePermissions.indexOf('org.labkey.api.ehr_billing.security.EHR_BillingAdminPermission') > -1; + return ctx.EHR_BillingContainerInfo.effectivePermissions.indexOf('org.labkey.api.ehr.security.EHR_BillingAdminPermission') > -1; } } }; \ No newline at end of file From a6c188eb1ebd9102f030e1f7fbda69dce480d618 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sat, 15 Aug 2020 11:22:02 -0700 Subject: [PATCH 15/39] Remove unused method to fix build --- .../labModules/ViralLoadAssayTest.java | 157 ------------------ 1 file changed, 157 deletions(-) diff --git a/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java b/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java index cbaca43d9..1d4eb5209 100644 --- a/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java +++ b/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java @@ -855,163 +855,6 @@ private void importWNPRCResults(String instrument) throws Exception verifyImportedVLs(totalRows, expected, results, new String[]{"Subject Id"}); } - private void importLightCyclerRun() throws Exception - { - log("Verifying Light Cycle Import"); - _helper.goToAssayResultImport(ASSAY_NAME); - - //a proxy for page loading - _helper.waitForField("Source Material"); - - //switch import method - Ext4FieldRef field = Ext4FieldRef.getForBoxLabel(this, "Light Cycler"); - field.setChecked(true); - Locator btn = Locator.linkContainingText("Download Example Data"); - waitForElement(btn); - - //set other field values - Ext4FieldRef.getForLabel(this, "Sample Type").setValue("Serum"); - assertEquals("Incorrect value for field", "Light Cycler", Ext4FieldRef.getForLabel(this, "Instrument").getValue()); - assertEquals("Incorrect value for field", Long.valueOf(50), Ext4FieldRef.getForLabel(this, "Eluate Volume").getValue()); - assertEquals("Incorrect value for field", Long.valueOf(5), Ext4FieldRef.getForLabel(this, "Sample Vol Per Rxn").getValue()); - waitAndClick(btn); - - Ext4FieldRef textarea = _ext4Helper.queryOne("#fileContent", Ext4FieldRef.class); - String text = _helper.getExampleData(); - - String errorText = text.replaceAll("CTL_negative", ""); - errorText = errorText.replaceAll("de0115_2008.09.08_1_JG\t\t\t0", ""); - textarea.setValue(errorText); - waitAndClick(Ext4Helper.Locators.ext4Button("Upload")); - waitForElement(Ext4Helper.Locators.window("Upload Failed")); - click(Ext4Helper.Locators.ext4Button("OK")); - assertTextPresent( - "There were errors in the upload", - "Missing sample name for row: 2", - "Unable to find sample information to match well: NTmiKt6kg3i0f4dB2VuZ3I", - "Template row with key NTmiKt6kg3i0f4dB2VuZ3H does not have a result", - "Template row with key nCmYQbLEikiQ73iDxmY33Y does not have a result"); - - log("Saving valid data"); - textarea.setValue(text); - waitAndClick(Ext4Helper.Locators.ext4Button("Upload")); - waitForElement(Ext4Helper.Locators.window("Success")); - clickAndWait(Ext4Helper.Locators.ext4Button("OK")); - waitForText("Import Samples"); - - log("Verifying results"); - _helper.clickNavPanelItemAndWait(fullAssayName + " Runs:", 1); - waitAndClickAndWait(Locator.linkContainingText("view results")); - - DataRegionTable results = new DataRegionTable("Data", this); - - int totalRows = 92; - Map expected = new LinkedHashMap<>(); - expected.put("0", new String[]{"LowQual1", "Unknown", "2018-02-20", "5.E+08"}); - expected.put("1", new String[]{"LowQual1", "Unknown", "2018-02-20", "5.3E+07"}); - expected.put("2", new String[]{"LowQual2", "Unknown", "2018-02-20", "5.2E+06"}); - expected.put("3", new String[]{"LowQual2", "Unknown", "2018-02-20", "4.9E+05"}); - expected.put("4", new String[]{"NTC", "Neg Control", "2018-02-20", "9.2E+05"}); - expected.put("5", new String[]{"NTC", "Neg Control", "2018-02-20", "9.5E+05"}); - expected.put("6", new String[]{"Positive Control-1", "Pos Control", "2018-02-20", "4.4E+04"}); - expected.put("7", new String[]{"Positive Control-1", "Pos Control", "2018-02-20", "3.4E+03"}); - expected.put("8", new String[]{"Positive Control-2", "Pos Control", "2018-02-20", "7.6E+02"}); - expected.put("9", new String[]{"Positive Control-2", "Pos Control", "2018-02-20", "6.2E+01"}); - expected.put("10", new String[]{"STD_10", "Standard", "2018-02-20", "4.4E+04"}); - expected.put("11", new String[]{"STD_10", "Standard", "2018-02-20", "3.4E+03"}); - expected.put("12", new String[]{"STD_32", "Standard", "2018-02-20", "5.E+06"}); - expected.put("13", new String[]{"STD_32", "Standard", "2018-02-20", "5.E+05"}); - expected.put("14", new String[]{"STD_100", "Standard", "2018-02-20", "5.3E+08"}); - expected.put("15", new String[]{"STD_100", "Standard", "2018-02-20", "5.E+07"}); - expected.put("16", new String[]{"STD_320", "Standard", "2018-02-20", "4.E+02"}); - expected.put("17", new String[]{"STD_320", "Standard", "2018-02-20", "1.9E+02"}); - expected.put("18", new String[]{"STD_1000", "Standard", "2018-02-20", "5.1E+04"}); - expected.put("19", new String[]{"STD_1000", "Standard", "2018-02-20", "5.1E+03"}); - expected.put("20", new String[]{"STD_3200", "Standard", "2018-02-20", "5.2E+06"}); - expected.put("21", new String[]{"STD_3200", "Standard", "2018-02-20", "4.9E+05"}); - expected.put("22", new String[]{"STD_10000", "Standard", "2018-02-20", "5.E+08"}); - expected.put("23", new String[]{"STD_10000", "Standard", "2018-02-20", "5.3E+07"}); - expected.put("24", new String[]{"STD_32000", "Standard", "2018-02-20", "1.E+06"}); - expected.put("25", new String[]{"STD_32000", "Standard", "2018-02-20", "1.7E+04"}); - expected.put("26", new String[]{"STD_100000", "Standard", "2018-02-20", "1.E+06"}); - expected.put("27", new String[]{"STD_100000", "Standard", "2018-02-20", "9.5E+05"}); - expected.put("28", new String[]{"STD_320000", "Standard", "2018-02-20", "1.3E+06"}); - expected.put("29", new String[]{"STD_320000", "Standard", "2018-02-20", "6.5E+05"}); - expected.put("30", new String[]{"STD_1000000", "Standard", "2018-02-20", "9.7E+05"}); - expected.put("31", new String[]{"STD_1000000", "Standard", "2018-02-20", "1.E+03"}); - expected.put("32", new String[]{"Subject1", "Unknown", "2018-02-20", "5.1E+04"}); - expected.put("33", new String[]{"Subject1", "Unknown", "2018-02-20", "5.1E+03"}); - expected.put("34", new String[]{"Subject2", "Unknown", "2018-02-20", "4.E+02"}); - expected.put("35", new String[]{"Subject2", "Unknown", "2018-02-20", "1.9E+02"}); - expected.put("36", new String[]{"Subject3", "Unknown", "2018-02-20", "5.3E+08"}); - expected.put("37", new String[]{"Subject3", "Unknown", "2018-02-20", "5.E+07"}); - expected.put("38", new String[]{"Subject4", "Unknown", "2018-02-20", "5.E+06"}); - expected.put("39", new String[]{"Subject4", "Unknown", "2018-02-20", "5.E+05"}); - expected.put("40", new String[]{"Subject5", "Unknown", "2018-02-20", "4.4E+04"}); - expected.put("41", new String[]{"Subject5", "Unknown", "2018-02-20", "3.4E+03"}); - expected.put("42", new String[]{"Subject6", "Unknown", "2018-02-20", "7.6E+02"}); - expected.put("43", new String[]{"Subject6", "Unknown", "2018-02-20", "6.2E+01"}); - expected.put("44", new String[]{"Subject7", "Unknown", "2018-02-20", "9.2E+05"}); - expected.put("45", new String[]{"Subject7", "Unknown", "2018-02-20", "9.5E+05"}); - expected.put("46", new String[]{"Subject8", "Unknown", "2018-02-20", "9.7E+05"}); - expected.put("47", new String[]{"Subject8", "Unknown", "2018-02-20", "1.E+03"}); - expected.put("48", new String[]{"Subject9", "Unknown", "2018-02-20", "1.3E+06"}); - expected.put("49", new String[]{"Subject9", "Unknown", "2018-02-20", "6.5E+05"}); - expected.put("50", new String[]{"Subject10", "Unknown", "2018-02-20", "1.E+06"}); - expected.put("51", new String[]{"Subject10", "Unknown", "2018-02-20", "9.5E+05"}); - expected.put("52", new String[]{"Subject11", "Unknown", "2018-02-20", "1.E+06"}); - expected.put("53", new String[]{"Subject11", "Unknown", "2018-02-20", "1.7E+04"}); - expected.put("54", new String[]{"Subject12", "Unknown", "2018-02-20", "5.E+08"}); - expected.put("55", new String[]{"Subject12", "Unknown", "2018-02-20", "5.3E+07"}); - expected.put("56", new String[]{"Subject13", "Unknown", "2018-02-20", "5.2E+06"}); - expected.put("57", new String[]{"Subject13", "Unknown", "2018-02-20", "4.9E+05"}); - expected.put("58", new String[]{"Subject14", "Unknown", "2018-02-20", "5.1E+04"}); - expected.put("59", new String[]{"Subject14", "Unknown", "2018-02-20", "5.1E+03"}); - expected.put("60", new String[]{"Subject15", "Unknown", "2018-02-20", "4.E+02"}); - expected.put("61", new String[]{"Subject15", "Unknown", "2018-02-20", "1.9E+02"}); - expected.put("62", new String[]{"Subject16", "Unknown", "2018-02-20", "5.3E+08"}); - expected.put("63", new String[]{"Subject16", "Unknown", "2018-02-20", "5.E+07"}); - expected.put("64", new String[]{"Subject17", "Unknown", "2018-02-20", "5.E+06"}); - expected.put("65", new String[]{"Subject17", "Unknown", "2018-02-20", "5.E+05"}); - expected.put("66", new String[]{"Subject18", "Unknown", "2018-02-20", "4.4E+04"}); - expected.put("67", new String[]{"Subject18", "Unknown", "2018-02-20", "3.4E+03"}); - expected.put("68", new String[]{"Subject19", "Unknown", "2018-02-20", "7.6E+02"}); - expected.put("69", new String[]{"Subject19", "Unknown", "2018-02-20", "6.2E+01"}); - expected.put("70", new String[]{"Subject20", "Unknown", "2018-02-20", "9.2E+05"}); - expected.put("71", new String[]{"Subject20", "Unknown", "2018-02-20", "9.5E+05"}); - expected.put("72", new String[]{"Subject21", "Unknown", "2018-02-20", "9.7E+05"}); - expected.put("73", new String[]{"Subject21", "Unknown", "2018-02-20", "1.E+03"}); - expected.put("74", new String[]{"Subject22", "Unknown", "2018-02-20", "1.3E+06"}); - expected.put("75", new String[]{"Subject22", "Unknown", "2018-02-20", "6.5E+05"}); - expected.put("76", new String[]{"Subject23", "Unknown", "2018-02-20", "1.E+06"}); - expected.put("77", new String[]{"Subject23", "Unknown", "2018-02-20", "9.5E+05"}); - expected.put("78", new String[]{"Subject24", "Unknown", "2018-02-20", "1.E+06"}); - expected.put("79", new String[]{"Subject24", "Unknown", "2018-02-20", "1.7E+04"}); - expected.put("80", new String[]{"Subject25", "Unknown", "2018-02-20", "5.E+08"}); - expected.put("81", new String[]{"Subject25", "Unknown", "2018-02-20", "5.3E+07"}); - expected.put("82", new String[]{"Subject26", "Unknown", "2018-02-20", "5.2E+06"}); - expected.put("83", new String[]{"Subject26", "Unknown", "2018-02-20", "4.9E+05"}); - expected.put("84", new String[]{"Subject27", "Unknown", "2018-02-20", "5.1E+04"}); - expected.put("85", new String[]{"Subject27", "Unknown", "2018-02-20", "5.1E+03"}); - expected.put("86", new String[]{"Subject28", "Unknown", "2018-02-20", "4.E+02"}); - expected.put("87", new String[]{"Subject28", "Unknown", "2018-02-20", "1.9E+02"}); - expected.put("88", new String[]{"Subject29", "Unknown", "2018-02-20", "5.3E+08"}); - expected.put("89", new String[]{"Subject29", "Unknown", "2018-02-20", "5.E+07"}); - expected.put("90", new String[]{"Subject30", "Unknown", "2018-02-20", "5.E+06"}); - expected.put("91", new String[]{"Subject30", "Unknown", "2018-02-20", "5.E+05"}); - - verifyImportedVLs(totalRows, expected, results, null); - - log("verifying run plan marked as complete"); - _helper.goToLabHome(); - _helper.clickNavPanelItem(fullAssayName + ":", IMPORT_DATA_TEXT); - click(Ext4Helper.Locators.menuItem("View Planned Runs")); - waitForElement(Locator.tagContainingText("span", "Planned Assay Runs"), WAIT_FOR_PAGE); - - DataRegionTable dr2 = new DataRegionTable("query", this); - assertEquals("Run plan not marked completed", 0, dr2.getDataRowCount()); - } - private void verifyImportedVLs(int totalRows, Map expected, DataRegionTable results, @Nullable String[] keyFields) throws Exception { assertEquals("Incorrect row count", totalRows, results.getDataRowCount()); From 1ca1cb8d4fbb46cdfcd28af6f7657b0be6777aa5 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sat, 15 Aug 2020 14:53:10 -0700 Subject: [PATCH 16/39] Fix up schema upgrades, including: Don't modify EHR schema from WNPRC_EHR scripts Update getVersion() to getSchemaVersion() Fix up schema XML files to match expected schema Fix bootstrapping for WNPRC_EHR upgrades --- .../postgresql/ehr-20.000-20.001.sql | 20 ++++++++++++++++++- .../dbscripts/sqlserver/ehr-20.000-20.001.sql | 4 +++- ehr/resources/schemas/ehr.xml | 1 + .../postgresql/ehr_billing-20.000-20.001.sql | 4 ++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql b/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql index eca994592..c89bcda4a 100644 --- a/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql +++ b/ehr/resources/schemas/dbscripts/postgresql/ehr-20.000-20.001.sql @@ -69,4 +69,22 @@ $$ LANGUAGE plpgsql; SELECT ehr.createTable_form_framework_types(); -DROP FUNCTION ehr.createTable_form_framework_types(); \ No newline at end of file +DROP FUNCTION ehr.createTable_form_framework_types(); + +CREATE FUNCTION ehr.handleAddSpeciesToSupplementalPedigree() RETURNS VOID AS $$ +DECLARE +BEGIN + IF NOT EXISTS ( + SELECT column_name + FROM information_schema.columns + WHERE table_name='supplemental_pedigree' and table_schema='ehr' and column_name='spcies' + ) + THEN + ALTER TABLE ehr.supplemental_pedigree ADD species VARCHAR(4000); + END IF; +END; +$$ LANGUAGE plpgsql; + +SELECT ehr.handleAddSpeciesToSupplementalPedigree(); + +DROP FUNCTION ehr.handleAddSpeciesToSupplementalPedigree(); diff --git a/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql b/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql index a23fd9a12..ff1e3f573 100644 --- a/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql +++ b/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql @@ -31,4 +31,6 @@ CREATE TABLE ehr.form_framework_types ( Modified datetime, CONSTRAINT PK_form_framework_types PRIMARY KEY (schemaname, queryname) -); \ No newline at end of file +); + +ALTER TABLE ehr.supplemental_pedigree ADD COLUMN species NVARCHAR(4000); diff --git a/ehr/resources/schemas/ehr.xml b/ehr/resources/schemas/ehr.xml index d1065195c..ea9fb7d51 100644 --- a/ehr/resources/schemas/ehr.xml +++ b/ehr/resources/schemas/ehr.xml @@ -1684,6 +1684,7 @@ entityid
+
diff --git a/ehr_billing/resources/schemas/dbscripts/postgresql/ehr_billing-20.000-20.001.sql b/ehr_billing/resources/schemas/dbscripts/postgresql/ehr_billing-20.000-20.001.sql index b322ad44f..4c399d204 100644 --- a/ehr_billing/resources/schemas/dbscripts/postgresql/ehr_billing-20.000-20.001.sql +++ b/ehr_billing/resources/schemas/dbscripts/postgresql/ehr_billing-20.000-20.001.sql @@ -28,7 +28,7 @@ BEGIN IF EXISTS ( SELECT column_name FROM information_schema.columns - WHERE table_name='chargeUnits' and table_schema='ehr_billing' and column_name='chargetype' + WHERE table_name='chargeunits' and table_schema='ehr_billing' and column_name='chargetype' ) THEN ALTER TABLE ehr_billing.chargeUnits DROP CONSTRAINT PK_chargeUnits; @@ -50,7 +50,7 @@ BEGIN IF NOT EXISTS ( SELECT column_name FROM information_schema.columns - WHERE table_name='miscCharges' and table_schema='ehr_billing' and column_name='totalCost' + WHERE table_name='misccharges' and table_schema='ehr_billing' and column_name='totalcost' ) THEN ALTER TABLE ehr_billing.miscCharges ADD totalCost double precision; From 380ca885ca052b88445dca101de3dd68f2d26d0d Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sat, 15 Aug 2020 17:19:46 -0700 Subject: [PATCH 17/39] Various test fixes, including: Customize source_material query directly instead of trying to mutate a locked FK lookup table Update to use new assay designer UI Migrate syntax --- .../resources/schemas/viral_load_assay.xml | 4 +- .../labModules/ViralLoadAssayTest.java | 47 ++++++++++--------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Viral_Load_Assay/resources/schemas/viral_load_assay.xml b/Viral_Load_Assay/resources/schemas/viral_load_assay.xml index d8961bf87..72f48953e 100644 --- a/Viral_Load_Assay/resources/schemas/viral_load_assay.xml +++ b/Viral_Load_Assay/resources/schemas/viral_load_assay.xml @@ -151,7 +151,7 @@
- org.labkey.ldk.query.DefaultTableCustomizer + DETAILED Nucleic Acid @@ -164,7 +164,7 @@
- org.labkey.ldk.query.DefaultTableCustomizer + DETAILED Source Material diff --git a/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java b/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java index 1d4eb5209..20f03e62e 100644 --- a/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java +++ b/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java @@ -33,6 +33,7 @@ import org.labkey.test.categories.EHR; import org.labkey.test.categories.External; import org.labkey.test.categories.LabModule; +import org.labkey.test.params.FieldDefinition; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.Ext4Helper; import org.labkey.test.util.TextSearcher; @@ -293,34 +294,34 @@ protected void setUpTest() throws Exception private void setUpLC480Assay() throws Exception { - Map resultFields = new HashMap<>(); - resultFields.put("uniqueSample", "Text (String)"); - resultFields.put("nucleicAcidVol", "Number (Double)"); + Map resultFields = new HashMap<>(); + resultFields.put("uniqueSample", FieldDefinition.ColumnType.String); + resultFields.put("nucleicAcidVol", FieldDefinition.ColumnType.Decimal); _helper.defineViralAssayWithAdditionalFields("Viral Loads", LC480 + " " + ASSAY_NAME, null, null, resultFields); } private void setUpLC96Assay() { - Map resultFields = new HashMap<>(); - resultFields.put("uniqueSample", "Text (String)"); - resultFields.put("nucleicAcidVol", "Number (Double)"); - resultFields.put("color", "Text (String)"); - resultFields.put("geneName", "Text (String)"); - resultFields.put("call", "Text (String)"); - resultFields.put("excluded", "Text (String)"); - resultFields.put("cqMean", "Number (Double)"); - resultFields.put("cqError", "Number (Double)"); - resultFields.put("concentrationMean", "Number (Double)"); - resultFields.put("concentrationError", "Number (Double)"); - resultFields.put("replicateGroup", "Text (String)"); - resultFields.put("dye", "Text (String)"); - resultFields.put("editedCall", "Text (String)"); - resultFields.put("slope", "Number (Double)"); - resultFields.put("epf", "Number (Double)"); - resultFields.put("failure", "Text (String)"); - resultFields.put("notes", "Text (String)"); - resultFields.put("samplePrepNotes", "Text (String)"); - resultFields.put("number", "Integer"); + Map resultFields = new HashMap<>(); + resultFields.put("uniqueSample", FieldDefinition.ColumnType.String); + resultFields.put("nucleicAcidVol", FieldDefinition.ColumnType.Decimal); + resultFields.put("color", FieldDefinition.ColumnType.String); + resultFields.put("geneName", FieldDefinition.ColumnType.String); + resultFields.put("call", FieldDefinition.ColumnType.String); + resultFields.put("excluded", FieldDefinition.ColumnType.String); + resultFields.put("cqMean", FieldDefinition.ColumnType.Decimal); + resultFields.put("cqError", FieldDefinition.ColumnType.Decimal); + resultFields.put("concentrationMean", FieldDefinition.ColumnType.Decimal); + resultFields.put("concentrationError", FieldDefinition.ColumnType.Decimal); + resultFields.put("replicateGroup", FieldDefinition.ColumnType.String); + resultFields.put("dye", FieldDefinition.ColumnType.String); + resultFields.put("editedCall", FieldDefinition.ColumnType.String); + resultFields.put("slope", FieldDefinition.ColumnType.Decimal); + resultFields.put("epf", FieldDefinition.ColumnType.Decimal); + resultFields.put("failure", FieldDefinition.ColumnType.String); + resultFields.put("notes", FieldDefinition.ColumnType.String); + resultFields.put("samplePrepNotes", FieldDefinition.ColumnType.String); + resultFields.put("number", FieldDefinition.ColumnType.Integer); _helper.defineViralAssayWithAdditionalFields("Viral Loads", LC96 + " " + ASSAY_NAME, null, null, resultFields); } From 8d83c547df485ea90e1651474b8190d432e3d05c Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sat, 15 Aug 2020 17:48:02 -0700 Subject: [PATCH 18/39] More test fixes --- .../viral_load_assay/assay/ViralLoadAssayDataProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java index 449c26e69..749d88eca 100644 --- a/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java +++ b/Viral_Load_Assay/src/org/labkey/viral_load_assay/assay/ViralLoadAssayDataProvider.java @@ -71,7 +71,7 @@ public JSONObject getTemplateMetadata(ViewContext ctx) domainMeta.put("Run", runMeta); JSONObject resultMeta = getJsonObject(domainMeta, "Results"); - String[] hiddenResultFields = new String[]{"viralLoad", "viralLoadScientific", "copiesPerRxn", "cp", "qcflag", "requestid", "dilutionFactor", "Run", "sampleType", "eluateVol", "volPerRxn", "sourceMaterial"}; + String[] hiddenResultFields = new String[]{"viralLoad", "viralloadoorindicator", "viralLoadScientific", "copiesPerRxn", "cp", "qcflag", "requestid", "dilutionFactor", "Run", "sampleType", "eluateVol", "volPerRxn", "sourceMaterial"}; for (String field : hiddenResultFields) { JSONObject json = getJsonObject(resultMeta, field); From 4384919d14eb04bb07d311ad67009eaaacceaedd Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sat, 15 Aug 2020 18:22:56 -0700 Subject: [PATCH 19/39] Fix SQLServer upgrade scripts --- .../dbscripts/sqlserver/Viral_Load_Assay-12.27-12.28.sql | 4 ---- .../schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.27-12.28.sql b/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.27-12.28.sql index 17951e367..52af38b90 100644 --- a/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.27-12.28.sql +++ b/Viral_Load_Assay/resources/schemas/dbscripts/sqlserver/Viral_Load_Assay-12.27-12.28.sql @@ -1,9 +1,5 @@ -BEGIN; - ALTER TABLE viral_load_assay.nucleic_acid DROP CONSTRAINT pk_nucleic_acid; ALTER TABLE viral_load_assay.nucleic_acid ADD CONSTRAINT pk_nucleic_acid PRIMARY KEY (type); ALTER TABLE viral_load_assay.source_material DROP CONSTRAINT pk_source_material; ALTER TABLE viral_load_assay.source_material ADD CONSTRAINT pk_source_material PRIMARY KEY (type); - -COMMIT; \ No newline at end of file diff --git a/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql b/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql index ff1e3f573..1568424f3 100644 --- a/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql +++ b/ehr/resources/schemas/dbscripts/sqlserver/ehr-20.000-20.001.sql @@ -33,4 +33,4 @@ CREATE TABLE ehr.form_framework_types ( CONSTRAINT PK_form_framework_types PRIMARY KEY (schemaname, queryname) ); -ALTER TABLE ehr.supplemental_pedigree ADD COLUMN species NVARCHAR(4000); +ALTER TABLE ehr.supplemental_pedigree ADD species NVARCHAR(4000); From 9b32f7a962589485170408b6bd6a8ce418bc388d Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sun, 16 Aug 2020 11:55:04 -0700 Subject: [PATCH 20/39] Cascade user delete though ehr_billing.dataaccess Move code from LabModuleHelper to only place that uses it, ViralLoadAssayTest Fix rate import codepath in WNPRC_EHRTest --- .../labModules/ViralLoadAssayTest.java | 37 ++++++++++++++++++- .../labkey/ehr_billing/EHR_BillingModule.java | 27 ++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java b/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java index 20f03e62e..1b80b072f 100644 --- a/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java +++ b/Viral_Load_Assay/test/src/org/labkey/test/tests/external/labModules/ViralLoadAssayTest.java @@ -33,10 +33,13 @@ import org.labkey.test.categories.EHR; import org.labkey.test.categories.External; import org.labkey.test.categories.LabModule; +import org.labkey.test.components.domain.DomainFormPanel; +import org.labkey.test.pages.ReactAssayDesignerPage; import org.labkey.test.params.FieldDefinition; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.Ext4Helper; import org.labkey.test.util.TextSearcher; +import org.labkey.test.util.UIAssayHelper; import org.labkey.test.util.ext4cmp.Ext4ComboRef; import org.labkey.test.util.ext4cmp.Ext4FieldRef; import org.labkey.test.util.ext4cmp.Ext4GridRef; @@ -297,7 +300,37 @@ private void setUpLC480Assay() throws Exception Map resultFields = new HashMap<>(); resultFields.put("uniqueSample", FieldDefinition.ColumnType.String); resultFields.put("nucleicAcidVol", FieldDefinition.ColumnType.Decimal); - _helper.defineViralAssayWithAdditionalFields("Viral Loads", LC480 + " " + ASSAY_NAME, null, null, resultFields); + defineViralAssayWithAdditionalFields("Viral Loads", LC480 + " " + ASSAY_NAME, null, null, resultFields); + } + + public void defineViralAssayWithAdditionalFields(String provider, String label, Map batchFields, Map runFields, Map resultFields) + { + log("Defining a test assay at the project level"); + //define a new assay at the project level + //the pipeline must already be setup + goToProjectHome(); + + //copied from old test + goToManageAssays(); + ReactAssayDesignerPage designerPage = new UIAssayHelper(this).createAssayDesign(provider, label); + + addViralAssayFields(batchFields, designerPage.goToBatchFields()); + addViralAssayFields(runFields, designerPage.goToRunFields()); + // This assay uses "Result" instead of "Results" for its domain name + addViralAssayFields(resultFields, designerPage.expandFieldsPanel("Result")); + + designerPage.clickFinish(); + } + + private void addViralAssayFields(Map fields, DomainFormPanel section) + { + if (fields != null) + { + for (Map.Entry entry : fields.entrySet()) + { + section.addField(new FieldDefinition(entry.getKey(), entry.getValue())); + } + } } private void setUpLC96Assay() @@ -323,7 +356,7 @@ private void setUpLC96Assay() resultFields.put("samplePrepNotes", FieldDefinition.ColumnType.String); resultFields.put("number", FieldDefinition.ColumnType.Integer); - _helper.defineViralAssayWithAdditionalFields("Viral Loads", LC96 + " " + ASSAY_NAME, null, null, resultFields); + defineViralAssayWithAdditionalFields("Viral Loads", LC96 + " " + ASSAY_NAME, null, null, resultFields); } private void ensureABI7500Records() throws CommandException, IOException diff --git a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingModule.java b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingModule.java index 1976ae9af..d863efb41 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingModule.java +++ b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingModule.java @@ -21,6 +21,8 @@ import org.json.JSONObject; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerManager; +import org.labkey.api.data.SimpleFilter; +import org.labkey.api.data.Table; import org.labkey.api.ehr_billing.EHR_BillingDomainKind; import org.labkey.api.ehr_billing.EHR_BillingService; import org.labkey.api.ehr_billing.notification.BillingNotificationProvider; @@ -31,7 +33,10 @@ import org.labkey.api.module.ModuleContext; import org.labkey.api.module.SpringModule; import org.labkey.api.query.DefaultSchema; +import org.labkey.api.query.FieldKey; import org.labkey.api.query.QuerySchema; +import org.labkey.api.security.User; +import org.labkey.api.security.UserManager; import org.labkey.api.security.roles.RoleManager; import org.labkey.api.view.WebPartFactory; import org.labkey.api.writer.ContainerUser; @@ -39,6 +44,7 @@ import org.labkey.ehr_billing.notification.BillingNotificationServiceImpl; import org.labkey.ehr_billing.security.EHR_BillingRole; +import java.beans.PropertyChangeEvent; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -104,6 +110,27 @@ public QuerySchema createSchema(final DefaultSchema schema, Module module) return new EHR_BillingUserSchema(EHR_BillingSchema.NAME, schema.getUser(), schema.getContainer()); } }); + + UserManager.addUserListener(new UserManager.UserListener() + { + @Override + public void userAddedToSite(User user) {} + + @Override + public void userDeletedFromSite(User user) + { + Table.delete(EHR_BillingSchema.getInstance().getDataAccessTable(), new SimpleFilter(FieldKey.fromParts("UserId"), user.getUserId())); + } + + @Override + public void userAccountDisabled(User user) {} + + @Override + public void userAccountEnabled(User user) {} + + @Override + public void propertyChange(PropertyChangeEvent evt) {} + }); } @Override From 747c9e17ef65460212f6cd94b001d278ce91f64b Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sun, 16 Aug 2020 13:32:11 -0700 Subject: [PATCH 21/39] Fix bad merge related to adding QueryWebParts to JS reports --- ehr/resources/web/ehr/reports.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/ehr/resources/web/ehr/reports.js b/ehr/resources/web/ehr/reports.js index 3cbd7e79f..8e790f07d 100644 --- a/ehr/resources/web/ehr/reports.js +++ b/ehr/resources/web/ehr/reports.js @@ -69,8 +69,6 @@ EHR.reports['abstract'] = function(panel, tab){ queryConfig: config }); - addQueryWebPart(tab,config) - config = panel.getQWPConfig({ title: 'Problem List' + title, frame: true, @@ -138,7 +136,6 @@ EHR.reports.pedigree = function(panel, tab){ titleField: 'Id', multiToGrid: true }); - addQueryWebPart(tab,config); var configOffspring = panel.getQWPConfig({ title: 'Offspring' + title, From 2d25cc611f873338564a8ed1f76059a60e3c4ef7 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sun, 16 Aug 2020 14:28:16 -0700 Subject: [PATCH 22/39] Remove uses of methods injected into object prototypes by Ext3 --- ehr/resources/web/ehr/data/BloodDrawClientStore.js | 2 +- ehr/resources/web/ehr/panel/SnapshotPanel.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ehr/resources/web/ehr/data/BloodDrawClientStore.js b/ehr/resources/web/ehr/data/BloodDrawClientStore.js index 39c55dcea..d3d2004ee 100644 --- a/ehr/resources/web/ehr/data/BloodDrawClientStore.js +++ b/ehr/resources/web/ehr/data/BloodDrawClientStore.js @@ -35,7 +35,7 @@ Ext4.define('EHR.data.BloodDrawClientStore', { if (!id || !date) continue; - date = date.format(LABKEY.extDefaultDateFormat); + date = Ext4.util.Format.date(date, LABKEY.extDefaultDateFormat); if (!bloodDrawMap[id]) bloodDrawMap[id] = []; diff --git a/ehr/resources/web/ehr/panel/SnapshotPanel.js b/ehr/resources/web/ehr/panel/SnapshotPanel.js index a9682b094..2fa076e3d 100644 --- a/ehr/resources/web/ehr/panel/SnapshotPanel.js +++ b/ehr/resources/web/ehr/panel/SnapshotPanel.js @@ -433,7 +433,10 @@ Ext4.define('EHR.panel.SnapshotPanel', { animals = row.animals.replace(/( )*,( )*/g, ','); animals = animals.split(','); animals.sort(); - animals = animals.remove(id); + var index = animals.indexOf(id); + if (index !== -1) { + animals = animals.splice(index, 1); + } } pairingType = row.category; From 63851c7b5a9f2ea2f40465da40c1f8db6f04b9ee Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sun, 16 Aug 2020 14:29:41 -0700 Subject: [PATCH 23/39] Remove uses of methods injected into object prototypes by Ext3 --- ehr/resources/web/ehr/panel/WeightGraphPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ehr/resources/web/ehr/panel/WeightGraphPanel.js b/ehr/resources/web/ehr/panel/WeightGraphPanel.js index 34e881ca4..f0228ffe1 100644 --- a/ehr/resources/web/ehr/panel/WeightGraphPanel.js +++ b/ehr/resources/web/ehr/panel/WeightGraphPanel.js @@ -85,7 +85,7 @@ Ext4.define('EHR.panel.WeightGraphPanel', { hoverText: function(row){ var lines = []; - lines.push('Date: ' + row.date.format(LABKEY.extDefaultDateFormat)); + lines.push('Date: ' + Ext4.util.Format.date(row.date, LABKEY.extDefaultDateFormat)); lines.push('Weight: ' + row.weight + ' kg'); lines.push('Latest Weight: ' + row.LatestWeight + ' kg'); if(row.LatestWeightDate) From 36af1c4394f4939d74bf2bd68da19d8559d12d6e Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sun, 16 Aug 2020 16:45:49 -0700 Subject: [PATCH 24/39] Update navMenu from Ext3 to Ext4 and don't pull it into WNPRC with the rest of the Ext3 code --- ehr/resources/web/ehr/ehr_api.lib.xml | 2 + ehr/resources/web/ehr/ext3/ExtOverrides.js | 227 --------------------- ehr/resources/web/ehr/navMenu.js | 122 +++++++++++ 3 files changed, 124 insertions(+), 227 deletions(-) delete mode 100644 ehr/resources/web/ehr/ext3/ExtOverrides.js create mode 100644 ehr/resources/web/ehr/navMenu.js diff --git a/ehr/resources/web/ehr/ehr_api.lib.xml b/ehr/resources/web/ehr/ehr_api.lib.xml index b4effed4c..744ea18fd 100644 --- a/ehr/resources/web/ehr/ehr_api.lib.xml +++ b/ehr/resources/web/ehr/ehr_api.lib.xml @@ -5,6 +5,8 @@