Skip to content

Commit 96d6882

Browse files
committed
Update implementation of study assignment pivot table
1 parent b7cebee commit 96d6882

File tree

4 files changed

+107
-126
lines changed

4 files changed

+107
-126
lines changed

Studies/resources/views/studiesDetails.html

Lines changed: 0 additions & 9 deletions
This file was deleted.

Studies/resources/web/studies/panel/StudiesFilterType.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ Ext4.define('Laboratory.panel.StudiesFilterType', {
7474
return filterArray;
7575
}
7676

77-
var studyName = filters.studies[0];
78-
filterArray.nonRemovable.push(LABKEY.Filter.create(studyFieldName, studyName, LABKEY.Filter.Types.CONTAINS));
77+
const studyName = filters.studies[0];
78+
const projectFieldName = 'allProjectsPivot/' + studyName + '::lastStartDate';
79+
filterArray.nonRemovable.push(LABKEY.Filter.create(projectFieldName, null, LABKEY.Filter.Types.NONBLANK));
7980

8081
return filterArray;
8182
},

Studies/src/org/labkey/studies/query/StudiesTableCustomizer.java

Lines changed: 17 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,21 @@
88
import org.labkey.api.data.BaseColumnInfo;
99
import org.labkey.api.data.ColumnInfo;
1010
import org.labkey.api.data.Container;
11-
import org.labkey.api.data.MutableColumnInfo;
1211
import org.labkey.api.data.TableCustomizer;
1312
import org.labkey.api.data.TableInfo;
1413
import org.labkey.api.ldk.LDKService;
1514
import org.labkey.api.query.ExprColumn;
1615
import org.labkey.api.query.FieldKey;
17-
import org.labkey.api.query.LookupForeignKey;
18-
import org.labkey.api.query.QueryDefinition;
19-
import org.labkey.api.query.QueryException;
16+
import org.labkey.api.query.QueryForeignKey;
2017
import org.labkey.api.query.QueryService;
2118
import org.labkey.api.query.UserSchema;
2219
import org.labkey.api.study.DatasetTable;
23-
import org.labkey.api.study.Study;
2420
import org.labkey.api.study.StudyService;
2521
import org.labkey.api.util.logging.LogHelper;
22+
import org.labkey.studies.StudiesSchema;
2623
import org.labkey.studies.StudiesServiceImpl;
2724

28-
import java.util.ArrayList;
29-
import java.util.List;
25+
import java.util.Objects;
3026

3127
public class StudiesTableCustomizer implements TableCustomizer
3228
{
@@ -81,58 +77,37 @@ private void doCustomize(AbstractTableInfo ati)
8177
addProjectAssignmentColumns(ati);
8278
}
8379

