From 2dc043fa65f80b5d84e98124c8f843f7aa3c646c Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Thu, 6 Aug 2026 04:31:22 -0700 Subject: [PATCH 1/3] Use shared treatment link display column factory (#10) ## Rationale Adopt the shared treatment link renderer so this module no longer carries its own copy. The renderer was duplicated across three centers, which meant a recent fix to how the scheduled date is passed had to be repeated here. This depends on the ehrModules change linked below and does not compile until that merges. ## Changes - Replaces the local treatment link display column with the shared one from ehrModules. - This center's form types match the shared defaults, so no overrides are needed and the rendered links are unchanged. --- .../nbri_ehr/table/NBRI_EHRCustomizer.java | 10 +- .../table/TreatmentDisplayColumnFactory.java | 130 ------------------ 2 files changed, 8 insertions(+), 132 deletions(-) delete mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/table/TreatmentDisplayColumnFactory.java diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java b/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java index b365680..4c39ae6 100644 --- a/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java +++ b/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java @@ -36,6 +36,8 @@ import org.labkey.api.ehr.security.EHRDataEntryPermission; import org.labkey.api.ehr.security.EHRVeterinarianPermission; import org.labkey.api.ehr.table.FixedWidthDisplayColumn; +import org.labkey.api.ehr.table.TreatmentLinkConfig; +import org.labkey.api.ehr.table.TreatmentLinkDisplayColumnFactory; import org.labkey.api.exp.api.StorageProvisioner; import org.labkey.api.exp.property.Domain; import org.labkey.api.gwt.client.FacetingBehaviorType; @@ -67,6 +69,10 @@ public class NBRI_EHRCustomizer extends AbstractTableCustomizer { + private static final TreatmentLinkConfig RECORD_TREATMENT = TreatmentLinkConfig.builder() + .formTypes("Behavior", "Behavioral Rounds", "Bulk Behavior Entry") + .build(); + public UserSchema getEHRUserSchema(AbstractTableInfo ds, String name) { Container ehrContainer = EHRService.get().getEHRStudyContainer(ds.getUserSchema().getContainer()); @@ -1008,7 +1014,7 @@ private void customizeTreatmentOrder(AbstractTableInfo ti) { WrappedColumn col = new WrappedColumn(ti.getColumn("objectid"), "treatmentRecord"); col.setLabel("Record Treatment"); - col.setDisplayColumnFactory(new TreatmentDisplayColumnFactory(false)); + col.setDisplayColumnFactory(TreatmentLinkDisplayColumnFactory.forOrder(RECORD_TREATMENT)); ti.addColumn(col); } } @@ -1019,7 +1025,7 @@ private void customizeTreatmentSchedule(AbstractTableInfo ti) { WrappedColumn col = new WrappedColumn(ti.getColumn("objectid"), "treatmentRecord"); col.setLabel("Record Treatment"); - col.setDisplayColumnFactory(new TreatmentDisplayColumnFactory(true)); + col.setDisplayColumnFactory(TreatmentLinkDisplayColumnFactory.forSchedule(RECORD_TREATMENT)); ti.addColumn(col); } } diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/table/TreatmentDisplayColumnFactory.java b/nbri_ehr/src/org/labkey/nbri_ehr/table/TreatmentDisplayColumnFactory.java deleted file mode 100644 index 83db906..0000000 --- a/nbri_ehr/src/org/labkey/nbri_ehr/table/TreatmentDisplayColumnFactory.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2026 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.nbri_ehr.table; - -import org.labkey.api.data.ColumnInfo; -import org.labkey.api.data.DataColumn; -import org.labkey.api.data.DisplayColumn; -import org.labkey.api.data.DisplayColumnFactory; -import org.labkey.api.data.RenderContext; -import org.labkey.api.ehr.security.EHRClinicalEntryPermission; -import org.labkey.api.query.FieldKey; -import org.labkey.api.util.DateUtil; -import org.labkey.api.util.LinkBuilder; -import org.labkey.api.view.ActionURL; -import org.labkey.api.writer.HtmlWriter; - -import java.util.Date; -import java.util.Set; - -/** - * Display column factory for creating Record Treatment links. When includeScheduledDate is set, the row's date is - * passed as the scheduledDate URL parameter, so it should only be set on tables whose date column is the scheduled - * slot being recorded (e.g. treatmentSchedule), not the treatment order's start date. - */ -public class TreatmentDisplayColumnFactory implements DisplayColumnFactory -{ - private final boolean _includeScheduledDate; - - public TreatmentDisplayColumnFactory(boolean includeScheduledDate) - { - _includeScheduledDate = includeScheduledDate; - } - - @Override - public DisplayColumn createRenderer(final ColumnInfo colInfo) - { - return new DataColumn(colInfo){ - - @Override - public void renderGridCellContents(RenderContext ctx, HtmlWriter out) - { - String objectid = (String)getBoundColumn().getValue(ctx); - Date date = (Date)ctx.get("date"); - String caseid = (String)ctx.get("caseid"); - String category = (String)ctx.get("category"); - ActionURL url = new ActionURL("ehr", "dataEntryForm", colInfo.getParentTable().getUserSchema().getContainer()); - if (!colInfo.getParentTable().getUserSchema().getContainer().hasPermission(colInfo.getParentTable().getUserSchema().getUser(), EHRClinicalEntryPermission.class)) - return; - - if (category == null) - return; - - if (category.equals("Behavior")) - { - if (caseid != null) - { - url.addParameter("formType", "Behavioral Rounds"); - url.addParameter("caseid", caseid); - } - else - { - url.addParameter("formType", "Bulk Behavior Entry"); - } - } - else - { - if (caseid != null) - { - url.addParameter("formType", "Clinical Rounds"); - url.addParameter("caseid", caseid); - } - else - { - url.addParameter("formType", "medicationTreatment"); - } - } - - url.addParameter("treatmentid", objectid); - if (_includeScheduledDate && date != null) - url.addParameter("scheduledDate", DateUtil.formatIsoDateShortTime(date)); - - String returnUrl = new ActionURL("ehr", "animalHistory", colInfo.getParentTable().getUserSchema().getContainer()) + "#inputType:none&showReport:0&activeReport:clinMedicationSchedule"; - url.addParameter("returnUrl", returnUrl); - - out.write(LinkBuilder.labkeyLink("Record Treatment", url).target("_blank")); - } - - @Override - public void addQueryFieldKeys(Set keys) - { - super.addQueryFieldKeys(keys); - keys.add(getBoundColumn().getFieldKey()); - keys.add(FieldKey.fromString("date")); - keys.add(FieldKey.fromString("caseid")); - keys.add(FieldKey.fromString("category")); - } - - @Override - public boolean isSortable() - { - return false; - } - - @Override - public boolean isFilterable() - { - return false; - } - - @Override - public boolean isEditable() - { - return false; - } - }; - } -} From 93d4c77acfd4b9dc59a182b1e838516c9efba8e0 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Mon, 10 Aug 2026 12:07:13 -0700 Subject: [PATCH 2/3] Add animal group assignment tracking and recode pairing formation types (#19) ## Rationale Animal group membership had nowhere to live in the NBRI EHR, so there was no record of which animals belonged to which group or when they joined and left. The pairing formation type list is recoded in the same change because it shared the same weakness: free-text labels with no way to retire an option that is no longer offered. ## Changes - Adds an animal group membership dataset that tracks when an animal joins and leaves a group, with a data-entry form for making those assignments. - Ends group memberships automatically when an animal dies or departs, and permits backdated entries since memberships are routinely recorded after the fact. - Surfaces an animal's active groups on demographics, and adds summary queries for group housing by room and for membership overlap across a date range. - Recodes pairing formation types as coded values carrying display titles and disable dates. --- .../data/pairing_formation_types.tsv | 18 +++-- .../study/animalGroupHousingSummary.query.xml | 15 ++++ .../study/animalGroupHousingSummary.sql | 13 ++++ .../study/animalGroupOverlapSummary.query.xml | 22 ++++++ .../study/animalGroupOverlapSummary.sql | 15 ++++ .../study/animalGroupOverlaps.query.xml | 18 +++++ .../queries/study/animalGroupOverlaps.sql | 34 +++++++++ .../study/animalGroupsPivoted.query.xml | 9 +++ .../queries/study/animalGroupsPivoted.sql | 17 +++++ .../study/animal_group_members.query.xml | 42 +++++++++++ .../demographicsActiveAnimalGroups.query.xml | 19 +++++ .../study/demographicsActiveAnimalGroups.sql | 16 +++++ .../queries/study/pairings.query.xml | 1 + .../study/datasets/datasets_manifest.xml | 1 + .../study/datasets/datasets_metadata.xml | 26 +++++++ nbri_ehr/resources/scripts/nbri_triggers.js | 12 +++- .../nbri_ehr/data/AllowAnyIdClientStore.js | 16 +++++ .../model/sources/AnimalGroupMembers.js | 52 ++++++++++++++ .../org/labkey/nbri_ehr/NBRI_EHRModule.java | 5 +- .../form/NBRIGroupAssignmentFormType.java | 48 +++++++++++++ .../NBRIGroupAssignmentFormSection.java | 32 +++++++++ .../history/AnimalGroupsDataSource.java | 52 ++++++++++++++ .../history/AnimalGroupsEndDataSource.java | 71 +++++++++++++++++++ .../nbri_ehr/table/NBRI_EHRCustomizer.java | 15 ++++ 24 files changed, 559 insertions(+), 10 deletions(-) create mode 100644 nbri_ehr/resources/queries/study/animalGroupHousingSummary.query.xml create mode 100644 nbri_ehr/resources/queries/study/animalGroupHousingSummary.sql create mode 100644 nbri_ehr/resources/queries/study/animalGroupOverlapSummary.query.xml create mode 100644 nbri_ehr/resources/queries/study/animalGroupOverlapSummary.sql create mode 100644 nbri_ehr/resources/queries/study/animalGroupOverlaps.query.xml create mode 100644 nbri_ehr/resources/queries/study/animalGroupOverlaps.sql create mode 100644 nbri_ehr/resources/queries/study/animalGroupsPivoted.query.xml create mode 100644 nbri_ehr/resources/queries/study/animalGroupsPivoted.sql create mode 100644 nbri_ehr/resources/queries/study/animal_group_members.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.query.xml create mode 100644 nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.sql create mode 100644 nbri_ehr/resources/web/nbri_ehr/data/AllowAnyIdClientStore.js create mode 100644 nbri_ehr/resources/web/nbri_ehr/model/sources/AnimalGroupMembers.js create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIGroupAssignmentFormType.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIGroupAssignmentFormSection.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsDataSource.java create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsEndDataSource.java diff --git a/nbri_ehr/resources/data/pairing_formation_types.tsv b/nbri_ehr/resources/data/pairing_formation_types.tsv index 64101aa..ed90dde 100644 --- a/nbri_ehr/resources/data/pairing_formation_types.tsv +++ b/nbri_ehr/resources/data/pairing_formation_types.tsv @@ -1,7 +1,11 @@ -value -Full Contact Pair -Group Formation -Introduction -Limited Contact Pair -Pair Formation -Other \ No newline at end of file +value title date_disabled +C Compatible 2026-08-06 +CF CF +CP Continuous pair +F Fought 2026-08-06 +FC Full Contact +IC Intermittent Contact +IG Indoor Group Housing +PC Protected Contact +S Single Housing +U Unsuccessful \ No newline at end of file diff --git a/nbri_ehr/resources/queries/study/animalGroupHousingSummary.query.xml b/nbri_ehr/resources/queries/study/animalGroupHousingSummary.query.xml new file mode 100644 index 0000000..95ce7a9 --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupHousingSummary.query.xml @@ -0,0 +1,15 @@ + + + + + Animal Groups Housing Summary + + + Total Animals + /query/executeQuery.view?schemaName=study&query.queryName=demographics&query.id/curLocation/room~eq=${room}&query.id/activeAnimalGroups/groups~contains=${groupId/title} + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/animalGroupHousingSummary.sql b/nbri_ehr/resources/queries/study/animalGroupHousingSummary.sql new file mode 100644 index 0000000..5ca3a32 --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupHousingSummary.sql @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + m.groupId, + m.id.curLocation.room, + count(distinct m.id) as totalAnimals + +FROM study.animal_group_members m +WHERE m.isActive = true +GROUP BY m.groupId, m.id.curLocation.room diff --git a/nbri_ehr/resources/queries/study/animalGroupOverlapSummary.query.xml b/nbri_ehr/resources/queries/study/animalGroupOverlapSummary.query.xml new file mode 100644 index 0000000..0db6a6c --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupOverlapSummary.query.xml @@ -0,0 +1,22 @@ + + + + + Animal Group Member Summary + This query identifies the total distinct animals that were part of a group over the provided date range + + + /query/executeQuery.view?schemaName=study&query.queryName=animalGroupOverlaps&query.param.StartDate=${StartDate}&query.param.EndDate=${EndDate}&query.groupId/title~eq=${groupId/title} + Total Animals + + + true + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/animalGroupOverlapSummary.sql b/nbri_ehr/resources/queries/study/animalGroupOverlapSummary.sql new file mode 100644 index 0000000..c855540 --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupOverlapSummary.sql @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + o.groupId, + count(distinct o.id) as totalAnimals, + + max(o.StartDate) as StartDate, + max(o.EndDate) as EndDate + +FROM study.animalGroupOverlaps o + +GROUP BY o.groupId diff --git a/nbri_ehr/resources/queries/study/animalGroupOverlaps.query.xml b/nbri_ehr/resources/queries/study/animalGroupOverlaps.query.xml new file mode 100644 index 0000000..92106fe --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupOverlaps.query.xml @@ -0,0 +1,18 @@ + + + + + Animal Group Overlaps + This query identifies distinct animals that were part of a group over the provided date range + + + true + + + true + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/animalGroupOverlaps.sql b/nbri_ehr/resources/queries/study/animalGroupOverlaps.sql new file mode 100644 index 0000000..c5a2e62 --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupOverlaps.sql @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * This query is designed to find distinct animals that were part of a group at a given point in time + */ +PARAMETERS(StartDate TIMESTAMP, EndDate TIMESTAMP) + +SELECT + m.Id, + m.groupId, + + max(StartDate) as StartDate, + max(EndDate) as EndDate +FROM study.animal_group_members m + +WHERE ( + /* entered startdate must be <= entered enddate */ + coalesce( StartDate , cast('1900-01-01 00:00:00.0' as timestamp)) <= coalesce(EndDate, now()) + AND + + /* entered startdate must be less than record's enddate */ + cast(coalesce( StartDate , cast('1900-01-01 00:00:00.0' as DATE)) AS DATE) <= m.enddateCoalesced + + and + + /* entered enddate must be greater than record's startdate */ + cast(coalesce(EndDate, curdate()) AS DATE) >= m.dateOnly + ) + +GROUP BY m.groupId, m.id diff --git a/nbri_ehr/resources/queries/study/animalGroupsPivoted.query.xml b/nbri_ehr/resources/queries/study/animalGroupsPivoted.query.xml new file mode 100644 index 0000000..3ff39fc --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupsPivoted.query.xml @@ -0,0 +1,9 @@ + + + + + Active Groups +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/animalGroupsPivoted.sql b/nbri_ehr/resources/queries/study/animalGroupsPivoted.sql new file mode 100644 index 0000000..5c5c53b --- /dev/null +++ b/nbri_ehr/resources/queries/study/animalGroupsPivoted.sql @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT +g.id, +g.groupId.title as name, +cast('yes' as varchar) as valueField + +FROM study.animal_group_members g + +WHERE (g.enddate IS NULL OR COALESCE(g.enddate, curdate()) >= curdate()) + +GROUP BY g.id, g.groupId.title + +PIVOT valueField by name IN (select title FROM ehr_lookups.breeding_type) diff --git a/nbri_ehr/resources/queries/study/animal_group_members.query.xml b/nbri_ehr/resources/queries/study/animal_group_members.query.xml new file mode 100644 index 0000000..4cf726e --- /dev/null +++ b/nbri_ehr/resources/queries/study/animal_group_members.query.xml @@ -0,0 +1,42 @@ + + + + + Animal Group Members + + + + Date Added + + + Date Removed + false + + + Group + + ehr_lookups + breeding_type + value + title + + + + + core + qcstate + rowid + + + + true + + + false + false + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.query.xml b/nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.query.xml new file mode 100644 index 0000000..f12d8e0 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.query.xml @@ -0,0 +1,19 @@ + + + + + Active Animal Groups + + + + ALWAYS_OFF + Total Groups + + + Groups + + +
+
+
+
diff --git a/nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.sql b/nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.sql new file mode 100644 index 0000000..435a4b4 --- /dev/null +++ b/nbri_ehr/resources/queries/study/demographicsActiveAnimalGroups.sql @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +SELECT + m.Id, + count(distinct m.objectid) as totalGroups, + group_concat(distinct m.name, chr(10)) as groups + +FROM (SELECT Id, + objectid, + groupId.title as name + FROM study.animal_group_members + WHERE enddate is NULL AND qcstate.publicdata = true) m +GROUP BY m.Id diff --git a/nbri_ehr/resources/queries/study/pairings.query.xml b/nbri_ehr/resources/queries/study/pairings.query.xml index 727a724..d75ab6a 100644 --- a/nbri_ehr/resources/queries/study/pairings.query.xml +++ b/nbri_ehr/resources/queries/study/pairings.query.xml @@ -45,6 +45,7 @@ ehr_lookups pairing_formation_types value + title diff --git a/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml index a4cd2a4..fbc9052 100644 --- a/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml +++ b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml @@ -2,6 +2,7 @@ + diff --git a/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml index 2ae212d..aa2bd6a 100644 --- a/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml +++ b/nbri_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -58,6 +58,32 @@ + + Animal Group Members + Records membership of individual primates in named animal groups, with the date the animal joined and the date it was removed. + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + Group + varchar + + +
ArrivalTracks the arrival of primates into the research facility, including source, acquisition type, and associated documentation. diff --git a/nbri_ehr/resources/scripts/nbri_triggers.js b/nbri_ehr/resources/scripts/nbri_triggers.js index 16b2ddc..320c63f 100644 --- a/nbri_ehr/resources/scripts/nbri_triggers.js +++ b/nbri_ehr/resources/scripts/nbri_triggers.js @@ -27,7 +27,7 @@ exports.init = function (EHR) { EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'cases', EHR.Server.TriggerManager.Events.AFTER_DELETE); helper.setScriptOptions({ - datasetsToClose: ['assignment', 'protocolAssignment' , 'housing', 'treatment_order', 'observation_order', 'cases', 'pairings', 'exemptions', 'flags'] + datasetsToClose: ['assignment', 'protocolAssignment' , 'housing', 'treatment_order', 'observation_order', 'cases', 'pairings', 'exemptions', 'flags', 'animal_group_members'] }); }); @@ -54,6 +54,14 @@ exports.init = function (EHR) { }); }); + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'animal_group_members', function(event, helper) { + // group memberships are routinely backdated, so historical dates must not raise a warning + helper.setScriptOptions({ + requiresStatusRecalc: false, + allowDatesInDistantPast: true + }); + }); + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'assignment', function(event, helper) { helper.setScriptOptions({ allowAnyId: isAllowAnyIdRequested(helper), @@ -136,7 +144,7 @@ exports.init = function (EHR) { EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'deaths', function(event, helper) { helper.setScriptOptions({ - datasetsToClose: ['assignment', 'protocolAssignment' , 'housing', 'treatment_order', 'observation_order', 'cases', 'pairings', 'exemptions', 'flags'], + datasetsToClose: ['assignment', 'protocolAssignment' , 'housing', 'treatment_order', 'observation_order', 'cases', 'pairings', 'exemptions', 'flags', 'animal_group_members'], allowShippedIds: false, allowDeadIds: false, requiresStatusRecalc: true, diff --git a/nbri_ehr/resources/web/nbri_ehr/data/AllowAnyIdClientStore.js b/nbri_ehr/resources/web/nbri_ehr/data/AllowAnyIdClientStore.js new file mode 100644 index 0000000..49ecfdb --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/data/AllowAnyIdClientStore.js @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +Ext4.define('NBRI_EHR.data.AllowAnyIdClientStore', { + extend: 'EHR.data.DataEntryClientStore', + + getExtraContext: function () { + var ret = this.callParent(arguments) || {}; + + // Tell the trigger scripts to allow any Id. Requires handling in trigger script to fully enable. + ret['allowAnyId'] = true; + return ret; + } +}); diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/AnimalGroupMembers.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/AnimalGroupMembers.js new file mode 100644 index 0000000..3678d54 --- /dev/null +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/AnimalGroupMembers.js @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('AnimalGroupMembers', { + byQuery: { + 'study.animal_group_members': { + Id: { + xtype: 'ehr-animalIdUpperField', + dataIndex: 'Id', + nullable: false, + allowBlank: false, + lookups: false, + noSaveInTemplateByDefault: true, + columnConfig: { + width: 95, + showLink: false + }, + editorConfig: { + allowAnyId: true + } + }, + date: { + allowBlank: false, + nullable: false, + noSaveInTemplateByDefault: true, + hidden: false, + getInitialValue: function(v, rec){ + if (v) + return v; + + let curDate = new Date(); + curDate.setHours(0, 0, 0, 0); + return curDate; + } + }, + groupId: { + allowBlank: false, + nullable: false, + lookup: { + // the shared default filters on a date column that the breeding type lookup does not have + filterArray: [] + } + }, + performedBy: { + shownInGrid: false, + hidden: true + } + } + } +}); diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java b/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java index aa76225..8cbb3f0 100644 --- a/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java +++ b/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java @@ -136,6 +136,8 @@ protected void doStartupAfterSpringConfig(ModuleContext moduleContext) ehrService.registerDemographicsProvider(new SourceDemographicsProvider(this)); ehrService.registerDemographicsProvider(new NecropsyStatusDemographicsProvider(this)); + EHRService.get().registerHistoryDataSource(new AnimalGroupsDataSource(this)); + EHRService.get().registerHistoryDataSource(new AnimalGroupsEndDataSource(this)); EHRService.get().registerHistoryDataSource(new ArrivalDataSource(this)); EHRService.get().registerHistoryDataSource(new BiopsyDataSource(this)); EHRService.get().registerHistoryDataSource(new BirthDataSource(this)); @@ -177,7 +179,7 @@ protected void doStartupAfterSpringConfig(ModuleContext moduleContext) ehrService.registerActionOverride("participantView", this, "views/participantView.html"); ehrService.registerActionOverride("enterData", this, "views/enterData.html"); - ehrService.registerTriggerScriptOption("datasetsToCloseOnNewEntry", List.of("assignment", "protocolAssignment")); + ehrService.registerTriggerScriptOption("datasetsToCloseOnNewEntry", List.of("assignment", "protocolAssignment", "animal_group_members")); RoleManager.registerRole(new NBRIEHRVetTechRole()); EHRService.get().registerMoreActionsButton(new ShowEditUIButton(this, "ehr", "observation_types", EHRDataAdminPermission.class), "ehr", "observation_types"); @@ -207,6 +209,7 @@ private void registerDataEntry() { EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIAliasFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIAssignmentFormType.class, this)); + EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIGroupAssignmentFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIArrivalFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIBirthFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIBulkClinicalFormType.class, this)); diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIGroupAssignmentFormType.java b/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIGroupAssignmentFormType.java new file mode 100644 index 0000000..5ebea19 --- /dev/null +++ b/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIGroupAssignmentFormType.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 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.nbri_ehr.dataentry.form; + +import org.labkey.api.ehr.dataentry.DataEntryFormContext; +import org.labkey.api.ehr.dataentry.FormSection; +import org.labkey.api.module.Module; +import org.labkey.api.view.template.ClientDependency; +import org.labkey.nbri_ehr.dataentry.section.NBRIAnimalDetailsFormSection; +import org.labkey.nbri_ehr.dataentry.section.NBRIGroupAssignmentFormSection; +import org.labkey.nbri_ehr.dataentry.section.NBRITaskFormSection; + +import java.util.List; + +public class NBRIGroupAssignmentFormType extends NBRIBaseTaskFormType +{ + public static final String NAME = "animalGroupAssignment"; + public static final String LABEL = "Animal Group Assignment"; + + public NBRIGroupAssignmentFormType(DataEntryFormContext ctx, Module owner) + { + super(ctx, owner, NAME, LABEL, "Colony Management", List.of( + new NBRITaskFormSection(), + new NBRIAnimalDetailsFormSection(), + new NBRIGroupAssignmentFormSection(false, true, false) + )); + + addClientDependency(ClientDependency.supplierFromPath("nbri_ehr/model/sources/AnimalGroupMembers.js")); + + for (FormSection s : getFormSections()) + { + s.addConfigSource("AnimalGroupMembers"); + } + } +} diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIGroupAssignmentFormSection.java b/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIGroupAssignmentFormSection.java new file mode 100644 index 0000000..3ef5297 --- /dev/null +++ b/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/section/NBRIGroupAssignmentFormSection.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 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.nbri_ehr.dataentry.section; + +import org.labkey.api.view.template.ClientDependency; + +public class NBRIGroupAssignmentFormSection extends BaseFormSection +{ + public NBRIGroupAssignmentFormSection(boolean allowAnyId, boolean collapsible, boolean initCollapsed) + { + super("study", "animal_group_members", "Group Assignments", "ehr-gridpanel", collapsible, initCollapsed, true); + + if (allowAnyId) + { + setClientStoreClass("NBRI_EHR.data.AllowAnyIdClientStore"); + addClientDependency(ClientDependency.supplierFromPath("nbri_ehr/data/AllowAnyIdClientStore.js")); + } + } +} diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsDataSource.java b/nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsDataSource.java new file mode 100644 index 0000000..69f1ace --- /dev/null +++ b/nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsDataSource.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2026 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.nbri_ehr.history; + +import org.labkey.api.data.Container; +import org.labkey.api.data.Results; +import org.labkey.api.ehr.history.AbstractDataSource; +import org.labkey.api.module.Module; +import org.labkey.api.query.FieldKey; +import org.labkey.api.util.PageFlowUtil; + +import java.sql.SQLException; +import java.util.Set; + +public class AnimalGroupsDataSource extends AbstractDataSource +{ + public AnimalGroupsDataSource(Module module) + { + super("study", "animal_group_members", "Added To Group", "Animal Groups", module); + } + + @Override + protected Set getColumnNames() + { + return PageFlowUtil.set("Id", "date", "enddate", "groupId", "groupId/title"); + } + + @Override + protected String getHtml(Container c, Results rs, boolean redacted) throws SQLException + { + StringBuilder sb = new StringBuilder(); + + FieldKey title = FieldKey.fromString("groupId/title"); + if (rs.hasColumn(title) && rs.getObject(title) != null) + sb.append("Added to group: ").append(rs.getString(title)).append("\n"); + + return sb.toString(); + } +} diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsEndDataSource.java b/nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsEndDataSource.java new file mode 100644 index 0000000..dfdf187 --- /dev/null +++ b/nbri_ehr/src/org/labkey/nbri_ehr/history/AnimalGroupsEndDataSource.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026 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.nbri_ehr.history; + +import org.jetbrains.annotations.NotNull; +import org.labkey.api.data.CompareType; +import org.labkey.api.data.Container; +import org.labkey.api.data.Results; +import org.labkey.api.data.SimpleFilter; +import org.labkey.api.ehr.history.AbstractDataSource; +import org.labkey.api.ehr.history.HistoryRow; +import org.labkey.api.module.Module; +import org.labkey.api.query.FieldKey; +import org.labkey.api.security.User; +import org.labkey.api.util.PageFlowUtil; + +import java.sql.SQLException; +import java.util.List; +import java.util.Set; + +public class AnimalGroupsEndDataSource extends AbstractDataSource +{ + public AnimalGroupsEndDataSource(Module module) + { + super("study", "animal_group_members", "Removed From Group", "Animal Groups", module); + } + + @Override + protected String getDateField() + { + return "enddate"; + } + + @Override + protected @NotNull List getRows(Container c, User u, SimpleFilter filter, boolean redacted) + { + filter.addCondition(FieldKey.fromString(getDateField()), null, CompareType.NONBLANK); + return super.getRows(c, u, filter, redacted); + } + + @Override + protected Set getColumnNames() + { + return PageFlowUtil.set("Id", "date", "enddate", "groupId", "groupId/title"); + } + + @Override + protected String getHtml(Container c, Results rs, boolean redacted) throws SQLException + { + StringBuilder sb = new StringBuilder(); + + FieldKey title = FieldKey.fromString("groupId/title"); + if (rs.hasColumn(title) && rs.getObject(title) != null) + sb.append("Removed from group: ").append(rs.getString(title)).append("\n"); + + return sb.toString(); + } +} diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java b/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java index 4c39ae6..7f4406b 100644 --- a/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java +++ b/nbri_ehr/src/org/labkey/nbri_ehr/table/NBRI_EHRCustomizer.java @@ -932,6 +932,21 @@ private void customizeAnimalTable(AbstractTableInfo ds) prjAssignment.setDescription("Shows all project to which the animal is actively assigned on the current date"); ds.addColumn(prjAssignment); } + if (ds.getColumn("activeAnimalGroups") == null) + { + var activeGroups = getWrappedCol(us, ds, "activeAnimalGroups", "demographicsActiveAnimalGroups", "Id", "Id"); + activeGroups.setLabel("Animal Groups - Active"); + activeGroups.setDescription("Displays the animal groups to which this animal currently belongs"); + ds.addColumn(activeGroups); + } + if (ds.getColumn("animalGroupsPivoted") == null) + { + var groupsPivoted = getWrappedCol(us, ds, "animalGroupsPivoted", "animalGroupsPivoted", "Id", "Id"); + groupsPivoted.setLabel("Active Group Summary"); + groupsPivoted.setHidden(true); + groupsPivoted.setDescription("Displays the active groups for each animal"); + ds.addColumn(groupsPivoted); + } if (ds.getColumn("alias") == null) { var col = getWrappedCol(us, ds, "alias", "demographicsAliases", "Id", "Id"); From dabb1a699b0e2cab05e4ecf161f90647ed4b0c6a Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Mon, 10 Aug 2026 12:08:41 -0700 Subject: [PATCH 3/3] Projects, protocols and investigators (#18) ## Rationale Investigators can now be recorded as EHR reference data rather than as LabKey user accounts, so a PI no longer needs a server login to be named on a project or protocol. Investigator references previously resolved against the core user table, which also limited the name shown to whatever an account's display name happened to be. The protocol domain is trimmed and extended in the same pass to match the fields this institution actually uses. ## Related Pull Requests None. ## Changes - Investigators are maintained as EHR reference data through an admin form, and project and protocol investigator references now point at that list. - Assignment views show an investigator's full name instead of an account display name. - Protocols carry new food, housing, and pairing exemption flags, visible on the protocol grid. - The protocol domain drops fields and a counts table that this institution does not use. --- .../domain-templates/ehr.template.xml | 106 +----------------- .../queries/ehr/investigators.query.xml | 26 +++++ .../resources/queries/ehr/project.query.xml | 8 +- .../resources/queries/ehr/protocol.query.xml | 73 +----------- .../resources/queries/ehr/protocol/.qview.xml | 34 +----- .../queries/ehr/protocol_counts.query.xml | 9 -- .../queries/study/activeAssignments.sql | 2 +- .../web/nbri_ehr/model/sources/Assignment.js | 12 +- .../org/labkey/nbri_ehr/NBRI_EHRModule.java | 1 + .../form/NBRIInvestigatorsFormType.java | 48 ++++++++ 10 files changed, 99 insertions(+), 220 deletions(-) create mode 100644 nbri_ehr/resources/queries/ehr/investigators.query.xml create mode 100644 nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIInvestigatorsFormType.java diff --git a/nbri_ehr/resources/domain-templates/ehr.template.xml b/nbri_ehr/resources/domain-templates/ehr.template.xml index 281f4bd..a29a278 100644 --- a/nbri_ehr/resources/domain-templates/ehr.template.xml +++ b/nbri_ehr/resources/domain-templates/ehr.template.xml @@ -6,118 +6,18 @@ - - diff --git a/nbri_ehr/resources/queries/ehr/investigators.query.xml b/nbri_ehr/resources/queries/ehr/investigators.query.xml new file mode 100644 index 0000000..13d4973 --- /dev/null +++ b/nbri_ehr/resources/queries/ehr/investigators.query.xml @@ -0,0 +1,26 @@ + + + +
+ Investigators + + + + + + + Last Name + true + + + First Name + + + User + http://www.labkey.org/types#userId + + +
+ + + diff --git a/nbri_ehr/resources/queries/ehr/project.query.xml b/nbri_ehr/resources/queries/ehr/project.query.xml index 5b72f21..8ce9715 100644 --- a/nbri_ehr/resources/queries/ehr/project.query.xml +++ b/nbri_ehr/resources/queries/ehr/project.query.xml @@ -49,10 +49,10 @@ true - core - Users - UserId - DisplayName + ehr + investigators + rowid + lastName diff --git a/nbri_ehr/resources/queries/ehr/protocol.query.xml b/nbri_ehr/resources/queries/ehr/protocol.query.xml index 82667e7..edf95db 100644 --- a/nbri_ehr/resources/queries/ehr/protocol.query.xml +++ b/nbri_ehr/resources/queries/ehr/protocol.query.xml @@ -9,78 +9,15 @@ PI false - core - Users - UserId - DisplayName + ehr + investigators + rowid + lastName true - - Author - - core - Users - UserId - DisplayName - - - - Owner - - core - Users - UserId - DisplayName - - - - Protocol Type - - ehr_lookups - protocol_type - value - title - - - - Protocol Category - - ehr_lookups - protocol_category - value - title - - - - Current State - - ehr_lookups - protocol_state - value - title - - - - Parent Protocol - - ehr - protocol - protocol - displayName - - - - Questionnaire - - ehr_lookups - questionnaire - value - title - - Approval Date @@ -88,4 +25,4 @@ - \ No newline at end of file + diff --git a/nbri_ehr/resources/queries/ehr/protocol/.qview.xml b/nbri_ehr/resources/queries/ehr/protocol/.qview.xml index e2e125f..62dfd8e 100644 --- a/nbri_ehr/resources/queries/ehr/protocol/.qview.xml +++ b/nbri_ehr/resources/queries/ehr/protocol/.qview.xml @@ -2,40 +2,14 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - \ No newline at end of file + diff --git a/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml b/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml index 6586f91..82b9060 100644 --- a/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml +++ b/nbri_ehr/resources/queries/ehr/protocol_counts.query.xml @@ -14,15 +14,6 @@ scientific_name - - Euthanasia - - ehr_lookups - euthanasia_type - value - title - - diff --git a/nbri_ehr/resources/queries/study/activeAssignments.sql b/nbri_ehr/resources/queries/study/activeAssignments.sql index 990598c..9cd67a4 100644 --- a/nbri_ehr/resources/queries/study/activeAssignments.sql +++ b/nbri_ehr/resources/queries/study/activeAssignments.sql @@ -6,7 +6,7 @@ SELECT pa.Id, pa.protocol.title AS protocolTitle, pa.protocol.InvestigatorId AS investigatorId, - pa.protocol.InvestigatorId.DisplayName AS investigatorName, + initcap(pa.protocol.InvestigatorId.FirstName) || ' ' || initcap(pa.protocol.InvestigatorId.LastName) AS investigatorName, pa.protocol.InvestigatorId.LastName AS investigatorLastName, a.project.name AS project, a.isActive AS isActiveAssignment, diff --git a/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js b/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js index 4d38d3c..b055afb 100644 --- a/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js +++ b/nbri_ehr/resources/web/nbri_ehr/model/sources/Assignment.js @@ -5,13 +5,12 @@ */ EHR.model.DataModelManager.registerMetadata('Assignment', { - allQueries: { - endDate: { - hidden: true - } - }, byQuery: { 'study.assignment': { + // the dataset column is hidden by default; project assignments are ended by entering an end date + 'enddate': { + hidden: false + }, 'project': { xtype: 'combo', nullable: false, @@ -27,6 +26,9 @@ EHR.model.DataModelManager.registerMetadata('Assignment', { } }, 'study.protocolAssignment': { + 'enddate': { + hidden: true + }, 'project': { hidden: true }, diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java b/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java index 8cbb3f0..b76fdbb 100644 --- a/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java +++ b/nbri_ehr/src/org/labkey/nbri_ehr/NBRI_EHRModule.java @@ -220,6 +220,7 @@ private void registerDataEntry() EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIMedicationTreatmentFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIProjectFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIProtocolFormType.class, this)); + EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIInvestigatorsFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIPregnancyFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIWeightFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NBRIFlagsFormType.class, this)); diff --git a/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIInvestigatorsFormType.java b/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIInvestigatorsFormType.java new file mode 100644 index 0000000..14055b2 --- /dev/null +++ b/nbri_ehr/src/org/labkey/nbri_ehr/dataentry/form/NBRIInvestigatorsFormType.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 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.nbri_ehr.dataentry.form; + +import org.labkey.api.ehr.dataentry.DataEntryFormContext; +import org.labkey.api.ehr.dataentry.forms.AdminLinksFormType; +import org.labkey.api.ehr.security.EHRDataAdminPermission; +import org.labkey.api.module.Module; +import org.labkey.api.view.ActionURL; + +import java.util.ArrayList; + +public class NBRIInvestigatorsFormType extends AdminLinksFormType +{ + public NBRIInvestigatorsFormType(DataEntryFormContext ctx, Module owner) + { + super(ctx, owner, "Investigators", "Investigators", "Admin", new ArrayList<>()); + } + + @Override + protected ActionURL dataEntryLink() + { + ActionURL url = new ActionURL("ldk", "updateQuery", getCtx().getContainer()); + url.addParameter("schemaName", "ehr"); + url.addParameter("query.queryName", "investigators"); + url.addParameter("showImport", "true"); + return url; + } + + @Override + public boolean isAvailable() + { + return (super.isAvailable() || getCtx().getContainer().hasPermission(getCtx().getUser(), EHRDataAdminPermission.class)); + } +}