diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5816605b..26976a1e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,11 @@ jobs: if: github.repository == 'BimberLabInternal/LabDevKitModules' runs-on: ubuntu-latest steps: + # Note: use slight delay in case there are associated commits across repos + - name: "Sleep for 30 seconds" + run: sleep 30s + shell: bash + - name: "Build DISCVR" uses: bimberlabinternal/DevOps/githubActions/discvr-build@master with: diff --git a/LDK/api-src/org/labkey/api/ldk/table/AbstractDataDefinedTable.java b/LDK/api-src/org/labkey/api/ldk/table/AbstractDataDefinedTable.java index a974a4d7..a4e67d92 100644 --- a/LDK/api-src/org/labkey/api/ldk/table/AbstractDataDefinedTable.java +++ b/LDK/api-src/org/labkey/api/ldk/table/AbstractDataDefinedTable.java @@ -194,9 +194,14 @@ protected Map updateRow(User user, Container container, Map { + if (c.isRoot() & user.hasSiteAdminPermission()) + { + trees.add(DeveloperMenuNavTrees.Section.tools, new NavTree("Notification Service Admin", DetailsURL.fromString("ldk/notificationSiteAdmin.view", c).getActionURL())); + } + else if (!c.isRoot() & c.hasPermission(user, AdminPermission.class)) + { + trees.add(DeveloperMenuNavTrees.Section.tools, new NavTree("Notification Service Admin", DetailsURL.fromString("ldk/notificationAdmin.view", c).getActionURL())); + } + }); + AdminConsole.addLink(AdminConsole.SettingsLinkType.Management, "file root usage summary", DetailsURL.fromString("/ldk/folderSizeSummary.view").getActionURL(), ReadPermission.class); if (isSqlServer()) diff --git a/LDK/src/org/labkey/ldk/query/DefaultTableCustomizer.java b/LDK/src/org/labkey/ldk/query/DefaultTableCustomizer.java index c49ec53d..2b16fa5b 100644 --- a/LDK/src/org/labkey/ldk/query/DefaultTableCustomizer.java +++ b/LDK/src/org/labkey/ldk/query/DefaultTableCustomizer.java @@ -118,13 +118,19 @@ private void setDetailsUrl(AbstractTableInfo ti) } String schemaName = ti.getUserSchema().getSchemaName(); - assert schemaName != null; - String queryName = ti.getPublicName(); - assert queryName != null; + if (queryName == null) + { + _log.error("TableInfo.getPublicName() was null", new Exception()); + return; + } List keyFields = ti.getPkColumnNames(); - assert !keyFields.isEmpty() : "No key fields found for the table: " + ti.getPublicSchemaName() + "." + ti.getPublicName(); + if (keyFields.isEmpty()) + { + _log.debug("No key fields found for the table, cannot set details URL: " + ti.getPublicSchemaName() + "." + ti.getPublicName()); + return; + } if (_settings.getPrimaryKeyField() != null) { @@ -169,13 +175,25 @@ else if (_settings.isSetEditLinkOverrides()) { //otherwise apply custom urls String schemaName = ti.getUserSchema().getSchemaName(); - assert schemaName != null; - String queryName = ti.getPublicName(); - assert queryName != null; + if (queryName == null) + { + _log.error("TableInfo.getPublicName() was null", new Exception()); + return; + } List keyFields = ti.getPkColumnNames(); - assert !keyFields.isEmpty() : "No key fields found for the table: " + ti.getPublicSchemaName() + "." + ti.getPublicName(); + if (keyFields.isEmpty()) + { + // There does not seem to be a more direct test for 'is editable' + if (ti.getUpdateService() == null) + { + return; + } + + _log.debug("No key fields found for the table, cannot customize edit UI: " + ti.getPublicSchemaName() + "." + ti.getPublicName()); + return; + } if (_settings.getPrimaryKeyField() != null) { diff --git a/LDK/test/src/org/labkey/test/tests/external/labModules/LabModulesTest.java b/LDK/test/src/org/labkey/test/tests/external/labModules/LabModulesTest.java index 9dd1ccb6..2e858363 100644 --- a/LDK/test/src/org/labkey/test/tests/external/labModules/LabModulesTest.java +++ b/LDK/test/src/org/labkey/test/tests/external/labModules/LabModulesTest.java @@ -47,6 +47,7 @@ import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.ExcelHelper; import org.labkey.test.util.Ext4Helper; +import org.labkey.test.util.LogMethod; import org.labkey.test.util.ext4cmp.Ext4CmpRef; import org.labkey.test.util.ext4cmp.Ext4ComboRef; import org.labkey.test.util.ext4cmp.Ext4FieldRef; @@ -67,6 +68,7 @@ import java.util.Map; import java.util.TimeZone; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -100,93 +102,93 @@ public class LabModulesTest extends BaseWebDriverTest implements AdvancedSqlTest protected static final String IMPORT_DATA_TEXT = "Import Data"; private static final String[][] SUBJECTS = new String[][]{ - {"Participant0001","m","02/03/2001", "02/03/2012"}, - {"Participant0002","f","02/04/2001", null}, - {"Participant0003","f","02/05/2001", null}, - {"Participant0004","f","02/06/2001", null}, - {"Participant0005","m","02/07/2001", null}, - {"Participant0006","m","02/08/2002", null}, - {"Participant0007","m","02/09/2001", null}, - {"Participant0008","f","02/10/2001", null}, - {"Participant0009","m","02/11/2001", null}, - {"Participant0010","m","02/12/2001", null}, - {"Participant0011","f","02/13/2001", null}, - {"Participant0012","f","02/14/2001", null}, - {"Participant0013","f","02/15/2001", null}, - {"Participant0014","f","02/16/2010", null}, - {"Participant0015","f","02/17/2001", null}, - {"Participant0016","f","02/18/2001", null}, - {"Participant0017","f","02/19/2001", null}, - {"Participant0018","m","02/20/2001", null}, - {"Participant0019","m","02/21/2001", null}, - {"Participant0020","m","02/22/2001", null} + {"Participant0001", "m", "02/03/2001", "02/03/2012"}, + {"Participant0002", "f", "02/04/2001", null}, + {"Participant0003", "f", "02/05/2001", null}, + {"Participant0004", "f", "02/06/2001", null}, + {"Participant0005", "m", "02/07/2001", null}, + {"Participant0006", "m", "02/08/2002", null}, + {"Participant0007", "m", "02/09/2001", null}, + {"Participant0008", "f", "02/10/2001", null}, + {"Participant0009", "m", "02/11/2001", null}, + {"Participant0010", "m", "02/12/2001", null}, + {"Participant0011", "f", "02/13/2001", null}, + {"Participant0012", "f", "02/14/2001", null}, + {"Participant0013", "f", "02/15/2001", null}, + {"Participant0014", "f", "02/16/2010", null}, + {"Participant0015", "f", "02/17/2001", null}, + {"Participant0016", "f", "02/18/2001", null}, + {"Participant0017", "f", "02/19/2001", null}, + {"Participant0018", "m", "02/20/2001", null}, + {"Participant0019", "m", "02/21/2001", null}, + {"Participant0020", "m", "02/22/2001", null} }; private static final String[][] SAMPLE_DATA = new String[][]{ - {"Participant0001_RNA","Participant0001","RNA","06/23/2009","Freezer1"}, - {"Participant0002_DNA","Participant0002","DNA","06/23/2005","Freezer1"}, - {"Participant0003_gDNA","Participant0003","gDNA","08/21/2007","Freezer1"}, - {"Participant0004_RNA","Participant0004","RNA","","Freezer1"}, - {"Participant0005_DNA","Participant0005","DNA","08/21/2007","Freezer1"}, - {"Participant0006_gDNA","Participant0006","gDNA","06/23/2009","Freezer1"}, - {"Participant0007_RNA","Participant0007","RNA","","Freezer1"}, - {"Participant0008_DNA","Participant0008","DNA","06/23/2009","Freezer1"}, - {"Participant0009_gDNA","Participant0009","gDNA","","Freezer1"}, - {"Participant0010_RNA","Participant0010","RNA","08/21/2007","Freezer1"}, - {"Participant0011_DNA","Participant0011","DNA","","Freezer1"}, - {"Participant0012_gDNA","Participant0012","gDNA","08/21/2007","Freezer1"}, - {"Participant0013_RNA","Participant0013","RNA","","Freezer1"}, - {"OtherSample","","DNA","","Freezer1"}, - {"Participant0015_gDNA","Participant0015","gDNA","06/23/2009","Freezer1"}, - {"Participant0016_RNA","Participant0016","RNA","08/21/2007","Freezer1"}, - {"Participant0017_DNA","Participant0017","DNA","08/21/2007","Freezer1"}, - {"Participant0018_gDNA","Participant0018","gDNA","02/03/2012","Freezer1"}, - {"OtherSample2","","RNA","","Freezer1"}, - {"Participant0020_DNA","Participant0020","DNA","02/03/2012","Freezer1"}, - {"Participant0001_gDNA","Participant0001","gDNA","04/23/2008","Freezer1"}, - {"Participant0002_RNA","Participant0002","RNA","10/23/2009","Freezer1"}, - {"Participant0003_DNA","Participant0003","DNA","05/02/2001","Freezer1"}, - {"Participant0004_gDNA","Participant0004","gDNA","04/23/2008","Freezer1"} + {"Participant0001_RNA", "Participant0001", "RNA", "06/23/2009", "Freezer1"}, + {"Participant0002_DNA", "Participant0002", "DNA", "06/23/2005", "Freezer1"}, + {"Participant0003_gDNA", "Participant0003", "gDNA", "08/21/2007", "Freezer1"}, + {"Participant0004_RNA", "Participant0004", "RNA", "", "Freezer1"}, + {"Participant0005_DNA", "Participant0005", "DNA", "08/21/2007", "Freezer1"}, + {"Participant0006_gDNA", "Participant0006", "gDNA", "06/23/2009", "Freezer1"}, + {"Participant0007_RNA", "Participant0007", "RNA", "", "Freezer1"}, + {"Participant0008_DNA", "Participant0008", "DNA", "06/23/2009", "Freezer1"}, + {"Participant0009_gDNA", "Participant0009", "gDNA", "", "Freezer1"}, + {"Participant0010_RNA", "Participant0010", "RNA", "08/21/2007", "Freezer1"}, + {"Participant0011_DNA", "Participant0011", "DNA", "", "Freezer1"}, + {"Participant0012_gDNA", "Participant0012", "gDNA", "08/21/2007", "Freezer1"}, + {"Participant0013_RNA", "Participant0013", "RNA", "", "Freezer1"}, + {"OtherSample", "", "DNA", "", "Freezer1"}, + {"Participant0015_gDNA", "Participant0015", "gDNA", "06/23/2009", "Freezer1"}, + {"Participant0016_RNA", "Participant0016", "RNA", "08/21/2007", "Freezer1"}, + {"Participant0017_DNA", "Participant0017", "DNA", "08/21/2007", "Freezer1"}, + {"Participant0018_gDNA", "Participant0018", "gDNA", "02/03/2012", "Freezer1"}, + {"OtherSample2", "", "RNA", "", "Freezer1"}, + {"Participant0020_DNA", "Participant0020", "DNA", "02/03/2012", "Freezer1"}, + {"Participant0001_gDNA", "Participant0001", "gDNA", "04/23/2008", "Freezer1"}, + {"Participant0002_RNA", "Participant0002", "RNA", "10/23/2009", "Freezer1"}, + {"Participant0003_DNA", "Participant0003", "DNA", "05/02/2001", "Freezer1"}, + {"Participant0004_gDNA", "Participant0004", "gDNA", "04/23/2008", "Freezer1"} }; private static final String[][] PROJECT_ENROLLMENT = new String[][]{ - {"Participant0001","Project1","Controls","01/02/2004","08/31/2007"}, - {"Participant0002","Project1","Controls","01/02/2004",""}, - {"Participant0003","Project1","Group A","01/02/2004","9/30/2007"}, - {"Participant0004","Project1","Group A","01/02/2004",""}, - {"Participant0005","Project1","Group A","01/02/2004",""}, - {"Participant0006","Project1","Group B","01/16/2004","9/30/2007"}, - {"Participant0007","Project1","Group B","01/16/2004","12/14/2006"}, - {"Participant0008","Project2","Controls","01/16/2004","12/14/2006"}, - {"Participant0009","Project2","Controls","07/21/2002",""}, - {"Participant0010","Project2","Group A","07/21/2002",""}, - {"Participant0011","Project2","Group A","09/09/2002","09/09/2003"}, - {"Participant0012","Project2","Group A","09/09/2002",""}, - {"Participant0013","Project2","Group B","03/25/2004",""}, - {"Participant0014","Project2","Group B","03/25/2004","03/25/2005"}, - {"Participant0015","Project22","","03/25/2004","03/25/2005"}, - {"Participant0016","Project22","","04/08/2004","04/08/2005"}, - {"Participant0017","Project13","","04/08/2004","04/08/2005"}, - {"Participant0018","Project13","","04/08/2004",""}, - {"Participant0019","Project13","","10/12/2002","10/12/2003"}, - {"Participant0020","Project13","","01/02/2004","01/01/2005"}, - {"Participant0001","Project3","","05/02/2002",""}, - {"Participant0002","Project3","","01/02/2003","08/31/2007"}, - {"Participant0003","Project3","","01/02/2003",""}, - {"Participant0004","Project3","","01/02/2003","9/30/2007"} + {"Participant0001", "Project1", "Controls", "01/02/2004", "08/31/2007"}, + {"Participant0002", "Project1", "Controls", "01/02/2004", ""}, + {"Participant0003", "Project1", "Group A", "01/02/2004", "9/30/2007"}, + {"Participant0004", "Project1", "Group A", "01/02/2004", ""}, + {"Participant0005", "Project1", "Group A", "01/02/2004", ""}, + {"Participant0006", "Project1", "Group B", "01/16/2004", "9/30/2007"}, + {"Participant0007", "Project1", "Group B", "01/16/2004", "12/14/2006"}, + {"Participant0008", "Project2", "Controls", "01/16/2004", "12/14/2006"}, + {"Participant0009", "Project2", "Controls", "07/21/2002", ""}, + {"Participant0010", "Project2", "Group A", "07/21/2002", ""}, + {"Participant0011", "Project2", "Group A", "09/09/2002", "09/09/2003"}, + {"Participant0012", "Project2", "Group A", "09/09/2002", ""}, + {"Participant0013", "Project2", "Group B", "03/25/2004", ""}, + {"Participant0014", "Project2", "Group B", "03/25/2004", "03/25/2005"}, + {"Participant0015", "Project22", "", "03/25/2004", "03/25/2005"}, + {"Participant0016", "Project22", "", "04/08/2004", "04/08/2005"}, + {"Participant0017", "Project13", "", "04/08/2004", "04/08/2005"}, + {"Participant0018", "Project13", "", "04/08/2004", ""}, + {"Participant0019", "Project13", "", "10/12/2002", "10/12/2003"}, + {"Participant0020", "Project13", "", "01/02/2004", "01/01/2005"}, + {"Participant0001", "Project3", "", "05/02/2002", ""}, + {"Participant0002", "Project3", "", "01/02/2003", "08/31/2007"}, + {"Participant0003", "Project3", "", "01/02/2003", ""}, + {"Participant0004", "Project3", "", "01/02/2003", "9/30/2007"} }; private static final String[][] MAJOR_EVENTS = new String[][]{ - {"Participant0001","09/26/2002","Appendectomy","Surgery"}, - {"Participant0002","09/27/2002","Appendectomy","Surgery"}, - {"Participant0003","09/28/2002","Gave Birth","Medical"}, - {"Participant0004","09/29/2002","Vaccination","Medical"}, - {"Participant0005","09/30/2002","Biopsy",""}, - {"Participant0001","11/04/2006","Influenza Infection",""}, - {"Participant0002","11/05/2006","Influenza Infection",""}, - {"Participant0003","11/06/2006","Influenza Infection",""}, - {"Participant0004","11/07/2006","Influenza Infection",""}, - {"Participant0005","11/08/2006","Influenza Infection",""} + {"Participant0001", "09/26/2002", "Appendectomy", "Surgery"}, + {"Participant0002", "09/27/2002", "Appendectomy", "Surgery"}, + {"Participant0003", "09/28/2002", "Gave Birth", "Medical"}, + {"Participant0004", "09/29/2002", "Vaccination", "Medical"}, + {"Participant0005", "09/30/2002", "Biopsy", ""}, + {"Participant0001", "11/04/2006", "Influenza Infection", ""}, + {"Participant0002", "11/05/2006", "Influenza Infection", ""}, + {"Participant0003", "11/06/2006", "Influenza Infection", ""}, + {"Participant0004", "11/07/2006", "Influenza Infection", ""}, + {"Participant0005", "11/08/2006", "Influenza Infection", ""} }; @Override @@ -262,7 +264,7 @@ private void populateData() throws Exception protected void setupAssays() { - for(Pair pair : getAssaysToCreate()) + for (Pair pair : getAssaysToCreate()) { _helper.defineAssay(pair.getKey(), pair.getValue()); } @@ -302,7 +304,7 @@ private void dateParseTest() throws ParseException checkDate("02/20/11", dateFormat3); checkDate("3/5/99", dateFormat3); - String clientFormattedString = (String)executeScript("return Ext4.Date.format(LDK.ConvertUtils.parseDate('2024-01-01', 'c'), 'Y-m-d');"); + String clientFormattedString = (String) executeScript("return Ext4.Date.format(LDK.ConvertUtils.parseDate('2024-01-01', 'c'), 'Y-m-d');"); assertEquals("Incorrect date parsing", "2024-01-01", clientFormattedString); } @@ -314,10 +316,10 @@ private void checkDate(String dateStr, String javaFormatStr) throws ParseExcepti Date expectedDate = format.parse(dateStr); String expectedString = stdFormat.format(expectedDate); - String clientDateStr = (String)executeScript("return (new Date()).toString()"); - String clientFormattedString = (String)executeScript("return Ext4.Date.format(LDK.ConvertUtils.parseDate('" + dateStr + "'), 'Y-m-d');"); + String clientDateStr = (String) executeScript("return (new Date()).toString()"); + String clientFormattedString = (String) executeScript("return Ext4.Date.format(LDK.ConvertUtils.parseDate('" + dateStr + "'), 'Y-m-d');"); - String clientTimezone = (String)executeScript("return Ext4.Date.getTimezone(LDK.ConvertUtils.parseDate('" + dateStr + "'));"); + String clientTimezone = (String) executeScript("return Ext4.Date.getTimezone(LDK.ConvertUtils.parseDate('" + dateStr + "'));"); String serverTimezone = Calendar.getInstance().getTimeZone().getDisplayName(false, TimeZone.SHORT); Date now = new Date(); @@ -347,9 +349,9 @@ private void workbookNumberingTest() throws Exception int idx = 0; for (Map row : resp1.getRows()) { - Integer workbookId = (Integer)row.get("workbookId"); - String container = (String)row.get("container"); - String containerName = (String)row.get("container/name"); + Integer workbookId = (Integer) row.get("workbookId"); + String container = (String) row.get("container"); + String containerName = (String) row.get("container/name"); CreateContainerResponse workbook = workbooks.get(idx); @@ -381,9 +383,9 @@ private void workbookNumberingTest() throws Exception int workbookIdOffset = 1 + highestWorkbookId; for (Map row : resp2.getRows()) { - Integer workbookId = (Integer)row.get("workbookId"); - String container = (String)row.get("container"); - String containerName = (String)row.get("container/name"); + Integer workbookId = (Integer) row.get("workbookId"); + String container = (String) row.get("container"); + String containerName = (String) row.get("container/name"); CreateContainerResponse workbook = workbooks.get(idx); @@ -413,10 +415,14 @@ private int deleteExistingWorkbooks() throws Exception int highestWorkbookId = 0; for (Map row : resp0.getRows()) { - highestWorkbookId = (Integer)row.get("workbookId"); + highestWorkbookId = (Integer) row.get("workbookId"); _apiContainerHelper.deleteWorkbook(getProjectName(), highestWorkbookId, true, 90000); } + log("resetting oligo count"); + _oligosTotal = 0; + verifyOligoCount(0); + return highestWorkbookId; } @@ -429,43 +435,43 @@ private void calculatedColumnsTest() throws Exception Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand sr = new SelectRowsCommand("laboratory", "samples"); List columns = Arrays.asList("samplename", "subjectId", "gender", "sampletype", "sampleDate", - "overlappingProjects/projects", "overlappingProjects/groups", - "allProjects/projects", "allProjects/groups", - "majorEvents/Appendectomy::DaysPostEvent", "majorEvents/Appendectomy::YearsPostEvent", "majorEvents/Gave Birth::DaysPostEvent", "majorEvents/Vaccination::YearsPostEventDecimal", "majorEvents/Biopsy::MonthsPostEvent", "majorEvents/Influenza Infection::DaysPostEvent", - "relativeDates/Project1::DaysPostStart", "relativeDates/Project2::MonthsPostStart", "relativeDates/Project3::YearsPostStartDecimal"); + "overlappingProjects/projects", "overlappingProjects/groups", + "allProjects/projects", "allProjects/groups", + "majorEvents/Appendectomy::DaysPostEvent", "majorEvents/Appendectomy::YearsPostEvent", "majorEvents/Gave Birth::DaysPostEvent", "majorEvents/Vaccination::YearsPostEventDecimal", "majorEvents/Biopsy::MonthsPostEvent", "majorEvents/Influenza Infection::DaysPostEvent", + "relativeDates/Project1::DaysPostStart", "relativeDates/Project2::MonthsPostStart", "relativeDates/Project3::YearsPostStartDecimal"); sr.setColumns(columns); sr.setSorts(Arrays.asList(new Sort("samplename"), new Sort("sampleDate"), new Sort("sampleType"))); SelectRowsResponse resp = sr.execute(cn, getProjectName()); assertEquals("Incorrect number of rows returned", SAMPLE_DATA.length, resp.getRowCount().intValue()); - List colOrder = Arrays.asList("samplename","subjectId","sampledate","sampletype","overlappingProjects/projects","overlappingProjects/groups","allProjects/projects","allProjects/groups","majorEvents/Appendectomy::DaysPostEvent","majorEvents/Appendectomy::YearsPostEvent","majorEvents/Gave Birth::DaysPostEvent","majorEvents/Vaccination::YearsPostEventDecimal","majorEvents/Biopsy::MonthsPostEvent","majorEvents/Influenza Infection::DaysPostEvent","relativeDates/Project1::DaysPostStart","relativeDates/Project2::MonthsPostStart","relativeDates/Project3::YearsPostStartDecimal"); + List colOrder = Arrays.asList("samplename", "subjectId", "sampledate", "sampletype", "overlappingProjects/projects", "overlappingProjects/groups", "allProjects/projects", "allProjects/groups", "majorEvents/Appendectomy::DaysPostEvent", "majorEvents/Appendectomy::YearsPostEvent", "majorEvents/Gave Birth::DaysPostEvent", "majorEvents/Vaccination::YearsPostEventDecimal", "majorEvents/Biopsy::MonthsPostEvent", "majorEvents/Influenza Infection::DaysPostEvent", "relativeDates/Project1::DaysPostStart", "relativeDates/Project2::MonthsPostStart", "relativeDates/Project3::YearsPostStartDecimal"); List expected = new ArrayList<>(); - expected.add(new String[]{"OtherSample",null,null,"DNA",null,null,null,null,null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"OtherSample2",null,null,"RNA",null,null,null,null,null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0001_gDNA","Participant0001","04/23/2008","gDNA","Project3",null,"Project1\nProject3","Project1 (Controls)","2036","5",null,null,null,"536",null,null,"5.9",null}); - expected.add(new String[]{"Participant0001_RNA","Participant0001","06/23/2009","RNA","Project3",null,"Project1\nProject3","Project1 (Controls)","2462","6",null,null,null,"962",null,null,"7.1",null}); - expected.add(new String[]{"Participant0002_DNA","Participant0002","06/23/2005","DNA","Project1\nProject3","Project1 (Controls)","Project1\nProject3","Project1 (Controls)","1000","2",null,null,null,"-500","538",null,"2.4",null}); - expected.add(new String[]{"Participant0002_RNA","Participant0002","10/23/2009","RNA","Project1","Project1 (Controls)","Project1\nProject3","Project1 (Controls)","2583","7",null,null,null,"1083","2121",null,null,null}); - expected.add(new String[]{"Participant0003_DNA","Participant0003","05/02/2001","DNA",null,null,"Project1\nProject3","Project1 (Group A)",null,null,"-514",null,null,"-2014",null,null,null,null}); - expected.add(new String[]{"Participant0003_gDNA","Participant0003","08/21/2007","gDNA","Project1\nProject3","Project1 (Group A)","Project1\nProject3","Project1 (Group A)",null,null,"1788",null,null,"288","1327",null,"4.6",null}); - expected.add(new String[]{"Participant0004_gDNA","Participant0004","04/23/2008","gDNA","Project1","Project1 (Group A)","Project1\nProject3","Project1 (Group A)",null,null,null,"5.5",null,"533","1573",null,null,null}); - expected.add(new String[]{"Participant0004_RNA","Participant0004",null,"RNA",null,null,"Project1\nProject3","Project1 (Group A)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0005_DNA","Participant0005","08/21/2007","DNA","Project1","Project1 (Group A)","Project1","Project1 (Group A)",null,null,null,null,"58","286","1327",null,null,null}); - expected.add(new String[]{"Participant0006_gDNA","Participant0006","06/23/2009","gDNA",null,null,"Project1","Project1 (Group B)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0007_RNA","Participant0007",null,"RNA",null,null,"Project1","Project1 (Group B)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0008_DNA","Participant0008","06/23/2009","DNA",null,null,"Project2","Project2 (Controls)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0009_gDNA","Participant0009",null,"gDNA",null,null,"Project2","Project2 (Controls)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0010_RNA","Participant0010","08/21/2007","RNA","Project2","Project2 (Group A)","Project2","Project2 (Group A)",null,null,null,null,null,null,null,"61",null,null}); - expected.add(new String[]{"Participant0011_DNA","Participant0011",null,"DNA",null,null,"Project2","Project2 (Group A)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0012_gDNA","Participant0012","08/21/2007","gDNA","Project2","Project2 (Group A)","Project2","Project2 (Group A)",null,null,null,null,null,null,null,"59",null,null}); - expected.add(new String[]{"Participant0013_RNA","Participant0013",null,"RNA",null,null,"Project2","Project2 (Group B)",null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0015_gDNA","Participant0015","06/23/2009","gDNA",null,null,"Project22",null,null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0016_RNA","Participant0016","08/21/2007","RNA",null,null,"Project22",null,null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0017_DNA","Participant0017","08/21/2007","DNA",null,null,"Project13",null,null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0018_gDNA","Participant0018","02/03/2012","gDNA","Project13",null,"Project13",null,null,null,null,null,null,null,null,null,null,null}); - expected.add(new String[]{"Participant0020_DNA","Participant0020","02/03/2012","DNA",null,null,"Project13",null,null,null,null,null,null,null,null,null,null,null}); + expected.add(new String[]{"OtherSample", null, null, "DNA", null, null, null, null, null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"OtherSample2", null, null, "RNA", null, null, null, null, null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0001_gDNA", "Participant0001", "04/23/2008", "gDNA", "Project3", null, "Project1\nProject3", "Project1 (Controls)", "2036", "5", null, null, null, "536", null, null, "5.9", null}); + expected.add(new String[]{"Participant0001_RNA", "Participant0001", "06/23/2009", "RNA", "Project3", null, "Project1\nProject3", "Project1 (Controls)", "2462", "6", null, null, null, "962", null, null, "7.1", null}); + expected.add(new String[]{"Participant0002_DNA", "Participant0002", "06/23/2005", "DNA", "Project1\nProject3", "Project1 (Controls)", "Project1\nProject3", "Project1 (Controls)", "1000", "2", null, null, null, "-500", "538", null, "2.4", null}); + expected.add(new String[]{"Participant0002_RNA", "Participant0002", "10/23/2009", "RNA", "Project1", "Project1 (Controls)", "Project1\nProject3", "Project1 (Controls)", "2583", "7", null, null, null, "1083", "2121", null, null, null}); + expected.add(new String[]{"Participant0003_DNA", "Participant0003", "05/02/2001", "DNA", null, null, "Project1\nProject3", "Project1 (Group A)", null, null, "-514", null, null, "-2014", null, null, null, null}); + expected.add(new String[]{"Participant0003_gDNA", "Participant0003", "08/21/2007", "gDNA", "Project1\nProject3", "Project1 (Group A)", "Project1\nProject3", "Project1 (Group A)", null, null, "1788", null, null, "288", "1327", null, "4.6", null}); + expected.add(new String[]{"Participant0004_gDNA", "Participant0004", "04/23/2008", "gDNA", "Project1", "Project1 (Group A)", "Project1\nProject3", "Project1 (Group A)", null, null, null, "5.5", null, "533", "1573", null, null, null}); + expected.add(new String[]{"Participant0004_RNA", "Participant0004", null, "RNA", null, null, "Project1\nProject3", "Project1 (Group A)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0005_DNA", "Participant0005", "08/21/2007", "DNA", "Project1", "Project1 (Group A)", "Project1", "Project1 (Group A)", null, null, null, null, "58", "286", "1327", null, null, null}); + expected.add(new String[]{"Participant0006_gDNA", "Participant0006", "06/23/2009", "gDNA", null, null, "Project1", "Project1 (Group B)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0007_RNA", "Participant0007", null, "RNA", null, null, "Project1", "Project1 (Group B)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0008_DNA", "Participant0008", "06/23/2009", "DNA", null, null, "Project2", "Project2 (Controls)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0009_gDNA", "Participant0009", null, "gDNA", null, null, "Project2", "Project2 (Controls)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0010_RNA", "Participant0010", "08/21/2007", "RNA", "Project2", "Project2 (Group A)", "Project2", "Project2 (Group A)", null, null, null, null, null, null, null, "61", null, null}); + expected.add(new String[]{"Participant0011_DNA", "Participant0011", null, "DNA", null, null, "Project2", "Project2 (Group A)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0012_gDNA", "Participant0012", "08/21/2007", "gDNA", "Project2", "Project2 (Group A)", "Project2", "Project2 (Group A)", null, null, null, null, null, null, null, "59", null, null}); + expected.add(new String[]{"Participant0013_RNA", "Participant0013", null, "RNA", null, null, "Project2", "Project2 (Group B)", null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0015_gDNA", "Participant0015", "06/23/2009", "gDNA", null, null, "Project22", null, null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0016_RNA", "Participant0016", "08/21/2007", "RNA", null, null, "Project22", null, null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0017_DNA", "Participant0017", "08/21/2007", "DNA", null, null, "Project13", null, null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0018_gDNA", "Participant0018", "02/03/2012", "gDNA", "Project13", null, "Project13", null, null, null, null, null, null, null, null, null, null, null}); + expected.add(new String[]{"Participant0020_DNA", "Participant0020", "02/03/2012", "DNA", null, null, "Project13", null, null, null, null, null, null, null, null, null, null, null}); assertEquals("Test has bad values for expected data", SAMPLE_DATA.length, expected.size()); @@ -522,7 +528,7 @@ private void insertSubjects() throws Exception for (String[] arr : SUBJECTS) { - Map rowMap = new HashMap<>(); + Map rowMap = new HashMap<>(); rowMap.put("subjectname", arr[0]); rowMap.put("gender", arr[1]); rowMap.put("birth", arr[2]); @@ -542,7 +548,7 @@ private void insertProjectEnrollment() throws Exception for (String[] arr : PROJECT_ENROLLMENT) { - Map rowMap = new HashMap<>(); + Map rowMap = new HashMap<>(); rowMap.put("subjectId", arr[0]); rowMap.put("project", arr[1]); //NOTE: this is deliberately inserting using empty string, not null. LK is expected to convert that to NULL. If this doesnt happen, @@ -586,7 +592,7 @@ private void insertSamples() throws Exception for (String[] arr : SAMPLE_DATA) { - Map rowMap = new HashMap<>(); + Map rowMap = new HashMap<>(); rowMap.put("samplename", arr[0]); rowMap.put("subjectId", arr[1]); rowMap.put("sampleType", arr[2]); @@ -610,7 +616,7 @@ private void insertMajorEvents() throws Exception for (String[] arr : MAJOR_EVENTS) { - Map rowMap = new HashMap<>(); + Map rowMap = new HashMap<>(); rowMap.put("subjectId", arr[0]); rowMap.put("date", arr[1]); rowMap.put("event", arr[2]); @@ -634,7 +640,7 @@ private void overviewUITest() waitForElement(LabModuleHelper.getNavPanelRow("Sequence:"), WAIT_FOR_PAGE); _helper.verifyNavPanelRowItemPresent("Sequence:"); - for(Pair pair : getAssaysToCreate()) + for (Pair pair : getAssaysToCreate()) { _helper.verifyNavPanelRowItemPresent(pair.getValue() + ":"); assertElementNotPresent(LabModuleHelper.getNavPanelItem(pair.getValue() + ":", IMPORT_DATA_TEXT)); @@ -892,8 +898,8 @@ private void dataSourcesTest() throws Exception SelectRowsResponse resp = sr.execute(cn, getProjectName()); List expected = new ArrayList<>(); - expected.add(new String[]{"Participant0001_gDNA","11","m"}); - expected.add(new String[]{"Participant0001_RNA","11","m"}); + expected.add(new String[]{"Participant0001_gDNA", "11", "m"}); + expected.add(new String[]{"Participant0001_RNA", "11", "m"}); assertEquals("Incorrect number of rows returned", expected.size(), resp.getRowCount().intValue()); @@ -989,7 +995,7 @@ private String replaceNonVisibleChars(String value) private void deleteSourceByLabel(String label, String parentItemId) { Ext4CmpRef panel = _ext4Helper.queryOne("#" + parentItemId, Ext4CmpRef.class); - Long idx = (Long)panel.getFnEval("return this.getSourceIdx(arguments[0])", label); + Long idx = (Long) panel.getFnEval("return this.getSourceIdx(arguments[0])", label); if (idx == null) return; @@ -1125,7 +1131,7 @@ private void settingsTest() Ext4FieldRef.getForBoxLabel(this, "Major Events").setValue(true); sleep(100); - assertTrue("Incorrect value for samples checkbox", (Boolean)_ext4Helper.queryOne(samplesSelector, Ext4FieldRef.class).getValue()); + assertTrue("Incorrect value for samples checkbox", (Boolean) _ext4Helper.queryOne(samplesSelector, Ext4FieldRef.class).getValue()); click(Ext4Helper.Locators.ext4Button("Submit")); new Window.WindowFinder(getDriver()).withTitle("Success").waitFor(); @@ -1193,7 +1199,7 @@ private void labToolsWebpartTest() waitAndClick(_helper.toolIcon("Import Data")); assertElementPresent(Ext4Helper.Locators.menuItem("Sequence")); - for(Pair pair : getAssaysToCreate()) + for (Pair pair : getAssaysToCreate()) { assertElementPresent(Ext4Helper.Locators.menuItem(pair.getValue())); } @@ -1217,7 +1223,8 @@ private void labToolsWebpartTest() goToProjectHome(); } - private void workbookCreationTest() + @LogMethod + private void workbookCreationTest() throws Exception { _helper.goToLabHome(); @@ -1256,15 +1263,39 @@ private void workbookCreationTest() new Window.WindowFinder(getDriver()).withTitle("Success").waitFor(); assertTextPresent("Your upload was successful"); _oligosTotal++; + verifyOligoCount(_oligosTotal); clickButton("OK", 0); _helper.goToLabHome(); } - private void dnaOligosTableTest() + private void verifyOligoCount(int expected) throws Exception + { + log("verifying oligo count, expected: " + expected); + + SelectRowsCommand sr = new SelectRowsCommand("laboratory", "dna_oligos"); + sr.setColumns(Arrays.asList("rowid", "name", "container", "sequence")); + + Connection cn = WebTestHelper.getRemoteApiConnection(); + SelectRowsResponse srr = sr.execute(cn, getCurrentContainerPath()); + + if (expected != srr.getRowCount().intValue()) + { + srr.getRows().forEach(row -> { + log("row: " + row); + }); + } + + String oligoNames = srr.getRows().stream().map(row -> row.get("name").toString()).collect(Collectors.joining(",")); + Assert.assertEquals("Incorrect number of oligos, found: " + oligoNames, expected, srr.getRowCount().intValue()); + } + + @LogMethod + private void dnaOligosTableTest() throws Exception { log("Testing DNA Oligos Table"); _helper.goToLabHome(); + verifyOligoCount(_oligosTotal); _helper.clickNavPanelItem("DNA_Oligos:", IMPORT_DATA_TEXT); new Window.WindowFinder(getDriver()).withTitle(IMPORT_DATA_TEXT).waitFor(); @@ -1277,7 +1308,11 @@ private void dnaOligosTableTest() setFormElement(Locator.name("oligo_type"), "Type1"); sleep(150); //there's a buffer when committing changes clickButton("Submit", 0); + new Window.WindowFinder(getDriver()).withTitle("Success").waitFor(); + assertTextPresent("Your upload was successful!"); + clickButton("OK"); _oligosTotal += 1; + verifyOligoCount(_oligosTotal); _helper.goToLabHome(); _helper.clickNavPanelItem("DNA_Oligos:", IMPORT_DATA_TEXT); @@ -1290,11 +1325,12 @@ private void dnaOligosTableTest() String sequence = "tggGg gGAAAAgg"; setFormElementJS(Locator.name("text"), "Name\tSequence\nTestPrimer1\tatg\nTestPrimer2\t" + sequence); clickButton("Upload", 0); - _oligosTotal += 2; new Window.WindowFinder(getDriver()).withTitle("Success").waitFor(); assertTextPresent("Success! 2 rows inserted."); clickButton("OK"); + _oligosTotal += 2; + verifyOligoCount(_oligosTotal); //verify row imported _helper.goToLabHome(); diff --git a/laboratory/api-src/org/labkey/api/laboratory/TabbedReportItem.java b/laboratory/api-src/org/labkey/api/laboratory/TabbedReportItem.java index 8859393f..d0dc301a 100644 --- a/laboratory/api-src/org/labkey/api/laboratory/TabbedReportItem.java +++ b/laboratory/api-src/org/labkey/api/laboratory/TabbedReportItem.java @@ -46,7 +46,6 @@ public class TabbedReportItem extends AbstractNavItem private final Map _additionalKeys = new HashMap<>(); public static final String OVERRIDES_PROP_KEY = "laboratory.tabItemOverride"; - public static final String FILTER_PROP_KEY = "laboratory.tabItemFilterOverride"; protected static final Logger _log = LogManager.getLogger(TabbedReportItem.class); @@ -177,6 +176,23 @@ public static String getOverridesPropertyKey(NavItem item) return item.getDataProvider().getKey() + "||tabReport||" + item.getReportCategory() + "||" + item.getName() + "||" + item.getLabel(); } + public boolean hasOverride(Container c, String propName) + { + Map map = PropertyManager.getProperties(c, OVERRIDES_PROP_KEY); + if (!map.containsKey(getPropertyManagerKey())) + { + return false; + } + + JSONObject props = new JSONObject(map.get(getPropertyManagerKey())); + if (!props.has(propName)) + { + return false; + } + + return true; + } + public static void applyOverrides(NavItem item, Container c, JSONObject json) { Map map = PropertyManager.getProperties(c, OVERRIDES_PROP_KEY); @@ -188,9 +204,9 @@ public static void applyOverrides(NavItem item, Container c, JSONObject json) if (props.has("reportCategory")) json.put("reportCategory", props.get("reportCategory")); - // retained for settings saved prior to refactor - else if (props.has("category")) - json.put("reportCategory", props.get("category")); + + if (props.has("isDefaultReport")) + json.put("isDefaultReport", props.get("isDefaultReport")); } } } diff --git a/laboratory/api-src/org/labkey/api/laboratory/assay/DefaultAssayParser.java b/laboratory/api-src/org/labkey/api/laboratory/assay/DefaultAssayParser.java index bbcd2ac4..f4e27df3 100644 --- a/laboratory/api-src/org/labkey/api/laboratory/assay/DefaultAssayParser.java +++ b/laboratory/api-src/org/labkey/api/laboratory/assay/DefaultAssayParser.java @@ -20,18 +20,18 @@ import org.apache.commons.beanutils.ConversionException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.json.JSONArray; import org.json.JSONObject; +import org.labkey.api.assay.AssayProvider; +import org.labkey.api.assay.AssayService; import org.labkey.api.collections.CaseInsensitiveHashMap; import org.labkey.api.data.Container; +import org.labkey.api.data.ContainerType; import org.labkey.api.data.ConvertHelper; -import org.labkey.api.data.DbSchema; -import org.labkey.api.data.RuntimeSQLException; import org.labkey.api.data.SimpleFilter; -import org.labkey.api.data.Table; import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; import org.labkey.api.exp.PropertyDescriptor; @@ -44,14 +44,14 @@ import org.labkey.api.laboratory.LaboratoryService; import org.labkey.api.query.BatchValidationException; import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryService; +import org.labkey.api.query.UserSchema; import org.labkey.api.query.ValidationException; import org.labkey.api.reader.ColumnDescriptor; import org.labkey.api.reader.ExcelFactory; import org.labkey.api.reader.Readers; import org.labkey.api.reader.TabLoader; import org.labkey.api.security.User; -import org.labkey.api.assay.AssayProvider; -import org.labkey.api.assay.AssayService; import org.labkey.api.util.FileType; import org.labkey.api.util.JsonUtil; import org.labkey.api.util.Pair; @@ -467,9 +467,10 @@ protected void saveTemplate(ViewContext ctx, int templateId, int runId) throws B try { //validate the template exists - TableInfo ti = DbSchema.get("laboratory").getTable("assay_run_templates"); + UserSchema us = QueryService.get().getUserSchema(ctx.getUser(), ctx.getContainer().getContainerFor(ContainerType.DataType.tabParent), "laboratory"); + TableInfo ti = us.getTable("assay_run_templates"); TableSelector ts = new TableSelector(ti, new SimpleFilter(FieldKey.fromString("rowid"), templateId), null); - if (ts.getRowCount() == 0) + if (!ts.exists()) { throw new BatchValidationException(Collections.singletonList(new ValidationException("Unknown template: " + templateId)), null); } @@ -478,11 +479,11 @@ protected void saveTemplate(ViewContext ctx, int templateId, int runId) throws B row.put("runid", runId); row.put("status", "Complete"); - Table.update(ctx.getUser(), ti, row, templateId); + ti.getUpdateService().updateRows(ctx.getUser(), ctx.getContainer(), Arrays.asList(row), Arrays.asList(Map.of("rowId", templateId)), null, null); } - catch (RuntimeSQLException e) + catch (Exception e) { - throw new BatchValidationException(Collections.singletonList(new ValidationException(e.getSQLException().getMessage())), null); + throw new BatchValidationException(Collections.singletonList(new ValidationException(e.getMessage())), null); } } @@ -584,8 +585,8 @@ protected Map> getTemplateRowMap(ImportContext conte if (templateId == null) return ret; - TableInfo ti = DbSchema.get("laboratory").getTable("assay_run_templates"); - + UserSchema us = QueryService.get().getUserSchema(context.getViewContext().getUser(), context.getViewContext().getContainer().getContainerFor(ContainerType.DataType.tabParent), "laboratory"); + TableInfo ti = us.getTable("assay_run_templates"); TableSelector ts = new TableSelector(ti, new SimpleFilter(FieldKey.fromString("rowid"), templateId), null); Map[] maps = ts.getMapArray(); if (maps.length == 0) diff --git a/laboratory/resources/web/laboratory/panel/AssayImportPanel.js b/laboratory/resources/web/laboratory/panel/AssayImportPanel.js index 34a61bb2..dea79ba4 100644 --- a/laboratory/resources/web/laboratory/panel/AssayImportPanel.js +++ b/laboratory/resources/web/laboratory/panel/AssayImportPanel.js @@ -80,7 +80,7 @@ Ext4.define('Laboratory.panel.AssayImportPanel', { Ext4.Msg.hide(); switch(action.failureType){ case 'client': - Ext4.Msg.alert("One or more fields has a missing or improper value"); + Ext4.Msg.alert("Error", "One or more fields has a missing or improper value"); break; default: this.handleFailure(action.response); diff --git a/laboratory/resources/web/laboratory/panel/CustomizeDataBrowserPanel.js b/laboratory/resources/web/laboratory/panel/CustomizeDataBrowserPanel.js index 49b3b789..0df95d10 100644 --- a/laboratory/resources/web/laboratory/panel/CustomizeDataBrowserPanel.js +++ b/laboratory/resources/web/laboratory/panel/CustomizeDataBrowserPanel.js @@ -69,6 +69,9 @@ Ext4.define('Laboratory.panel.CustomizeDataBrowserPanel', { },{ html: 'Visible?', style: 'padding-bottom: 5px;margin-left: 5px;' + },{ + html: 'Default Report?', + style: 'padding-bottom: 5px;margin-left: 5px;' }]; items = LDK.Utils.sortByProperty(items, 'name', false); @@ -90,9 +93,14 @@ Ext4.define('Laboratory.panel.CustomizeDataBrowserPanel', { width: 300, value: item.label },{ - xtype: 'displayfield', - value: item.visible, + xtype: 'checkbox', + checked: item.visible, style: 'margin-left: 15px;' + },{ + xtype: 'radio', + name: 'isDefaultReport', + inputValue: true, + checked: item.isDefaultReport }]); }, this); @@ -100,7 +108,7 @@ Ext4.define('Laboratory.panel.CustomizeDataBrowserPanel', { itemId: 'theTable', layout: { type: 'table', - columns: 4 + columns: 5 }, border: false, defaults: { @@ -117,15 +125,17 @@ Ext4.define('Laboratory.panel.CustomizeDataBrowserPanel', { doSave: function(btn){ var toSave = {}; var items = btn.up('form').down('#theTable').items; - var cols = 4; + var cols = 5; var rows = (items.getCount() / cols); for (var i=1;i results = new HashMap<>(); WritablePropertyMap propMap = PropertyManager.getWritableProperties(getContainer(), TabbedReportItem.OVERRIDES_PROP_KEY, true); + WritablePropertyMap visibilityMap = PropertyManager.getWritableProperties(getContainer(), NavItem.PROPERTY_CATEGORY, true); + boolean shouldSaveVisibility = false; List tabbedReports = LaboratoryService.get().getTabbedReportItems(getContainer(), getUser()); Map reportMap = new HashMap<>(); @@ -1669,7 +1671,7 @@ public ApiResponse execute(JsonDataForm form, BindException errors) JSONObject json = new JSONObject(form.getJsonData()); for (String key : json.keySet()) { - JSONObject toSave= new JSONObject(); + JSONObject toSave = new JSONObject(); TabbedReportItem ti = reportMap.get(key); if (ti == null) @@ -1685,13 +1687,49 @@ public ApiResponse execute(JsonDataForm form, BindException errors) if (reportCategory != null && !ti.getReportCategory().equals(reportCategory)) toSave.put("reportCategory", reportCategory); - if (!toSave.keySet().isEmpty()) + String isDefaultReport = StringUtils.trimToNull(props.optString("isDefaultReport")); + if (isDefaultReport != null) + { + if (!ti.hasOverride(getContainer(), "isDefaultReport")) + { + if ("true".equals(isDefaultReport)) + { + toSave.put("isDefaultReport", isDefaultReport); + } + } + else + { + toSave.put("isDefaultReport", isDefaultReport); + } + } + + String isVisible = StringUtils.trimToNull(props.optString("isVisible")); + if (isVisible != null) + { + if (!isVisible.equals(visibilityMap.get(ti.getPropertyManagerKey()))) + { + visibilityMap.put(ti.getPropertyManagerKey(), isVisible); + shouldSaveVisibility = true; + } + } + + if (!toSave.isEmpty()) + { propMap.put(key, toSave.toString()); - else propMap.remove(key); + } + else + { + propMap.remove(key); + } } propMap.save(); + if (shouldSaveVisibility) + { + visibilityMap.save(); + } + results.put("success", true); return new ApiSimpleResponse(results); } diff --git a/laboratory/src/org/labkey/laboratory/LaboratoryModule.java b/laboratory/src/org/labkey/laboratory/LaboratoryModule.java index 6cb8a7d8..d4e111b1 100644 --- a/laboratory/src/org/labkey/laboratory/LaboratoryModule.java +++ b/laboratory/src/org/labkey/laboratory/LaboratoryModule.java @@ -197,6 +197,10 @@ protected void doStartupAfterSpringConfig(ModuleContext moduleContext) LDKService.get().registerQueryButton(btn4, LaboratoryModule.SCHEMA_NAME, LaboratorySchema.TABLE_SAMPLES); LDKService.get().registerQueryButton(new ShowBulkEditButton(this, LaboratoryModule.SCHEMA_NAME, LaboratorySchema.TABLE_SAMPLES), LaboratoryModule.SCHEMA_NAME, LaboratorySchema.TABLE_SAMPLES); + + SimpleButtonConfigFactory btn5 = new SimpleButtonConfigFactory(this, "Manage Freezers", DetailsURL.fromString("/query/executeQuery.view?schemaName=laboratory&query.queryName=freezers")); + btn5.setPermission(LaboratoryAdminPermission.class); + LDKService.get().registerQueryButton(btn5, LaboratoryModule.SCHEMA_NAME, LaboratorySchema.TABLE_SAMPLES); } @Override diff --git a/laboratory/src/org/labkey/laboratory/LaboratoryUserSchema.java b/laboratory/src/org/labkey/laboratory/LaboratoryUserSchema.java index bfefbb45..324a7a2f 100644 --- a/laboratory/src/org/labkey/laboratory/LaboratoryUserSchema.java +++ b/laboratory/src/org/labkey/laboratory/LaboratoryUserSchema.java @@ -67,7 +67,7 @@ else if (LaboratorySchema.TABLE_SAMPLES.equalsIgnoreCase(name)) return super.createWrappedTable(name, sourceTable, cf); } - private SimpleTable getSubjectsTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) + private SimpleTable getSubjectsTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) { return new ContainerScopedTable<>(this, schematable, cf, "subjectname").init(); } @@ -77,27 +77,27 @@ private TableInfo getContainerScopedTable(String name, @NotNull TableInfo schema return new ContainerScopedTable<>(this, schematable, cf, pkCol).init(); } - private SimpleTable getDnaOligosTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) + private SimpleTable getDnaOligosTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) { return new ContainerIncrementingTable(this, schematable, cf, "oligo_id").init(); } - private SimpleTable getSamplesTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) + private SimpleTable getSamplesTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) { return new ContainerIncrementingTable(this, schematable, cf, "freezerid").init(); } - private SimpleTable getPeptideTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) + private SimpleTable getPeptideTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) { return new ContainerIncrementingTable(this, schematable, cf, "peptideId").init(); } - private SimpleTable getAntibodiesTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) + private SimpleTable getAntibodiesTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) { return new ContainerIncrementingTable(this, schematable, cf, "antibodyId").init(); } - private SimpleTable getWorkbooksTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) + private SimpleTable getWorkbooksTable(String name, @NotNull TableInfo schematable, ContainerFilter cf) { return new LaboratoryWorkbooksTable(this, schematable, cf).init(); } diff --git a/laboratory/src/org/labkey/laboratory/assay/AssayHelper.java b/laboratory/src/org/labkey/laboratory/assay/AssayHelper.java index ee4a9816..3076ea5c 100644 --- a/laboratory/src/org/labkey/laboratory/assay/AssayHelper.java +++ b/laboratory/src/org/labkey/laboratory/assay/AssayHelper.java @@ -32,9 +32,9 @@ import org.labkey.api.collections.CollectionUtils; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerManager; -import org.labkey.api.data.RuntimeSQLException; +import org.labkey.api.data.ContainerType; +import org.labkey.api.data.SimpleFilter; import org.labkey.api.data.TSVMapWriter; -import org.labkey.api.data.Table; import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; import org.labkey.api.exp.ChangePropertyDescriptorException; @@ -51,8 +51,12 @@ import org.labkey.api.laboratory.assay.AssayDataProvider; import org.labkey.api.laboratory.assay.AssayImportMethod; import org.labkey.api.query.BatchValidationException; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryService; +import org.labkey.api.query.UserSchema; import org.labkey.api.query.ValidationException; import org.labkey.api.security.User; +import org.labkey.api.security.permissions.UpdatePermission; import org.labkey.api.util.FileUtil; import org.labkey.api.util.Pair; import org.labkey.api.view.ActionURL; @@ -66,6 +70,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -125,27 +130,27 @@ public Map saveTemplate(User u, Container c, ExpProtocol protoco { validateTemplate(u, c, protocol, templateId, title, importMethod, json); - TableInfo ti = LaboratorySchema.getInstance().getSchema().getTable(LaboratorySchema.TABLE_ASSAY_RUN_TEMPLATES); + UserSchema us = QueryService.get().getUserSchema(u, c, "laboratory"); + TableInfo ti = us.getTable(LaboratorySchema.TABLE_ASSAY_RUN_TEMPLATES); Map row = new HashMap<>(); row.put("assayId", protocol.getRowId()); row.put("title", title); row.put("importMethod", importMethod); row.put("json", json.toString()); - row.put("container", c.getId()); if (templateId == null) { - row = Table.insert(u, ti, row); + ti.getUpdateService().insertRows(u, c, Arrays.asList(row), null, null, null); } else { row.put("rowid", templateId); - row = Table.update(u, ti, row, templateId); + ti.getUpdateService().updateRows(u, c, Arrays.asList(row), Arrays.asList(Map.of("rowId", templateId)), null, null); } return row; } - catch (RuntimeSQLException e) + catch (Exception e) { _log.error(e.getMessage(), e); errors.addRowError(new ValidationException(e.getMessage())); @@ -153,7 +158,7 @@ public Map saveTemplate(User u, Container c, ExpProtocol protoco } } - public void validateTemplate(User u, Container c, ExpProtocol protocol, Integer templateId, String title, String importMethod, JSONObject json) throws BatchValidationException + public void validateTemplate(User u, Container c, ExpProtocol protocol, @Nullable Integer templateId, String title, String importMethod, JSONObject json) throws BatchValidationException { BatchValidationException errors = new BatchValidationException(); @@ -178,6 +183,42 @@ public void validateTemplate(User u, Container c, ExpProtocol protocol, Integer throw errors; } + // Verify if this template exists and permissions: + if (templateId != null) + { + UserSchema us = QueryService.get().getUserSchema(u, c.getContainerFor(ContainerType.DataType.tabParent), "laboratory"); + TableInfo ti = us.getTable("assay_run_templates"); + TableSelector ts = new TableSelector(ti, new SimpleFilter(FieldKey.fromString("rowId"), templateId), null); + if (ts.exists()) + { + Container rowContainer = ContainerManager.getForId(ts.getObject(String.class)); + if (rowContainer == null) + { + errors.addRowError(new ValidationException("Unable to determine the container for template: " + templateId)); + throw errors; + } + + if (!rowContainer.hasPermission("AssayHelper.validateTemplate()", u, UpdatePermission.class)) + { + errors.addRowError(new ValidationException("The current user does not have permission to edit template: " + templateId)); + throw errors; + } + } + else + { + errors.addRowError(new ValidationException("Unable to find template with ID: " + templateId)); + throw errors; + } + } + else + { + if (!c.hasPermission("AssayHelper.validateTemplate()", u, UpdatePermission.class)) + { + errors.addRowError(new ValidationException("The current user does not have permission to creates templates in folder: " + c.getName())); + throw errors; + } + } + method.validateTemplate(u, c, protocol, templateId, title, json, errors); if (errors.hasErrors()) diff --git a/laboratory/src/org/labkey/laboratory/view/dataBrowser.jsp b/laboratory/src/org/labkey/laboratory/view/dataBrowser.jsp index 70beda3c..137d72de 100644 --- a/laboratory/src/org/labkey/laboratory/view/dataBrowser.jsp +++ b/laboratory/src/org/labkey/laboratory/view/dataBrowser.jsp @@ -27,6 +27,11 @@ public void addClientDependencies(ClientDependencies dependencies) { dependencies.add("laboratory.context"); + dependencies.add("/laboratory/panel/DataBrowserPanel.js"); + dependencies.add("LDK/panel/AbstractFilterType.js"); + dependencies.add("LDK/panel/SingleSubjectFilterType.js"); + dependencies.add("LDK/panel/MultiSubjectFilterType.js"); + dependencies.add("LDK/panel/NoFiltersFilterType.js"); } private String getFilterConfig() @@ -59,53 +64,13 @@
\ No newline at end of file