84-
private String getSubjectColName(Container c)
85-
{
86-
Study s = StudyService.get().getStudy(c.isWorkbookOrTab() ? c.getParent() : c);
87-
if (s == null)
88-
{
89-
return null;
90-
}
91-
92-
return s.getSubjectColumnName();
93-
}
94-
9580
private void addProjectAssignmentColumns(AbstractTableInfo ati)
9681
{
9782
final String pivotColName = "allProjectsPivot";
9883
if (ati.getColumn(pivotColName) != null)
99-
return;
100-
101-
List<ColumnInfo> pks = ati.getPkColumns();
102-
ColumnInfo pk;
103-
if (pks.size() == 1)
10484
{
105-
pk = pks.get(0);
85+
return;
10686
}
107-
else
87+
88+
if (!StudiesServiceImpl.get().hasAssignmentDataset(ati.getUserSchema().getContainer()))
10889
{
109-
if (! (ati instanceof DatasetTable))
110-
{
111-
_log.error("Table does not have a single PK column: " + ati.getName());
112-
return;
113-
}
114-
else
115-
{
116-
pk = pks.get(0);
117-
}
90+
return;
11891
}
11992

120-
if (!StudiesServiceImpl.get().hasAssignmentDataset(ati.getUserSchema().getContainer()))
93+
final String subjectColumnName = Objects.requireNonNull(StudyService.get()).getSubjectColumnName(ati.getUserSchema().getContainer().isWorkbookOrTab() ? ati.getUserSchema().getContainer().getParent() : ati.getUserSchema().getContainer());
94+
if (subjectColumnName == null)
12195
{
96+
_log.error("Unable to find the study's subjectColumn in StudiesTableCustomizer");
12297
return;
12398
}
12499

125-
final String subjectSelectName = getSubjectColName(ati.getUserSchema().getContainer());
126-
if (subjectSelectName == null)
100+
ColumnInfo subjectCol = ati.getColumn(subjectColumnName);
101+
if (subjectCol == null)
127102
{
128-
_log.error("Unable to find subjectSelectName in StudiesTableCustomizer");
103+
_log.error("Table lacks the column " + subjectColumnName + ", " + ati.getName());
129104
return;
130105
}
131106

132-
final String pkColSelectName = pk.getFieldKey().toSQLString();
107+
Container target = ati.getUserSchema().getContainer().isWorkbookOrTab() ? ati.getUserSchema().getContainer().getParent() : ati.getUserSchema().getContainer();
133108

134-
final String lookupName = ati.getName() + "_allProjectsPivot";
135-
BaseColumnInfo col2 = new ExprColumn(ati, FieldKey.fromString(pivotColName), pk.getValueSql(ExprColumn.STR_TABLE_ALIAS), pk.getJdbcType(), pk);
109+
UserSchema studiesUs = QueryService.get().getUserSchema(ati.getUserSchema().getUser(), target, StudiesSchema.NAME);
110+
BaseColumnInfo col2 = new ExprColumn(ati, FieldKey.fromString(pivotColName), subjectCol.getValueSql(ExprColumn.STR_TABLE_ALIAS), subjectCol.getJdbcType(), subjectCol);
136111
col2.setLabel("Assignment By Study");
137112
col2.setName(pivotColName);
138113
col2.setCalculated(true);
@@ -144,80 +119,8 @@ private void addProjectAssignmentColumns(AbstractTableInfo ati)
144119
col2.setIsUnselectable(true);
145120
col2.setUserEditable(false);
146121
col2.setKeyField(false);
147-
col2.setFk(new LookupForeignKey(){
148-
@Override
149-
public TableInfo getLookupTableInfo()
150-
{
151-
final UserSchema us = ati.getUserSchema();
152-
Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer();
153-
QueryDefinition qd = createQueryDef(us, lookupName);
154-
155-
qd.setSql(getAssignmentPivotSql(target, ati, pkColSelectName, subjectSelectName));
156-
qd.setIsTemporary(true);
157-
158-
List<QueryException> errors = new ArrayList<>();
159-
TableInfo ti = qd.getTable(errors, true);
160-
161-
if (!errors.isEmpty()){
162-
_log.error("Problem with table customizer: " + ati.getPublicName());
163-
for (QueryException e : errors)
164-
{
165-
_log.error(e.getMessage());
166-
}
167-
}
168-
169-
if (ti != null)
170-
{
171-
MutableColumnInfo col = (MutableColumnInfo) ti.getColumn(pk.getName());
172-
col.setKeyField(true);
173-
col.setHidden(true);
174-
175-
((MutableColumnInfo)ti.getColumn("lastStartDate")).setLabel("Most Recent Assignment Date");
176-
}
177-
178-
return ti;
179-
}
180-
});
122+
col2.setFk(new QueryForeignKey(studiesUs, null, studiesUs, target, StudiesUserSchema.TABLE_ASSIGNMENT_BY_STUDY, subjectColumnName, subjectColumnName));
181123

182124
ati.addColumn(col2);
183125
}
184-
185-
private String getAssignmentPivotSql(Container source, final AbstractTableInfo ati, String pkColSelectName, String subjectSelectName)
186-
{
187-
return "SELECT\n" +
188-
"s." + pkColSelectName + ",\n" +
189-
"p.study,\n" +
190-
"max(p.date) as lastStartDate\n" +
191-
"\n" +
192-
"FROM " + ati.getPublicSchemaName() + "." + ati.getPublicName() + " s\n" +
193-
"JOIN \"" + source.getPath() + "\".study.assignment p\n" +
194-
"ON (s." + subjectSelectName + " = p." + subjectSelectName + ")\n" +
195-
"WHERE s." + subjectSelectName + " IS NOT NULL\n" +
196-
"\n" +
197-
"GROUP BY s." + pkColSelectName + ", p.study\n" +
198-
"PIVOT lastStartDate by study IN (select distinct studyName from studies.studies)";
199-
}
200-
201-
// TODO: move to parent class
202-
protected QueryDefinition createQueryDef(UserSchema us, String queryName)
203-
{
204-
if (!us.getContainer().isWorkbook())
205-
{
206-
return QueryService.get().createQueryDef(us.getUser(), us.getContainer(), us, queryName);
207-
}
208-
209-
// The rationale is that if we are querying from a workbook, preferentially translate to the parent US
210-
// However, there are situations like workbook-scoped lists, where that query might not exist on the parent
211-
UserSchema parentUserSchema = QueryService.get().getUserSchema(us.getUser(), us.getContainer().getParent(), us.getSchemaPath());
212-
assert parentUserSchema != null;
213-
214-
if (parentUserSchema.getTableNames().contains(queryName))
215-
{
216-
return QueryService.get().createQueryDef(parentUserSchema.getUser(), parentUserSchema.getContainer(), parentUserSchema, queryName);
217-
}
218-
else
219-
{
220-
return QueryService.get().createQueryDef(us.getUser(), us.getContainer(), us, queryName);
221-
}
222-
}
223126
}

