diff --git a/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicController.java b/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicController.java index e175e68c..4e8dcf0d 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicController.java +++ b/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicController.java @@ -178,6 +178,7 @@ import org.labkey.panoramapublic.query.ExperimentAnnotationsManager; import org.labkey.panoramapublic.query.JournalManager; import org.labkey.panoramapublic.query.ModificationInfoManager; +import org.labkey.panoramapublic.query.MyDataTableInfo; import org.labkey.panoramapublic.query.PxXmlManager; import org.labkey.panoramapublic.query.SpecLibInfoManager; import org.labkey.panoramapublic.query.SubmissionManager; @@ -8952,7 +8953,7 @@ public ModelAndView getView(IdForm form, BindException errors) ensureCorrectContainer(getContainer(), expAnnotations.getContainer(), getViewContext()); // container check - return new CatalogEntryWebPart(expAnnotations, getUser(), true); + return new CatalogEntryWebPart(expAnnotations, getUser(), form.getReturnActionURL(PageFlowUtil.urlProvider(ProjectUrls.class).getBeginURL(getContainer()))); } @Override @@ -9183,6 +9184,34 @@ public ModelAndView getView(Object o, BindException errors) } } + @RequiresPermission(ReadPermission.class) + @RequiresLogin + public class MyDataViewAction extends SimpleViewAction + { + @Override + public void addNavTrail(NavTree root) + { + root.addChild("My Panorama Public Data"); + } + + @Override + public ModelAndView getView(Object o, BindException errors) throws Exception + { + QuerySettings settings = new QuerySettings(getViewContext(), MyDataTableInfo.NAME, MyDataTableInfo.NAME); + settings.setContainerFilterName(ContainerFilter.Type.CurrentAndSubfolders.name()); + QueryView view = new QueryView(new PanoramaPublicSchema(getUser(), getContainer()), settings, errors); + view.setTitle("Panorama Public Experiments"); + view.setShowRecordSelectors(false); + view.setShowExportButtons(false); + view.setShowDetailsColumn(false); + view.setShowDeleteButton(false); + view.setShowUpdateColumn(false); + view.setShowInsertNewButton(false); + view.disableContainerFilterSelection(); + return view; + } + } + // ------------------------------------------------------------------------ // BEGIN Assign PanoramaPublicSubmitterRole to data submitters and lab heads // ------------------------------------------------------------------------ diff --git a/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicSchema.java b/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicSchema.java index 6b37837d..556fe805 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicSchema.java +++ b/panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicSchema.java @@ -54,6 +54,7 @@ import org.labkey.panoramapublic.query.DataValidationTableInfo; import org.labkey.panoramapublic.query.ExperimentAnnotationsTableInfo; import org.labkey.panoramapublic.query.JournalExperimentTableInfo; +import org.labkey.panoramapublic.query.MyDataTableInfo; import org.labkey.panoramapublic.query.PanoramaPublicTable; import org.labkey.panoramapublic.query.SubmissionTableInfo; import org.labkey.panoramapublic.query.modification.ExperimentIsotopeModInfoTableInfo; @@ -129,6 +130,10 @@ public TableInfo createTable(String name, ContainerFilter cf) { return new ExperimentAnnotationsTableInfo(this, cf); } + if (MyDataTableInfo.NAME.equalsIgnoreCase(name)) + { + return new MyDataTableInfo(this, cf, getUser()); + } if (TABLE_JOURNAL_EXPERIMENT.equalsIgnoreCase(name)) { return new JournalExperimentTableInfo(this, cf); diff --git a/panoramapublic/src/org/labkey/panoramapublic/query/ExperimentAnnotationsTableInfo.java b/panoramapublic/src/org/labkey/panoramapublic/query/ExperimentAnnotationsTableInfo.java index 45f3c317..0b4372b8 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/query/ExperimentAnnotationsTableInfo.java +++ b/panoramapublic/src/org/labkey/panoramapublic/query/ExperimentAnnotationsTableInfo.java @@ -53,6 +53,7 @@ import org.labkey.api.security.roles.ProjectAdminRole; import org.labkey.api.security.roles.Role; import org.labkey.api.security.roles.RoleManager; +import org.labkey.api.settings.AppProps; import org.labkey.api.util.DOM; import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; @@ -65,8 +66,10 @@ import org.labkey.panoramapublic.PanoramaPublicController; import org.labkey.panoramapublic.PanoramaPublicManager; import org.labkey.panoramapublic.PanoramaPublicSchema; +import org.labkey.panoramapublic.model.CatalogEntry; import org.labkey.panoramapublic.model.DataLicense; import org.labkey.panoramapublic.model.ExperimentAnnotations; +import org.labkey.panoramapublic.view.publish.CatalogEntryWebPart; import org.labkey.panoramapublic.view.publish.ShortUrlDisplayColumnFactory; import java.io.IOException; @@ -75,8 +78,12 @@ import java.util.List; import java.util.Set; +import static org.labkey.api.util.DOM.Attribute.height; +import static org.labkey.api.util.DOM.Attribute.href; import static org.labkey.api.util.DOM.Attribute.onclick; import static org.labkey.api.util.DOM.Attribute.src; +import static org.labkey.api.util.DOM.Attribute.title; +import static org.labkey.api.util.DOM.Attribute.width; import static org.labkey.api.util.DOM.IMG; import static org.labkey.api.util.DOM.at; @@ -337,6 +344,10 @@ public Class getDisplayValueClass() getMutableColumn("CreatedBy").setFk(new UserIdQueryForeignKey(schema)); getMutableColumn("ModifiedBy").setFk(new UserIdQueryForeignKey(schema)); + ExprColumn catalogEntryCol = getCatalogEntryCol(); + catalogEntryCol.setDisplayColumnFactory(colInfo -> new CatalogEntryIconColumn(colInfo)); + addColumn(catalogEntryCol); + List visibleColumns = new ArrayList<>(); visibleColumns.add(FieldKey.fromParts("Share")); visibleColumns.add(FieldKey.fromParts("Title")); @@ -407,6 +418,18 @@ private ExprColumn getVersionCountCol() return versionCountCol; } + private ExprColumn getCatalogEntryCol() + { + SQLFragment catalogEntrySql = new SQLFragment(" (SELECT entry.id AS CatalogEntry ") + .append(" FROM ").append(PanoramaPublicManager.getTableInfoCatalogEntry(), "entry") + .append(" WHERE ") + .append(" entry.shortUrl = ").append(ExprColumn.STR_TABLE_ALIAS).append(".shortUrl") + .append(") "); + ExprColumn col = new ExprColumn(this, "CatalogEntry", catalogEntrySql, JdbcType.INTEGER); + col.setDescription("Add or view the catalog entry for the experiment"); + return col; + } + @Override public String getName() { @@ -724,4 +747,48 @@ String getRenderId() return "input-picker-div-instrument"; } } + + public static class CatalogEntryIconColumn extends DataColumn + { + public CatalogEntryIconColumn(ColumnInfo col) + { + super(col); + super.setCaption("Catalog Entry"); + } + + @Override + public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + { + User user = ctx.getViewContext().getUser(); + if (user == null || user.isGuest()) + { + HtmlString.NBSP.appendTo(out); + return; + } + Integer catalogEntryId = ctx.get(getColumnInfo().getFieldKey(), Integer.class); + + // Get the experiment connected with this catalog entry. + Integer experimentId = ctx.get(FieldKey.fromParts("id"), Integer.class); + if (experimentId != null) + { + ExperimentAnnotations expAnnot = ExperimentAnnotationsManager.get(experimentId); + // Display the catalog entry link only if the user has the required permissions (Admin or PanoramaPublicSubmitter) in the the experiment folder. + if (expAnnot != null && CatalogEntryWebPart.canBeDisplayed(expAnnot, user)) + { + CatalogEntry entry = catalogEntryId == null ? null : CatalogEntryManager.get(catalogEntryId); + String imageUrl = entry != null ? AppProps.getInstance().getContextPath() + "/PanoramaPublic/images/slideshow-icon-green.png" + : AppProps.getInstance().getContextPath() + "/PanoramaPublic/images/slideshow-icon.png"; + String imageTitle = entry != null ? "View catalog entry" : "Add catalog entry"; + ActionURL returnUrl = ctx.getViewContext().getActionURL().clone(); + ActionURL catalogEntryLink = entry != null ? PanoramaPublicController.getViewCatalogEntryUrl(expAnnot, entry).addReturnURL(returnUrl) + : PanoramaPublicController.getAddCatalogEntryUrl(expAnnot).addReturnURL(returnUrl); + DOM.A(at(href, catalogEntryLink.getLocalURIString(), title, PageFlowUtil.filter(imageTitle)), + DOM.IMG(at(src, imageUrl, height, 22, width, 22))) + .appendTo(out); + return; + } + } + HtmlString.NBSP.appendTo(out); + } + } } diff --git a/panoramapublic/src/org/labkey/panoramapublic/query/MyDataTableInfo.java b/panoramapublic/src/org/labkey/panoramapublic/query/MyDataTableInfo.java new file mode 100644 index 00000000..27df8965 --- /dev/null +++ b/panoramapublic/src/org/labkey/panoramapublic/query/MyDataTableInfo.java @@ -0,0 +1,45 @@ +package org.labkey.panoramapublic.query; + +import org.labkey.api.data.CompareType; +import org.labkey.api.data.ContainerFilter; +import org.labkey.api.data.SimpleFilter; +import org.labkey.api.query.FieldKey; +import org.labkey.api.security.User; +import org.labkey.panoramapublic.PanoramaPublicSchema; + +import java.util.ArrayList; +import java.util.List; + +public class MyDataTableInfo extends ExperimentAnnotationsTableInfo +{ + public static final String NAME = "MyPanoramaPublicData"; + + public MyDataTableInfo(PanoramaPublicSchema schema, ContainerFilter cf, User user) + { + super(schema, cf); + + if (user != null) + { + // Filter to rows where the given user is either the submitter or the lab head. + SimpleFilter.OrClause or = new SimpleFilter.OrClause(); + or.addClause(new CompareType.EqualsCompareClause(FieldKey.fromParts("submitter"), CompareType.EQUAL, user.getUserId())); + or.addClause(new CompareType.EqualsCompareClause(FieldKey.fromParts("labhead"), CompareType.EQUAL, user.getUserId())); + SimpleFilter filter = new SimpleFilter(); + filter.addClause(or); + addCondition(filter); + } + + List visibleColumns = new ArrayList<>(); + visibleColumns.add(FieldKey.fromParts("Share")); + visibleColumns.add(FieldKey.fromParts("Title")); + visibleColumns.add(FieldKey.fromParts("Organism")); + visibleColumns.add(FieldKey.fromParts("Instrument")); + visibleColumns.add(FieldKey.fromParts("Runs")); + visibleColumns.add(FieldKey.fromParts("Keywords")); + visibleColumns.add(FieldKey.fromParts("Citation")); + visibleColumns.add(FieldKey.fromParts("pxid")); + visibleColumns.add(FieldKey.fromParts("Public")); + visibleColumns.add(FieldKey.fromParts("CatalogEntry")); + setDefaultVisibleColumns(visibleColumns); + } +} diff --git a/panoramapublic/src/org/labkey/panoramapublic/view/expannotations/TargetedMSExperimentsWebPart.java b/panoramapublic/src/org/labkey/panoramapublic/view/expannotations/TargetedMSExperimentsWebPart.java index 410f0d61..54b817d3 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/view/expannotations/TargetedMSExperimentsWebPart.java +++ b/panoramapublic/src/org/labkey/panoramapublic/view/expannotations/TargetedMSExperimentsWebPart.java @@ -77,5 +77,12 @@ protected void populateButtonBar(DataView view, ButtonBar bb) deleteExperimentAnnotation.setDisplayPermission(DeletePermission.class); deleteExperimentAnnotation.setRequiresSelection(true); bb.add(deleteExperimentAnnotation); + + if (!view.getViewContext().getUser().isGuest()) + { + ActionURL viewMyDataUrl = new ActionURL(PanoramaPublicController.MyDataViewAction.class, getContainer()); + ActionButton viewMyDataButton = new ActionButton(viewMyDataUrl, "My Data"); + bb.add(viewMyDataButton); + } } } \ No newline at end of file diff --git a/panoramapublic/src/org/labkey/panoramapublic/view/publish/CatalogEntryWebPart.java b/panoramapublic/src/org/labkey/panoramapublic/view/publish/CatalogEntryWebPart.java index 837ff9d2..5af35fff 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/view/publish/CatalogEntryWebPart.java +++ b/panoramapublic/src/org/labkey/panoramapublic/view/publish/CatalogEntryWebPart.java @@ -1,13 +1,11 @@ package org.labkey.panoramapublic.view.publish; -import org.labkey.api.action.UrlProvider; +import org.jetbrains.annotations.Nullable; import org.labkey.api.data.Container; -import org.labkey.api.portal.ProjectUrls; import org.labkey.api.security.User; import org.labkey.api.security.permissions.AdminPermission; import org.labkey.api.util.Button; import org.labkey.api.util.HtmlString; -import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.URLHelper; import org.labkey.api.view.ActionURL; import org.labkey.api.view.HtmlView; @@ -40,10 +38,10 @@ public class CatalogEntryWebPart extends VBox { public CatalogEntryWebPart(ExperimentAnnotations expAnnotations, User user) { - this(expAnnotations, user, false); + this(expAnnotations, user, null); } - public CatalogEntryWebPart(ExperimentAnnotations expAnnotations, User user, boolean standalone) + public CatalogEntryWebPart(ExperimentAnnotations expAnnotations, User user, @Nullable ActionURL returnUrl) { Container container = expAnnotations.getContainer(); setTitle("Panorama Public Catalog Entry"); @@ -108,9 +106,8 @@ public CatalogEntryWebPart(ExperimentAnnotations expAnnotations, User user, bool HtmlString.NBSP, new Button.ButtonBuilder("Delete").href(deleteUrl) .usePost("Are you sure you want to delete the Panorama Public catalog entry for this experiment?"), - standalone ? DIV(at(style, "margin-top:25px;"), - new Button.ButtonBuilder("Back to Folder").href(PageFlowUtil.urlProvider(ProjectUrls.class).getBeginURL(container))) - : HtmlString.EMPTY_STRING + returnUrl != null ? DIV(at(style, "margin-top:25px;"), new Button.ButtonBuilder("Back").href(returnUrl)) + : HtmlString.EMPTY_STRING ))); } } diff --git a/panoramapublic/src/org/labkey/panoramapublic/view/publish/catalogEntryForm.jsp b/panoramapublic/src/org/labkey/panoramapublic/view/publish/catalogEntryForm.jsp index ae8017a0..95ba4faa 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/view/publish/catalogEntryForm.jsp +++ b/panoramapublic/src/org/labkey/panoramapublic/view/publish/catalogEntryForm.jsp @@ -53,7 +53,7 @@ int imgWidth = settings.getImgWidth(); int imgHeight = settings.getImgHeight(); - ActionURL cancelUrl = PanoramaPublicController.getViewExperimentDetailsURL(form.getId(), form.getContainer()); + ActionURL cancelUrl = bean.getForm().getReturnActionURL(PanoramaPublicController.getViewExperimentDetailsURL(form.getId(), form.getContainer())); %> diff --git a/panoramapublic/src/org/labkey/panoramapublic/view/search/panoramaWebSearch.jsp b/panoramapublic/src/org/labkey/panoramapublic/view/search/panoramaWebSearch.jsp index a8af3e1c..97c5a883 100644 --- a/panoramapublic/src/org/labkey/panoramapublic/view/search/panoramaWebSearch.jsp +++ b/panoramapublic/src/org/labkey/panoramapublic/view/search/panoramaWebSearch.jsp @@ -479,6 +479,16 @@ success: function (wp) { let expWebpart = wp.body.filter(webpart => webpart.name === "Targeted MS Experiment List"); if (expWebpart.length === 1) { + + let buttonBarItems = []; + if (!LABKEY.user.isGuest) + { + buttonBarItems = [ + {text: 'My Data', url: LABKEY.ActionURL.buildURL('panoramapublic', 'myDataView')}, + LABKEY.QueryWebPart.standardButtons.views + ]; + } + let wp = new LABKEY.QueryWebPart({ renderTo: 'webpart_'+ expWebpart[0].webPartId, title: 'Panorama Public Experiments', @@ -491,6 +501,10 @@ showExportButtons: false,//this needs to be set to false otherwise setting selectRecordSelector to false still shows the checkbox column showDetailsColumn: false, dataRegionName: "Targeted MS Experiment List", + buttonBar: { + includeStandardButtons: true, + items: buttonBarItems, + }, success: function () { } }); diff --git a/panoramapublic/test/src/org/labkey/test/components/panoramapublic/TargetedMsExperimentWebPart.java b/panoramapublic/test/src/org/labkey/test/components/panoramapublic/TargetedMsExperimentWebPart.java index 6507ca0f..80f33a52 100644 --- a/panoramapublic/test/src/org/labkey/test/components/panoramapublic/TargetedMsExperimentWebPart.java +++ b/panoramapublic/test/src/org/labkey/test/components/panoramapublic/TargetedMsExperimentWebPart.java @@ -43,7 +43,7 @@ public TargetedMsExperimentInsertPage startInsert() public void clickSubmit() { - getWrapper().clickAndWait(Locator.linkContainingText("Submit")); + getWrapper().clickAndWait(Locator.linkWithText("Submit")); } public void clickResubmit() diff --git a/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicBaseTest.java b/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicBaseTest.java index 2f55e345..fef815e2 100644 --- a/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicBaseTest.java +++ b/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicBaseTest.java @@ -70,6 +70,9 @@ public class PanoramaPublicBaseTest extends TargetedMSTest implements PostgresOn static final String SMALLMOL_PLUS_PEPTIDES_SKY_VIEW = SMALLMOL_PLUS_PEPTIDES_SKY + ".view"; static final String SMALLMOL_PLUS_PEPTIDES_SKY_ZIP = SMALLMOL_PLUS_PEPTIDES_SKY + ".zip"; + static final String CATALOG_IMAGE_FILE = "skyline_panorama_workflow.png"; + static final String CATALOG_IMAGE_PATH = "TargetedMS/panoramapublic/" + CATALOG_IMAGE_FILE; + static final String SAMPLEDATA_FOLDER = "panoramapublic/"; PortalHelper portalHelper = new PortalHelper(this); @@ -194,10 +197,9 @@ private void setupSourceFolder(String projectName, String folderName, FolderType setupSubfolder(projectName, folderName, folderType); // Create the subfolder ApiPermissionsHelper permissionsHelper = new ApiPermissionsHelper(this); + _userHelper.ensureUsersExist(List.of(adminUsers)); for(String user: adminUsers) { - _userHelper.deleteUser(user); - _userHelper.createUser(user); permissionsHelper.addMemberToRole(user, "Folder Administrator", PermissionsHelper.MemberType.user, projectName + "/" + folderName); } } @@ -456,6 +458,103 @@ public File getSampleDataPath(String file) return TestFileUtils.getSampleData("TargetedMS/" + getSampleDataFolder() + file); } + protected String setupFolderSubmitAndCopy(String projectName, String folderName, String targetFolder, String experimentTitle, String submitter, @Nullable String submitterLastName, + @Nullable String admin, String skylineDocName) + { + setupSourceFolder(projectName, folderName, submitter); + + if (admin != null) + { + createFolderAdmin(projectName, folderName, admin); + } + + impersonate(submitter); + if (submitterLastName != null) + { + updateSubmitterAccountInfo(submitterLastName); + } + + // Import a Skyline document to the folder + importData(skylineDocName, 1); + + // Add the "Targeted MS Experiment" webpart and submit + TargetedMsExperimentWebPart expWebPart = createExperimentCompleteMetadata(experimentTitle); + expWebPart.clickSubmit(); + String shortAccessUrl = submitWithoutPXId(); + + // Copy the experiment to the Panorama Public project + makeCopy(shortAccessUrl, experimentTitle, targetFolder, false, false); + + return shortAccessUrl; + } + + private void createFolderAdmin(String projectName, String folderName, String user) + { + _userHelper.ensureUsersExist(Collections.singletonList(user)); + ApiPermissionsHelper permissionsHelper = new ApiPermissionsHelper(this); + permissionsHelper.addMemberToRole(user, "Folder Administrator", PermissionsHelper.MemberType.user, projectName + "/" + folderName); + } + + protected void makeDataPublic(boolean unpublishedData) + { + TargetedMsExperimentWebPart expWebPart = new TargetedMsExperimentWebPart(this); + + if (unpublishedData) + { + expWebPart.clickMakePublic(); + assertTextPresent("Publication Details"); + _ext4Helper.checkCheckbox(Ext4Helper.Locators.checkbox(this, "Unpublished:")); + } + else + { + expWebPart.clickAddPublication(); + assertTextPresent("Publication Details"); + setFormElement(Locator.input("link"), "http://panorama-publication-test.org"); + setFormElement(Locator.tagWithName("textarea", "citation"), "Paper citation goes here"); + } + + clickButton("Continue"); + assertTextPresent("Confirm Publication Details"); + clickButton("OK"); + if (unpublishedData) + { + assertTextPresent("Data on Panorama Public", "was made public."); + } + else + { + assertTextPresent("Publication details were updated for data on Panorama Public"); + } + clickAndWait(Locator.linkContainingText("Back to Folder")); + } + + protected void createCatalogEntry() + { + assertTextPresent("Use the form below to provide a brief description and an image that will be displayed in a slideshow "); + setFormElement(Locator.textarea("datasetDescription"), "Cool research with Skyline"); + File imageFile = TestFileUtils.getSampleData(CATALOG_IMAGE_PATH); + setFormElement(Locator.input("imageFileInput"), imageFile); + assertTextPresent("Drag and resize the crop-box"); + clickButton("Crop", 0); + // waitForElementToDisappear(Locator.IdLocator.id("cropperContainer")); + clickButton("Submit"); + assertTextPresent("Thank you for submitting your entry for the Panorama Public data catalog"); + } + + protected void enableCatalogEntries() + { + goToAdminConsole().goToSettingsSection(); + clickAndWait(Locator.linkWithText("Panorama Public")); + clickAndWait(Locator.linkWithText("Panorama Public Catalog Settings")); + checkCheckbox(Locator.input("enabled")); + setFormElement(Locator.input("maxFileSize"), "5242880"); + setFormElement(Locator.input("imgWidth"), "600"); + setFormElement(Locator.input("imgHeight"), "400"); + setFormElement(Locator.input("maxTextChars"), "500"); + setFormElement(Locator.input("maxEntries"), "25"); + clickButton("Save"); + waitForText("Panorama Public catalog entry settings were saved"); + } + @Override protected void doCleanup(boolean afterTest) throws TestTimeoutException { diff --git a/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMakePublicTest.java b/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMakePublicTest.java index 60454ed1..93e16b5f 100644 --- a/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMakePublicTest.java +++ b/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMakePublicTest.java @@ -4,10 +4,8 @@ import org.junit.Assert; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.labkey.remoteapi.CommandException; import org.labkey.test.BaseWebDriverTest; import org.labkey.test.Locator; -import org.labkey.test.TestFileUtils; import org.labkey.test.WebTestHelper; import org.labkey.test.categories.External; import org.labkey.test.categories.MacCossLabModules; @@ -20,8 +18,6 @@ import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; -import java.io.File; -import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -36,11 +32,8 @@ public class PanoramaPublicMakePublicTest extends PanoramaPublicBaseTest private static final String SKY_FILE_1 = "MRMer.zip"; private static final String ADMIN_2 = "admin_2@panoramapublic.test"; - private static final String IMAGE_FILE = "skyline_panorama_workflow.png"; - private static final String IMAGE_PATH = "TargetedMS/panoramapublic/" + IMAGE_FILE; - @Test - public void testExperimentCopy() throws IOException, CommandException + public void testExperimentCopy() { // Set up our source folder. We will create an experiment and submit it to our "Panorama Public" project. String projectName = getProjectName(); @@ -89,16 +82,7 @@ public void testAddCatalogEntry() String shortAccessUrl = setupFolderSubmitAndCopy(projectName, folderName, targetFolder, experimentTitle); // Enable Panorama Public catalog entries in the admin console. - goToAdminConsole().goToSettingsSection(); - clickAndWait(Locator.linkWithText("Panorama Public")); - clickAndWait(Locator.linkWithText("Panorama Public Catalog Settings")); - checkCheckbox(Locator.input("enabled")); - setFormElement(Locator.input("maxFileSize"), "5242880"); - setFormElement(Locator.input("imgWidth"), "600"); - setFormElement(Locator.input("imgHeight"), "400"); - setFormElement(Locator.input("maxTextChars"), "500"); - setFormElement(Locator.input("maxEntries"), "25"); - clickButton("Save", "Panorama Public catalog entry settings were saved"); + enableCatalogEntries(); // 1. Make the data public and add a catalog entry addCatalogEntry(PANORAMA_PUBLIC, targetFolder); @@ -160,19 +144,11 @@ private void makeDataPublicWithCatalogEntry() assertTextPresent("Data on Panorama Public", "was made public."); clickButton("Add Catalog Entry"); - assertTextPresent("Use the form below to provide a brief description and an image that will be displayed in a slideshow "); - setFormElement(Locator.textarea("datasetDescription"), "Cool research with Skyline"); - File imageFile = TestFileUtils.getSampleData(IMAGE_PATH); - setFormElement(Locator.input("imageFileInput"), imageFile); - assertTextPresent("Drag and resize the crop-box"); - clickButton("Crop", 0); - // waitForElementToDisappear(Locator.IdLocator.id("cropperContainer")); - clickButton("Submit"); - assertTextPresent("Thank you for submitting your entry for the Panorama Public data catalog"); + createCatalogEntry(); clickButton("View Entry"); assertTextPresent("Pending approval"); assertElementNotPresent("Approve button should be displayed only for site admins.", Locator.lkButton("Approve")); - clickButton("Back to Folder"); + clickButton("Back"); } private void verifyCatalogEntryWebpart(String projectName, String folderName, boolean expectWebpart) @@ -185,7 +161,7 @@ private void verifyCatalogEntryWebpart(String projectName, String folderName, bo { assertTextPresent("Panorama Public Catalog Entry"); BodyWebPart catalogEntryWp = new BodyWebPart(getDriver(), "Panorama Public Catalog Entry"); - WebElement imgTag = Locator.XPathLocator.tag("img").withAttributeContaining("src", IMAGE_FILE).findElement(catalogEntryWp); + WebElement imgTag = Locator.XPathLocator.tag("img").withAttributeContaining("src", CATALOG_IMAGE_FILE).findElement(catalogEntryWp); int responseCode = WebTestHelper.getHttpResponse(imgTag.getAttribute("src")).getResponseCode(); assertEquals("Catalog entry image is missing. Unexpected response code. " + responseCode, HttpStatus.SC_OK, responseCode); @@ -198,25 +174,7 @@ private void verifyCatalogEntryWebpart(String projectName, String folderName, bo private String setupFolderSubmitAndCopy(String projectName, String folderName, String targetFolder, String experimentTitle) { - setupSourceFolder(projectName, folderName, SUBMITTER); - - createFolderAdmin(projectName, folderName, ADMIN_2); - - impersonate(SUBMITTER); - updateSubmitterAccountInfo("One"); - - // Import a Skyline document to the folder - importData(SKY_FILE_1, 1); - - // Add the "Targeted MS Experiment" webpart and submit - TargetedMsExperimentWebPart expWebPart = createExperimentCompleteMetadata(experimentTitle); - expWebPart.clickSubmit(); - String shortAccessUrl = submitWithoutPXId(); - - // Copy the experiment to the Panorama Public project - makeCopy(shortAccessUrl, experimentTitle, targetFolder, false, false); - - return shortAccessUrl; + return setupFolderSubmitAndCopy(projectName, folderName, targetFolder, experimentTitle, SUBMITTER, "One", ADMIN_2, SKY_FILE_1); } private void resubmitFolder(String projectName, String folderName, String submitter, boolean keepPrivate) @@ -322,51 +280,11 @@ private void verifyMakePublic(String projectName, String folderName, String user private void makeDataPublic() { - makePublic(true); + makeDataPublic(true); } private void addPublication() { - makePublic(false); - } - - private void makePublic(boolean unpublishedData) - { - TargetedMsExperimentWebPart expWebPart = new TargetedMsExperimentWebPart(this); - - if (unpublishedData) - { - expWebPart.clickMakePublic(); - assertTextPresent("Publication Details"); - _ext4Helper.checkCheckbox(Ext4Helper.Locators.checkbox(this, "Unpublished:")); - } - else - { - expWebPart.clickAddPublication(); - assertTextPresent("Publication Details"); - setFormElement(Locator.input("link"), "http://panorama-publication-test.org"); - setFormElement(Locator.tagWithName("textarea", "citation"), "Paper citation goes here"); - } - - clickButton("Continue"); - assertTextPresent("Confirm Publication Details"); - clickButton("OK"); - if (unpublishedData) - { - assertTextPresent("Data on Panorama Public", "was made public."); - } - else - { - assertTextPresent("Publication details were updated for data on Panorama Public"); - } - clickAndWait(Locator.linkContainingText("Back to Folder")); - } - - private void createFolderAdmin(String projectName, String folderName, String user) - { - ApiPermissionsHelper permissionsHelper = new ApiPermissionsHelper(this); - _userHelper.deleteUser(user); - _userHelper.createUser(user); - permissionsHelper.addMemberToRole(user, "Folder Administrator", PermissionsHelper.MemberType.user, projectName + "/" + folderName); + makeDataPublic(false); } } diff --git a/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMyDataViewTest.java b/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMyDataViewTest.java new file mode 100644 index 00000000..6bbdbbf9 --- /dev/null +++ b/panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMyDataViewTest.java @@ -0,0 +1,198 @@ +package org.labkey.test.tests.panoramapublic; + +import org.jetbrains.annotations.NotNull; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.labkey.test.BaseWebDriverTest; +import org.labkey.test.categories.External; +import org.labkey.test.categories.MacCossLabModules; +import org.labkey.test.util.ApiPermissionsHelper; +import org.labkey.test.util.DataRegionTable; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +@Category({External.class, MacCossLabModules.class}) +@BaseWebDriverTest.ClassTimeout(minutes = 5) +public class PanoramaPublicMyDataViewTest extends PanoramaPublicBaseTest +{ + private static final String SUBMITTER_1 = "submitter1@panoramapublic.test"; + private static final String SUBMITTER_2 = "submitter2@panoramapublic.test"; + + private static final String COL_TITLE = "Title"; + private static final String COL_PUBLIC = "Public"; + private static final String COL_CATALOG_ENTRY = "Catalog Entry"; + + @BeforeClass + public static void initialSetUp() + { + PanoramaPublicMyDataViewTest test = (PanoramaPublicMyDataViewTest) getCurrentTest(); + test.init(); + } + + private void init() + { + goToProjectHome(PANORAMA_PUBLIC); + ApiPermissionsHelper permissionsHelper = new ApiPermissionsHelper(this); + permissionsHelper.setSiteGroupPermissions("Guests", "Reader"); + portalHelper.removeAllWebParts(); + portalHelper.addBodyWebPart("Panorama Public Search"); + portalHelper.addBodyWebPart("Targeted MS Experiment List"); + portalHelper.addBodyWebPart("Messages"); + + // Enable Panorama Public catalog entries in the admin console. + enableCatalogEntries(); + } + + @Override + public String getSampleDataFolder() + { + return "panoramapublic/"; + } + + @Test + public void testMyDataView() + { + // Set up our source folders, and submit to "Panorama Public" + String projectName = getProjectName(); + + // Dataset 1 by submitter1 + String experimentTitle_1_1 = "This is dataset One submitted by Submitter One"; + setupFolderSubmitAndCopy(projectName, "Folder Submitter1 Data1", "Test Copy 1_1", experimentTitle_1_1, SUBMITTER_1, "One", null, SKY_FILE_1); + + // Dataset 2 by submitter1 + String experimentTitle_1_2 = "This is dataset Two submitted by Submitter One"; + setupFolderSubmitAndCopy(projectName, "Folder Submitter1 Data2", "Test Copy 1_2", experimentTitle_1_2, SUBMITTER_1, null, null, SKY_FILE_1); + + // Dataset 1 by submitter2 + String experimentTitle_2_1 = "This is dataset One submitted by Submitter Two"; + setupFolderSubmitAndCopy(projectName, "Folder Submitter2 Data1", "Test Copy 2_1", experimentTitle_2_1, SUBMITTER_2, "Two", null, SKY_FILE_1); + + // Verify the "My Data" views for each submitter + viewSubmitterData(SUBMITTER_1, List.of(experimentTitle_1_1, experimentTitle_1_2), true); + viewSubmitterData(SUBMITTER_2, List.of(experimentTitle_2_1), false); + + // Sign out. Guest should not be able to see the "My Data" button + simpleSignOut(); + goToProjectHome(PANORAMA_PUBLIC); + var table = new DataRegionTable.DataRegionFinder(getDriver()).refindWhenNeeded(); + assertFalse(table.hasHeaderMenu("My Data")); + + simpleSignIn(); + } + + private void viewSubmitterData(String submitter, List experimentTitles, boolean addCatalogEntry) + { + if (isImpersonating()) + { + stopImpersonating(true); + } + goToProjectHome(PANORAMA_PUBLIC); + impersonate(submitter); + + DataRegionTable table = myDataView(); + assertEquals("Unexpected row count", experimentTitles.size(), table.getDataRowCount()); + List expectedColumns = List.of(COL_TITLE, COL_PUBLIC, COL_CATALOG_ENTRY); + List actualColumns = table.getColumnLabels(); + assertTrue("Expected table columns " + expectedColumns + ". Found: " + actualColumns, + actualColumns.containsAll(expectedColumns)); + + List actualExptTitles = table.getColumnDataAsText(COL_TITLE); + assertEquals("Unexpected experiment titles", experimentTitles.stream().sorted().collect(Collectors.toList()), + actualExptTitles.stream().map(String::trim).sorted().collect(Collectors.toList())); + + + int catalogEntryCol = table.getColumnIndex(COL_CATALOG_ENTRY); + int dataPublicCol = table.getColumnIndex(COL_PUBLIC); + verifyColumnValues(table, catalogEntryCol, dataPublicCol, experimentTitles.size()); + + String firstExptTitle = actualExptTitles.get(0); + + // Make one dataset public + int titleCol = table.getColumnIndex(COL_TITLE); + int rowIdx = getExperimentRowIndex(table, firstExptTitle, titleCol); + clickAndWait(table.link(rowIdx, titleCol)); // Go to the folder where the data lives + makeDataPublic(true); + + // The "Catalog Entry" column for the data that was made public should have an icon linking to the AddCatalogEntry action. + verifyColumnValues(catalogEntryCol, dataPublicCol, titleCol, experimentTitles.size(), firstExptTitle, false); + + if (addCatalogEntry) + { + // Add a catalog entry + WebElement catalogEntryLink = table.link(rowIdx, catalogEntryCol); + clickAndWait(catalogEntryLink); + createCatalogEntry(); + + // The "Catalog Entry" column for the data to which the catalog entry was added should have an icon linking to the ViewCatalogEntry action. + verifyColumnValues(catalogEntryCol, dataPublicCol, titleCol, experimentTitles.size(), firstExptTitle, true); + } + } + + private int getExperimentRowIndex(DataRegionTable table, String firstExptTitle, int titleCol) + { + int rowIdx = table.getRowIndex(titleCol, firstExptTitle); + assertNotEquals("Row index not found for experiment title: " + firstExptTitle, -1, rowIdx); + return rowIdx; + } + + private void verifyColumnValues(DataRegionTable table, int catalogEntryCol, int dataPublicCol, int rowCount) + { + verifyColumnValues(table, catalogEntryCol, dataPublicCol, rowCount, -1, false); + } + + private void verifyColumnValues(int catalogEntryCol, int dataPublicCol, int titleCol, int rowCount, String publicExptTitle, boolean hasCatalogEntry) + { + goToProjectHome(PANORAMA_PUBLIC); + DataRegionTable table = myDataView(); + int rowIdx = getExperimentRowIndex(table, publicExptTitle, titleCol); + verifyColumnValues(table, catalogEntryCol, dataPublicCol, rowCount, rowIdx, hasCatalogEntry); + } + + private void verifyColumnValues(DataRegionTable table, int catalogEntryCol, int dataPublicCol, int rowCount, int publicRowIdx, boolean hasCatalogEntry) + { + for (int row = 0; row < rowCount; row++) + { + String expectedPublicValue = row == publicRowIdx ? "Yes" : "No"; + assertEquals("Unexpected value in \"Public\" column for row " + row, expectedPublicValue, table.getDataAsText(row, dataPublicCol)); + if (row == publicRowIdx) + { + // If this is a row for a public dataset, we expect to see an icon linking to either + // AddCatalogEntryAction if the data does not have a catalog entry, or + // ViewCatalogEntryAction if the data has a catalog entry. + WebElement catalogEntryLink = table.link(row, catalogEntryCol); + String href = catalogEntryLink.getAttribute("href"); + String expectedInHref = hasCatalogEntry ? "panoramapublic-viewCatalogEntry.view" : "panoramapublic-addCatalogEntry.view"; + String linkTitle = hasCatalogEntry ? "View catalog entry" : "Add catalog entry"; + assertTrue("Expected \"" + expectedInHref + "\" in link. Found: " + href, href.contains(expectedInHref)); + assertEquals("Unexpected link title", linkTitle, catalogEntryLink.getAttribute("title")); + WebElement imgEl = catalogEntryLink.findElement(By.tagName("img")); + String expectedIconImg = hasCatalogEntry ? "slideshow-icon-green.png" : "slideshow-icon.png"; + String catalogEntryIcon = imgEl.getAttribute("src"); + assertTrue("Expected " + expectedIconImg + " in catalog entry icon. Found: " + catalogEntryIcon, imgEl.getAttribute("src").contains(expectedIconImg)); + } + else + { + // This data is not public. The Catalog Entry column should be blank. + assertEquals("Unexpected value in \"Catalog Entry\" column for row " + row, "", table.getDataAsText(row, catalogEntryCol).trim()); + } + } + } + + @NotNull + private DataRegionTable myDataView() + { + var table = new DataRegionTable.DataRegionFinder(getDriver()).refindWhenNeeded(); + assertTrue(table.hasHeaderMenu("My Data")); + table.clickHeaderButtonAndWait("My Data"); + return new DataRegionTable.DataRegionFinder(getDriver()).refindWhenNeeded(); + } +}