diff --git a/SequenceAnalysis/src/org/labkey/sequenceanalysis/SequenceProvider.java b/SequenceAnalysis/src/org/labkey/sequenceanalysis/SequenceProvider.java index b6fc6f47f..092902552 100644 --- a/SequenceAnalysis/src/org/labkey/sequenceanalysis/SequenceProvider.java +++ b/SequenceAnalysis/src/org/labkey/sequenceanalysis/SequenceProvider.java @@ -236,8 +236,8 @@ public List getTabbedReportItems(Container c, User u) TabbedReportItem analyses = new QueryTabbedReportItem(cache, this, SequenceAnalysisSchema.SCHEMA_NAME, SequenceAnalysisSchema.TABLE_ANALYSES, "Sequence Analyses", category); analyses.setSubjectIdFieldKey(FieldKey.fromString("readset/subjectid")); analyses.setSampleDateFieldKey(FieldKey.fromString("readset/sampledate")); - analyses.setAllProjectsFieldKey(FieldKey.fromString("readset/allProjectsPivot")); - analyses.setOverlappingProjectsFieldKey(FieldKey.fromString("readset/overlappingProjectsPivot")); + analyses.setKeyOverride("allProjectsFieldName", FieldKey.fromString("readset/allProjectsPivot")); + analyses.setKeyOverride("overlappingProjectsFieldName", FieldKey.fromString("readset/overlappingProjectsPivot")); analyses.setOwnerKey(owner.getPropertyManagerKey()); analyses.setVisible(owner.isVisible(c, u)); items.add(analyses); @@ -245,8 +245,8 @@ public List getTabbedReportItems(Container c, User u) TabbedReportItem outputs = new QueryTabbedReportItem(cache, this, SequenceAnalysisSchema.SCHEMA_NAME, SequenceAnalysisSchema.TABLE_OUTPUTFILES, "Sequence Outputs", category); outputs.setSubjectIdFieldKey(FieldKey.fromString("readset/subjectid")); outputs.setSampleDateFieldKey(FieldKey.fromString("readset/sampledate")); - outputs.setAllProjectsFieldKey(FieldKey.fromString("readset/allProjectsPivot")); - outputs.setOverlappingProjectsFieldKey(FieldKey.fromString("readset/overlappingProjectsPivot")); + outputs.setKeyOverride("allProjectsFieldName", FieldKey.fromString("readset/allProjectsPivot")); + outputs.setKeyOverride("overlappingProjectsFieldName", FieldKey.fromString("readset/overlappingProjectsPivot")); outputs.setOwnerKey(owner.getPropertyManagerKey()); outputs.setVisible(owner.isVisible(c, u)); items.add(outputs); diff --git a/Studies/resources/web/studies/panel/StudiesFilterType.js b/Studies/resources/web/studies/panel/StudiesFilterType.js new file mode 100644 index 000000000..ede4ebf09 --- /dev/null +++ b/Studies/resources/web/studies/panel/StudiesFilterType.js @@ -0,0 +1,127 @@ +Ext4.define('Laboratory.panel.StudiesFilterType', { + extend: 'LDK.panel.AbstractFilterType', + alias: 'widget.studies-filtertype', + + statics: { + filterName: 'study', + label: 'Studies' + }, + + initComponent: function(){ + this.items = this.getItems(); + + this.callParent(); + }, + + getItems: function(){ + var ctx = this.filterContext; + var toAdd = []; + + toAdd.push({ + width: 200, + html: 'Choose Study:', + style: 'margin-bottom:10px' + }); + + toAdd.push({ + xtype: 'panel', + items: [{ + xtype: 'combo', + width: 265, + itemId: 'studyField', + displayField: 'studyName', + valueField: 'studyName', + multiSelect: false, + store: { + type: 'labkey-store', + schemaName: 'studies', + queryName: 'studies', + autoLoad: true + }, + value: Ext4.isArray(ctx.studies) ? ctx.studies.join(';') : ctx.studies + }] + }); + + return toAdd; + }, + + getFilters: function(){ + return { + studies: this.getStudies() + } + }, + + getFilterArray: function(tab){ + var filterArray = { + removable: [], + nonRemovable: [] + }; + + if (this.reportQCStates?.length) { + filterArray.nonRemovable.push(LABKEY.Filter.create('qcstate/label', this.reportQCStates, LABKEY.Filter.Types.EQUALS_ONE_OF)); + } + + var filters = this.getFilters(); + var report = tab.report; + var studyFieldName = report.additionalFieldKeys?.studyAssignmentFieldKey; + if (!studyFieldName){ + LDK.Utils.logToServer({ + message: 'A TabbedReport is attempting to load a study filter when it should have been stopped upstream', + level: 'ERROR', + includeContext: true + }); + + return filterArray; + } + + var studyName = filters.studies[0]; + filterArray.nonRemovable.push(LABKEY.Filter.create(studyFieldName, studyName, LABKEY.Filter.Types.CONTAINS)); + + return filterArray; + }, + + isValid: function(){ + var val = this.down('#studyField').getValue(); + if (!val || !val.length){ + return false; + } + + return true; + }, + + getFilterInvalidMessage: function(){ + return 'Error: Must choose a study'; + }, + + validateReportForFilterType: function(report){ + if (!report.additionalFieldKeys?.studyAssignmentFieldKey){ + return 'This report cannot be used with the selected filter type, because the report does not contain a field with study assignment information'; + } + + return null; + }, + + getTitle: function(){ + var studies = this.getStudies(); + + if (studies && studies.length){ + return studies.join(', '); + } + + return ''; + }, + + getStudies: function(){ + var projectArray = this.down('#studyField').getValue(); + if (projectArray && !Ext4.isArray(projectArray)) { + projectArray = [projectArray]; + } + + if (projectArray && projectArray.length > 0){ + projectArray = Ext4.unique(projectArray); + projectArray.sort(); + } + + return projectArray; + } +}); \ No newline at end of file diff --git a/Studies/src/org/labkey/studies/StudiesModule.java b/Studies/src/org/labkey/studies/StudiesModule.java index 287ba42ad..b9f880983 100644 --- a/Studies/src/org/labkey/studies/StudiesModule.java +++ b/Studies/src/org/labkey/studies/StudiesModule.java @@ -3,6 +3,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.data.Container; +import org.labkey.api.laboratory.LaboratoryService; import org.labkey.api.ldk.ExtendedSimpleModule; import org.labkey.api.module.Module; import org.labkey.api.module.ModuleContext; @@ -10,8 +11,9 @@ import org.labkey.api.query.QuerySchema; import org.labkey.api.security.roles.RoleManager; import org.labkey.api.studies.StudiesService; -import org.labkey.studies.query.StudiesUserSchema; import org.labkey.api.studies.security.StudiesDataAdminRole; +import org.labkey.studies.query.StudiesUserSchema; +import org.labkey.studies.study.StudiesFilterProvider; import org.labkey.studies.study.StudyEnrollmentEventProvider; import java.util.Collection; @@ -42,6 +44,7 @@ protected void init() StudiesService.setInstance(StudiesServiceImpl.get()); StudiesService.get().registerEventProvider(new StudyEnrollmentEventProvider()); RoleManager.registerRole(new StudiesDataAdminRole()); + LaboratoryService.get().registerTabbedReportFilterProvider(new StudiesFilterProvider()); } @Override diff --git a/Studies/src/org/labkey/studies/study/StudiesFilterProvider.java b/Studies/src/org/labkey/studies/study/StudiesFilterProvider.java new file mode 100644 index 000000000..956d36df4 --- /dev/null +++ b/Studies/src/org/labkey/studies/study/StudiesFilterProvider.java @@ -0,0 +1,73 @@ +package org.labkey.studies.study; + +import org.jetbrains.annotations.NotNull; +import org.labkey.api.data.ColumnInfo; +import org.labkey.api.data.TableInfo; +import org.labkey.api.laboratory.TabbedReportItem; +import org.labkey.api.laboratory.query.TabbedReportFilterProvider; +import org.labkey.api.module.Module; +import org.labkey.api.module.ModuleLoader; +import org.labkey.api.query.FieldKey; +import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.view.template.ClientDependency; +import org.labkey.studies.StudiesModule; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class StudiesFilterProvider implements TabbedReportFilterProvider +{ + @Override + public Module getOwningModule() + { + return ModuleLoader.getInstance().getModule(StudiesModule.class); + } + + @Override + public Collection getClientDependencies() + { + return List.of(ClientDependency.fromPath("studies/panel/StudiesFilterType.js")); + } + + @Override + public String getXType() + { + return "studies-filtertype"; + } + + @Override + public String getLabel() + { + return "Study"; + } + + @Override + public String getInputValue() + { + return "studies"; + } + + @Override + public @NotNull Map getAdditionalFieldKeys(TableInfo ti, TabbedReportItem tri, Map overrides) + { + Map ret = new HashMap<>(); + + if (overrides.get("studyAssignmentFieldKey") == null) + { + FieldKey subject = tri.getSubjectIdFieldKey(); + if (subject != null) + { + subject = subject.getParent(); + } + + FieldKey fk = FieldKey.fromString(subject, "projects/allStudies"); + Map colMap = tri.getQueryCache().getColumns(ti, PageFlowUtil.set(fk)); + if (colMap.containsKey(fk)) + ret.put("studyAssignmentFieldKey", colMap.get(fk).getFieldKey()); + } + + return ret; + } +} diff --git a/singlecell/src/org/labkey/singlecell/SingleCellProvider.java b/singlecell/src/org/labkey/singlecell/SingleCellProvider.java index 7c1b2e9e1..c9bd534f6 100644 --- a/singlecell/src/org/labkey/singlecell/SingleCellProvider.java +++ b/singlecell/src/org/labkey/singlecell/SingleCellProvider.java @@ -173,15 +173,15 @@ public List getTabbedReportItems(Container c, User u) TabbedReportItem sorts = new QueryTabbedReportItem(cache, this, SingleCellSchema.NAME, SingleCellSchema.TABLE_SORTS, "Single Cell Sorts", category); sorts.setSubjectIdFieldKey(FieldKey.fromString("sampleId/subjectId")); sorts.setSampleDateFieldKey(FieldKey.fromString("sampleId/date")); - sorts.setAllProjectsFieldKey(FieldKey.fromString("sampleId/allProjectsPivot")); - sorts.setOverlappingProjectsFieldKey(FieldKey.fromString("sampleId/overlappingProjectsPivot")); + sorts.setKeyOverride("allProjectsFieldName", FieldKey.fromString("sampleId/allProjectsPivot")); + sorts.setKeyOverride("overlappingProjectsFieldName", FieldKey.fromString("sampleId/overlappingProjectsPivot")); items.add(sorts); TabbedReportItem cdnas = new QueryTabbedReportItem(cache, this, SingleCellSchema.NAME, SingleCellSchema.TABLE_CDNAS, "Single Cell Libraries", category); cdnas.setSubjectIdFieldKey(FieldKey.fromString("sortId/sampleId/subjectId")); cdnas.setSampleDateFieldKey(FieldKey.fromString("sortId/sampleId/date")); - cdnas.setAllProjectsFieldKey(FieldKey.fromString("sortId/sampleId/allProjectsPivot")); - cdnas.setOverlappingProjectsFieldKey(FieldKey.fromString("sortId/sampleId/overlappingProjectsPivot")); + cdnas.setKeyOverride("allProjectsFieldName", FieldKey.fromString("sortId/sampleId/allProjectsPivot")); + cdnas.setKeyOverride("overlappingProjectsFieldName", FieldKey.fromString("sortId/sampleId/overlappingProjectsPivot")); items.add(cdnas); return items;