Studies/src/org/labkey/studies/query/StudiesUserSchema.java

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.labkey.studies.query;
22

3-
import com.google.gwt.user.client.ui.TabBar;
43
import org.apache.logging.log4j.Logger;
54
import org.labkey.api.collections.CaseInsensitiveHashMap;
65
import org.labkey.api.collections.CaseInsensitiveTreeSet;
@@ -9,6 +8,7 @@
98
import org.labkey.api.data.ContainerFilter;
109
import org.labkey.api.data.DbSchema;
1110
import org.labkey.api.data.JdbcType;
11+
import org.labkey.api.data.MutableColumnInfo;
1212
import org.labkey.api.data.SQLFragment;
1313
import org.labkey.api.data.SchemaTableInfo;
1414
import org.labkey.api.data.SimpleFilter;
@@ -22,20 +22,24 @@
2222
import org.labkey.api.query.QueryException;
2323
import org.labkey.api.query.QueryService;
2424
import org.labkey.api.query.SimpleUserSchema;
25+
import org.labkey.api.query.UserSchema;
2526
import org.labkey.api.security.User;
2627
import org.labkey.api.security.permissions.DeletePermission;
2728
import org.labkey.api.security.permissions.InsertPermission;
2829
import org.labkey.api.security.permissions.ReadPermission;
2930
import org.labkey.api.security.permissions.UpdatePermission;
3031
import org.labkey.api.studies.StudiesService;
3132
import org.labkey.api.studies.security.StudiesDataAdminPermission;
33+
import org.labkey.api.study.StudyService;
3234
import org.labkey.api.util.logging.LogHelper;
3335
import org.labkey.studies.StudiesSchema;
36+
import org.labkey.studies.StudiesServiceImpl;
3437

3538
import java.util.ArrayList;
3639
import java.util.Collections;
3740
import java.util.List;
3841
import java.util.Map;
42+
import java.util.Objects;
3943
import java.util.Set;
4044

4145
import static org.labkey.studies.StudiesSchema.TABLE_ANCHOR_EVENTS;
@@ -50,6 +54,7 @@ public class StudiesUserSchema extends SimpleUserSchema
5054
{
5155
private static final Logger _log = LogHelper.getLogger(StudiesUserSchema.class, "Messages related to Studies Service");
5256
private static final String TABLE_EVENT_TYPES = "studyEventTypes";
57+
public static final String TABLE_ASSIGNMENT_BY_STUDY = "assignmentByStudy";
5358

5459
public StudiesUserSchema(User user, Container container, DbSchema dbschema)
5560
{
@@ -63,6 +68,11 @@ public Set<String> getTableNames()
6368
available.add(TABLE_EVENT_TYPES);
6469
available.addAll(getPropertySetNames().keySet());
6570

71+
if (StudiesServiceImpl.get().hasAssignmentDataset(getContainer()))
72+
{
73+
available.add(TABLE_ASSIGNMENT_BY_STUDY);
74+
}
75+
6676
return Collections.unmodifiableSet(available);
6777
}
6878

@@ -160,6 +170,10 @@ else if (TABLE_EVENT_TYPES.equalsIgnoreCase(name))
160170
{
161171
return createEventTypesTable(getContainer());
162172
}
173+
else if (TABLE_ASSIGNMENT_BY_STUDY.equalsIgnoreCase(name))
174+
{
175+
return createAssignmentByStudyTable(getContainer());
176+
}
163177

164178
//try to find it in propertySets
165179
Map<String, Map<String, Object>> nameMap = getPropertySetNames();
@@ -241,6 +255,76 @@ private LookupSetTable createForPropertySet(StudiesUserSchema us, ContainerFilte
241255
return ret.init();
242256
}
243257

258+
private TableInfo createAssignmentByStudyTable(Container c)
259+
{
260+
if (!StudiesServiceImpl.get().hasAssignmentDataset(c))
261+
{
262+
return null;
263+
}
264+
265+
final String subjectSelectName = Objects.requireNonNull(StudyService.get()).getSubjectColumnName(getTargetContainer());
266+
QueryDefinition qd = createQueryDef(TABLE_ASSIGNMENT_BY_STUDY);
267+
qd.setSql(getAssignmentPivotSql(subjectSelectName));
268+
269+
List<QueryException> errors = new ArrayList<>();
270+
TableInfo ti = qd.getTable(errors, true);
271+
if (!errors.isEmpty()){
272+
_log.error("Problem creating: " + TABLE_ASSIGNMENT_BY_STUDY);
273+
for (QueryException e : errors)
274+
{
275+
_log.error(e.getMessage(), e);
276+
}
277+
}
278+
279+
if (ti != null)
280+
{
281+
MutableColumnInfo col = (MutableColumnInfo) ti.getColumn(subjectSelectName);
282+
col.setKeyField(true);
283+
col.setHidden(true);
284+
285+
((MutableColumnInfo)ti.getColumn("lastStartDate")).setLabel("Most Recent Assignment Date");
286+
if (ti instanceof AbstractTableInfo ati)
287+
{
288+
ati.setTitle("Assignment By Study");
289+
}
290+
}
291+
292+
return ti;
293+
}
294+
295+
private String getAssignmentPivotSql(final String subjectSelectName)
296+
{
297+
return "SELECT\n" +
298+
"p." + subjectSelectName + ",\n" +
299+
"p.study,\n" +
300+
"max(p.date) as lastStartDate\n" +
301+
"FROM \"" + getTargetContainer().getPath() + "\".study.assignment p\n" +
302+
"GROUP BY p." + subjectSelectName + ", p.study\n" +
303+
"PIVOT lastStartDate by study IN (select distinct studyName from studies.studies)";
304+
}
305+
306+
private QueryDefinition createQueryDef(String queryName)
307+
{
308+
if (!getContainer().isWorkbook())
309+
{
310+
return QueryService.get().createQueryDef(getUser(), getContainer(), this, queryName);
311+
}
312+
313+
// The rationale is that if we are querying from a workbook, preferentially translate to the parent US
314+
// However, there are situations like workbook-scoped lists, where that query might not exist on the parent
315+
UserSchema parentUserSchema = QueryService.get().getUserSchema(getUser(), getContainer().getParent(), getSchemaPath());
316+
assert parentUserSchema != null;
317+
318+
if (parentUserSchema.getTableNames().contains(queryName))
319+
{
320+
return QueryService.get().createQueryDef(parentUserSchema.getUser(), parentUserSchema.getContainer(), parentUserSchema, queryName);
321+
}
322+
else
323+
{
324+
return QueryService.get().createQueryDef(getUser(), getContainer(), this, queryName);
325+
}
326+
}
327+
244328
private TableInfo createEventTypesTable(Container container)
245329
{
246330
StringBuilder sql = new StringBuilder("SELECT * FROM (");
@@ -283,4 +367,6 @@ private TableInfo createEventTypesTable(Container container)
283367

284368
return ti;
285369
}
370+
371+
286372
}

0 commit comments

Comments
 (0)