From ff2817353ea08cdaad166988f9fe5a1baf7604a4 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 18 May 2022 16:02:39 +0200 Subject: [PATCH] Merged manually with branch task_21363 --- .classpath | 21 +- .../com.gwtplugins.gdt.eclipse.core.prefs | 2 +- .../com.gwtplugins.gwt.eclipse.core.prefs | 2 + .settings/org.eclipse.jdt.core.prefs | 9 +- .settings/org.eclipse.wst.common.component | 47 +- ...se.wst.common.project.facet.core.prefs.xml | 7 + ....eclipse.wst.common.project.facet.core.xml | 3 +- CHANGELOG.md | 8 +- .../CkanContentModeratorWidget.gwt.xml | 23 + .../client/CheckConfigsUxController.java | 202 ++++++ .../CkanContentModeratorCheckConfigs.java | 196 ++++++ .../client/CkanContentModeratorService.java | 127 +++- .../CkanContentModeratorServiceAsync.java | 121 +++- .../client/CkanContentModeratorWidget.java | 118 ++-- .../CkanContentModeratorWidgetController.java | 331 +++++++++ .../CkanContentModeratorWidgetEntryPoint.java | 22 + .../CkanContentModeratorWidgetTrusted.java | 76 ++ .../ContentModeratorWidgetConstants.java | 23 + .../events/CheckBoxSelectIemsEvent.java | 62 ++ .../CheckBoxSelectIemsEventHandler.java | 23 + .../client/events/ClickItemEvent.java | 68 ++ .../client/events/ClickItemEventHandler.java | 21 + .../client/events/CloseAllTabsEvent.java | 45 ++ .../events/CloseAllTabsEventHandler.java | 21 + .../client/events/IFrameInstanciedEvent.java | 91 +++ .../events/IFrameInstanciedEventHandler.java | 23 + .../SelectItemsWithItemStatusEvent.java | 108 +++ ...SelectItemsWithItemStatusEventHandler.java | 21 + .../client/events/ShowItemEvent.java | 80 +++ .../client/events/ShowItemEventHandler.java | 23 + .../client/events/ShowMessageEvent.java | 68 ++ .../events/ShowMessageEventHandler.java | 20 + .../events/TableRangeViewChangedEvent.java | 47 ++ .../TableRangeViewChangedEventHandler.java | 16 + .../client/resources/CellTable.css | 110 +++ .../client/resources/CellTableResources.java | 23 + .../resources/ContentModeratorIcons.java | 56 ++ .../ContentModeratorWidgetResources.java | 56 ++ .../client/resources/cancel.png | Bin 0 -> 908 bytes .../client/resources/css/data-table.css | 11 + .../client/resources/folder.png | Bin 0 -> 380 bytes .../client/resources/info-icon.png | Bin 0 -> 245 bytes .../client/resources/info-square.png | Bin 0 -> 325 bytes .../client/resources/info.png | Bin 0 -> 260 bytes .../client/resources/loading.gif | Bin 0 -> 8114 bytes .../client/ui/BaseViewTemplate.java | 73 ++ .../client/ui/BaseViewTemplate.ui.xml | 13 + .../client/ui/CkanShowItemFrame.java | 160 +++++ .../client/ui/CkanShowItemFrame.ui.xml | 22 + .../ui/ContentModeratorPaginatedView.java | 353 ++++++++++ .../ui/ContentModeratorSystemBaseView.java | 61 ++ .../client/ui/ContentModeratorToolbar.java | 142 ++++ .../client/ui/ContentModeratorToolbar.ui.xml | 44 ++ .../client/ui/DoActionCMSView.java | 229 ++++++ .../client/ui/DoActionCMSView.ui.xml | 46 ++ .../client/ui/HomeView.java | 652 ++++++++++++++++++ .../client/ui/HomeView.ui.xml | 61 ++ .../client/ui/MainPanel.java | 40 ++ .../client/ui/MainPanel.ui.xml | 19 + .../client/ui/MainTabPanel.java | 211 ++++++ .../client/ui/MainTabPanel.ui.xml | 16 + .../client/ui/SelectionItems.java | 25 + .../ui/table/AbstractItemsCellTable.java | 224 ++++++ .../client/ui/table/ItemsTable.java | 546 +++++++++++++++ .../client/ui/table/MyToolTipColumn.java | 83 +++ .../client/ui/table/SortedCellTable.java | 302 ++++++++ .../client/ui/util/ExtModal.java | 133 ++++ .../client/ui/util/LoadingPanel.java | 37 + .../client/ui/util/UtilFunct.java | 75 ++ .../client/ui/util/UtilUx.java | 43 ++ .../util/ModerationQueryStringUtil.java | 209 ++++++ .../client/util/QueryStringUtil.java | 71 ++ .../public/content-moderator-widget.css | 40 ++ .../server/ActionRequired.java | 22 + .../server/CatalogueBeansConverter.java | 58 ++ .../server/CatalogueCMSFactory.java | 112 +++ .../CkanContentModeratorServiceAImpl.java | 52 -- .../CkanContentModeratorServiceImpl.java | 500 ++++++++++++++ .../server/CkanContentModeratorUtil.java | 102 +++ .../server/ContentModeratorSystem.java | 108 --- .../server/GcubeContextUtil.java | 164 +++++ .../shared/CMSUserRole.java | 17 + .../shared/CatalogueDataset.java | 228 ++++++ .../shared/DISPLAY_FIELD.java | 47 ++ .../shared/FieldVerifier.java | 42 -- .../shared/ItemFieldDV.java | 165 +++++ .../shared/ModerationUserRole.java | 53 ++ .../shared/OperationReport.java | 66 ++ .../shared/SearchedData.java | 181 +++++ .../shared/SearchingFilter.java | 191 +++++ .../shared/WhereClause.java | 98 +++ .../CkanContentModeratorWidget.gwt.xml | 29 +- .../client/Messages_fr.properties | 2 - .../webapp/CkanContentModeratorWidget.css | 322 +++++++++ .../webapp/CkanContentModeratorWidget.html | 85 +-- src/main/webapp/WEB-INF/web.xml | 35 +- .../CkanContentModeratorServiceAImplTest.java | 14 - .../CkanContentModeratorServiceTest.java | 53 ++ 98 files changed, 8634 insertions(+), 373 deletions(-) create mode 100644 .settings/com.gwtplugins.gwt.eclipse.core.prefs create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.prefs.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CheckConfigsUxController.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorCheckConfigs.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetController.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetEntryPoint.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetTrusted.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ContentModeratorWidgetConstants.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEvent.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTable.css create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTableResources.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorIcons.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorWidgetResources.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/cancel.png create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/css/data-table.css create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/folder.png create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/info-icon.png create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/info-square.png create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/info.png create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/loading.gif create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/BaseViewTemplate.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/BaseViewTemplate.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorPaginatedView.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorSystemBaseView.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.ui.xml create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/SelectionItems.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/AbstractItemsCellTable.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/ItemsTable.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/MyToolTipColumn.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/SortedCellTable.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/ExtModal.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/LoadingPanel.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilFunct.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilUx.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/ModerationQueryStringUtil.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/QueryStringUtil.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/public/content-moderator-widget.css create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ActionRequired.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueBeansConverter.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueCMSFactory.java delete mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImpl.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceImpl.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorUtil.java delete mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ContentModeratorSystem.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/GcubeContextUtil.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CMSUserRole.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CatalogueDataset.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/DISPLAY_FIELD.java delete mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/FieldVerifier.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ItemFieldDV.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ModerationUserRole.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/OperationReport.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchedData.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchingFilter.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/WhereClause.java delete mode 100644 src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/client/Messages_fr.properties delete mode 100644 src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImplTest.java create mode 100644 src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceTest.java diff --git a/.classpath b/.classpath index 08662b4..d3cfefb 100644 --- a/.classpath +++ b/.classpath @@ -11,17 +11,9 @@ - - - - - - - - + - @@ -29,10 +21,19 @@ - + + + + + + + + + + diff --git a/.settings/com.gwtplugins.gdt.eclipse.core.prefs b/.settings/com.gwtplugins.gdt.eclipse.core.prefs index 9f63340..a21cd08 100644 --- a/.settings/com.gwtplugins.gdt.eclipse.core.prefs +++ b/.settings/com.gwtplugins.gdt.eclipse.core.prefs @@ -1,4 +1,4 @@ eclipse.preferences.version=1 -lastWarOutDir=/home/francescomangiacrapa/eclipse-workspace/ckan-content-moderator-widget/target/ckan-content-moderator-widget-0.0.1-SNAPSHOT +lastWarOutDir=/home/francescomangiacrapa/git/ckan-content-moderator-widget/target/ckan-content-moderator-widget-0.1.0-SNAPSHOT warSrcDir=src/main/webapp warSrcDirIsOutput=false diff --git a/.settings/com.gwtplugins.gwt.eclipse.core.prefs b/.settings/com.gwtplugins.gwt.eclipse.core.prefs new file mode 100644 index 0000000..f23a752 --- /dev/null +++ b/.settings/com.gwtplugins.gwt.eclipse.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +entryPointModules= diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 43c8195..8b5c4dc 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,11 +1,16 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 408fe15..3422968 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,11 +1,54 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + uses + + + + + - + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..cc81385 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml index 9004727..8867594 100644 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -1,8 +1,9 @@ - + + diff --git a/CHANGELOG.md b/CHANGELOG.md index c7381cd..7cef2f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [v0.0.1-SNAPSHOT] - 2021-05-06 +## [v1.0.0-SNAPSHOT] - 2022-04-04 -First Release +- [#21363] Implemented the ckan-content-moderator-widget +- [#20650] Provided moderator skills to Catalogue Moderator(s) +- [#23108] Provided Moderation facility accessible to Catalogue Editor/Admin (only) in read only mode +- [#23197] Revised the query passed to gCat with the moderation states +- [#23258] Implemented the requirement described in #23156 diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml new file mode 100644 index 0000000..0660eee --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CheckConfigsUxController.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CheckConfigsUxController.java new file mode 100644 index 0000000..5b85d31 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CheckConfigsUxController.java @@ -0,0 +1,202 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.MainPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.LoadingPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.UtilUx; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; + +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.ComplexPanel; +import com.google.gwt.user.client.ui.HTML; + +/** + * The Class CheckConfigsUxController. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 8, 2022 + */ +public class CheckConfigsUxController { + + private LoadingPanel loader; + + private CkanContentModeratorCheckConfigs moderatorCheckConfig; + + private ComplexPanel basePanelContainer; + + private CkanContentModeratorWidgetController cmsController; + + private MainPanel mainPanel; + + private DISPLAY_FIELD[] orderByFields; + + private ItemStatus initItemStatus; + + private DISPLAY_FIELD[] displayFields; + + private String initOnItemName; + + /** + * Instantiates a new check configs ux controller. + * + * @param mainPanel the main panel + * @param initItemStatus the init item status + * @param initOnItemName + * @param displayFields the display fields + * @param sortByFields the sort by fields + * @param moderatorcheckConfig the moderatorcheck config + */ + protected CheckConfigsUxController(MainPanel mainPanel, ItemStatus initItemStatus, String initOnItemName, + DISPLAY_FIELD[] displayFields, DISPLAY_FIELD[] sortByFields, + CkanContentModeratorCheckConfigs moderatorcheckConfig) { + + this.mainPanel = mainPanel; + this.basePanelContainer = mainPanel.getMainPanelContainer(); + this.moderatorCheckConfig = moderatorcheckConfig; + this.initItemStatus = initItemStatus; + this.initOnItemName = initOnItemName; + this.displayFields = displayFields; + this.orderByFields = sortByFields; + + if (this.initItemStatus == null) + this.initItemStatus = ItemStatus.PENDING; + + if (this.displayFields == null) + this.displayFields = DISPLAY_FIELD.values(); + + if (this.orderByFields == null) + this.orderByFields = DISPLAY_FIELD.values(); + + checkConfigs(); + } + + /** + * Check configs. + */ + private void checkConfigs() { + + if (moderatorCheckConfig == null) { + // here the moderatorCheckConfig is null, so loading configurations from server + // and + // checking them + loader = new LoadingPanel(new HTML("Checking configurations and authorizations... please wait")); + basePanelContainer.add(loader); + moderatorCheckConfig = new CkanContentModeratorCheckConfigs(); + + final Command whenDone = new Command() { + + @Override + public void execute() { + onConfigurationsLoaded(); + } + }; + + try { + moderatorCheckConfig.checkConfigs(whenDone, false); + } catch (Exception e) { + GWT.log("Check configs error: " + e.getMessage()); + } + } else { + // here the moderatorCheckConfig is already full + onConfigurationsLoaded(); + } + } + + /** + * On configurations loaded. + */ + private void onConfigurationsLoaded() { + GWT.log("onConfigurationLoaded executed"); + boolean isContentModerationEnabled = false; + boolean isModeratorRoleAssingned = false; + boolean isExistsMyItemInModeration = false; + + try { + isContentModerationEnabled = moderatorCheckConfig.isContentModerationEnabled(); + } catch (Exception e) { + GWT.log("Command - Check configs error: " + e.getMessage()); + } + + try { + isModeratorRoleAssingned = moderatorCheckConfig.isModeratorRoleAssigned(); + } catch (Exception e) { + GWT.log("Command - Check configs error: " + e.getMessage()); + } + try { + isExistsMyItemInModeration = moderatorCheckConfig.isExistsMyItemInModeration(); + } catch (Exception e) { + GWT.log("Command - Check configs error: " + e.getMessage()); + } + + GWT.log("Moderation is enabled? " + isContentModerationEnabled); + GWT.log("Moderator role is assigned? " + isModeratorRoleAssingned); + GWT.log("isExistsMyItemInModeration? " + isExistsMyItemInModeration); + + if (!isContentModerationEnabled) { + try { + basePanelContainer.remove(loader); + } catch (Exception e) { + } + UtilUx.showAlert("The Moderation facility is not enabled in this context", AlertType.WARNING, false, + basePanelContainer, null); + return; + } + + // moderator logged in + if (isModeratorRoleAssingned) { + try { + basePanelContainer.remove(loader); + } catch (Exception e) { + } + + cmsController = new CkanContentModeratorWidgetController(initItemStatus, initOnItemName, displayFields, + orderByFields, false, false); + basePanelContainer.add(cmsController.getMainPanel()); + + mainPanel.setLoggedLabelText("Logged in as Moderator"); + return; + } + + // no item under moderation or already moderated + if (!isExistsMyItemInModeration) { + try { + basePanelContainer.remove(loader); + } catch (Exception e) { + } + UtilUx.showAlert("You are not authorized to access to Moderation facility", AlertType.WARNING, false, + basePanelContainer, null); + return; + } + + try { + basePanelContainer.remove(loader); + } catch (Exception e) { + } + + // read only mode enabled in case of moderator role not assigned + boolean readOnlyMode = !isModeratorRoleAssingned; + // Listing only data belonging to user logged in. He/She must be the owner of. + boolean restrictDataToLoggedInUser = readOnlyMode; + + GWT.log("readOnlyMode is enabled? " + readOnlyMode); + GWT.log("restrictDataToLoggedInUser is? " + restrictDataToLoggedInUser); + + cmsController = new CkanContentModeratorWidgetController(initItemStatus, initOnItemName, displayFields, + orderByFields, readOnlyMode, restrictDataToLoggedInUser); + + basePanelContainer.add(cmsController.getMainPanel()); + } + + /** + * Gets the moderator check config. + * + * @return the moderator check config + */ + public CkanContentModeratorCheckConfigs getModeratorCheckConfig() { + return moderatorCheckConfig; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorCheckConfigs.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorCheckConfigs.java new file mode 100644 index 0000000..90b677d --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorCheckConfigs.java @@ -0,0 +1,196 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.rpc.AsyncCallback; + +/** + * The Class CkanContentModeratorCheckConfigs. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 8, 2022 + */ +public class CkanContentModeratorCheckConfigs { + + private int configurationLoaded = 0; + private static final int CONFIGURATION_EXPECTED = 3; + private int MAX_RETRY_ON_LOADING_CONFIG = 50; + private int attemptLC = 0; + private Boolean contentModerationEnabled = null; + private Boolean moderatorRoleAssigned = null; + private Boolean existsMyItemInModeration = null; + + /** + * Instantiates a new ckan content moderator check config. + */ + public CkanContentModeratorCheckConfigs() { + + } + + /** + * Check configs. + * + * @param whenDone the when done + * @param reloadGCatConfig the reload G cat config + * @throws Exception the exception + */ + public void checkConfigs(final Command whenDone, boolean reloadGCatConfig) throws Exception { + + configurationLoaded = 0; + attemptLC = 0; + + CkanContentModeratorWidgetController.contentModeratorService.isModerationEnabled(reloadGCatConfig, + new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + contentModerationEnabled = false; + incrementConfigurationLoaded(); + + } + + @Override + public void onSuccess(Boolean result) { + incrementConfigurationLoaded(); + GWT.log("isContentModeratorEnabled: " + result); + contentModerationEnabled = result; + } + }); + + CkanContentModeratorWidgetController.contentModeratorService + .isModeratorRoleAssigned(new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + moderatorRoleAssigned = false; + incrementConfigurationLoaded(); + + } + + @Override + public void onSuccess(Boolean result) { + incrementConfigurationLoaded(); + GWT.log("isModeratorRoleAssigned: " + result); + moderatorRoleAssigned = result; + + } + }); + + CkanContentModeratorWidgetController.contentModeratorService + .existsMyItemInModeration(new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + existsMyItemInModeration = false; + incrementConfigurationLoaded(); + + } + + @Override + public void onSuccess(Boolean result) { + incrementConfigurationLoaded(); + GWT.log("existsMyItemInModeration: " + result); + existsMyItemInModeration = result; + + } + }); + + if (whenDone != null) { + + final Timer timer = new Timer() { + + @Override + public void run() { + attemptLC++; + GWT.log("checking configuration loaded, attempt " + attemptLC + " of " + + MAX_RETRY_ON_LOADING_CONFIG); + boolean configsLoaded = getConfigurationLoaded() == CONFIGURATION_EXPECTED; + GWT.log("configsLoaded: " + configsLoaded); + if (configsLoaded) { + GWT.log("ContentModeratorCheckConfig loaded correclty"); + whenDone.execute(); + this.cancel(); + } + + if (attemptLC > MAX_RETRY_ON_LOADING_CONFIG) { + GWT.log("MAX_RETRY_ON_LOADING_CONFIG reached, timer cancelled"); + this.cancel(); + } + + } + }; + + timer.scheduleRepeating(500); + } + } + + /** + * Increment configuration loaded. + */ + private void incrementConfigurationLoaded() { + configurationLoaded++; + } + + /** + * Decrement configuration loaded. + */ + private synchronized void decrementConfigurationLoaded() { + configurationLoaded--; + } + + /** + * Gets the configuration loaded. + * + * @return the configuration loaded + */ + private synchronized int getConfigurationLoaded() { + return configurationLoaded; + } + + /** + * Checks if is moderator role assigned. + * + * @return the boolean + * @throws Exception the exception + */ + public Boolean isModeratorRoleAssigned() throws Exception { + if (moderatorRoleAssigned == null) + throw new Exception( + "Please, first check if the Moderator role is assigned in this context by calling checkContentModeratorConfiguration"); + + return moderatorRoleAssigned; + } + + /** + * Checks if is content moderation enabled. + * + * @return true, if is content moderation enabled + * @throws Exception the exception + */ + public boolean isContentModerationEnabled() throws Exception { + + if (contentModerationEnabled == null) + throw new Exception( + "Please, first check if the content moderation is enabled in this context by calling checkContentModeratorConfiguration"); + + return contentModerationEnabled; + + } + + /** + * Checks if is exists my item in moderation. + * + * @return the boolean + * @throws Exception the exception + */ + public Boolean isExistsMyItemInModeration() throws Exception { + if (existsMyItemInModeration == null) + throw new Exception( + "Please, first check if the content moderation is enabled in this context by calling checkContentModeratorConfiguration"); + + return existsMyItemInModeration; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorService.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorService.java index 8af893d..5b28c9b 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorService.java +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorService.java @@ -2,28 +2,135 @@ package org.gcube.portlets.widgets.ckancontentmoderator.client; import java.util.List; -import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; -import org.gcube.portlets.widgets.ckancontentmoderator.server.ContentModeratorSystem.ItemStatus; +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.ModerationUserRole; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.OperationReport; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchedData; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** - * The client side stub for the RPC service. + * The Interface CkanContentModeratorService. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jan 11, 2022 */ -@RemoteServiceRelativePath("greet") +@RemoteServiceRelativePath("ckanContentModeratorService") public interface CkanContentModeratorService extends RemoteService { - public boolean isContentModeratorEnabled(); + /** + * Sets the status. Currently, this only used to change the status from Rejected + * to Pending + * + * @param theStatus the the status + * @param itemNames the item names + * @return the operation report + * @throws Exception the exception + */ + public OperationReport setStatus(ItemStatus theStatus, List itemNames) throws Exception; - public void setStatus(String itemId, ItemStatus theStatus); + /** + * Reject item. + * + * @param itemNames the item names + * @param permanentlyDelete the permanently delete + * @param reasonMsg the reason msg + * @return the operation report + * @throws Exception the exception + */ + public OperationReport rejectItem(List itemNames, boolean permanentlyDelete, String reasonMsg) + throws Exception; - public List getListItemsForStatus(ItemStatus theStatus); + /** + * Permanently delete. + * + * @param itemNames the item names + * @return the operation report + * @throws Exception the exception + */ + public OperationReport permanentlyDelete(List itemNames) throws Exception; - public void approveItem(String itemId); + /** + * Gets the list items for status. + * + * @param theStatus the the status + * @param offset the offset + * @param limit the limit + * @param restrictedToLoggedInUser the restricted to logged in user + * @param sortForField the sort for field + * @return the list items for status + * @throws Exception the exception + */ + public List getListItemsForStatus(ItemStatus theStatus, int offset, int limit, + boolean restrictedToLoggedInUser, String sortForField) throws Exception; - public void rejectItem(String itemId, boolean permanentlyDelete, String reasonMsg); + /** + * Gets the data for status. + * + * @param status the status + * @param offset the offset + * @param limit the limit + * @param serverStartIndex the server start index + * @param restrictedToLoggedInUser the restricted to logged in user + * @param sortForField the sort for field + * @return the data for status + * @throws Exception the exception + */ + public SearchedData getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex, + boolean restrictedToLoggedInUser, String sortForField) throws Exception; - public void permanentlyDelete(String itemId); + /** + * Approve item. + * + * @param itemNames the item names + * @param moderatorMessage the moderator message + * @return the operation report + * @throws Exception the exception + */ + public OperationReport approveItem(List itemNames, String moderatorMessage) throws Exception; + /** + * Gets the CMS roles for user in the context. + * + * @return the CMS roles for user in the context + * @throws Exception the exception + */ + public ModerationUserRole getCMSRolesForUserInTheContext() throws Exception; + + /** + * Checks if is moderation enabled. + * + * @param reloadConfig the reload config + * @return the boolean + */ + public Boolean isModerationEnabled(boolean reloadConfig); + + /** + * Checks if is moderator role assigned. + * + * @return true, if is moderat@Override or role assigned + * @throws Exception the exception + */ + public Boolean isModeratorRoleAssigned() throws Exception; + + /** + * Exists my item in moderation. + * + * @return true if the user has at least one item moderatorated or in + * moderation. + * @throws Exception the exception + */ + public Boolean existsMyItemInModeration() throws Exception; + + /** + * Gets the item for name. + * + * @param itemName the item name + * @return the item for name + * @throws Exception the exception + */ + CatalogueDataset getItemForName(String itemName) throws Exception; } diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorServiceAsync.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorServiceAsync.java index 1c261b3..f49295f 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorServiceAsync.java +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorServiceAsync.java @@ -2,23 +2,128 @@ package org.gcube.portlets.widgets.ckancontentmoderator.client; import java.util.List; -import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; -import org.gcube.portlets.widgets.ckancontentmoderator.server.ContentModeratorSystem.ItemStatus; +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.ModerationUserRole; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.OperationReport; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchedData; import com.google.gwt.user.client.rpc.AsyncCallback; +/** + * The Interface CkanContentModeratorServiceAsync. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jan 11, 2022 + */ public interface CkanContentModeratorServiceAsync { - void isContentModeratorEnabled(AsyncCallback callback); + /** + * Reject item. + * + * @param itemNames the item names + * @param permanentlyDelete the permanently delete + * @param reasonMsg the reason msg + * @param callback the callback + */ + void rejectItem(List itemNames, boolean permanentlyDelete, String reasonMsg, + AsyncCallback callback); - void approveItem(String itemId, AsyncCallback callback); + /** + * Gets the list items for status. + * + * @param theStatus the the status + * @param offset the offset + * @param limit the limit + * @param restrictedToLoggedInUser the restricted to logged in user + * @param sortForField the sort for field + * @param callback the callback + * @return the list items for status + */ + void getListItemsForStatus(ItemStatus theStatus, int offset, int limit, boolean restrictedToLoggedInUser, + String sortForField, AsyncCallback> callback); - void getListItemsForStatus(ItemStatus theStatus, AsyncCallback> callback); + /** + * Gets the data for status. + * + * @param status the status + * @param offset the offset + * @param limit the limit + * @param serverStartIndex the server start index + * @param restrictedToLoggedInUser the restricted to logged in user + * @param sortForField the sort for field + * @param asyncCallback the async callback + * @return the data for status + */ + void getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex, + boolean restrictedToLoggedInUser, String sortForField, AsyncCallback asyncCallback); - void permanentlyDelete(String itemId, AsyncCallback callback); + /** + * Approve item. + * + * @param itemNames the item names + * @param moderatorMessage the moderator message + * @param callback the callback + */ + void approveItem(List itemNames, String moderatorMessage, AsyncCallback callback); - void rejectItem(String itemId, boolean permanentlyDelete, String reasonMsg, AsyncCallback callback); + /** + * Permanently delete. + * + * @param itemNames the item names + * @param callback the callback + */ + void permanentlyDelete(List itemNames, AsyncCallback callback); - void setStatus(String itemId, ItemStatus theStatus, AsyncCallback callback); + /** + * Sets the status. + * + * @param theStatus the the status + * @param itemNames the item names + * @param callback the callback + */ + void setStatus(ItemStatus theStatus, List itemNames, AsyncCallback callback); + + /** + * Gets the CMS roles for user in the context. + * + * @param callback the callback + * @return the CMS roles for user in the context + */ + void getCMSRolesForUserInTheContext(AsyncCallback callback); + + /** + * Checks if is moderation enabled. + * + * @param reloadConfig the reload config + * @param callback the callback + */ + void isModerationEnabled(boolean reloadConfig, AsyncCallback callback); + + /** + * Checks if is moderator role assigned. + * + * @param callback the callback + */ + void isModeratorRoleAssigned(AsyncCallback callback); + + /** + * Exists my item in moderation. + * + * @param callback the callback + * @return true if the user has at least one item moderatorated or in + * moderation. + */ + void existsMyItemInModeration(AsyncCallback callback); + + /** + * Gets the item for name. + * + * @param itemName the item name + * @param callback the callback + * @return the item for name + */ + void getItemForName(String itemName, AsyncCallback callback); } diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidget.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidget.java index e581ffc..8225c1c 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidget.java +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidget.java @@ -1,53 +1,93 @@ package org.gcube.portlets.widgets.ckancontentmoderator.client; -import java.util.List; +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.MainPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.ExtModal; +import org.gcube.portlets.widgets.ckancontentmoderator.client.util.ModerationQueryStringUtil.ModerationBuilder; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; -import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; -import org.gcube.portlets.widgets.ckancontentmoderator.server.ContentModeratorSystem.ItemStatus; - -import com.google.gwt.core.client.EntryPoint; -import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.rpc.AsyncCallback; +import com.github.gwtbootstrap.client.ui.Modal; +import com.google.gwt.user.client.ui.Composite; /** - * Entry point classes define onModuleLoad(). + * The Class CkanContentModeratorWidget. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 7, 2022 */ -public class CkanContentModeratorWidget implements EntryPoint { - /** - * The message displayed to the user when the server cannot be reached or - * returns an error. - */ - private static final String SERVER_ERROR = "An error occurred while " - + "attempting to contact the server. Please check your network " - + "connection and try again."; +public class CkanContentModeratorWidget { - /** - * Create a remote service proxy to talk to the server-side Greeting service. - */ - private final CkanContentModeratorServiceAsync greetingService = GWT.create(CkanContentModeratorService.class); + private MainPanel mainPanel = new MainPanel(); + private CheckConfigsUxController ccux; + /** + * Instantiates a new ckan content moderator widget. + * + * @param initItemStatus the init item status + * @param initOnItemName the init on item name + * @param displayFields the display fields + * @param sortByFields the sort by fields + */ + public CkanContentModeratorWidget(ItemStatus initItemStatus, String initOnItemName, DISPLAY_FIELD[] displayFields, + DISPLAY_FIELD[] sortByFields) { + mainPanel.setWidth("100%"); + ccux = new CheckConfigsUxController(mainPanel, initItemStatus, initOnItemName, displayFields, sortByFields, null); - /** - * This is the entry point method. - */ - public void onModuleLoad() { - + boolean isModeratorRoleAssigned = false; + try { + isModeratorRoleAssigned = ccux.getModeratorCheckConfig().isModeratorRoleAssigned(); + } catch (Exception e) { - greetingService.getListItemsForStatus(ItemStatus.PENDING, new AsyncCallback>() { - - @Override - public void onSuccess(List result) { - // TODO Auto-generated method stub - } - - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - + + if (isModeratorRoleAssigned) { + mainPanel.setLoggedLabelText("Logged in as Moderator"); } - }); - } - + } + + /** + * Instantiates a new ckan content moderator widget. + * + * @param builder the builder + */ + public CkanContentModeratorWidget(ModerationBuilder builder) { + this(builder.getItemStatus(), builder.getItemName(), builder.getDisplayFields(), builder.getSortByFields()); + } + + /** + * Show as modal. + * + * @param modalTitle the modal title + */ + public void showAsModal(String modalTitle) { + final Modal modal = new ExtModal(true, true); + modalTitle = modalTitle == null || modalTitle.isEmpty() ? "Manage Items" : modalTitle; + modal.setTitle(modalTitle); + modal.setWidth(1200); + modal.getElement().addClassName("modal-content-moderator"); + // modal.getElement().getStyle().setProperty("min-height", "500px"); + modal.add(mainPanel); + modal.setCloseVisible(true); + modal.show(); + } + + /** + * Gets the panel. + * + * @return the panel + */ + public Composite getPanel() { + return mainPanel; + } + + /** + * Gets the congifs. + * + * @return the congifs + */ + public CkanContentModeratorCheckConfigs getCongifs() { + return ccux.getModeratorCheckConfig(); + } } diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetController.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetController.java new file mode 100644 index 0000000..5c0fbef --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetController.java @@ -0,0 +1,331 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.CheckBoxSelectIemsEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.CheckBoxSelectIemsEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ClickItemEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ClickItemEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.CloseAllTabsEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.CloseAllTabsEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.IFrameInstanciedEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.IFrameInstanciedEvent.OPERATION; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.IFrameInstanciedEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.SelectItemsWithItemStatusEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.SelectItemsWithItemStatusEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ShowItemEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ShowItemEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ShowMessageEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ShowMessageEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.TableRangeViewChangedEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.TableRangeViewChangedEventHandler; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.CkanShowItemFrame; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.ContentModeratorToolbar; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.HomeView; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.MainTabPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.UtilUx; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.ItemFieldDV; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchingFilter; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.ComplexPanel; +import com.google.gwt.user.client.ui.FlowPanel; + +/** + * The Class CkanContentModeratorWidgetController. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 29, 2021 + */ +public class CkanContentModeratorWidgetController { + + public final static CkanContentModeratorServiceAsync contentModeratorService = GWT + .create(CkanContentModeratorService.class); + + private FlowPanel mainPanel = new FlowPanel(); + private FlowPanel infoPanel = new FlowPanel(); + + private ContentModeratorToolbar toolbar; + private MainTabPanel mainTabPanel = new MainTabPanel(); + + public final static HandlerManager eventBus = new HandlerManager(null); + private HomeView howeView; + + private HashMap mapOfItemsTabDisplayed = new HashMap(); + + private boolean readOnlyMode; + + /** + * Instantiates a new ckan content moderator widget. + * + * @param status the status + * @param initOnItemName the init on item name + * @param displayFields the display fields + * @param sortByFields the sort by fields + * @param readOnlyMode the read only mode + * @param restrictDataToLoggedInUser the restrict data to logged in user + */ + protected CkanContentModeratorWidgetController(ItemStatus status, final String initOnItemName, + DISPLAY_FIELD[] displayFields, DISPLAY_FIELD[] sortByFields, boolean readOnlyMode, + boolean restrictDataToLoggedInUser) { + + DISPLAY_FIELD firstSortField = null; + if (sortByFields == null || sortByFields.length == 0) { + firstSortField = DISPLAY_FIELD.NAME; + sortByFields[0] = firstSortField; + } else + firstSortField = sortByFields[0]; + + List sortBy = displayFieldsToItemFields(sortByFields); + + toolbar = new ContentModeratorToolbar(eventBus, status, sortBy); + +// GWT.log("***************** HARD CODED READONLY ********************** "); +// readOnlyMode = true; +// restrictDataToLoggedInUser = readOnlyMode; + + howeView = new HomeView(eventBus, status, displayFields, firstSortField, readOnlyMode, + restrictDataToLoggedInUser); + mainTabPanel.addHomeWidget(howeView.getPanel()); + mainPanel.add(toolbar); + mainPanel.add(infoPanel); + mainPanel.add(mainTabPanel); + this.readOnlyMode = readOnlyMode; + + howeView.hideUpdateStatusAction(readOnlyMode); + howeView.hideSelectableRow(readOnlyMode); + bindEvents(); + + if (initOnItemName != null) { + + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + + @Override + public void execute() { + + CkanContentModeratorWidgetController.contentModeratorService.getItemForName(initOnItemName, + new AsyncCallback() { + + @Override + public void onSuccess(CatalogueDataset result) { + GWT.log("CatalogueDataset read is: " + result); + + if (result != null) { + eventBus.fireEvent(new ShowItemEvent(Arrays.asList(result),true)); + } + + } + + @Override + public void onFailure(Throwable caught) { + GWT.log("Error on reading " + initOnItemName + ". Either the item with name: " + + initOnItemName + " is not valid dataset or not readable"); + + } + }); + } + + }); + + } + + } + + /** + * TEMPORARY SOLUTION... IT SHOULD BE A CONFIGURATION + * + * @param sortByFields + * @return + */ + + private List displayFieldsToItemFields(DISPLAY_FIELD[] sortByFields) { + + List listSortByIF = new ArrayList(sortByFields.length); + for (DISPLAY_FIELD display_FIELD : sortByFields) { + for (SearchingFilter.ORDER order : SearchingFilter.ORDER.values()) { + ItemFieldDV itemField = new ItemFieldDV(); + itemField.setDisplayName(display_FIELD.getLabel() + " - " + order); + itemField.setJsonFields(Arrays.asList(display_FIELD.getJsonField() + " " + order.name().toLowerCase())); + listSortByIF.add(itemField); + } + } + + return listSortByIF; + } + + /** + * Bind events. + */ + private void bindEvents() { + + eventBus.addHandler(ClickItemEvent.TYPE, new ClickItemEventHandler() { + + @Override + public void onClick(ClickItemEvent clickItemEvent) { + + if (clickItemEvent.getSelectItems() != null) { + List items = clickItemEvent.getSelectItems(); + // if items selected are > 0 then shows button "Update status as.." + howeView.setVisibleUpdateStatusAction(items.size() > 0); + + if (howeView.getDisplayingItemStatus().equals(ItemStatus.APPROVED)) { + GWT.log("The Item Status displayed is " + ItemStatus.APPROVED + + " hiding update status actions"); + howeView.setVisibleUpdateStatusAction(false); + } + + // If an action updated the item status we reloading it + reloadItemsDisplayedInTab(); + } + } + }); + + eventBus.addHandler(ShowItemEvent.TYPE, new ShowItemEventHandler() { + + @Override + public void onShowItemClicked(ShowItemEvent showItemEvent) { + GWT.log("onShowItemClicked fired"); + if (showItemEvent.getSelectItems() != null) { + List items = showItemEvent.getSelectItems(); + + for (T t : items) { + CatalogueDataset clickedDataset = (CatalogueDataset) t; + CkanShowItemFrame csif = new CkanShowItemFrame(eventBus); + csif.instanceFrame(clickedDataset.getUrl()); + mainTabPanel.addTab(clickedDataset.getTitle(), csif, showItemEvent.isFocusOnDisplaying()); + mapOfItemsTabDisplayed.put(clickedDataset.getUrl(), csif); + } + } + } + }); + + eventBus.addHandler(IFrameInstanciedEvent.TYPE, new IFrameInstanciedEventHandler() { + + @Override + public void onIFrameAction(IFrameInstanciedEvent iFrameInstanciedEent) { + + OPERATION operation = iFrameInstanciedEent.getOperation(); + if (operation != null) { + switch (operation) { + case INIT: + break; + case ONLOAD: + + break; + + default: + break; + } + } + + } + }); + + eventBus.addHandler(CheckBoxSelectIemsEvent.TYPE, new CheckBoxSelectIemsEventHandler() { + + @Override + public void onValueChanged(CheckBoxSelectIemsEvent onValueChangedEvent) { + howeView.markItemsAsChecked(onValueChangedEvent.isChecked(), true); + + } + }); + + eventBus.addHandler(TableRangeViewChangedEvent.TYPE, new TableRangeViewChangedEventHandler() { + + @Override + public void onRangeChanged(TableRangeViewChangedEvent tableRangeViewChangedEvent) { + howeView.setVisibleUpdateStatusAction(false); + howeView.setCheckedCheckboxSelectAll(false); + } + }); + + eventBus.addHandler(CloseAllTabsEvent.TYPE, new CloseAllTabsEventHandler() { + + @Override + public void onClick(CloseAllTabsEvent closeAllTabsEvent) { + mainTabPanel.closeTabs(); + mapOfItemsTabDisplayed.clear(); + } + }); + + eventBus.addHandler(SelectItemsWithItemStatusEvent.TYPE, new SelectItemsWithItemStatusEventHandler() { + + @Override + public void onValueChanged(SelectItemsWithItemStatusEvent statusSelectedEvent) { + GWT.log("On value changed: " + statusSelectedEvent.getItemStatus()); + infoPanel.clear(); + if (statusSelectedEvent.getItemStatus() != null) { + ItemFieldDV sortBy = statusSelectedEvent.getSortBy(); + + if (sortBy == null) { + sortBy = toolbar.getActiveSortBy(); + + } + String sortForField = sortBy.getJsonFields().get(0); + GWT.log("sortForField is: " + sortForField); + howeView.loadItemsWithStatus(statusSelectedEvent.getItemStatus(), sortForField); + mainTabPanel.selectTab(0); + } + + if (statusSelectedEvent.getDisplayMessage() != null) { + UtilUx.showAlert(statusSelectedEvent.getDisplayMessage(), statusSelectedEvent.getAlertType(), true, + infoPanel, 15000); + } + + } + }); + + eventBus.addHandler(ShowMessageEvent.TYPE, new ShowMessageEventHandler() { + + @Override + public void onShowMessage(ShowMessageEvent showMessageEvent) { + + if (showMessageEvent.getMsg() != null) { + UtilUx.showAlert(showMessageEvent.getMsg(), showMessageEvent.getAlerType(), true, infoPanel, 15000); + + } + } + }); + } + + /** + * Reload items displayed in tab. + */ + private void reloadItemsDisplayedInTab() { + + for (String datasetURL : mapOfItemsTabDisplayed.keySet()) { + CkanShowItemFrame showItemFrame = mapOfItemsTabDisplayed.get(datasetURL); + showItemFrame.reloadPage(); + } + } + + /** + * Gets the main panel. + * + * @return the main panel + */ + public ComplexPanel getMainPanel() { + return mainPanel; + } + + /** + * Checks if is read only mode. + * + * @return true, if is read only mode + */ + public boolean isReadOnlyMode() { + return readOnlyMode; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetEntryPoint.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetEntryPoint.java new file mode 100644 index 0000000..85a6868 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetEntryPoint.java @@ -0,0 +1,22 @@ +//package org.gcube.portlets.widgets.ckancontentmoderator.client; +// +//import com.google.gwt.core.client.EntryPoint; +// +///** +// * Entry point classes define onModuleLoad(). +// */ +//public class CkanContentModeratorWidgetEntryPoint implements EntryPoint { +// /** +// * The message displayed to the user when the server cannot be reached or +// * returns an error. +// */ +// private static final String SERVER_ERROR = "An error occurred while " +// + "attempting to contact the server. Please check your network " + "connection and try again."; +// +// /** +// * This is the entry point method. +// */ +// public void onModuleLoad() { +// } +// +//} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetTrusted.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetTrusted.java new file mode 100644 index 0000000..a8a6fc3 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/CkanContentModeratorWidgetTrusted.java @@ -0,0 +1,76 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.MainPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.ExtModal; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; + +import com.github.gwtbootstrap.client.ui.Modal; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Composite; + +/** + * The Class CkanContentModeratorWidget. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + */ +public class CkanContentModeratorWidgetTrusted { + + private MainPanel mainPanel = new MainPanel(); + + private CheckConfigsUxController ccux; + + /** + * Instantiates a new ckan content moderator widget trusted. + * + * @param initItemStatus the init item status + * @param displayFields the display fields + * @param sortByField the sort by field + * @param ckanContentModeratorCheckConfig the ckan content moderator check + * config + */ + public CkanContentModeratorWidgetTrusted(ItemStatus initItemStatus, DISPLAY_FIELD[] displayFields, + DISPLAY_FIELD[] sortByFields, CkanContentModeratorCheckConfigs ckanContentModeratorCheckConfig) { + GWT.log("CkanContentModeratorWidget called. CkanContentModeratorCheckConfigs: " + + ckanContentModeratorCheckConfig); + mainPanel.setWidth("100%"); + ccux = new CheckConfigsUxController(mainPanel, initItemStatus, null, displayFields, sortByFields, ckanContentModeratorCheckConfig); + } + + /** + * Show as modal. + * + * @param modalTitle the modal title + */ + public void showAsModal(String modalTitle) { + final Modal modal = new ExtModal(true, true); + modalTitle = modalTitle == null || modalTitle.isEmpty() ? "Manage Items" : modalTitle; + modal.setTitle(modalTitle); + modal.setWidth(1200); + modal.getElement().addClassName("modal-content-moderator"); + // modal.getElement().getStyle().setProperty("min-height", "500px"); + modal.add(mainPanel); + modal.setCloseVisible(true); + modal.show(); + } + + /** + * Gets the panel. + * + * @return the panel + */ + public Composite getPanel() { + return mainPanel; + } + + /** + * Gets the configs. + * + * @return the configs + */ + public CkanContentModeratorCheckConfigs getConfigs() { + return ccux.getModeratorCheckConfig(); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ContentModeratorWidgetConstants.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ContentModeratorWidgetConstants.java new file mode 100644 index 0000000..6e31019 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ContentModeratorWidgetConstants.java @@ -0,0 +1,23 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client; + +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; + +/** + * The Class ContentModeratorWidgetConstants. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + */ +public class ContentModeratorWidgetConstants { + + public static final String NO_DATA = "No data"; + + public static int ITEMS_PER_PAGE = 10; + public static int ITEM_START_INDEX = 0; + + public static String CKAN_FIELD_NAME_AUTHOR_MAIL = "author_email"; + + public static DISPLAY_FIELD[] DEFAULT_SORT_BY_FIELDS = new DISPLAY_FIELD[] { DISPLAY_FIELD.NAME, DISPLAY_FIELD.TITLE, + DISPLAY_FIELD.CREATED, DISPLAY_FIELD.LAST_UPDATE, DISPLAY_FIELD.TYPE }; +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEvent.java new file mode 100644 index 0000000..9f39cf7 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEvent.java @@ -0,0 +1,62 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class CheckBoxSelectIemsEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + * @param the generic type + */ +public class CheckBoxSelectIemsEvent extends GwtEvent { + public static Type TYPE = new Type(); + private boolean isChecked; + + /** + * Instantiates a new click item event. + * + * @param selectItems the select items + */ + public CheckBoxSelectIemsEvent(boolean checkedValue) { + this.isChecked = checkedValue; + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + /* + * (non-Javadoc) + * + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared. + * EventHandler) + */ + @Override + protected void dispatch(CheckBoxSelectIemsEventHandler handler) { + handler.onValueChanged(this); + } + + public boolean isChecked() { + return isChecked; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEventHandler.java new file mode 100644 index 0000000..99169fc --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CheckBoxSelectIemsEventHandler.java @@ -0,0 +1,23 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface CheckBoxSelectIemsEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public interface CheckBoxSelectIemsEventHandler extends EventHandler { + + + /** + * On value changed. + * + * @param the generic type + * @param onValueChangedEvent the on value changed event + */ + void onValueChanged(CheckBoxSelectIemsEvent onValueChangedEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEvent.java new file mode 100644 index 0000000..5788651 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEvent.java @@ -0,0 +1,68 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import java.util.List; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class ClickItemEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + * @param the generic type + */ +public class ClickItemEvent extends GwtEvent { + public static Type TYPE = new Type(); + private List selectItems; + + /** + * Instantiates a new click item event. + * + * @param selectItems the select items + */ + public ClickItemEvent(List selectItems) { + this.selectItems = selectItems; + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + /* + * (non-Javadoc) + * + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared. + * EventHandler) + */ + @Override + protected void dispatch(ClickItemEventHandler handler) { + handler.onClick(this); + } + + /** + * Gets the select items. + * + * @return the select items + */ + public List getSelectItems() { + return selectItems; + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEventHandler.java new file mode 100644 index 0000000..756baed --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ClickItemEventHandler.java @@ -0,0 +1,21 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface ClickItemEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 6, 2015 + */ +public interface ClickItemEventHandler extends EventHandler { + + /** + * On click. + * + * @param the generic type + * @param moreInfoShowEvent the more info show event + */ + void onClick(ClickItemEvent moreInfoShowEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEvent.java new file mode 100644 index 0000000..85640b0 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEvent.java @@ -0,0 +1,45 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.GwtEvent; + + + +// TODO: Auto-generated Javadoc +/** + * The Class CloseAllTabsEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public class CloseAllTabsEvent extends GwtEvent { + public static Type TYPE = new Type(); + + /** + * Instantiates a new close all tabs event. + */ + public CloseAllTabsEvent() { + + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + @Override + protected void dispatch(CloseAllTabsEventHandler handler) { + handler.onClick(this); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEventHandler.java new file mode 100644 index 0000000..55b9ea2 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/CloseAllTabsEventHandler.java @@ -0,0 +1,21 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface CloseAllTabsEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public interface CloseAllTabsEventHandler extends EventHandler { + + /** + * On click. + * + * @param closeAllTabsEvent the close all tabs event + */ + void onClick(CloseAllTabsEvent closeAllTabsEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEvent.java new file mode 100644 index 0000000..ee84ed5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEvent.java @@ -0,0 +1,91 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.GwtEvent; +import com.google.gwt.user.client.ui.Frame; + + +/** + * The Class IFrameInstanciedEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 28, 2021 + */ +public class IFrameInstanciedEvent extends GwtEvent { + public static Type TYPE = new Type(); + private Frame iFrame; + private OPERATION operation; + + /** + * The Enum OPERATION. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 28, 2021 + */ + public static enum OPERATION { + INIT, ONLOAD + } + + /** + * Instantiates a new insert metadata event. + * + * @param iFrame the i frame + * @param operation the operation + */ + public IFrameInstanciedEvent(Frame iFrame, OPERATION operation) { + this.iFrame = iFrame; + this.operation = operation; + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + /* + * (non-Javadoc) + * + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared. + * EventHandler) + */ + @Override + protected void dispatch(IFrameInstanciedEventHandler handler) { + handler.onIFrameAction(this); + } + + /** + * Gets the i frame. + * + * @return the i frame + */ + public Frame getiFrame() { + return iFrame; + } + + /** + * Gets the operation. + * + * @return the operation + */ + public OPERATION getOperation() { + return operation; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEventHandler.java new file mode 100644 index 0000000..51a2704 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/IFrameInstanciedEventHandler.java @@ -0,0 +1,23 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface IFrameInstanciedEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 28, 2021 + */ +public interface IFrameInstanciedEventHandler extends EventHandler { + + + /** + * On I frame action. + * + * @param iFrameInstanciedEent the i frame instancied eent + */ + void onIFrameAction(IFrameInstanciedEvent iFrameInstanciedEent); + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEvent.java new file mode 100644 index 0000000..59a942e --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEvent.java @@ -0,0 +1,108 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.ItemFieldDV; + +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class SelectItemsWithItemStatusEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 28, 2021 + */ +public class SelectItemsWithItemStatusEvent extends GwtEvent { + public static Type TYPE = new Type(); + private ItemStatus itemStatus; + private String displayMessage; + private AlertType alertType = AlertType.INFO; + private ItemFieldDV sortBy; + + /** + * Instantiates a new click item event. + * + * @param itemStatus the item status + * @param displayMessage the display message + * @param alerType the aler type + * @param sortBy the sort by + */ + public SelectItemsWithItemStatusEvent(ItemStatus itemStatus, String displayMessage, AlertType alerType, + ItemFieldDV sortBy) { + this.itemStatus = itemStatus; + this.displayMessage = displayMessage; + this.alertType = alerType; + this.sortBy = sortBy; + } + + /** + * Instantiates a new select items with item status event. + * + * @param itemStatus the item status + * @param displayMessage the display message + * @param alerType the aler type + */ + public SelectItemsWithItemStatusEvent(ItemStatus itemStatus, String displayMessage, AlertType alerType) { + this.itemStatus = itemStatus; + this.displayMessage = displayMessage; + this.alertType = alerType; + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + @Override + protected void dispatch(SelectItemsWithItemStatusEventHandler handler) { + handler.onValueChanged(this); + } + + /** + * Gets the item status. + * + * @return the item status + */ + public ItemStatus getItemStatus() { + return itemStatus; + } + + /** + * Gets the display message. + * + * @return the display message + */ + public String getDisplayMessage() { + return displayMessage; + } + + /** + * Gets the alert type. + * + * @return the alert type + */ + public AlertType getAlertType() { + return alertType; + } + + /** + * Gets the sort by. + * + * @return the sort by + */ + public ItemFieldDV getSortBy() { + return sortBy; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEventHandler.java new file mode 100644 index 0000000..eb805dd --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/SelectItemsWithItemStatusEventHandler.java @@ -0,0 +1,21 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface SelectItemsWithItemStatusEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 28, 2021 + */ +public interface SelectItemsWithItemStatusEventHandler extends EventHandler { + + /** + * On value changed. + * + * @param statusSelectedEvent the status selected event + */ + void onValueChanged(SelectItemsWithItemStatusEvent statusSelectedEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEvent.java new file mode 100644 index 0000000..a434fec --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEvent.java @@ -0,0 +1,80 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import java.util.List; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class ShowItemEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + * @param the generic type + */ +public class ShowItemEvent extends GwtEvent { + public static Type TYPE = new Type(); + private List selectItems; + private boolean focusOnDisplaying = false; + + /** + * Instantiates a new click item event. + * + * @param selectItems the select items + * @param focusOnDisplaying the focus on displaying + */ + public ShowItemEvent(List selectItems, boolean focusOnDisplaying) { + this.selectItems = selectItems; + this.focusOnDisplaying = focusOnDisplaying; + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + /* + * (non-Javadoc) + * + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared. + * EventHandler) + */ + @Override + protected void dispatch(ShowItemEventHandler handler) { + handler.onShowItemClicked(this); + } + + /** + * Gets the select items. + * + * @return the select items + */ + public List getSelectItems() { + return selectItems; + } + + /** + * Checks if is focus on displaying. + * + * @return true, if is focus on displaying + */ + public boolean isFocusOnDisplaying() { + return focusOnDisplaying; + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEventHandler.java new file mode 100644 index 0000000..75bceb8 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowItemEventHandler.java @@ -0,0 +1,23 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + + +// TODO: Auto-generated Javadoc +/** + * The Interface ShowItemEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public interface ShowItemEventHandler extends EventHandler { + + /** + * On show item clicked. + * + * @param the generic type + * @param showItemEvent the show item event + */ + void onShowItemClicked(ShowItemEvent showItemEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEvent.java new file mode 100644 index 0000000..836e0ef --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEvent.java @@ -0,0 +1,68 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class ShowMessageEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Feb 22, 2022 + */ +public class ShowMessageEvent extends GwtEvent { + public static Type TYPE = new Type(); + private String msg; + private AlertType alerType; + + /** + * Instantiates a new click item event. + * + * @param msg the msg + * @param alerType the aler type + */ + public ShowMessageEvent(String msg, AlertType alerType) { + this.msg = msg; + this.alerType = alerType; + } + + /** + * Gets the associated type. + * + * @return the associated type + */ + /* + * (non-Javadoc) + * + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * Dispatch. + * + * @param handler the handler + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared. + * EventHandler) + */ + @Override + protected void dispatch(ShowMessageEventHandler handler) { + handler.onShowMessage(this); + } + + public String getMsg() { + return msg; + } + + public AlertType getAlerType() { + return alerType; + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEventHandler.java new file mode 100644 index 0000000..dbdddd8 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/ShowMessageEventHandler.java @@ -0,0 +1,20 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + +/** + * The Interface ShowMessageEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Feb 22, 2022 + */ +public interface ShowMessageEventHandler extends EventHandler { + + /** + * On show message. + * + * @param showMessageEvent the show message event + */ + void onShowMessage(ShowMessageEvent showMessageEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEvent.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEvent.java new file mode 100644 index 0000000..b235763 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEvent.java @@ -0,0 +1,47 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class TableRangeViewChangedEvent. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + * @param the generic type + */ +public class TableRangeViewChangedEvent extends GwtEvent { + public static Type TYPE = new Type(); + private int startIndex; + private int limitIndex; + + /** + * Instantiates a new click item event. + * + * @param handler the handler + * @return + */ + public TableRangeViewChangedEvent(int start, int limit) { + this.startIndex = start; + this.limitIndex = limit; + } + + @Override + public Type getAssociatedType() { + return TYPE; + } + + @Override + protected void dispatch(TableRangeViewChangedEventHandler handler) { + handler.onRangeChanged(this); + } + + public int getStartIndex() { + return startIndex; + } + + public int getLimitIndex() { + return limitIndex; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEventHandler.java new file mode 100644 index 0000000..a7538ab --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/events/TableRangeViewChangedEventHandler.java @@ -0,0 +1,16 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.events; + +import com.google.gwt.event.shared.EventHandler; + +/** + * The Interface TableRangeViewChangedEventHandler. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public interface TableRangeViewChangedEventHandler extends EventHandler { + + void onRangeChanged(TableRangeViewChangedEvent tableRangeViewChangedEvent); + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTable.css b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTable.css new file mode 100644 index 0000000..5d44a9d --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTable.css @@ -0,0 +1,110 @@ +@def selectionBorderWidth 1px ; .cellTableWidget { + +} + +.cellTableFirstColumn { + +} + +.cellTableLastColumn { + +} + +.cellTableFooter { + +} + +.cellTableHeader { +} + +.cellTableCell { + +} + +.cellTableFirstColumnFooter { + +} + +.cellTableFirstColumnHeader { + +} + +.cellTableLastColumnFooter { + +} + +.cellTableLastColumnHeader { + +} + +.cellTableSortableHeader { + +} + +.cellTableSortableHeader:hover { + +} + +.cellTableSortedHeaderAscending { + +} + +.cellTableSortedHeaderDescending { + +} + +.cellTableEvenRow { + +} + +.cellTableEvenRowCell { + +} + +.cellTableOddRow { + +} + +.cellTableOddRowCell { + +} + +.cellTableHoveredRow { + background: #D9EDF7 !important; + cursor: pointer; +} + +.cellTableHoveredRowCell { + background: #D9EDF7 !important; + cursor: pointer; +} + +.cellTableKeyboardSelectedRow, .cellTableKeyboardSelectedRow td, .cellTableKeyboardSelectedRow th { + background: #b0cddd !important; +} + +.cellTableSelectedRow, .cellTableSelectedRow td, .cellTableSelectedRow th + { + /* background: #D9EDF7 !important; */ + /* color: white !important; */ + /* height: auto; */ + /* overflow: auto; */ + +} + +.cellTableSelectedRowCell, .cellTableSelectedRow td.cellTableSelectedRowCell { + background: #b0cddd !important; +} + +.cellTableKeyboardSelectedRowCell, .cellTableKeyboardSelectedRow td.cellTableKeyboardSelectedRowCell{ + background: #b0cddd !important; +} + +.cellTableKeyboardSelectedCell, .cellTableKeyboardSelectedRow td.cellTableKeyboardSelectedCell{ + background: #b0cddd !important; + color: white !important; +} + +.cellTableLoading { + margin: 30px; +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTableResources.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTableResources.java new file mode 100644 index 0000000..36eb66c --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/CellTableResources.java @@ -0,0 +1,23 @@ +/** + * + */ +package org.gcube.portlets.widgets.ckancontentmoderator.client.resources; + +import com.github.gwtbootstrap.client.ui.CellTable; +import com.github.gwtbootstrap.client.ui.CellTable.Resources; +import com.google.gwt.core.shared.GWT; + +/** + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 23, 2015 + */ +public interface CellTableResources extends Resources { + + public CellTableResources INSTANCE = GWT.create(CellTableResources.class); + + // The styles used in this widget. + @Override + @Source("CellTable.css") + CellTable.Style cellTableStyle(); +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorIcons.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorIcons.java new file mode 100644 index 0000000..a24b08f --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorIcons.java @@ -0,0 +1,56 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.resources; + +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.ImageResource; + +/** + * The Interface WorkspaceExplorerIcons. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + */ +public interface ContentModeratorIcons extends ClientBundle { + + /** + * Cancel. + * + * @return the image resource + */ + @Source("cancel.png") + ImageResource cancel(); + + /** + * Loading. + * + * @return the image resource + */ + @Source("loading.gif") + ImageResource loading(); + + /** + * Our sample image icon. Makes the image resource for the gwt-compiler's css + * composer accessible + * + * @return the image resource + */ + @Source("loading.gif") + ImageResource logo(); + + /** + * Info. + * + * @return the image resource + */ + @Source("info-icon.png") + ImageResource info(); + + /** + * Info square. + * + * @return the image resource + */ + + @Source("info-square.png") + ImageResource infoSquare(); +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorWidgetResources.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorWidgetResources.java new file mode 100644 index 0000000..9763cc6 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/ContentModeratorWidgetResources.java @@ -0,0 +1,56 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.resources; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.AbstractImagePrototype; + +/** + * The Class ContentModeratorWidgetResources. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + */ +public class ContentModeratorWidgetResources { + + public static final ContentModeratorIcons ICONS = GWT.create(ContentModeratorIcons.class); + + /** + * Gets the icon cancel. + * + * @return the icon cancel + */ + public static AbstractImagePrototype getIconCancel() { + + return AbstractImagePrototype.create(ICONS.cancel()); + } + + /** + * Gets the icon loading. + * + * @return the icon loading + */ + public static AbstractImagePrototype getIconLoading() { + + return AbstractImagePrototype.create(ICONS.loading()); + } + + /** + * Gets the icon info. + * + * @return the icon info + */ + public static AbstractImagePrototype getIconInfo() { + + return AbstractImagePrototype.create(ICONS.info()); + } + + /** + * Gets the icon info square. + * + * @return the icon info square + */ + public static AbstractImagePrototype getIconInfoSquare() { + + return AbstractImagePrototype.create(ICONS.infoSquare()); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/cancel.png b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..9aa895bbf38f2303b1039c96f84b204a74281936 GIT binary patch literal 908 zcmV;719SX|P)F7{~vo_uSiCN+Y%uS|>6jKEz1I0J_tJB>NecODCrDtb3ma?D3-L7LZRTjr}v)Sl0bZ!&$siO=l{!j z{^xlJ9uo}(1-VPh%8IRSw;1m0yS?}P`TqZ_BM&EzQo4Dm$J3DaLUp<1auXs+(2_~q z4Fm>*EzO5I5|f9I0PGRKc7WEnT}Pg(t9w^mXeY|QF-(WU;EX}cc0kI>g{~+VZg0PK zJs5m>A4l{7z%i$zadrJ$yEIin@Z8z%-oAkYy})lOpe_Se6+0bY6uweZN<kq9x4&0jsd_qvMY3Fu7wPup86DOK~o|vpZWeDfs`yKX8B`bra( zoShB7zoUXw07dVVKhsMoMeCI=&q<&&E&gi#^WMtEPM-io8eG8i37?%-#&c9RFzCWAxtnwm@FmQB=^Hrx3HzFs=(Mdb)q4+6UZR z37G0ELQ><9|53E}NePg#%}V2TjZ42XeeXTagRf?azGVq!wipimY7=9=1grYd5T{?Z z!T6DlR(d0C($!?DYSzRLY}CJEGF3U2B}JBSZeKpZ%nOa1%L~NV596%*63{*8%kB)} zyOpZ`#vO~0Xq!yAX94SgjkOEJGr7|mu`?YGBYQ1NihUnft2^%#*NUdyUfFa=Wt?2% ze1D6ge>y)%TP;G<7DDQs(M@opk< iJFcpK8rze4xb{EOv{#A~ISFF`0000WFkZsqLGJ(ht=89 z#hsI#D}v$wf42WH6aW2ZU}9nV#5iO9nKi1?qQPv;j10_75X=NJ2#guQ=J2unXJBLa zhs|MM7}e^}{sJ;s@j0KHor%F-mYqRQmH`Lq5GIQQ+!hO%x)_h0ll8dw*5~_9jqSNjzn7nw$9$9j)}gJ9!RsI0**L?} zX2n{Wc$N4(<;nxQlxLP-(bCJGCeh>K^7xp1&TXmwvwL|wfc7zXy85}Sb4q9e0I392 As{jB1 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/info-square.png b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/info-square.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a1251a5150e23d6c0a427453eab03a7d294c02 GIT binary patch literal 325 zcmV-L0lNN)P)-@25Jle#6$nu|C&-DM3ozV)0-Ct88yYGuz;J>1U~#7rG>{@T<1r#*7uiay-Fe!t z`6~c@-|wAspTHY1@pmZT+gf|dvg|Bf*X_OcU!l%R4jR~nULJ;lq9_1p+xB<%HDssQ&>Tfk@ccNa4&90fT5IaMMntgIqIIy9 zwXmxM=Nwg4QI;jcFf1SXG$4-SB~R1zHNXvWi)q@n#wOs|_&>nC`$8tV2dt_h!Z?mg z?ws4Qv(mr?cz*<>X-d;H02pJo02gJ9IfjZNLXspTNwO)yT6+|L>qfq`&c>Kip6BNu X1a@656k}1ryO8ObC|<)WRb%k zX{}>iN7gr1@CnR!3Omzrco{O|IFHCW z)J$Qt-@x{WOM#DFlF2y1Oh8}3$#|0@r^B369AAx3Y)R7L@?KbCF19mn!fHphGfa=v zbn4oE&Svb7kv-Ay)j_7?@XEM=Drvr-Ulo|c7z-u%Sic7B5^VpYwMwGlJa-FEgujNs zM@a^Lmzs+ad`qo2o;bKzkVV7GL&2dis7=zTEX|2cB{iMFA>1N)*0Rf@KyNX4y85}S Ib4q9e00*vG{r~^~ literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/loading.gif b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/resources/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..e147426f23b581693164b7cdf22fd5f99b15c0ed GIT binary patch literal 8114 zcmbW6X;@T;xyNTcXSOpNvz*yC7-nVmnKJ|43p1`MA{vuuM6ROAMK4;kn&hUoVG$P; z#3kZ_2F19dLIgAh4JaB+iFLu&L}F3V8f&c0^)_uEpXR>f(YX|ieeU%GALfA%p5OWX z-~ap0m~o?t@JtCsLivzF@#ojoebif2+1~Tj{p`0ITh8_^-QIQo!J~}1yYk9fx-JcD z*x%E5vaj#X{YQU$ykuin-Y;9a&JV2K-IG1PG2_i$jmLWzt!wYQd4KX-jqULH&aOv) zewAenrJ}`2A&-nC@RmSo35MZqkb zQ$eRV7DXhN_pM(sa?<<6y2V6p&bcmgloeTv9B%)TSQaSjK{~^~Uu;M#RGGY96Z&2> zqDotnp||2z-KrQL-J#XKDr z_KP@@y=$pjfyB(~scGszQz_-)n=F)@r;JLM%wZAD7=Hbc>MbFd1t3-T_{rR_+nnLerc9 zy4HImiU`?kD&h@&77%gf_7;A|>RKhD5*hDMPE)XwWY)jzbC=SWvw2tvWnu%G%oIUkAWZfN193^ z1e`-m1x*1Vydpr66cj*`f|3Y_JBoY*`u(L|@sbi}pp&oOWgW^)aGznhc%GXnNzwLL#P3)?oAVC<|_ku8^--#-P4PJxD_^B|#4o7U+@c zk=}uT@w7eO3+j>aO4~N! z)*(n>UyNua4kP>{QNnyu*OB^3#C#C52m~K}Lg43(0=Mxru0QXfeu*Bz(ypJBD3wNh zJAvN49pNh_Z05CGJp3q}6E(42MrI&<9aR?>7aNyH@(*y{*(A!!s-ilONXfvN&WZ}o z=-$1ZWoK5F=VuS#nadlpf)f(z4bM%OjW8jB985?EO-RoKyhLaMIZ%d#2f%F_Ef4&Q=;E^)WM#LP4o~rDlID z)k+cb`L2}KXvk<)Q>m$;PooNikWkg$bHrsru9nEpnXj3pY_=0=B@`G&m`zTT4yz~h z3PnzY%V6j@>vGKw$DfLpF4DVAWi$mc(CjWgT|$*TSk_;&ptByMYGyku3mRrF8;3}0 zj#(O_6-?}#@uz0aC|zBfB1Y6=##0MJ&l`ZlEd&L@KQcPuL6b>JDhN19`Qn~Iu^BWE zpZd4+sed3Jm`BDX8J)xBBj?@_`AGA~=o~H|NfCY`zwg+ZORQtgwUo|Uiv!5bl^e#L zk5;ldj1w1MU#7gG+>*`OO8IuGd+9hwcjl{m=dl>C&DgYm5s$0P^?NyK%h@3ll`A#M zrbkm;A`i!8b#S@CwK29wrxU7;M(6gJ-^Y?8cxtM3UyLf3C*jApwS?41b>dU)EozEc z=fp6)HGpF5%#g zI#@!|K!6C74;fP{(W0vv}!L>|N?yqD{>Oip`v3fL*`7iW$j)ScLWm)$FF$=VdOSQ{ zn$TY#BWRw0ftkkU9Ehm`ffQ3a(iZg_jUJ|s>G(9FV2UR)PQm+`b-9IGyS!DSGpR?QfQqPn??Rn%U+*5 zW%ld8y>(MPccf#%n5HSow0mES_BTp7awd|mM6D{i^52A-DrtTc5zs?v!GKVrvDd_C z8$y0JTUfbmB&s&2(ERMco)|~1Rvq-OX(rfen_1cMakG$N)A2wcXp}mYO(jmSvFfNY$=&E zvtoHka#77#YCi*EV;3-ksD@g;0=1ni$*dYVQYD?TsQ&w8)<4m2$d(WENd4fE159!Z z0vyu7#B%>*`o%lwvl%$tJwTVhm?)rRlOgpZJLq8dhV1uG0e&0T&lK>guAGg9LBFk^ zy+0PouKr00?aGbW+oQYpb2>iKZA8D{HRa8MRXuIT=3PR{|NWi9DH#|#ohwI7CU1TS z!$N}TQFIx{k&4noA$?8Eo1|9LlQnd1U5wD#?KbZr=bjjoMhi%e;?2>J%SGdMe0&_^ z3GKn;nV;RP1uc2{{R!J&-ZkyW;IsrdmG?i4LAU1@dPdH6Qxvszqi>wVZi zZ|t)LK7E*igJh&ROe_-MA_z)ue=q>y9RN*-1SkoS?4p1>!7(ug zVE_Wt7ehoIbZpDr^vU83)78D5nV?|o^krq0Wc~QeiKPz~@?O4m$(DDd^yT~Oety09 zn6-L=ubRe3?|7FiMvC?MJSvXsriZ1z)j9d;E`A!q59@h8sbWn`iXcH>h_|RNX7MB^ za~7wR?T$LR5`1x}x`~jelVOt=G(`!AL*hbRou^E+0HSc|w>E_lV}NQ=^v&B%2-yK5 zy-#o~KNJuOCG)}-OZfVPFlLlRgagsqX&HxNOCHP0GL`XY z_PZnIP$!l%7zT^kJ<~RZ%V9+Cxr?b^S3jG9gRW5ju*Q?S1c?yf!J{Xu3j`@3B-cT* ze8wBgpxOxt0c0H5lSv2`4PgoEAb1G&k_8456{0nD=XRw-*@GLASPbEAZN>jbUBrP_&Z*&W3Y#OH2Zb2uXy z3L#3PGUpiGY(AmvIF^wnm5Qwb>(Sj2g;Oet{JL{@n08&i@=KXuE1~oIk)x3iMO`!@ z@-_c1J!aKV>`64?D<0`vBXOKwxm0S8WN*@!Gf*Brd1S|(3d-^dwz#`Lmr_o7r$&3s zy`#WXC6{-PVAGyv=x_tcAxLIuVh933pa$$9NlA7-e4c-P585*yz&sISoIQ#??-yohC$aT(c+tpK}id1ZF=$ZAhW zNi7Yke(hW2`^ETWul`}TrAVCCdSSsIey7eum~4q;TG)wHj?YUsq-iv1Var0Nr79Mp z)^Yg;gJN?In<~&N_=-&p(V$YGvFuxYP^xUQY-nxp8jZ^EsrJnx6m^FcD(}H`i<=-+ z={kyyc2LVpP5r|9TRE~hM95^u@l2cAW(`gV(`0m=?A>%!oy0Qf(l|vm#KW6sN~pgooSt-ov_|*n#S1BT&#Jf;ma;4_~VqjvMPe@2o z1lfQh7zh->MsgUE+kC>nr*i(|v76+VFff7e$BHQF-r$4GbC2D~{kVab)k>N2;EhWV zqMsR-PyXfnUDv2K|DA=Yt8V*_StWArZRBuEg2jx*RHkMXe|-DPs}i>uZ9lz5rt2t^j;O6DDxqRJ4eMb8b$QHJ|2O*8&w#C zL9baA3bAI-xKUclrcGGX)BhSJR>|TQu!J2uY1HgkW>?J(VF7O?@-M3|6&uP+R!Cp! zV?9drnEyu+1#18xzyyG#fQduQ-~}RHM5_lC(cSSKaBvYNH~K__A&V%GhaCbeOU%Cn zHxk;5is(0)b;V;}SIlh~^+f?VIBM3xHvCM%`YTCuoAEWP&b<;lFk;^HpVr>cuo*2~ z1%)Qh)i3s>@=Nihi%X|PWqzrKJ)W2RpXE_RqhTTzTrI24Vaw$-Un)hjIp&cYHT9{6 zhG>Apaf)%Vzmect6dbo$%xR-pEOH4;FKKg{sZzOK?^8A;30!8b%;ppE-z&GfbOK8< zp>f|0d8Q@l91h*jqB=LjWJ;>o8nkxF*@oJ9L>k*6DTVq_UHkl=61wV|2v_7q|_0VD15*fNcKyf(iHJP+- zkw?&}O=1Tb9uL#|A=heErN~_#9sL(e^;RlX@s?KSm)UxAB-FHlVgi%N_%2*KpF=g^ zn389_d9$LEYKvr)EGS`Svfir8y!)^q6Ri;N)x^c>8a6X^M#eiOhSJq5Vu?%Wh+*)a zTR>s_fo?;Vc(T1D#@~-F63@Owda_8wzl0$9fqE~fp~E{U>EH`$DDqz&+l!A~+vgu! zHMcwY&yznv#YnnZ`^EJKXQpPpGHGIY1|ng!(t5*8gH4MwKAc|rZ%*XJx zw4ykMapZDl>j<7+k0Ek9(v2|#x_~`Hrb;M z+7>Nh&D4*q#Qc4pe_CU}Kq#U^B!t+6CPNNDKtS#c36B48OxxM@bg3sh%(`}v5I80v zLY9JliIW<5n7C+@$29Pel#m>NgTItWoYaOa^~gh5B<@-Yb0eD1cc>!ED{#ugNfGyy z-k8PU?*E98;@f^Ed>y%C-Ml+eKqY|xF;8sftk54Qq zTg6beVOeYYJIm?lY{!(`GCEp*a(mwjiYLaXq!NWCKVw&vFj8dg^~I&7viL { + } + + /** + * Instantiates a new base view template. + */ + public BaseViewTemplate() { + initWidget(uiBinder.createAndBindUi(this)); + } + + /** + * Adds the to top. + * + * @param widget the widget + */ + public void addToTop(Widget widget){ + top_container.add(widget); + } + + /** + * Adds the to middle. + * + * @param widget the widget + */ + public void addToMiddle(Widget widget){ + base_container.add(widget); + } + + /** + * Adds the to bottom. + * + * @param widget the widget + */ + public void addToBottom(Widget widget){ + bottom_container.add(widget); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/BaseViewTemplate.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/BaseViewTemplate.ui.xml new file mode 100644 index 0000000..03a8f04 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/BaseViewTemplate.ui.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.java new file mode 100644 index 0000000..60eb2ff --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.java @@ -0,0 +1,160 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.IFrameInstanciedEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.IFrameInstanciedEvent.OPERATION; +import org.gcube.portlets.widgets.ckancontentmoderator.client.resources.ContentModeratorWidgetResources; + +import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.constants.IconType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style.Display; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.LoadEvent; +import com.google.gwt.event.dom.client.LoadHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.http.client.URL; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.Random; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Frame; +import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.NamedFrame; +import com.google.gwt.user.client.ui.Widget; + +/** + * The Class CkanShowItemFrame. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 4, 2022 + */ +public class CkanShowItemFrame extends Composite { + + private static CkanShowItemFrameUiBinder uiBinder = GWT.create(CkanShowItemFrameUiBinder.class); + + private NamedFrame namedFrame; + private HandlerManager eventBus; + private Image loading = new Image(ContentModeratorWidgetResources.ICONS.loading()); + private String messageToSend; + private String iFrameRandomName; + + @UiField + Button button_reload; + + @UiField + HTMLPanel panel_container; + +// @UiField +// AlertBlock alertBlockNav; + + private String datasetURL; + + /** + * The Interface CkanShowItemFrameUiBinder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 4, 2022 + */ + interface CkanShowItemFrameUiBinder extends UiBinder { + } + + /** + * Instantiates a new ckan show item frame. + * + * @param eventBus the event bus + */ + public CkanShowItemFrame(HandlerManager eventBus) { + initWidget(uiBinder.createAndBindUi(this)); + this.eventBus = eventBus; +// alertBlockNav.setType(AlertType.INFO); + button_reload.setIcon(IconType.ROTATE_RIGHT); + button_reload.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + reloadPage(); + } + }); + } + + /** + * Instance frame. + * + * @param datasetURL the dataset URL + * @return the frame + */ + public Frame instanceFrame(String datasetURL) { + this.datasetURL = datasetURL; + GWT.log("Instancing new IFRAME with uri: " + datasetURL); + addLoading(); + String urlEncoded = URL.encode(datasetURL); + GWT.log("Encoded url for instanciating namedFrame is " + urlEncoded); + iFrameRandomName = Random.nextInt() + "dataset-internal-iframe" + Random.nextInt(); + namedFrame = new NamedFrame(iFrameRandomName); + namedFrame.setUrl(urlEncoded); + + namedFrame.getElement().setId(iFrameRandomName); + namedFrame.setWidth("100%"); + namedFrame.setHeight("580px"); + namedFrame.getElement().getStyle().setBorderWidth(0, Unit.PX); + namedFrame.addLoadHandler(new LoadHandler() { + + @Override + public void onLoad(LoadEvent arg0) { + + removeLoading(); + eventBus.fireEvent(new IFrameInstanciedEvent(namedFrame, OPERATION.ONLOAD)); + } + }); + panel_container.add(namedFrame); + namedFrame.setVisible(true); + eventBus.fireEvent(new IFrameInstanciedEvent(namedFrame, OPERATION.INIT)); + return namedFrame; + + } + + /** + * Gets the namedFrame. + * + * @return the namedFrame + */ + public Frame getFrame() { + return namedFrame; + } + + /** + * add loading image. + */ + private void addLoading() { + panel_container.add(loading); + loading.getElement().getStyle().setProperty("margin", "auto"); + loading.getElement().getStyle().setDisplay(Display.BLOCK); + button_reload.setEnabled(false); + } + + /** + * Removes the loading. + */ + private void removeLoading() { + try { + panel_container.remove(loading); + button_reload.setEnabled(true); + } catch (Exception e) { + + } + } + + /** + * Reload page. + */ + public void reloadPage() { + panel_container.clear(); + instanceFrame(datasetURL); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.ui.xml new file mode 100644 index 0000000..3365f3d --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/CkanShowItemFrame.ui.xml @@ -0,0 +1,22 @@ + + + + .important { + font-weight: bold; + } + + .as_simple_link { + background: none; + border: none; + } + + + + Reload + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorPaginatedView.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorPaginatedView.java new file mode 100644 index 0000000..0324a2c --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorPaginatedView.java @@ -0,0 +1,353 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import java.util.List; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorWidgetController; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ShowMessageEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.TableRangeViewChangedEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table.ItemsTable; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table.SortedCellTable; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.LoadingPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchedData; + +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.cellview.client.SimplePager; +import com.google.gwt.user.cellview.client.SimplePager.TextLocation; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.view.client.AsyncDataProvider; +import com.google.gwt.view.client.HasData; +import com.google.gwt.view.client.MultiSelectionModel; +import com.google.gwt.view.client.Range; +import com.google.gwt.view.client.SelectionModel; +import com.google.gwt.view.client.SingleSelectionModel; + +/** + * The Class GeonaRecordsPaginatedView. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 16, 2021 + */ +public class ContentModeratorPaginatedView { + + private static final int ITEM_START_INDEX = ContentModeratorWidgetConstants.ITEM_START_INDEX; + private static final int ITEMS_PER_PAGE = ContentModeratorWidgetConstants.ITEMS_PER_PAGE; + private VerticalPanel vPanel = new VerticalPanel(); + private FlowPanel pagerPanel = new FlowPanel(); + private Boolean initClassFirstRangeChanged = false; + private ItemsTable itemsTable; + private MyCustomDataProvider dataProvider = new MyCustomDataProvider(); + protected Widget orginalLoadingIndicator = null; + private LoadingPanel loadingPanel = new LoadingPanel(new HTML("Loading data...")); + private ItemStatus itemStatus; + private int serverStartIndex; + private HandlerManager eventBus; + private boolean restrictDataToLoggedInUser; + private String sortForField; + + /** + * Instantiates a new content moderator paginated view. + * + * @param eventbus the eventbus + * @param theStatus the the status + * @param displayFields the display fields + * @param sortByField the sort by field + * @param restrictDataToLoggedInUser the restrict data to logged in user + * @param sortForField + */ + public ContentModeratorPaginatedView(HandlerManager eventbus, ItemStatus theStatus, DISPLAY_FIELD[] displayFields, + DISPLAY_FIELD sortByField, boolean restrictDataToLoggedInUser) { + this.itemStatus = theStatus; + this.restrictDataToLoggedInUser = restrictDataToLoggedInUser; + this.initClassFirstRangeChanged = true; + this.eventBus = eventbus; + itemsTable = new ItemsTable(eventbus, displayFields, sortByField); + itemsTable.initTable(null, null, dataProvider); + + orginalLoadingIndicator = itemsTable.getCellTable().getLoadingIndicator(); + initPagination(ITEMS_PER_PAGE); + // loadNewPage(ITEM_START_INDEX, ITEMS_PER_PAGE, false); + loadItemsForStatus(theStatus, sortForField); + + } + + /** + * Gets the asycn data provider. + * + * @return the asycn data provider + */ + public AsyncDataProvider getAsycnDataProvider() { + return (AsyncDataProvider) getCellTable().getDataProvider(); + } + + /** + * Gets the cell tale. + * + * @return the cell tale + */ + private SortedCellTable getCellTable() { + return itemsTable.getCellTable(); + } + + /** + * Inits the pagination. + * + * @param itemsPerPage the items per page + */ + public void initPagination(int itemsPerPage) { + + SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class); + SimplePager pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true); + pager.setDisplay(getCellTable()); + pager.setPageSize(itemsPerPage); + pager.getElement().getStyle().setProperty("margin", "auto"); + vPanel.add(loadingPanel); + + ScrollPanel scroll = new ScrollPanel(); + scroll.getElement().getStyle().setProperty("maxHeight", "470px"); + scroll.add(getCellTable()); + vPanel.add(scroll); + vPanel.getElement().addClassName("vPanel"); + pagerPanel.add(pager); + } + + /** + * Gets the pager panel. + * + * @return the pager panel + */ + public VerticalPanel getCellPanel() { + return vPanel; + } + + /** + * Set the panel in loading mode. + * + * @param show the show + */ + protected void showLoading(boolean show) { + loadingPanel.setVisible(show); + } + + /** + * Gets the pager panel. + * + * @return the pager panel + */ + public FlowPanel getPagerPanel() { + return pagerPanel; + } + + /** + * Load new page. + * + * @param startIdx the start idx + * @param limit the limit + * @param resetStore the reset store + * @param sortForField + */ + private void loadNewPage(final int startIdx, final int limit, final boolean resetStore) { + // initFirstRangeChanged = resetStore; + GWT.log("loadNewPage with parameters [startIdx: " + startIdx + ", limit: " + limit + ", resetStore:" + + resetStore + "]"); + // showLoading(true); + + int newStartIndex = startIdx; + + if (resetStore) { + GWT.log("Cleaning all data..."); + newStartIndex = 0; + serverStartIndex = 0; + GWT.log("Store reset performed start index is: " + newStartIndex); + getAsycnDataProvider().updateRowCount(ITEMS_PER_PAGE, false); + } + + loadItemsForStatus(itemStatus, newStartIndex, limit, serverStartIndex, sortForField); + + } + + /** + * Load items for status. + * + * @param itemStatus the item status + * @param sortForField + */ + public void loadItemsForStatus(ItemStatus itemStatus, String sortForField) { + this.itemStatus = itemStatus; + this.sortForField = sortForField; + getCellTable().setVisibleRangeAndClearData(new Range(0, ITEMS_PER_PAGE), false); + loadNewPage(ITEM_START_INDEX, ITEMS_PER_PAGE, true); + } + + /** + * Sets the new page result. + * + * @param result the new new page result + */ + private void setNewPageResult(SearchedData result) { + GWT.log("setNewPageResult: " + result); + serverStartIndex = result.getServerEndIndex(); + SelectionModel sm = getCellTable().getSelectionModel(); + + if (sm instanceof SingleSelectionModel) { + SingleSelectionModel ssm = (SingleSelectionModel) sm; + ssm.clear(); + } else if (sm instanceof MultiSelectionModel) { + MultiSelectionModel msm = (MultiSelectionModel) sm; + msm.clear(); + } + + getAsycnDataProvider().updateRowCount((int) result.getTotalItems(), true); + getAsycnDataProvider().updateRowData(result.getClientStartIndex(), result.getData()); + + /* + * MOCK-UP int total = 35; List listData = new + * ArrayList(35); for (int i = 0; i < total; i++) { + * CatalogueDataset cd = new CatalogueDataset(); cd.setId(i+""); + * cd.setName("name "+i); + * + * listData.add(cd); + * + * } + * + * getAsycnDataProvider().updateRowCount(total, true); + * getAsycnDataProvider().updateRowData(result.getClientStartIndex(), listData); + */ + + if (result.getData().size() == 0) { + getCellTable().setLoadingIndicator(new Label("No data")); + } else { + getCellTable().setLoadingIndicator(orginalLoadingIndicator); + } + + GWT.log("Updating row data startIndex: " + result.getClientStartIndex() + " children size: " + + result.getData().size()); + GWT.log("getAsycnDataProvider().getDataDisplays().size(): " + getCellTable().getRowCount()); + + if (result.isServerSearchFinished()) { + GWT.log("Search finished!!!"); + getAsycnDataProvider().updateRowCount(getCellTable().getRowCount(), true); + } + // initFirstRangeChanged = false; + + } + + /** + * Load items for status. + * + * @param status the status + * @param offset the offset + * @param limit the limit + * @param serverIndex the server index + * @param sortForField + */ + private void loadItemsForStatus(ItemStatus status, int offset, int limit, int serverIndex, String sortForField) { + showLoading(true); + + GWT.log("calling getDataForStatus with parameters [startIndex: " + offset + ", limit: " + limit + + ", serverIndex:" + serverIndex + "]"); + + CkanContentModeratorWidgetController.contentModeratorService.getDataForStatus(status, offset, limit, + serverIndex, restrictDataToLoggedInUser, sortForField, new AsyncCallback() { + + @Override + public void onSuccess(SearchedData result) { + showLoading(false); + setNewPageResult(result); + } + + @Override + public void onFailure(Throwable caught) { + showLoading(false); + eventBus.fireEvent(new ShowMessageEvent(caught.getMessage(), AlertType.ERROR)); + + } + }); + + } + + /** + * Select items. + * + * @param select the select + * @param limitToPage the limit to page + */ + public void selectItems(boolean select, boolean limitToPage) { + SortedCellTable table = getCellTable(); + int rowSize = table.getVisibleItemCount(); + + for (int i = 0; i < rowSize; i++) { + CatalogueDataset item = table.getVisibleItem(i); + itemsTable.getSelectionModel().setSelected(item, select); + } + } + + /** + * Gets the select items. + * + * @return the select items + */ + public List getSelectItems() { + return itemsTable.getSelectedItems(); + } + + /** + * A custom {@link AsyncDataProvider}. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jul 5, 2017 + * @param the generic type + */ + public class MyCustomDataProvider extends AsyncDataProvider { + + /** + * {@link #onRangeChanged(HasData)} is called when the table requests a new + * range of data. You can push data back to the displays using + * {@link #updateRowData(int, List)}. + * + * @param display the display + */ + @Override + public void onRangeChanged(HasData display) { + + // Get the new range. + final Range range = display.getVisibleRange(); + + int start = range.getStart(); + int length = range.getLength(); + + if (initClassFirstRangeChanged) { + GWT.log("initClassFirstRangeChanged is true.. returning"); + initClassFirstRangeChanged = false; + return; + } + GWT.log("Range changed: " + start + " " + length + " visible count: " + display.getVisibleItemCount()); + loadNewPage(start, length, false); + eventBus.fireEvent(new TableRangeViewChangedEvent(start, length)); + + } + + } + + public void hideSelectableRow(boolean bool) { + Element tableEl = itemsTable.getCellTable().getElement(); + if (bool) + tableEl.addClassName("hide_checkbox"); + else + tableEl.removeClassName("hide_checkbox"); + + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorSystemBaseView.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorSystemBaseView.java new file mode 100644 index 0000000..3a41357 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorSystemBaseView.java @@ -0,0 +1,61 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.Widget; + +/** + * The Class ContentModeratorSystemBaseView. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 16, 2021 + */ +public class ContentModeratorSystemBaseView { + + private BaseViewTemplate baseViewTemplate = new BaseViewTemplate(); + private ScrollPanel centerPanel = new ScrollPanel(); + + /** + * Instantiates a new content moderator system base view. + */ + public ContentModeratorSystemBaseView() { + baseViewTemplate.addToMiddle(centerPanel); + } + + /** + * Adds the to top. + * + * @param w the w + */ + public void addToTop(Widget w) { + baseViewTemplate.addToTop(w); + } + + /** + * Adds the to center. + * + * @param w the w + */ + public void addToCenter(Widget w) { + centerPanel.add(w); + } + + /** + * Adds the to bottom. + * + * @param w the w + */ + public void addToBottom(Widget w) { + baseViewTemplate.addToBottom(w); + } + + /** + * Gets the panel. + * + * @return the panel + */ + public Composite getPanel() { + return baseViewTemplate; + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.java new file mode 100644 index 0000000..1ec30e8 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.java @@ -0,0 +1,142 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import java.util.List; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.CloseAllTabsEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.SelectItemsWithItemStatusEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.ItemFieldDV; + +import com.github.gwtbootstrap.client.ui.Dropdown; +import com.github.gwtbootstrap.client.ui.Label; +import com.github.gwtbootstrap.client.ui.NavLink; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + +public class ContentModeratorToolbar extends Composite { + + private static ContentModeratorToolbarUiBinder uiBinder = GWT.create(ContentModeratorToolbarUiBinder.class); + + interface ContentModeratorToolbarUiBinder extends UiBinder { + } + + @UiField + Dropdown dropdownSelectStatus; + + @UiField + Dropdown dropdownSortBy; + + @UiField + NavLink closeAllTabs; + + @UiField + Label statusInfo; + + @UiField + Label orderInfo; + + private HandlerManager eventBus; + + private ItemStatus activeStatus; + + private List sortByList; + + private ItemFieldDV activeSortBy; + + public ContentModeratorToolbar(HandlerManager eventBus, ItemStatus status, List sortBy) { + initWidget(uiBinder.createAndBindUi(this)); + this.eventBus = eventBus; + this.sortByList = sortBy; + setActiveStatus(status); + setActiveSortBy(sortBy.get(0)); + fillSelectionOptions(); + bindEvents(); + + } + + private void bindEvents() { + closeAllTabs.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + eventBus.fireEvent(new CloseAllTabsEvent()); + + } + }); + } + + private void fillSelectionOptions() { + for (final ItemStatus status : ItemStatus.values()) { + + NavLink navLink = new NavLink(); + navLink.setText(status.getLabel()); + navLink.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + GWT.log("clicked: " + status); + setActiveStatus(status); + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(status, null, null, getActiveSortBy())); + + } + }); + dropdownSelectStatus.add(navLink); + } + + for (final ItemFieldDV itemField : sortByList) { + + NavLink navLink = new NavLink(); + navLink.setText(itemField.getDisplayName()); + navLink.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + setActiveSortBy(itemField); + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(getActiveStatus(), null, null, itemField)); + + } + + }); + dropdownSortBy.add(navLink); + } + } + + private void setActiveSortBy(ItemFieldDV itemField) { + this.activeSortBy = itemField; + this.orderInfo.setText(activeSortBy.getDisplayName()); + } + + private void setActiveStatus(ItemStatus status) { + this.activeStatus = status; + this.statusInfo.setText(activeStatus.getLabel()); + + } + + public ItemFieldDV getActiveSortBy() { + + if (activeSortBy != null) + return activeSortBy; + + NavLink navLink = dropdownSortBy.getLastSelectedNavLink(); + String selectedText = navLink.getText(); + for (ItemFieldDV itemField : sortByList) { + + if (itemField.getDisplayName().compareTo(selectedText) == 0) { + return itemField; + } + } + + return sortByList.get(0); + } + + public ItemStatus getActiveStatus() { + return activeStatus; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.ui.xml new file mode 100644 index 0000000..c81f686 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/ContentModeratorToolbar.ui.xml @@ -0,0 +1,44 @@ + + + + + .important { + font-weight: bold; + } + + .margin-top-12 { + margin-top: 12px; + } + + .margin-left-20 { + margin-left: 20px; + } + + + + + + + + + + + + + + + + + + + Close All Tabs + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.java new file mode 100644 index 0000000..1010c6c --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.java @@ -0,0 +1,229 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import java.util.List; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; + +import com.github.gwtbootstrap.client.ui.AlertBlock; +import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.CheckBox; +import com.github.gwtbootstrap.client.ui.HelpBlock; +import com.github.gwtbootstrap.client.ui.TextArea; +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Widget; + +/** + * The Class DoActionCMSView. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 29, 2021 + */ +public class DoActionCMSView extends Composite { + + private static DoActionCMSUiBinder uiBinder = GWT.create(DoActionCMSUiBinder.class); + + /** + * The Interface DoActionCMSUiBinder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 29, 2021 + */ + interface DoActionCMSUiBinder extends UiBinder { + } + + @UiField + HTML htmlDisplayMessage; + + @UiField + CheckBox checkBoxPermDelete; + + @UiField + TextArea txtMsgReason; + + @UiField + Button buttonActionConfirmYES; + + @UiField + Button buttonActionConfirmNO; + + @UiField + AlertBlock alertBlockDoAction; + + @UiField + HelpBlock helpPermDelete; + + + private List listSelectItems; + + private ItemStatus fromStatus; + + private ItemStatus toStatus; + + /** + * Instantiates a new do action CMS view. + * + * @param fromStatus the from status + * @param toStatus the to status + * @param listSelectItems the list select items + */ + public DoActionCMSView() { + initWidget(uiBinder.createAndBindUi(this)); + this.alertBlockDoAction.setClose(true); + this.alertBlockDoAction.setAnimation(true); + this.alertBlockDoAction.setType(AlertType.INFO); + this.checkBoxPermDelete.setVisible(false); + this.txtMsgReason.setVisible(false); + + checkBoxPermDelete.addValueChangeHandler(new ValueChangeHandler() { + + @Override + public void onValueChange(ValueChangeEvent event) { + helpPermDelete.setVisible(false); + if(event.getValue()) { + helpPermDelete.setVisible(true); + } + } + }); + + } + + public void updateStatus(ItemStatus fromStatus, ItemStatus toStatus, List listSelectItems) { + this.fromStatus = fromStatus; + this.toStatus = toStatus; + this.listSelectItems = listSelectItems; + int count = listSelectItems.size(); + String msg = "Going to update the status of"; + if (count > 0) { + if (count == 1) { + msg += " one item"; + } else { + msg += " " + count + " items"; + } + + msg += " from " + fromStatus.getLabel() + " to " + toStatus.getLabel() + ". Confirm?"; + } else + return; + + switch (toStatus) { + case PENDING: + checkBoxPermDelete.setVisible(false); + txtMsgReason.setVisible(false); + break; + case APPROVED: + checkBoxPermDelete.setVisible(false); + txtMsgReason.setVisible(true); + txtMsgReason.setPlaceholder("(Optional) Type a message..."); + break; + case REJECTED: + checkBoxPermDelete.setVisible(true); + txtMsgReason.setVisible(true); + txtMsgReason.setPlaceholder("(Optional) Rejecting reason..."); + break; + default: + break; + } + + htmlDisplayMessage.setHTML(msg); + } + + public void permanentlyDelete(List listSelectItems) { + this.listSelectItems = listSelectItems; + int count = listSelectItems.size(); + String msg = "Going to delete permanently "; + if (count > 0) { + if (count == 1) { + msg += " one item"; + } else { + msg += " " + count + " items"; + } + + msg += " from Catalogue. This operation cannot be undone. Would you like to proceed?"; + } else + return; + + htmlDisplayMessage.setHTML(msg); + } + + /** + * Checks if is permanently delete. + * + * @return true, if is permanently delete + */ + boolean isPermanentlyDelete() { + return checkBoxPermDelete.getValue(); + } + + /** + * Gets the txt reason msg. + * + * @return the txt reason msg + */ + public String getTxtReasonMsg() { + return txtMsgReason.getValue(); + } + + /** + * Gets the list select items. + * + * @return the list select items + */ + public List getListSelectItems() { + return listSelectItems; + } + + /** + * Gets the from status. + * + * @return the from status + */ + public ItemStatus getFromStatus() { + return fromStatus; + } + + /** + * Gets the to status. + * + * @return the to status + */ + public ItemStatus getToStatus() { + return toStatus; + } + + /** + * Gets the button action confirm YES. + * + * @return the button action confirm YES + */ + public Button getButtonActionConfirmYES() { + return buttonActionConfirmYES; + } + + /** + * Gets the button action confirm NO. + * + * @return the button action confirm NO + */ + public Button getButtonActionConfirmNO() { + return buttonActionConfirmNO; + } + + /** + * Gets the alert block do action. + * + * @return the alert block do action + */ + public AlertBlock getAlertBlockDoAction() { + return alertBlockDoAction; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.ui.xml new file mode 100644 index 0000000..a532d64 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/DoActionCMSView.ui.xml @@ -0,0 +1,46 @@ + + + + .important { + font-weight: bold; + } + + .fontsize-16 { + font-size: 16px; + } + + .margin-top-15 { + margin-top: 15px; + } + + .margin-left-10 { + margin-left: 10px; + } + .text-area-message{ + max-width: 100%; + width: 100%; + margin-bottom: 2px; + } + + + + + + + Permanently Delete + This operation cannot be undone. The selected items will be permantently deleted from Catalogue + + YES + NO + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.java new file mode 100644 index 0000000..53d3909 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.java @@ -0,0 +1,652 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorWidgetController; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.CheckBoxSelectIemsEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.SelectItemsWithItemStatusEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.LoadingPanel; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.UtilFunct; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.OperationReport; + +import com.github.gwtbootstrap.client.ui.AlertBlock; +import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.CheckBox; +import com.github.gwtbootstrap.client.ui.Dropdown; +import com.github.gwtbootstrap.client.ui.Heading; +import com.github.gwtbootstrap.client.ui.NavLink; +import com.github.gwtbootstrap.client.ui.base.AlertBase; +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.github.gwtbootstrap.client.ui.event.ClosedEvent; +import com.github.gwtbootstrap.client.ui.event.ClosedHandler; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.Widget; + +/** + * The Class HomeView. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public class HomeView extends Composite { + + private static HomeViewUiBinder uiBinder = GWT.create(HomeViewUiBinder.class); + private ContentModeratorSystemBaseView cmsPanel = new ContentModeratorSystemBaseView(); + private ContentModeratorPaginatedView paginatedView; + + @UiField + HTMLPanel panelContainer; + + @UiField + CheckBox cbSelectAll; + + @UiField + Dropdown dropdownSetStatus; + + @UiField + Heading pageHeader; + + @UiField + HTMLPanel actionLoaderPanel; + + @UiField + HTMLPanel confirmPanel; + + @UiField + Button permanentlyDelete; + + @UiField + HorizontalPanel updateStatusActionPanel; + + private ScrollPanel confirmPanelContainer = new ScrollPanel(); + + private List setStatusOptions = new ArrayList(); + + private ItemStatus displayingItemStatus; + + private HandlerManager eventBus; + + private LoadingPanel actionInProgressLoader = new LoadingPanel(new HTML("Performing action...")); + private boolean readOnlyMode; + private boolean restrictDataToLoggedInUser; + + /** + * The Interface HomeViewUiBinder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ + interface HomeViewUiBinder extends UiBinder { + } + + /** + * Instantiates a new home view. + * + * @param eventBus the event bus + * @param status the status + * @param displayFields the display fields + * @param sortByField the sort by field + * @param readOnlyMode the read only mode + * @param restrictDataToLoggedInUser the restrict data to logged in user + */ + public HomeView(HandlerManager eventBus, ItemStatus status, DISPLAY_FIELD[] displayFields, + DISPLAY_FIELD sortByField, boolean readOnlyMode, boolean restrictDataToLoggedInUser) { + initWidget(uiBinder.createAndBindUi(this)); + setDisplayingWithStatus(status); + this.eventBus = eventBus; + this.readOnlyMode = readOnlyMode; + this.restrictDataToLoggedInUser = restrictDataToLoggedInUser; + paginatedView = new ContentModeratorPaginatedView(eventBus, status, displayFields, sortByField, + restrictDataToLoggedInUser); + cmsPanel.addToCenter(paginatedView.getCellPanel()); + cmsPanel.addToBottom(paginatedView.getPagerPanel()); + panelContainer.add(cmsPanel.getPanel()); + setVisibleUpdateStatusAction(false); + setVisiblePermanentlyDelete(false); + + // Filling the Dropdown with status options + for (ItemStatus iStatus : ItemStatus.values()) { + NavLink nl = new NavLink(iStatus.getLabel()); + dropdownSetStatus.add(nl); + setStatusOptions.add(nl); + + } + + showActionLoader(false); + actionLoaderPanel.add(actionInProgressLoader); + + setStatusOptions(status); + bindEvents(); + confirmPanel.add(confirmPanelContainer); + + } + + /** + * Show action loader. + * + * @param showActionInProgress the show action in progress + */ + private void showActionLoader(boolean showActionInProgress) { + GWT.log("Show action in progress: " + showActionInProgress); + actionLoaderPanel.setVisible(showActionInProgress); + } + + /** + * Sets the status options according to item status selected. + * + * @param selectedStatus the new status options + */ + private void setStatusOptions(ItemStatus selectedStatus) { + + // Fired when user clicks on CMS action + for (final NavLink navLink : setStatusOptions) { + navLink.setVisible(true); + // Hiding the status selected/displayed from navigation link + if (navLink.getText().trim().equals(displayingItemStatus.getLabel())) { + navLink.setVisible(false); + } + + // Hiding the changing REJECT -> APPROVED + // One item REJECT must be only updated to return to PENDING status + if (selectedStatus.equals(ItemStatus.REJECTED)) { + if (navLink.getText().trim().equals(ItemStatus.APPROVED.getLabel())) { + navLink.setVisible(false); + } + } + + // Hiding the changing of any status from the APPROVED + if (selectedStatus.equals(ItemStatus.APPROVED)) { + navLink.setVisible(false); + } + + } + } + + /** + * Sets the displaying with status. + * + * @param status the new displaying with status + */ + private void setDisplayingWithStatus(ItemStatus status) { + this.displayingItemStatus = status; + this.pageHeader.setSubtext(status.getLabel()); + } + + /** + * Bind events. + */ + public void bindEvents() { + + cbSelectAll.addValueChangeHandler(new ValueChangeHandler() { + + @Override + public void onValueChange(ValueChangeEvent event) { + GWT.log("Is checked: " + cbSelectAll.getValue()); + eventBus.fireEvent(new CheckBoxSelectIemsEvent(cbSelectAll.getValue())); + + } + }); + + // Fired when user clicks on CMS action + for (final NavLink navLink : setStatusOptions) { + navLink.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + if (paginatedView.getSelectItems().size() > 0) { + showDoActionView(navLink); + } + + } + }); + } + + permanentlyDelete.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + if (paginatedView.getSelectItems().size() > 0) { + showDoActionViewDeletePermanently(); + + } + + } + }); + } + + /** + * Gets the panel. + * + * @return the panel + */ + public Composite getPanel() { + return this; + } + + /** + * Sets the visible update status action. + * + * @param bool the new visible update status action + */ + public void setVisibleUpdateStatusAction(boolean bool) { + dropdownSetStatus.setVisible(bool); + } + + /** + * Sets the visible permanently delete. + * + * @param bool the new visible permanently delete + */ + public void setVisiblePermanentlyDelete(boolean bool) { + permanentlyDelete.setVisible(bool); + } + + /** + * Mark items as checked. + * + * @param select the select + * @param limitToPage the limit to page + */ + public void markItemsAsChecked(boolean select, boolean limitToPage) { + paginatedView.selectItems(select, limitToPage); + } + + /** + * Sets the checked checkbox select all. + * + * @param bool the new checked checkbox select all + */ + public void setCheckedCheckboxSelectAll(boolean bool) { + cbSelectAll.setValue(bool); + } + + /** + * Show do action view. + * + * @param navLink the nav link + */ + private void showDoActionView(NavLink navLink) { + confirmPanelContainer.clear(); + GWT.log("showDoActionView clicked link: " + navLink.getText()); + ItemStatus fromStatus = displayingItemStatus; + final ItemStatus toStatus = UtilFunct.toStatusFromStatusLabel(navLink.getText().trim()); + GWT.log("Do action on from: " + fromStatus + " to: " + toStatus); + if (toStatus == null) { + return; + } + + final DoActionCMSView doActionCMS = new DoActionCMSView(); + final List selectedItems = paginatedView.getSelectItems(); + doActionCMS.updateStatus(fromStatus, toStatus, selectedItems); + + final AlertBlock newAlertBlock = doActionCMS.getAlertBlockDoAction(); + newAlertBlock.addClosedHandler(new ClosedHandler() { + + @Override + public void onClosed(ClosedEvent event) { + confirmPanelContainer.clear(); + } + }); + + Button buttActionConfirmYes = doActionCMS.getButtonActionConfirmYES(); + buttActionConfirmYes.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + confirmPanelContainer.clear(); + performCMSAction(doActionCMS); + } + }); + + Button buttonActionConfirmNo = doActionCMS.getButtonActionConfirmNO(); + buttonActionConfirmNo.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + confirmPanelContainer.clear(); + + } + }); + + confirmPanelContainer.add(doActionCMS); + } + + /** + * Show do action delete permanently. + */ + private void showDoActionViewDeletePermanently() { + + confirmPanelContainer.clear(); + GWT.log("showDoActionViewDeletePermanently..."); + + final DoActionCMSView doActionCMS = new DoActionCMSView(); + final List selectedItems = paginatedView.getSelectItems(); + doActionCMS.permanentlyDelete(selectedItems); + + final AlertBlock newAlertBlock = doActionCMS.getAlertBlockDoAction(); + newAlertBlock.addClosedHandler(new ClosedHandler() { + + @Override + public void onClosed(ClosedEvent event) { + confirmPanelContainer.clear(); + } + }); + + Button buttActionConfirmYes = doActionCMS.getButtonActionConfirmYES(); + buttActionConfirmYes.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + confirmPanelContainer.clear(); + showActionLoader(true); + + List listDatasetNames = UtilFunct.toListDatasetNames(doActionCMS.getListSelectItems()); + CkanContentModeratorWidgetController.contentModeratorService.permanentlyDelete(listDatasetNames, + new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + showActionLoader(false); + Window.alert(caught.getMessage()); + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, + "Sorry an error occurred. Please, refresh and try again", AlertType.ERROR)); + + } + + @Override + public void onSuccess(OperationReport result) { + showActionLoader(false); + AlertType alert = AlertType.SUCCESS; + int count = selectedItems.size(); + String msg = "Deleted permanently"; + if (count > 0) { + if (count == 1) { + msg += " one item"; + } else { + msg += " " + count + " items"; + } + + msg += " from Catalogue"; + } + + int errorCount = result.getErrorMapItems().size(); + if (errorCount > 0) { + msg += "
Error occurred on deleting permanently " + errorCount + " item/s:"; + for (String key : result.getErrorMapItems().keySet()) { + msg += "
" + key + ". Error: " + result.getErrorMapItems().get(key); + } + + alert = AlertType.WARNING; + } + + eventBus.fireEvent( + new SelectItemsWithItemStatusEvent(displayingItemStatus, msg, alert)); + + } + }); + } + }); + + Button buttonActionConfirmNo = doActionCMS.getButtonActionConfirmNO(); + buttonActionConfirmNo.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + confirmPanelContainer.clear(); + + } + }); + + confirmPanelContainer.add(doActionCMS); + } + + /** + * Load form server the items with status. + * + * @param itemStatus the item status + * @param sortForField + */ + public void loadItemsWithStatus(ItemStatus itemStatus, String sortForField) { + GWT.log("loadItemsWithStatus started"); + setDisplayingWithStatus(itemStatus); + setCheckedCheckboxSelectAll(false); + setVisibleUpdateStatusAction(false); + setVisiblePermanentlyDelete(false); + setStatusOptions(itemStatus); + confirmPanelContainer.clear(); + if (itemStatus.equals(ItemStatus.REJECTED)) + setVisiblePermanentlyDelete(true); + + paginatedView.loadItemsForStatus(itemStatus, sortForField); + + GWT.log("loadItemsWithStatus end"); + } + + /** + * Perform CMS action. + * + * @param doActionCMSView the do action CMS view + */ + private void performCMSAction(final DoActionCMSView doActionCMSView) { + + showActionLoader(true); + final ItemStatus toStatus = doActionCMSView.getToStatus(); + List listDatasetNames = UtilFunct.toListDatasetNames(doActionCMSView.getListSelectItems()); + switch (toStatus) { + case PENDING: + + CkanContentModeratorWidgetController.contentModeratorService.setStatus(toStatus, listDatasetNames, + new AsyncCallback() { + + @Override + public void onSuccess(OperationReport result) { + showActionLoader(false); + AlertType alert = AlertType.SUCCESS; + int count = result.getPassedListItems().size(); + String msg = ""; + if (count > 0) { + if (count == 1) { + msg += "One item"; + } else { + msg += count + " items"; + } + + msg += " moved to " + toStatus + " status."; + } + + int errorCount = result.getErrorMapItems().size(); + if (errorCount > 0) { + msg += "
Error occurred on updating status to " + errorCount + " item/s:"; + for (String key : result.getErrorMapItems().keySet()) { + msg += "
" + key + ". Error: " + result.getErrorMapItems().get(key); + } + + alert = AlertType.WARNING; + } + + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, msg, alert)); + } + + @Override + public void onFailure(Throwable caught) { + showActionLoader(false); + Window.alert(caught.getMessage()); + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, + "Sorry an error occurred. Please, refresh and try again", AlertType.ERROR)); + + } + }); + + break; + + case APPROVED: + + CkanContentModeratorWidgetController.contentModeratorService.approveItem(listDatasetNames, + doActionCMSView.getTxtReasonMsg(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + showActionLoader(false); + Window.alert(caught.getMessage()); + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, + "Sorry an error occurred. Please, refresh and try again", AlertType.ERROR)); + + } + + @Override + public void onSuccess(OperationReport result) { + showActionLoader(false); + AlertType alert = AlertType.SUCCESS; + int count = result.getPassedListItems().size(); + String msg = ""; + if (count > 0) { + if (count == 1) { + msg += "One item"; + } else { + msg += count + " items"; + } + + msg += " moved to " + toStatus + " status."; + } + + int errorCount = result.getErrorMapItems().size(); + if (errorCount > 0) { + msg += "
Error occurred on approving " + errorCount + " item/s:"; + for (String key : result.getErrorMapItems().keySet()) { + msg += "
" + key + ". Error: " + result.getErrorMapItems().get(key); + } + + alert = AlertType.WARNING; + } + + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, msg, alert)); + + } + }); + + break; + + case REJECTED: + + CkanContentModeratorWidgetController.contentModeratorService.rejectItem(listDatasetNames, + doActionCMSView.isPermanentlyDelete(), doActionCMSView.getTxtReasonMsg(), + new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + showActionLoader(false); + Window.alert(caught.getMessage()); + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, + "Sorry an error occurred. Please, refresh and try again", AlertType.ERROR)); + } + + @Override + public void onSuccess(OperationReport result) { + showActionLoader(false); + AlertType alert = AlertType.SUCCESS; + int count = result.getPassedListItems().size(); + String msg = ""; + if (count > 0) { + if (count == 1) { + msg += "One item"; + } else { + msg += count + " items"; + } + + boolean isPermanentlyDelete = doActionCMSView.isPermanentlyDelete(); + + if (isPermanentlyDelete) { + msg += " deleted permanently from Catalogue"; + } else { + msg += " moved to " + toStatus + " status."; + } + } + + int errorCount = result.getErrorMapItems().size(); + if (errorCount > 0) { + msg += "
Error occurred on rejecting " + errorCount + " item/s:"; + for (String key : result.getErrorMapItems().keySet()) { + msg += "
" + key + ". Error: " + result.getErrorMapItems().get(key); + } + + alert = AlertType.WARNING; + } + + eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, msg, alert)); + + } + }); + + break; + + default: + break; + } + } + + /** + * Gets the displaying item status. + * + * @return the displaying item status + */ + public ItemStatus getDisplayingItemStatus() { + return displayingItemStatus; + } + + /** + * Hide update status action. + * + * @param readOnlyMode the read only mode + */ + public void hideUpdateStatusAction(boolean readOnlyMode) { + updateStatusActionPanel.setVisible(!readOnlyMode); + } + + /** + * Hide selectable row. + * + * @param bool the bool + */ + public void hideSelectableRow(boolean bool) { + paginatedView.hideSelectableRow(bool); + } + + /** + * Checks if is read only mode. + * + * @return true, if is read only mode + */ + public boolean isReadOnlyMode() { + return readOnlyMode; + } + + /** + * Checks if is restrict data to logged in user. + * + * @return true, if is restrict data to logged in user + */ + public boolean isRestrictDataToLoggedInUser() { + return restrictDataToLoggedInUser; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.ui.xml new file mode 100644 index 0000000..33a13cf --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/HomeView.ui.xml @@ -0,0 +1,61 @@ + + + + .important { + font-weight: bold; + } + + .margin-left-20 { + margin-left: 20px; + } + + .margin-left-5 { + margin-left: 5px; + } + + .headinghome { + margin-left: 5px; + margin-bottom: 20px; + font-size: 16px !important; + } + + .button-style { + margin-left: 20px; + padding: 0px; + } + + .font-size-14 { + font-size: 14px; + } + + .font-size-14 li { + font-size: 14px; + } + + .headinghome>small { + font-size: 16px !important; + } + + + Items with status: + + + + + + + Permanently + Delete + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.java new file mode 100644 index 0000000..f2c8c29 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.java @@ -0,0 +1,40 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import com.github.gwtbootstrap.client.ui.Label; +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Widget; + +public class MainPanel extends Composite { + + private static MainPanelUiBinder uiBinder = GWT.create(MainPanelUiBinder.class); + + interface MainPanelUiBinder extends UiBinder { + } + + @UiField + HTMLPanel mainPanel; + + @UiField + HTMLPanel mainPanelContainer; + + @UiField + Label labelLoggedIn; + + public MainPanel() { + initWidget(uiBinder.createAndBindUi(this)); + } + + public void setLoggedLabelText(String text){ + labelLoggedIn.setText(text); + } + + public HTMLPanel getMainPanelContainer() { + return mainPanelContainer; + } + + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.ui.xml new file mode 100644 index 0000000..0c6e735 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainPanel.ui.xml @@ -0,0 +1,19 @@ + + + + .important { + font-weight: bold; + } + + .margin-bottom-2 { + margin-bottom: 2px; + } + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.java new file mode 100644 index 0000000..abbf0db --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.java @@ -0,0 +1,211 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util.UtilFunct; + +import com.github.gwtbootstrap.client.ui.Icon; +import com.github.gwtbootstrap.client.ui.Tab; +import com.github.gwtbootstrap.client.ui.TabPanel; +import com.github.gwtbootstrap.client.ui.constants.IconType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Style.Cursor; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.LoadEvent; +import com.google.gwt.event.dom.client.LoadHandler; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + +// TODO: Auto-generated Javadoc +/** + * The Class MainTabPanel. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 18, 2021 + */ +public class MainTabPanel extends Composite { + + private static MainTabPanelUiBinder uiBinder = GWT.create(MainTabPanelUiBinder.class); + + /** + * The Interface MainTabPanelUiBinder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 18, 2021 + */ + interface MainTabPanelUiBinder extends UiBinder { + } + + private List results = new ArrayList(); + + @UiField + TabPanel mainTabPanel; + + @UiField + Tab homeTab; + + /** + * Instantiates a new main tab panel. + */ + public MainTabPanel() { + initWidget(uiBinder.createAndBindUi(this)); + results.add(homeTab); + } + + /** + * Adds the home widget. + * + * @param w the w + */ + public void addHomeWidget(Widget w) { + homeTab.add(w); + } + + /** + * Adds the tab. + * + * @param heading the heading + * @param w the w + * @return the tab + */ + public Tab addTab(String heading, Widget w, boolean selectTab) { + final Tab tab = new Tab(); + + if (w instanceof CkanShowItemFrame) { + tab.setCustomIconStyle("icon-rotate-right icon-spin"); + CkanShowItemFrame ckanFramePanel = (CkanShowItemFrame) w; + ckanFramePanel.getFrame().addLoadHandler(new LoadHandler() { + + @Override + public void onLoad(LoadEvent event) { + tab.setIcon(IconType.BOOK); + setNoSpinner(tab); + } + }); + } + + tab.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + } + }); + + Icon icon = new Icon(IconType.REMOVE); + icon.setTitle("Close this tab"); + icon.getElement().getStyle().setCursor(Cursor.POINTER); + ClickHandler clickHandler = new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + try { + mainTabPanel.remove(tab); + results.remove(tab); + mainTabPanel.selectTab(results.size() - 1); + } catch (Exception e) { + // silent + } + } + }; + + icon.addDomHandler(clickHandler, ClickEvent.getType()); + tab.addDecorate(icon); + + String shortTitle = UtilFunct.ellipsis(heading, 20, false); + tab.asWidget().setTitle(heading); + tab.setHeading(shortTitle); + if (w != null) + tab.add(w); + + results.add(tab); + mainTabPanel.add(tab); + // activeTabPanels(false); + + if (selectTab) { + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + + @Override + public void execute() { + mainTabPanel.selectTab(results.size() - 1); + } + }); + } + + return tab; + } + + /** + * Active tab panels. + * + * @param bool the bool + */ + private void activeTabPanels(boolean bool) { + for (Tab tab : results) { + tab.setActive(false); + } + } + + /** + * Count tab. + * + * @return the int + */ + public int countTab() { + + return results.size(); + } + + /** + * Close tabs. + */ + public void closeTabs() { + int tabSize = results.size(); + GWT.log("tab size is: " + tabSize); + for (int i = 1; i < tabSize; i++) { + // each remove shifts any subsequent elements to the left, so I'm removing + // always the first element + mainTabPanel.remove(1); + results.remove(1); + } + // selecting Home Tab + selectTab(0); + } + + public void selectTab(int tabIndex) { + if (tabIndex <= results.size()) { + mainTabPanel.selectTab(tabIndex); + } + + } + + /** + * Sets the no spinner. + * + * @param tab the new no spinner + */ + private void setNoSpinner(Tab tab) { + try { + tab.asTabLink().getAnchor().removeStyleName("icon-spin"); + tab.asTabLink().getAnchor().removeStyleName("icon-rotate-right"); + Element anchorElem = tab.asTabLink().getAnchor().asWidget().getElement(); + anchorElem.getFirstChildElement().removeClassName("icon-spin"); + anchorElem.getFirstChildElement().removeClassName("icon-rotate-right"); + } catch (Exception e) { + // silent + } + tab.asTabLink().getAnchor().setIcon(IconType.BOOK); + // tab.asTabLink().getAnchor().setVisible(false); + // if(tab.asTabLink().getAnchor().setVisible(false);) + + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.ui.xml new file mode 100644 index 0000000..e06a8f9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/MainTabPanel.ui.xml @@ -0,0 +1,16 @@ + + + + .important { + font-weight: bold; + } + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/SelectionItems.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/SelectionItems.java new file mode 100644 index 0000000..f7d0c8e --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/SelectionItems.java @@ -0,0 +1,25 @@ +/** + * + */ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui; + +import java.util.List; + +/** + * The Interface SelectionItems. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 18, 2021 + */ +public interface SelectionItems { + + /** + * Gets the selected items. + * + * @param the generic type + * @return the selected items + */ + List getSelectedItems(); + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/AbstractItemsCellTable.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/AbstractItemsCellTable.java new file mode 100644 index 0000000..34e774d --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/AbstractItemsCellTable.java @@ -0,0 +1,224 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ClickItemEvent; + +import com.github.gwtbootstrap.client.ui.Pagination; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.core.shared.GWT; +import com.google.gwt.dom.client.Style.BorderStyle; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; +import com.google.gwt.event.dom.client.DoubleClickEvent; +import com.google.gwt.event.dom.client.DoubleClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.cellview.client.SimplePager; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.DialogBox; +import com.google.gwt.user.client.ui.MenuBar; +import com.google.gwt.user.client.ui.MenuItem; +import com.google.gwt.view.client.AbstractDataProvider; +import com.google.gwt.view.client.AsyncDataProvider; +import com.google.gwt.view.client.DefaultSelectionEventManager; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.MultiSelectionModel; +import com.google.gwt.view.client.SelectionChangeEvent; +import com.google.gwt.view.client.SelectionChangeEvent.Handler; +import com.google.gwt.view.client.SelectionModel; +import com.google.gwt.view.client.SingleSelectionModel; + + +/** + * The Class AbstractItemsCellTable. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jul 11, 2017 + * @param the generic type + */ +public abstract class AbstractItemsCellTable { + + protected SortedCellTable sortedCellTable; + protected T itemContextMenu = null; + protected boolean fireEventOnClick = true; + protected SelectionModel theSelectionModel; + protected HandlerManager eventBus; + + /** + * Inits the table. + * + * @param pager the pager + * @param pagination the pagination + * @param dataProvider the data provider + */ + public abstract void initTable(final SimplePager pager, final Pagination pagination, + AbstractDataProvider dataProvider); + + /** + * Inits the abstract table. + * + * @param eventBus the event bus + * @param fireOnClick the fire on click + * @param dataProvider the data provider + * @param selectionModel the selection model + * @param pageSize the page size + */ + protected void initAbstractTable(HandlerManager eventBus, boolean fireOnClick, AbstractDataProvider dataProvider, + SelectionModel selectionModel, int pageSize) { + this.eventBus = eventBus; + this.fireEventOnClick = fireOnClick; + this.theSelectionModel = selectionModel; + sortedCellTable = new SortedCellTable(pageSize, dataProvider); + sortedCellTable.addStyleName("table-cms-widget"); + sortedCellTable.addStyleName("table-cms-widget-vertical-middle"); + sortedCellTable.setStriped(true); + sortedCellTable.setCondensed(true); + sortedCellTable.setWidth("100%", true); +// dataProvider.addDataDisplay(sortedCellTable); +// initTable(cellTable, null, null); + //sortedCellTable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED); + + DefaultSelectionEventManager checkBoxManager = DefaultSelectionEventManager. createCheckboxManager(); + sortedCellTable.setSelectionModel(theSelectionModel,checkBoxManager); + + theSelectionModel.addSelectionChangeHandler(new Handler() { + @Override + public void onSelectionChange(final SelectionChangeEvent event) { + + if (theSelectionModel instanceof SingleSelectionModel) { + SingleSelectionModel ssm = (SingleSelectionModel) theSelectionModel; + final T selectedObject = ssm.getSelectedObject(); + if (selectedObject != null) { + GWT.log("Clicked: " + selectedObject); +// selectedItem(selectedObject); + if (fireEventOnClick) + AbstractItemsCellTable.this.eventBus.fireEvent(new ClickItemEvent(Arrays.asList(selectedObject))); + } + }else if (theSelectionModel instanceof MultiSelectionModel) { + Set selected = ((MultiSelectionModel) theSelectionModel).getSelectedSet(); + GWT.log("Selected are:" +selected); + if (fireEventOnClick) + AbstractItemsCellTable.this.eventBus.fireEvent(new ClickItemEvent(new ArrayList(selected))); + } + } + }); + + sortedCellTable.addDomHandler(new DoubleClickHandler() { + + @Override + public void onDoubleClick(final DoubleClickEvent event) { + if (theSelectionModel instanceof SingleSelectionModel) { + SingleSelectionModel ssm = (SingleSelectionModel) theSelectionModel; + T selected = ssm.getSelectedObject(); + if (selected != null) { + GWT.log("Double Click: " + selected); + // AbstractItemsCellTable.this.eventBus.fireEvent(new + // org.gcube.portlets.widgets.wsexplorer.client.event.LoadFolderEvent(selected)); + } + } + + } + }, DoubleClickEvent.getType()); + + MenuBar options = new MenuBar(true); + ScheduledCommand openCommand = new ScheduledCommand() { + + @Override + public void execute() { + GWT.log("Context menu shown: " + itemContextMenu); + // AbstractItemsCellTable.this.eventBus.fireEvent(new + // org.gcube.portlets.widgets.wsexplorer.client.event.LoadFolderEvent(itemContextMenu)); + } + }; + + MenuItem openItem = new MenuItem("Open", openCommand); + options.addItem(openItem); + final DialogBox menuWrapper = new DialogBox(true); + menuWrapper.getElement().getStyle().setBorderStyle(BorderStyle.NONE); + menuWrapper.getElement().getStyle().setZIndex(10000); + menuWrapper.add(options); + sortedCellTable.sinkEvents(Event.ONCONTEXTMENU); + + sortedCellTable.addHandler(new ContextMenuHandler() { + @Override + public void onContextMenu(ContextMenuEvent event) { + } + }, ContextMenuEvent.getType()); + + } + +// /** +// * Update items. +// * +// * @param items the items +// * @param removeOldItems the remove old items +// */ +// public void updateItems(List items, boolean removeOldItems) { +// +// if (removeOldItems) { +// if (theSelectionModel instanceof SingleSelectionModel) { +// ((SingleSelectionModel) theSelectionModel).clear(); +// } else if (theSelectionModel instanceof MultiSelectionModel) { +// ((MultiSelectionModel) theSelectionModel).clear(); +// } +// } +// sortedCellTable.setList(items); +// sortedCellTable.setPageSize(items.size() + 1); +// sortedCellTable.redraw(); +// } + + /** + * Gets the cell tables. + * + * @return the cell tables + */ + public SortedCellTable getCellTable() { + return sortedCellTable; + } + + /** + * Checks if is fire event on click. + * + * @return the fireEventOnClick + */ + public boolean isFireEventOnClick() { + + return fireEventOnClick; + } + + /** + * Sets the fire event on click. + * + * @param fireEventOnClick the fireEventOnClick to set + */ + public void setFireEventOnClick(boolean fireEventOnClick) { + + this.fireEventOnClick = fireEventOnClick; + } + + /** + * Adds the items. + * + * @param items the items + */ + public void addItems(List items) { + + AbstractDataProvider dataProvider = sortedCellTable.getDataProvider(); + + if (dataProvider instanceof ListDataProvider) { + List ldp = ((ListDataProvider) dataProvider).getList(); + for (int i = 0; i < items.size(); i++) { + ldp.add(i, items.get(i)); + } + + sortedCellTable.setPageSize(items.size() + 1); + sortedCellTable.redraw(); + } else if (dataProvider instanceof AsyncDataProvider) { + + // TODO ??? + + } + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/ItemsTable.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/ItemsTable.java new file mode 100644 index 0000000..8e36838 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/ItemsTable.java @@ -0,0 +1,546 @@ +/** + * + */ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants; +import org.gcube.portlets.widgets.ckancontentmoderator.client.events.ShowItemEvent; +import org.gcube.portlets.widgets.ckancontentmoderator.client.resources.ContentModeratorWidgetResources; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.SelectionItems; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; + +import com.github.gwtbootstrap.client.ui.Pagination; +import com.google.gwt.cell.client.ButtonCell; +import com.google.gwt.cell.client.Cell.Context; +import com.google.gwt.cell.client.CheckboxCell; +import com.google.gwt.cell.client.DateCell; +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.shared.GWT; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent; +import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo; +import com.google.gwt.user.cellview.client.SimplePager; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.view.client.AbstractDataProvider; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.MultiSelectionModel; +import com.google.gwt.view.client.SelectionModel; +import com.google.gwt.view.client.SingleSelectionModel; + +/** + * The Class ItemsTable. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + * @param the generic type + */ +public class ItemsTable extends AbstractItemsCellTable implements SelectionItems { + + private TextColumn type; + private TextColumn name; + private TextColumn title; + private TextColumn author; + public DateTimeFormat dtformat = DateTimeFormat.getFormat("dd MMM hh:mm aaa yyyy"); + public ImageResource info = ContentModeratorWidgetResources.ICONS.infoSquare(); + + private AbstractDataProvider dataProvider; + + private List displayFields; + private Column createdColumn; + private Column lastUpdateColumn; + private DISPLAY_FIELD startSortByColumn; + private boolean isAsyncronusTable; + + /** + * Instantiates a new items table. + * + * @param eventBus the event bus + * @param fields the fields + * @param startSortByColumn the start sort by column + */ + public ItemsTable(HandlerManager eventBus, DISPLAY_FIELD[] fields, DISPLAY_FIELD startSortByColumn) { + this.eventBus = eventBus; + this.startSortByColumn = startSortByColumn; + setDisplayFields(fields); + } + + /** + * Adds the items. + * + * @param items the items + */ + public void addItems(List items) { + super.addItems(items); + } + + /** + * Inits the table. + * + * @param pager the pager + * @param pagination the pagination + * @param dataProvider the data provider + */ + @Override + public void initTable(final SimplePager pager, final Pagination pagination, AbstractDataProvider dataProvider) { + this.dataProvider = dataProvider; + this.theSelectionModel = new MultiSelectionModel(); + initAbstractTable(eventBus, fireEventOnClick, dataProvider, theSelectionModel, + ContentModeratorWidgetConstants.ITEMS_PER_PAGE); + this.dataProvider.addDataDisplay(sortedCellTable); + + this.isAsyncronusTable = dataProvider instanceof ListDataProvider ? false : true; + setEmptyTableMessage(ContentModeratorWidgetConstants.NO_DATA); + + final CheckboxCell cellCheckBox = new CheckboxCell(true, false); + Column checkColumn = new Column(cellCheckBox) { + @Override + public Boolean getValue(T object) { + // Get the value from the selection model. + return theSelectionModel.isSelected(object); + } + + @Override + public void render(Context context, T object, SafeHtmlBuilder sb) { + super.render(context, object, sb); + GWT.log("added checkbox: " + cellCheckBox + " to object: " + object); + } + + }; + + sortedCellTable.addColumn(checkColumn, "", false); + sortedCellTable.setColumnWidth(checkColumn, 40, Unit.PX); + + ButtonCell previewButton = new ButtonCell(); + Column showdItemColumn = new Column(previewButton) { + public String getValue(T object) { + return "Show"; + } + }; + + showdItemColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, T object, String value) { + GWT.log("clicked show"); + eventBus.fireEvent(new ShowItemEvent(Arrays.asList(object), false)); + } + }); + sortedCellTable.addColumn(showdItemColumn); + sortedCellTable.setColumnWidth(showdItemColumn, 80, Unit.PX); + + if (this.displayFields.contains(DISPLAY_FIELD.NAME)) { + + // NAME + name = new TextColumn() { + @Override + public String getValue(T object) { + if (object == null) + return ""; + return ((CatalogueDataset) object).getName(); + } + + // ADDING TOOLTIP + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, T object, SafeHtmlBuilder sb) { + if (object == null) + return; + sb.appendHtmlConstant("
"); + super.render(context, object, sb); + sb.appendHtmlConstant("
"); + }; + }; + + sortedCellTable.addColumn(name, "Name", true); + + if (!isAsyncronusTable) { + Comparator c = new Comparator() { + @Override + public int compare(T o1, T o2) { + return ((CatalogueDataset) o1).getName().compareTo(((CatalogueDataset) o2).getName()); + } + }; + + sortedCellTable.setComparator(name, c); + } + + } + + if (this.displayFields.contains(DISPLAY_FIELD.TITLE)) { + + title = new TextColumn() { + @Override + public String getValue(T object) { + if (object == null) + return ""; + return ((CatalogueDataset) object).getTitle() != null ? ((CatalogueDataset) object).getTitle() : ""; + } + }; + + sortedCellTable.addColumn(title, "Title", true); + + if (!isAsyncronusTable) { + Comparator c = new Comparator() { + @Override + public int compare(T o1, T o2) { + return ((CatalogueDataset) o1).getTitle().compareTo(((CatalogueDataset) o2).getTitle()); + } + }; + sortedCellTable.setComparator(title, c); + } + + } + + if (this.displayFields.contains(DISPLAY_FIELD.AUTHOR)) { + + author = new TextColumn() { + @Override + public String getValue(T object) { + if (object == null) + return ""; + return ((CatalogueDataset) object).getAuthor() != null ? ((CatalogueDataset) object).getAuthor() + : ""; + } + }; + + sortedCellTable.addColumn(author, "Author", true); + + if (!isAsyncronusTable) { + Comparator c = new Comparator() { + @Override + public int compare(T o1, T o2) { + return ((CatalogueDataset) o1).getAuthor().compareTo(((CatalogueDataset) o2).getAuthor()); + } + }; + sortedCellTable.setComparator(author, c); + } + + } + + if (this.displayFields.contains(DISPLAY_FIELD.CREATED)) { + + DateCell date = new DateCell(dtformat); + createdColumn = new Column(date) { + + @Override + public Date getValue(T object) { + if (object == null) + return null; + + return new Date(((CatalogueDataset) object).getCreated()); + } + }; + sortedCellTable.addColumn(createdColumn, "Created", true); + + if (!isAsyncronusTable) { + Comparator c = new Comparator() { + @Override + public int compare(T o1, T o2) { + if (o1 == null || o1.getCreated() == 0) + return -1; + + if (o2 == null || o2.getCreated() == 0) + return 1; + + Date d1 = new Date(((CatalogueDataset) o1).getCreated()); + Date d2 = new Date(((CatalogueDataset) o2).getCreated()); + + // GWT.log(d1.toString() + "is after "+d2.toString() +" ? "+d2.after(d1)); + + if (d1.after(d2)) + return 1; + else + return -1; + } + }; + GWT.log("date colum sortable"); + sortedCellTable.setComparator(createdColumn, c); + } + + } + + if (this.displayFields.contains(DISPLAY_FIELD.LAST_UPDATE)) { + + DateCell date = new DateCell(dtformat); + lastUpdateColumn = new Column(date) { + + @Override + public Date getValue(T object) { + if (object == null) + return null; + + return new Date(((CatalogueDataset) object).getLastUpdate()); + } + }; + sortedCellTable.addColumn(lastUpdateColumn, "Last Update", true); + + if (!isAsyncronusTable) { + Comparator c = new Comparator() { + @Override + public int compare(T o1, T o2) { + if (o1 == null || o1.getCreated() == 0) + return -1; + + if (o2 == null || o2.getCreated() == 0) + return 1; + + Date d1 = new Date(((CatalogueDataset) o1).getLastUpdate()); + Date d2 = new Date(((CatalogueDataset) o2).getLastUpdate()); + + // GWT.log(d1.toString() + "is after "+d2.toString() +" ? "+d2.after(d1)); + + if (d1.after(d2)) + return 1; + else + return -1; + } + }; + GWT.log("date colum sortable"); + sortedCellTable.setComparator(lastUpdateColumn, c); + } + + } + + if (this.displayFields.contains(DISPLAY_FIELD.TYPE)) { + + // NAME + type = new TextColumn() { + @Override + public String getValue(T object) { + if (object == null) + return ""; + + String type = ((CatalogueDataset) object).getExtra_SystemType(); + + if (type == null) + return ""; + return type; + } + + // ADDING TOOLTIP + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, T object, SafeHtmlBuilder sb) { + if (object == null) + return; + String type = ((CatalogueDataset) object).getExtra_SystemType(); + if (type == null) + type = ""; + sb.appendHtmlConstant("
"); + super.render(context, object, sb); + sb.appendHtmlConstant("
"); + }; + }; + + sortedCellTable.addColumn(type, "Type", true); + + if (!isAsyncronusTable) { + Comparator c = new Comparator() { + @Override + public int compare(T o1, T o2) { + if (o1 == null || o1.getExtra_SystemType() == null) + return -1; + + if (o2 == null || o2.getExtra_SystemType() == null) + return 1; + return ((CatalogueDataset) o1).getExtra_SystemType() + .compareTo(((CatalogueDataset) o2).getExtra_SystemType()); + } + }; + + sortedCellTable.setComparator(type, c); + } + + } + + GWT.log("startSortByColumn: " + startSortByColumn); + + if (startSortByColumn != null) + switch (startSortByColumn) { + case NAME: + if (this.displayFields.contains(DISPLAY_FIELD.NAME)) { + sortedCellTable.setInitialSortColumn(name); + } + break; + case TITLE: + if (this.displayFields.contains(DISPLAY_FIELD.TITLE)) { + sortedCellTable.setInitialSortColumn(title); + } + break; + case AUTHOR: + if (this.displayFields.contains(DISPLAY_FIELD.AUTHOR)) { + sortedCellTable.setInitialSortColumn(author); + } + break; + case TYPE: + if (this.displayFields.contains(DISPLAY_FIELD.TYPE)) { + sortedCellTable.setInitialSortColumn(type); + } + break; + case CREATED: + if (this.displayFields.contains(DISPLAY_FIELD.CREATED)) { + sortedCellTable.setDefaultSortOrder(createdColumn, false); // sorts ascending on first click + sortedCellTable.setInitialSortColumn(createdColumn); + GWT.log("sortedCellTable: " + sortedCellTable); + } + break; + case LAST_UPDATE: + if (this.displayFields.contains(DISPLAY_FIELD.LAST_UPDATE)) { + sortedCellTable.setDefaultSortOrder(lastUpdateColumn, false); // sorts ascending on first click + sortedCellTable.setInitialSortColumn(lastUpdateColumn); + GWT.log("sortedCellTable: " + sortedCellTable); + } + break; + default: + break; + } + + } + + /** + * Displays the appropriate sorted icon in the header of the column for the + * given index. + * + * @param columnIndex of the column to mark as sorted + * @param ascending true for ascending icon, false + * for descending icon + */ + public void setSortedColumn(int columnIndex, boolean ascending) { + GWT.log("Column index: " + columnIndex); + GWT.log("ascending: " + ascending); + Column column = sortedCellTable.getColumn(columnIndex); + if (column != null && column.isSortable()) { + ColumnSortInfo info = sortedCellTable.getColumnSortList().push(column); +// ColumnSortEvent.fire(cellTable, cellTable.getColumnSortList()); + GWT.log("info.isAscending(): " + info.isAscending()); + if (info.isAscending() != ascending) { + sortedCellTable.getColumnSortList().push(column); + ColumnSortEvent.fire(sortedCellTable, sortedCellTable.getColumnSortList()); + } + } + } + + /** + * Sets the display fields. + * + * @param fields the new display fields + */ + public void setDisplayFields(DISPLAY_FIELD[] fields) { + this.displayFields = fields != null && fields.length > 0 ? Arrays.asList(fields) + : Arrays.asList(DISPLAY_FIELD.values()); + } + + /** + * Reset columns table. + */ + public void reInitColumnsTable() { + int count = sortedCellTable.getColumnCount(); + for (int i = 0; i < count; i++) { + sortedCellTable.removeColumn(0); + } + initTable(null, null, dataProvider); + } + + /** + * Gets the display fields. + * + * @return the displayFields + */ + public List getDisplayFields() { + return displayFields; + } + + /** + * The Class ButtonImageCell. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Feb 1, 2016 + */ + public class ButtonImageCell extends ButtonCell { + + /** + * Render. + * + * @param context the context + * @param value the value + * @param sb the sb + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.cell.client.AbstractSafeHtmlCell#render(com.google.gwt.cell. + * client.Cell.Context, java.lang.Object, + * com.google.gwt.safehtml.shared.SafeHtmlBuilder) + */ + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb) { + SafeHtml html = SafeHtmlUtils.fromTrustedString(new Image(value).toString()); + sb.append(html); + } + } + + /** + * Gets the selected item. + * + * @return the selected item + */ + /* + * (non-Javadoc) + * + * @see org.gcube.portlets.widgets.wsexplorer.client.notification. + * SelectionItemHandler#getSelectionItem() + */ + @Override + public List getSelectedItems() { + if (theSelectionModel instanceof SingleSelectionModel) { + T selected = ((SingleSelectionModel) theSelectionModel).getSelectedObject(); + if (selected != null) { + return Arrays.asList(selected); + } + + } else if (theSelectionModel instanceof MultiSelectionModel) { + Set selected = ((MultiSelectionModel) theSelectionModel).getSelectedSet(); + if (selected != null) { + return new ArrayList(selected); + } + } + + return null; + } + + /** + * Sets the empty table message. + * + * @param msg the new empty table message + */ + public void setEmptyTableMessage(String msg) { + msg = msg != null ? msg : ContentModeratorWidgetConstants.NO_DATA; + if (sortedCellTable != null) + sortedCellTable.setEmptyTableWidget(new Label(msg)); + } + + /** + * Gets the selection model. + * + * @return the selection model + */ + public SelectionModel getSelectionModel() { + return theSelectionModel; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/MyToolTipColumn.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/MyToolTipColumn.java new file mode 100644 index 0000000..5080d11 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/MyToolTipColumn.java @@ -0,0 +1,83 @@ +/** + * + */ + +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table; + +import com.google.gwt.cell.client.Cell; +import com.google.gwt.cell.client.Cell.Context; +import com.google.gwt.core.client.GWT; +import com.google.gwt.safehtml.client.SafeHtmlTemplates; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.user.cellview.client.Column; + + +/** + * The Class MyToolTipColumn. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + * @param the generic type + * @param the generic type + */ +public abstract class MyToolTipColumn extends Column { + + /** + * The Interface Templates. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + */ + interface Templates extends SafeHtmlTemplates { + + /** + * Start tool tip. + * + * @param toolTipText the tool tip text + * @return the safe html + */ + @Template("
") + SafeHtml startToolTip(String toolTipText); + + /** + * End tool tip. + * + * @return the safe html + */ + @Template("
") + SafeHtml endToolTip(); + } + + private static final Templates TEMPLATES = GWT.create(Templates.class); + private final String toolTipText; + + /** + * Instantiates a new my tool tip column. + * + * @param cell the cell + * @param toolTipText the tool tip text + */ + public MyToolTipColumn(final Cell cell, final String toolTipText) { + + super(cell); + this.toolTipText = toolTipText; + } + + /** + * Render. + * + * @param context the context + * @param object the object + * @param sb the sb + */ + @Override + public void render(final Context context, final T object, final SafeHtmlBuilder sb) { + + sb.append(TEMPLATES.startToolTip(toolTipText)); + super.render(context, object, sb); + sb.append(TEMPLATES.endToolTip()); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/SortedCellTable.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/SortedCellTable.java new file mode 100644 index 0000000..c18d579 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/table/SortedCellTable.java @@ -0,0 +1,302 @@ +/** + * + */ + +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gcube.portlets.widgets.ckancontentmoderator.client.resources.CellTableResources; + +import com.github.gwtbootstrap.client.ui.CellTable; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent; +import com.google.gwt.user.cellview.client.ColumnSortEvent.AsyncHandler; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo; +import com.google.gwt.user.cellview.client.Header; +import com.google.gwt.view.client.AbstractDataProvider; +import com.google.gwt.view.client.AsyncDataProvider; +import com.google.gwt.view.client.ListDataProvider; + +/** + * The Class SortedCellTable. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 15, 2021 + * @param the generic type + */ +public class SortedCellTable extends CellTable { + + /** + * To keep track of the currently sorted column + */ + private Column currentlySortedColumn; + /** + * Tells us which way to sort a column initially + */ + private Map, Boolean> defaultSortOrderMap = new HashMap, Boolean>(); + /** + * Comparators associated with their columns + */ + private Map, Comparator> comparators = new HashMap, Comparator>(); + /** + * Column to sort when the data provider's list is refreshed using + * {@link SortedCellTable#setList(List)} + */ + private Column initialSortColumn; + /** + * Data provider we will attach to this table + */ + private AbstractDataProvider dataProvider; + + /** + * Special column sorting handler that will allow us to do more controlled + * sorting + */ + private ColumnSortEvent.Handler columnSortHandler; + + /** + * Instantiates a new sorted cell table. + * + * @param pageSize the page size + * @param dataProv the data prov + */ + public SortedCellTable(int pageSize, AbstractDataProvider dataProv) { + super(pageSize, CellTableResources.INSTANCE); + this.dataProvider = dataProv; + + if (this.dataProvider instanceof ListDataProvider) { + ListDataProvider listDataProvider = (ListDataProvider) this.dataProvider; + ListHandler listSortHandler = new ListHandler((listDataProvider).getList()) { + + @Override + public void onColumnSort(ColumnSortEvent event) { + + @SuppressWarnings("unchecked") + Column column = (Column) event.getColumn(); + if (column == null) { + return; + } + if (column.equals(currentlySortedColumn)) { + // Default behavior + super.onColumnSort(event); + } else { + // Initial sort; look up which direction we need + final Comparator comparator = comparators.get(column); + if (comparator == null) { + return; + } + Boolean ascending = defaultSortOrderMap.get(column); + if (ascending == null || ascending) { + // Default behavior + super.onColumnSort(event); + } else { + // Sort the column descending + Collections.sort(getList(), new Comparator() { + + public int compare(T o1, T o2) { + + return -comparator.compare(o1, o2); + } + }); + // Set the proper arrow in the header + getColumnSortList().push(new ColumnSortInfo(column, false)); + } + currentlySortedColumn = column; + } + } + + @Override + public void setComparator(Column column, Comparator comparator) { + + comparators.put(column, comparator); + super.setComparator(column, comparator); + } + }; + addColumnSortHandler(listSortHandler); + columnSortHandler = listSortHandler; + } else if (this.dataProvider instanceof AsyncDataProvider) { + //AsyncDataProvider asyncDataProvider = ((AsyncDataProvider) this.dataProvider); + //asyncDataProvider.get + AsyncHandler asyncSortHandler = new AsyncHandler(this) { + @Override + public void onColumnSort(ColumnSortEvent event) { + + @SuppressWarnings("unchecked") + Column column = (Column) event.getColumn(); + if (column == null) { + return; + } + if (column.equals(currentlySortedColumn)) { + // Default behavior + super.onColumnSort(event); + } else { + // Initial sort; look up which direction we need + final Comparator comparator = comparators.get(column); + if (comparator == null) { + return; + } + Boolean ascending = defaultSortOrderMap.get(column); + if (ascending == null || ascending) { + // Default behavior + super.onColumnSort(event); + } else { + // Sort the column descending + Collections.sort(getVisibleItems(), new Comparator() { + + public int compare(T o1, T o2) { + + return -comparator.compare(o1, o2); + } + }); + // Set the proper arrow in the header + getColumnSortList().push(new ColumnSortInfo(column, false)); + } + currentlySortedColumn = column; + } + } + }; + +// addColumnSortHandler(asyncSortHandler); +// columnSortHandler = asyncSortHandler; + } + + } + + /** + * Adds a column to the table and sets its sortable state. + * + * @param column the column + * @param headerName the header name + * @param sortable the sortable + */ + public void addColumn(Column column, String headerName, boolean sortable) { + + addColumn(column, headerName); + column.setSortable(sortable); + if (sortable) { + defaultSortOrderMap.put(column, true); + } + } + + /** + * Adds the column. + * + * @param column the column + * @param headerName the header name + */ + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.user.cellview.client.AbstractCellTable#addColumn(com.google. + * gwt.user.cellview.client.Column, java.lang.String) + */ + public void addColumn(Column column, String headerName) { + + super.addColumn(column, headerName); + } + + /** + * Adds a column to the table and sets its sortable state. + * + * @param column the column + * @param header the header + * @param sortable the sortable + */ + public void addColumn(Column column, Header header, boolean sortable) { + + addColumn(column, header); + column.setSortable(sortable); + if (sortable) { + defaultSortOrderMap.put(column, true); + } + } + + /** + * Sets the column to sort when the data list is reset using + * {@link SortedCellTable#setList(List)}. + * + * @param column the column + */ + public void setInitialSortColumn(Column column) { + + initialSortColumn = column; + } + + /** + * Set the comparator used to sort the specified column in ascending order. + * + * @param column the {@link Column} + * @param comparator the {@link Comparator} to use for the {@link Column} + */ + public void setComparator(Column column, Comparator comparator) { + comparators.put(column, comparator); + } + + /** + * Sets the sort order to use when this column is clicked and it was not + * previously sorted. + * + * @param column the column + * @param ascending the ascending + */ + public void setDefaultSortOrder(Column column, boolean ascending) { + + defaultSortOrderMap.put(column, ascending); + } + + /** + * Sets the table's data provider list and sorts the table based on the column + * given in {@link SortedCellTable#setInitialSortColumn(Column)}. + * + * @param list the new list + */ + public void setList(List list) { + + if (dataProvider instanceof ListDataProvider) { + List myData = ((ListDataProvider) dataProvider).getList(); + myData.clear(); + if (list != null) { + /* + * for (T t : list) { dataProvider.getList().add(t); } + */ + myData.addAll(list); + } + // Do a first-time sort based on which column was set in + // setInitialSortColumn() + if (initialSortColumn != null) { + Collections.sort(myData, new Comparator() { + + @Override + public int compare(T o1, T o2) { + + return (defaultSortOrderMap.get(initialSortColumn) ? 1 : -1) + * comparators.get(initialSortColumn).compare(o1, o2); + } + }); + // Might as well get the little arrow on the header to make it + // official + getColumnSortList().push(new ColumnSortInfo(initialSortColumn, defaultSortOrderMap.get(initialSortColumn))); + + currentlySortedColumn = initialSortColumn; + } + } + } + + /** + * Gets the data provider. + * + * @return the data provider + */ + public AbstractDataProvider getDataProvider() { + + return dataProvider; + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/ExtModal.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/ExtModal.java new file mode 100644 index 0000000..3ab7f1b --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/ExtModal.java @@ -0,0 +1,133 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util; + +import com.github.gwtbootstrap.client.ui.Modal; +import com.github.gwtbootstrap.client.ui.event.HideEvent; +import com.github.gwtbootstrap.client.ui.event.HideHandler; +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; +import com.google.gwt.user.client.Random; + +/** + * The Class ExtModal. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 29, 2021 + * + * This Class extends the {{@link Modal} preventing the default close of + * the Modal Bootstrap when clicking outside of the modal Window + */ +public class ExtModal extends Modal { + + private String elementId; + private String closeElementId; + private Boolean closeButtoClicked = false; + final private ExtModal INSTANCE = this; + + /** + * Instantiates a new ext modal. + */ + public ExtModal() { + super(); + setElementIds(); + addDeferredCommandToPreventModalClose(); + } + + /** + * Creates an empty, hidden widget with specified show behavior. + * + * @param animated true if the widget should be animated. + */ + public ExtModal(boolean animated) { + super(animated, false); + setElementIds(); + addDeferredCommandToPreventModalClose(); + } + + /** + * Creates an empty, hidden widget with specified show behavior. + * + * @param animated true if the widget should be animated. + * @param dynamicSafe true removes from RootPanel when hidden + */ + public ExtModal(boolean animated, boolean dynamicSafe) { + super(animated, dynamicSafe); + setElementIds(); + addDeferredCommandToPreventModalClose(); + } + + private void addDeferredCommandToPreventModalClose() { + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + + @Override + public void execute() { + ((Element) INSTANCE.getElement().getChildNodes().getItem(0)).getFirstChildElement() + .setId(closeElementId); + preventModalCloseWhenClickingOutside(); + + } + }); + + } + + /** + * Sets the element id. + */ + private void setElementIds() { + this.elementId = "my-modal-publish-meta" + Random.nextInt(); + this.getElement().setId(elementId); + + this.closeElementId = "my-modal-close-button" + Random.nextInt(); + } + + /** + * Prevent modal close when clicking outside. + */ + private void preventModalCloseWhenClickingOutside() { + + com.google.gwt.user.client.Element buttonCloseElement = DOM.getElementById(this.closeElementId); + + if (buttonCloseElement != null) { + + Event.sinkEvents(buttonCloseElement, Event.ONCLICK); + Event.setEventListener(buttonCloseElement, new EventListener() { + + @Override + public void onBrowserEvent(Event event) { + System.out.println("ok"); + if (Event.ONCLICK == event.getTypeInt()) { + GWT.log("close event clicked"); + closeButtoClicked = true; + } + + } + }); + } else { + GWT.log("button close element not found"); + closeButtoClicked = true; + } + + // hide any popup panel opened + this.addHideHandler(new HideHandler() { + + @Override + public void onHide(HideEvent hideEvent) { + GWT.log("HideEvent on modal fired"); + GWT.log(hideEvent.toDebugString()); + GWT.log("CloseButtonClicked is: " + closeButtoClicked); + + if (!closeButtoClicked) { + hideEvent.preventDefault(); + hideEvent.stopPropagation(); + } + } + }); + + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/LoadingPanel.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/LoadingPanel.java new file mode 100644 index 0000000..dff8763 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/LoadingPanel.java @@ -0,0 +1,37 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util; + +import org.gcube.portlets.widgets.ckancontentmoderator.client.resources.ContentModeratorWidgetResources; + +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Image; + +/** + * The Class LoadingPanel. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 16, 2021 + */ +public class LoadingPanel extends HorizontalPanel { + + protected final Image LOADING_IMAGE = ContentModeratorWidgetResources.getIconLoading().createImage(); + + /** + * Instantiates a new loading panel. + * + * @param html the html + */ + public LoadingPanel(HTML html) { + this.getElement().getStyle().setMargin(5.0, Unit.PX); +// LOADING_PANEL.setSpacing(3); + this.add(LOADING_IMAGE); + + if (html == null) + html = new HTML("Loading..."); + + html.getElement().getStyle().setPaddingLeft(5.0, Unit.PX); + this.add(html); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilFunct.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilFunct.java new file mode 100644 index 0000000..f261fdd --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilFunct.java @@ -0,0 +1,75 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; + + +/** + * The Class UtilFunct. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 22, 2021 + */ +public class UtilFunct { + + /** + * Ellipsis. + * + * @param value the value + * @param length the length + * @param left the left + * @return the string + */ + public static String ellipsis(String value, int length, boolean left) { + if (value.length() < 3) + return value; + + if (value.length() > length) { + if (left) + return "..." + value.substring(value.length() - length + 3); + else + return value.substring(0, length) + "..."; + } + return value; + } + + /** + * To status from status label. + * + * @param label the label + * @return the item status + */ + public static ItemStatus toStatusFromStatusLabel(String label) { + + for (ItemStatus theStatus : ItemStatus.values()) { + if (theStatus.getLabel().compareTo(label.trim()) == 0) { + return theStatus; + + } + } + + return null; + } + + + /** + * To list dataset names. + * + * @param itemsSelected the items selected + * @return the list + */ + public static List toListDatasetNames(List itemsSelected) { + + List listDatasetNames = new ArrayList(itemsSelected.size()); + for (CatalogueDataset catalogueDataset : itemsSelected) { + listDatasetNames.add(catalogueDataset.getName()); + } + + return listDatasetNames; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilUx.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilUx.java new file mode 100644 index 0000000..b51b439 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/ui/util/UtilUx.java @@ -0,0 +1,43 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.ui.util; + +import com.github.gwtbootstrap.client.ui.Alert; +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.Panel; + +public class UtilUx { + + /** + * Show message. + * + * @param msg the msg + * @param alertType the alert type + * @param closable the closable + * @param addToPanel the add to panel + * @param scheduleTimerMls the schedule timer mls + */ + public static void showAlert(String msg, AlertType alertType, boolean closable, final Panel addToPanel, final Integer scheduleTimerMls) { + + final Alert alert = new Alert(msg); + alertType = alertType != null ? alertType : AlertType.INFO; + alert.setType(alertType); + alert.setClose(closable); + alert.setAnimation(true); + addToPanel.add(alert); + + if (scheduleTimerMls != null) { + + // Cleans the info panel after 12 sec. + Timer t = new Timer() { + + @Override + public void run() { + addToPanel.clear(); + } + }; + + t.schedule(scheduleTimerMls); + } + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/ModerationQueryStringUtil.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/ModerationQueryStringUtil.java new file mode 100644 index 0000000..6acc6a9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/ModerationQueryStringUtil.java @@ -0,0 +1,209 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.util; + +import java.util.Arrays; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.DISPLAY_FIELD; + +import com.google.gwt.core.client.GWT; + +/** + * The Class ModerationQueryStringUtil. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * May 4, 2022 + */ +public class ModerationQueryStringUtil { + + public static final String MODERATION_PARAMETER = "moderation"; + public static final String ITEM_NAME_PARAMETER = "item_name"; + public static final String STATUS_PARAMETER = "status"; + + /** + * The Enum MODERATION_VALUE. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * May 4, 2022 + */ + public enum MODERATION_VALUE { + show + } + + /** + * Instantiates a new moderation query string util. + */ + public ModerationQueryStringUtil() { + } + + /** + * To moderation builder. + * + * @param decodedQueryString the decoded query string + * @return the moderation builder + */ + public ModerationBuilder toModerationBuilder(String decodedQueryString) { + ModerationBuilder mbuilder = null; + + if (decodedQueryString == null || decodedQueryString.isEmpty()) + return null; + + String moderationValue = QueryStringUtil.getValueOfParameterInTheURL(MODERATION_PARAMETER, decodedQueryString); + + MODERATION_VALUE toModerationValue = null; + // Moderation parameter in the query string has a not empty value + if (moderationValue != null) { + try { + toModerationValue = MODERATION_VALUE.valueOf(moderationValue.toLowerCase()); + } catch (Exception e) { + GWT.log("Moderation value: " + moderationValue + " is not a value of " + MODERATION_VALUE.values()); + } + } + + if (toModerationValue != null) { + + mbuilder = new ModerationBuilder(); + + String itemNameValue = QueryStringUtil.getValueOfParameterInTheURL(ITEM_NAME_PARAMETER, decodedQueryString); + if (itemNameValue != null) { + mbuilder.setItemName(itemNameValue); + } + + String statusValue = QueryStringUtil.getValueOfParameterInTheURL(STATUS_PARAMETER, decodedQueryString); + if (statusValue != null) { + try { + ItemStatus theStatus = ItemStatus.valueOf(statusValue.toUpperCase()); + mbuilder.setItemStatus(theStatus); + } catch (Exception e) { + GWT.log("Error on assigning "+ItemStatus.values() +" from string "+statusValue); + } + + } + } + + return mbuilder; + } + + /** + * The Class ModerationBuilder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * May 4, 2022 + */ + public class ModerationBuilder { + + private ItemStatus itemStatus = ItemStatus.PENDING; + private String itemName = null; + private DISPLAY_FIELD[] displayFields = DISPLAY_FIELD.values(); + private DISPLAY_FIELD[] sortByFields = ContentModeratorWidgetConstants.DEFAULT_SORT_BY_FIELDS; + + /** + * Instantiates a new moderation builder. + */ + ModerationBuilder() { + + } + + /** + * Gets the item name. + * + * @return the item name + */ + public String getItemName() { + return itemName; + } + + /** + * Sets the item name. + * + * @param itemName the new item name + */ + public void setItemName(String itemName) { + this.itemName = itemName; + } + + /** + * Gets the item status. + * + * @return the item status + */ + public ItemStatus getItemStatus() { + return itemStatus; + } + + /** + * Gets the display fields. + * + * @return the display fields + */ + public DISPLAY_FIELD[] getDisplayFields() { + return displayFields; + } + + /** + * Gets the sort by fields. + * + * @return the sort by fields + */ + public DISPLAY_FIELD[] getSortByFields() { + return sortByFields; + } + + /** + * Sets the item status. + * + * @param itemStatus the new item status + */ + public void setItemStatus(ItemStatus itemStatus) { + this.itemStatus = itemStatus; + } + + /** + * Sets the display fields. + * + * @param displayFields the new display fields + */ + public void setDisplayFields(DISPLAY_FIELD[] displayFields) { + this.displayFields = displayFields; + } + + /** + * Sets the sort by fields. + * + * @param sortByFields the new sort by fields + */ + public void setSortByFields(DISPLAY_FIELD[] sortByFields) { + this.sortByFields = sortByFields; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ModerationBuilder [itemStatus="); + builder.append(itemStatus); + builder.append(", itemName="); + builder.append(itemName); + builder.append(", displayFields="); + builder.append(Arrays.toString(displayFields)); + builder.append(", sortByFields="); + builder.append(Arrays.toString(sortByFields)); + builder.append("]"); + return builder.toString(); + } + + } + + /** + * Base 64 decode. + * + * @param a the a + * @return the string + */ + protected static native String base64decode(String a) /*-{ + return window.atob(a); + }-*/; + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/QueryStringUtil.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/QueryStringUtil.java new file mode 100644 index 0000000..7a4d85c --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/client/util/QueryStringUtil.java @@ -0,0 +1,71 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.client.util; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.http.client.URL; + +/** + * The Class QueryStringUtil. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * May 3, 2022 + */ +public class QueryStringUtil { + + /** + * Gets the value of parameter in the URL. + * + * @param paramName the param name + * @param url the url + * @return the value of parameter in the URL + */ + public static String getValueOfParameterInTheURL(String paramName, String url) { + int index = url.toLowerCase().indexOf(paramName.toLowerCase() + "="); // ADDING CHAR "=" IN TAIL TO BE SURE THAT + // IT IS A PARAMETER + String value = null; + if (index > -1) { + + int start = index + paramName.length() + 1; // add +1 for char '=' + String sub = url.substring(start, url.length()); + int indexOfSeparator = sub.indexOf("&"); + int end = indexOfSeparator != -1 ? indexOfSeparator : sub.length(); + value = sub.substring(0, end); + } + + GWT.log("Returning value " + value + " for the parameter: " + paramName); + return value; + } + + /** + * Base 64 decode. + * + * @param a the a + * @return the string + */ + private static native String base64decode(String a) /*-{ + return window.atob(a); + }-*/; + + /** + * Base 64 decode query string. + * + * @param base64EncodedQueryString the base 64 encoded query string + * @return the string + */ + public static String base64DecodeQueryString(String base64EncodedQueryString) { + + if (base64EncodedQueryString != null && !base64EncodedQueryString.isEmpty()) { + String b64DecodedQueryStringParameter = base64decode(base64EncodedQueryString); + GWT.log("Base64 Decoded string is: " + b64DecodedQueryStringParameter); + b64DecodedQueryStringParameter = URL.decodeQueryString(b64DecodedQueryStringParameter); // equals should be + // encoded too (%3D) + GWT.log("Decoded query string is: " + b64DecodedQueryStringParameter); + + return b64DecodedQueryStringParameter; + } + + return base64EncodedQueryString; + + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/public/content-moderator-widget.css b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/public/content-moderator-widget.css new file mode 100644 index 0000000..381028e --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/public/content-moderator-widget.css @@ -0,0 +1,40 @@ +@charset "UTF-8"; + +/*** TABLE ***/ +.table-cms-widget { + word-wrap: break-word; +} + +.table-cms-widget th { + border-top: 1px solid black !important; +} + +.table-cms-widget td, th { + overflow: hidden !important; +} + +.table-cms-widget th { + text-align: center !important; +} + +.table-cms-widget-vertical-middle td, th { + height: 50%; + vertical-align: middle !important; +} + +.hide_checkbox input[type="checkbox"] { + display: none; +} + +/***** WS EXPLORER DOCK PANEL - CENTER FLOW PANEL *****/ +.we-dock-center-panel { + overflow-y: auto !important; + /* border: 1px solid #DDD; */ +} + +.as_simple_link { + background: none !important; + border: none !important; + padding: 0 !important; + margin: 0 !important; +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ActionRequired.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ActionRequired.java new file mode 100644 index 0000000..84821a9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ActionRequired.java @@ -0,0 +1,22 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import java.io.Serializable; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; + +public class ActionRequired implements Serializable{ + + + /** + * + */ + private static final long serialVersionUID = 6975224903479593671L; + + String reasonMsg; + + ItemStatus from; + + ItemStatus to; + + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueBeansConverter.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueBeansConverter.java new file mode 100644 index 0000000..62bbf0a --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueBeansConverter.java @@ -0,0 +1,58 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import java.util.Map; +import java.util.function.Function; + +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CatalogueBeansConverter { + + private static Logger LOG = LoggerFactory.getLogger(CatalogueBeansConverter.class); + + /** The to S sync folder descriptor. */ + public static Function toCatalogueDataset = new Function() { + + public CatalogueDataset apply(CkanDataset t) { + CatalogueDataset myDataset = new CatalogueDataset(); + if (t == null) { + LOG.info("Input " + CkanDataset.class.getSimpleName() + " is null, returning empty " + + CkanDataset.class.getSimpleName()); + return myDataset; + } + + myDataset.setAuthor(t.getAuthor()); + myDataset.setAuthorEmail(t.getAuthorEmail()); + + //is it needed?? + myDataset.setExtra_ItemURL(null); + + System.out.println("Extras: "+t.getExtrasAsHashMap()); + Map extrasMap = t.getExtrasAsHashMap(); + if(extrasMap!=null) { + String type = extrasMap.get("system:type"); + myDataset.setExtra_SystemType(type); + String itemURL = extrasMap.get("Item URL"); + myDataset.setExtra_ItemURL(itemURL); + } + + myDataset.setId(t.getId()); + myDataset.setLicenseId(t.getLicenseId()); + myDataset.setMaintainer(t.getMaintainer()); + myDataset.setMaintainerEmail(t.getMaintainerEmail()); + myDataset.setName(t.getName()); + myDataset.setNotes(t.getNotes()); + myDataset.setOwnerOrg(t.getOwnerOrg()); + myDataset.setTitle(t.getTitle()); + + //here is always null + myDataset.setUrl(t.getUrl()); + myDataset.setCreated(t.getMetadataCreated().getTime()); + myDataset.setLastUpdate(t.getMetadataModified().getTime()); + return myDataset; + } + }; + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueCMSFactory.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueCMSFactory.java new file mode 100644 index 0000000..29e9fea --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CatalogueCMSFactory.java @@ -0,0 +1,112 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import java.util.concurrent.ConcurrentHashMap; + +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueImpl; +import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorSystem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * A factory for getting CatalogueContentModeratorSystem objects. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 14, 2021 + */ +public class CatalogueCMSFactory { + + private static final Logger logger = LoggerFactory.getLogger(CatalogueCMSFactory.class); + private static final long MAX_LIFETIME = 1000 * 60 * 30; // 30 MINUTES + private static CatalogueCMSFactory instance = new CatalogueCMSFactory(); + private static ConcurrentHashMap cache; + + /** + * The Class CacheBean. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 16, 2021 + */ + private class CacheBean { + DataCatalogueImpl dataCatalogueImpl; + long ttl; + + /** + * Instantiates a new cache bean. + * + * @param ttl the ttl + * @param dataCatalogueImpl the data catalogue impl + */ + public CacheBean(long ttl, DataCatalogueImpl dataCatalogueImpl) { + this.ttl = ttl; + this.dataCatalogueImpl = dataCatalogueImpl; + } + } + + /** + * Private constructor. + */ + private CatalogueCMSFactory() { + + logger.debug(CatalogueCMSFactory.class.getSimpleName() + " object build"); + cache = new ConcurrentHashMap(); + + } + + /** + * Get the factory instance. + * + * @return the factory + */ + public static CatalogueCMSFactory getFactory() { + logger.debug(CatalogueCMSFactory.class.getSimpleName() + " requested"); + return instance; + } + + /** + * Gets the CMS per scope. + * + * @param scope the scope + * @return the CMS per scope + * @throws Exception the exception + */ + public CatalogueContentModeratorSystem getCMSPerScope(String scope) throws Exception { + + DataCatalogueImpl dataCatalogueImpl = getCatalogueImplPerScope(scope); + return dataCatalogueImpl.getCatalogueContentModerator(); + } + + /** + * Gets the catalogue impl per scope. + * + * @param scope the scope + * @return the catalogue impl per scope + * @throws Exception the exception + */ + public DataCatalogueImpl getCatalogueImplPerScope(String scope) throws Exception { + + if (scope == null || scope.isEmpty()) + throw new IllegalArgumentException("Invalid scope given!"); + + if (cache.containsKey(scope) && !expired(cache.get(scope))) { + return cache.get(scope).dataCatalogueImpl; + } else { + logger.info("Creating " + CatalogueCMSFactory.class.getSimpleName() + " for scope " + scope); + DataCatalogueImpl dci = new DataCatalogueImpl(scope); + cache.put(scope, new CacheBean(System.currentTimeMillis(), dci)); + return dci; + } + } + + /** + * Check if the ckan information must be retrieved again. + * + * @param cacheBean the cache bean + * @return true, if successful + */ + private boolean expired(CacheBean cacheBean) { + return (cacheBean.ttl + MAX_LIFETIME < System.currentTimeMillis()); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImpl.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImpl.java deleted file mode 100644 index 6e99383..0000000 --- a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.gcube.portlets.widgets.ckancontentmoderator.server; - -import java.util.List; - -import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; -import org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorService; - -import com.google.gwt.user.server.rpc.RemoteServiceServlet; - -/** - * The server side implementation of the RPC service. - */ -@SuppressWarnings("serial") -public class CkanContentModeratorServiceAImpl extends RemoteServiceServlet implements - CkanContentModeratorService, ContentModeratorSystem { - - @Override - public boolean isContentModeratorEnabled() { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setStatus(String itemId, ItemStatus theStatus) { - // TODO Auto-generated method stub - - } - - @Override - public List getListItemsForStatus(ItemStatus theStatus) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void approveItem(String itemId) { - // TODO Auto-generated method stub - - } - - @Override - public void rejectItem(String itemId, boolean permanentlyDelete, String reasonMsg) { - // TODO Auto-generated method stub - - } - - @Override - public void permanentlyDelete(String itemId) { - // TODO Auto-generated method stub - - } -} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceImpl.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceImpl.java new file mode 100644 index 0000000..3b20ab9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceImpl.java @@ -0,0 +1,500 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.datacatalogue.utillibrary.gcat.GCatCaller; +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueImpl; +import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorSystem; +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorService; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants; +import org.gcube.portlets.widgets.ckancontentmoderator.server.CkanContentModeratorUtil.QUERY_OPERATOR; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CMSUserRole; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.ModerationUserRole; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.OperationReport; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchedData; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gwt.user.server.rpc.RemoteServiceServlet; + +/** + * The Class CkanContentModeratorServiceImpl. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jan 11, 2022 + * @return the boolean + */ +@SuppressWarnings("serial") +public class CkanContentModeratorServiceImpl extends RemoteServiceServlet implements CkanContentModeratorService { + + private static Logger LOG = LoggerFactory.getLogger(CkanContentModeratorServiceImpl.class); + + /** + * Checks if is moderation enabled. + * + * @param reloadConfig the reload config + * @return the boolean + */ + @Override + public Boolean isModerationEnabled(boolean reloadConfig) { + LOG.info("called isContentModeratorEnabled"); + String scope = setContexts(); + boolean isModerationEnabled = false; + try { + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator(); + isModerationEnabled = cmsInstance.isModerationEnabled(reloadConfig); + } catch (Exception e) { + LOG.error("Error occured on checking isContentModeratorEnabled, so returning false", e); + return false; + } + return isModerationEnabled; + } + + /** + * Checks if is moderator role is assigned to working user in the context. + * + * @return the moderation user role + * @throws Exception the exception + */ + @Override + public Boolean isModeratorRoleAssigned() throws Exception { + LOG.info("called isModeratorRoleAssigned"); + ModerationUserRole userRole = getCMSRolesForUserInTheContext(); + + boolean isCatalogueModerator = false; + if (userRole != null && userRole.getRoles() != null + && userRole.getRoles().contains(CMSUserRole.CATALOGUE_MODERATOR)) { + LOG.info("called isModeratorRoleAssigned"); + isCatalogueModerator = true; + } + LOG.info("is " + CMSUserRole.CATALOGUE_MODERATOR.getRoleName() + " assigned? " + isCatalogueModerator); + return isCatalogueModerator; + } + + /** + * Exists my item in moderation. + * + * @return true if the user has at least one item moderatorated or in + * moderation. + * @throws Exception the exception + */ + @Override + public Boolean existsMyItemInModeration() throws Exception { + LOG.info("called existsMyItemInModeration"); + try { + + /* + * if(!GcubeContextUtil.isWithinPortal()) { + * LOG.warn("#### DEV MODE ENABLED #######"); boolean defaultValue = true; + * LOG.info("DEV MODE: existsMyItemInModeration returning: " + defaultValue); + * return defaultValue; } + */ + + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + + GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest()); + String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR); + + StringBuilder emailsValuesBuilder = new StringBuilder(); + // QUERYING AUTHOR_MAIL. IT MUST BE IN LIST OF EMAILs + emailsValuesBuilder + .append(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL + ":" + valueOfQueryEmails); + + Map params = new HashMap(1); + params.put("q", emailsValuesBuilder.toString()); + // QUERYING THE ITEM HAVING ANY MODERATIONS STATUS + params.put(GCatCaller.MODERATOR_ITEM_STATUS_PARAMETER, GCatCaller.MODERATOR_ITEM_ANY_STATUS_VALUE); + + List listItems = catalogueImpl.performQueryForItems(params); + LOG.debug("existsMyItemInModeration query returned items: " + listItems); + + boolean haveItemInModeration = false; + + if (listItems != null && listItems.size() > 0) { + haveItemInModeration = true; + } + + LOG.info("existsMyItemInModeration returning: " + haveItemInModeration); + return haveItemInModeration; + + } catch (Exception e) { + LOG.warn("Error occurred on checking existsMyItemInModeration, so returning false"); + return false; + } + } + + /** + * Gets the CMS roles for user in the context. + * + * @return the CMS roles for user in the context + * @throws Exception the exception + */ + @Override + public ModerationUserRole getCMSRolesForUserInTheContext() throws Exception { + LOG.info("called getCMSRolesForUserInTheContext"); + setContexts(); + List roles = GcubeContextUtil.getCMSRoleForUserInTheScope(getThreadLocalRequest()); + + GcubeContextUtil.getCurrentUser(getThreadLocalRequest()); + ModerationUserRole userRole = new ModerationUserRole(getServletInfo(), roles); + LOG.info("return: " + userRole); + return userRole; + } + + /** + * Sets the contexts. + * + * @return the scope operating in + */ + private String setContexts() { + String scope = GcubeContextUtil.getCurrentScope(this.getThreadLocalRequest()); + ScopeProvider.instance.set(scope); + + GCubeUser user = GcubeContextUtil.getCurrentUser(this.getThreadLocalRequest()); + if (user != null) { + String token = GcubeContextUtil.getCurrentToken(scope, user.getUsername()); + SecurityTokenProvider.instance.set(token); + } + return scope; + } + + /** + * Gets the list items for status. + * + * @param theStatus the the status + * @param offset the offset + * @param limit the limit + * @param restrictedToLoggedInUser if true restricts the list of items to logged + * in user + * @param sortForField the sort for field + * @return the list items for status + * @throws Exception the exception + */ + @Override + public List getListItemsForStatus(ItemStatus theStatus, int offset, int limit, + boolean restrictedToLoggedInUser, String sortForField) throws Exception { + LOG.info("called getListItemsForStatus with [status: " + theStatus + ", offset: " + offset + ", limit: " + limit + + ", restrictedToLoggedInUser: " + restrictedToLoggedInUser + "]"); + List datasetList = null; + try { + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator(); + + Map filters = null; + if (restrictedToLoggedInUser) { + filters = new HashMap(1); + GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest()); + String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR); + filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails); + } + + List datasets = cmsInstance.getListItemsForStatus(theStatus, limit, offset, filters, + sortForField); + if (datasets != null) { + int size = datasets.size(); + datasetList = new ArrayList(size); + LOG.info("datasetList for input parameters returned by CMS has size: " + size); + for (CkanDataset ckanDataset : datasets) { + CatalogueDataset ds = toPatchedCatalogueDataset(ckanDataset, catalogueImpl.getCatalogueUrl()); + LOG.trace("converted dataset is: " + ds); + datasetList.add(ds); + } + } + + } catch (Exception e) { + LOG.error("Error occurred on reading items for status: " + theStatus, e); + throw e; + } + + LOG.info("returning " + datasetList.size() + " dataset"); + return datasetList; + } + + private CatalogueDataset toPatchedCatalogueDataset(CkanDataset ckanDataset, String catalogueURL) { + if (ckanDataset == null) + return null; + + CatalogueDataset ds = CatalogueBeansConverter.toCatalogueDataset.apply(ckanDataset); + String datasetURL = String.format("%s/dataset/%s", catalogueURL, ds.getName()); + ds.setUrl(datasetURL); + return ds; + } + + /** + * Gets the item for name. + * + * @param itemName the item name + * @return the item for name + * @throws Exception the exception + */ + @Override + public CatalogueDataset getItemForName(String itemName) throws Exception { + LOG.info("called getItemForName for: " + itemName); + CatalogueDataset ds = null; + try { + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + GCubeUser user = GcubeContextUtil.getCurrentUser(this.getThreadLocalRequest()); + + boolean moderationCheckPassed = false; + + if (user != null) { + CkanDataset ckanDataset = catalogueImpl.getDataset(itemName, user.getUsername()); + ds = null; + if (ckanDataset != null) { + ds = toPatchedCatalogueDataset(ckanDataset, catalogueImpl.getCatalogueUrl()); + + Boolean userModerator = isModeratorRoleAssigned(); + moderationCheckPassed = userModerator?true:false; + LOG.info("Moderation check: is the user a Moderator? "+moderationCheckPassed); + //The user is not a Moderator, yes otherwise + if(!moderationCheckPassed) { + String datasetAuthorMail = ds.getAuthorEmail(); + String userMail = user.getEmail(); + if(datasetAuthorMail!=null && userMail!=null && datasetAuthorMail.compareTo(userMail)==0) { + //The user is the owner of the dataset, so he/she can view the dataset (moderation check passed) + moderationCheckPassed = true; + } + LOG.info("Moderation check: is the user the owner of the dataset? "+moderationCheckPassed); + } + } + } + + if(!moderationCheckPassed) { + LOG.info("Moderation ckeck not passed, returning null"); + ds = null; + } + + } catch (Exception e) { + LOG.error("Error occurred on reading item for name: " + itemName, e); + throw e; + } + + LOG.info("getItemForName "+itemName+", returning: " + ds); + return ds; + } + + /** + * Sets the status. + * + * @param theStatus the the status + * @param itemNames the item names + * @return the operation report + * @throws Exception the exception + */ + @Override + public OperationReport setStatus(ItemStatus theStatus, List itemNames) throws Exception { + LOG.info("Called set status " + theStatus + " for Items with name: " + itemNames); + + try { + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + Map errorMapItems = new HashMap(); + List changedStatusListItems = new ArrayList(); + for (String itemName : itemNames) { + try { + catalogueImpl.refreshDataset(itemName); + changedStatusListItems.add(itemName); + } catch (Exception e) { + LOG.warn("Error when setting status (updating) the itemName: " + itemName, e); + errorMapItems.put(itemName, e.getMessage()); + } + } + + return new OperationReport(theStatus.getLabel(), changedStatusListItems, errorMapItems); + + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new Exception("Error occurred on updating the status for item/s: " + itemNames + ". Caused by: " + + e.getMessage()); + } + } + + /** + * Approve item. + * + * @param itemNames the item names + * @param moderatorMessage the moderator message + * @return the operation report + * @throws Exception the exception + */ + @Override + public OperationReport approveItem(List itemNames, String moderatorMessage) throws Exception { + LOG.info("Called approveItem with name/s: " + itemNames); + + try { + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator(); + + Map errorMapItems = new HashMap(); + List approvedListItems = new ArrayList(); + for (String itemName : itemNames) { + try { + cmsInstance.approveItem(itemName, moderatorMessage); + approvedListItems.add(itemName); + } catch (Exception e) { + LOG.warn("Error when approving itemName: " + itemName, e); + errorMapItems.put(itemName, e.getMessage()); + } + } + + return new OperationReport(ItemStatus.APPROVED.getLabel(), approvedListItems, errorMapItems); + + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new Exception("Error occurred on approving item/s: " + itemNames + ". Caused by: " + e.getMessage()); + } + } + + /** + * Reject item. + * + * @param itemNames the item names + * @param permanentlyDelete the permanently delete + * @param reasonMsg the reason msg + * @return the operation report + * @throws Exception the exception + */ + @Override + public OperationReport rejectItem(List itemNames, boolean permanentlyDelete, String reasonMsg) + throws Exception { + LOG.info("Called rejectItem with name/s: " + itemNames + ", permanentlyDelete: " + permanentlyDelete); + + try { + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator(); + + Map errorMapItems = new HashMap(); + List passedListItems = new ArrayList(); + for (String itemName : itemNames) { + try { + cmsInstance.rejectItem(itemName, permanentlyDelete, reasonMsg); + passedListItems.add(itemName); + } catch (Exception e) { + LOG.warn("Error when rejecting itemName: " + itemName, e); + errorMapItems.put(itemName, e.getMessage()); + } + } + + return new OperationReport(ItemStatus.REJECTED.getLabel(), passedListItems, errorMapItems); + + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new Exception("Error occurred on rejecting item/s: " + itemNames + ". Caused by: " + e.getMessage()); + } + } + + /** + * Permanently delete. + * + * @param itemNames the item names + * @return the operation report + * @throws Exception the exception + */ + @Override + public OperationReport permanentlyDelete(List itemNames) throws Exception { + LOG.info("Called permanently delete Items with name/s: " + itemNames); + + try { + String scope = setContexts(); + DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope); + CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator(); + + Map errorMapItems = new HashMap(); + List passedListItems = new ArrayList(); + for (String itemName : itemNames) { + try { + cmsInstance.permanentlyDelete(itemName); + passedListItems.add(itemName); + } catch (Exception e) { + LOG.warn("Error when deleting permanently the itemName: " + itemName, e); + errorMapItems.put(itemName, e.getMessage()); + } + } + + return new OperationReport("Permanently Delete", passedListItems, errorMapItems); + + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new Exception( + "Error occurred on permanently delete item/s: " + itemNames + ". Caused by: " + e.getMessage()); + } + } + + /** + * Gets the data for status. + * + * @param status the status + * @param offset the offset + * @param limit the limit + * @param serverStartIndex the server start index + * @param restrictedToLoggedInUser the restricted to logged in user + * @param sortForField the sort for field + * @return the data for status + * @throws Exception the exception + */ + @Override + public SearchedData getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex, + boolean restrictedToLoggedInUser, String sortForField) throws Exception { + LOG.info("called getDataForStatus [status: " + status + ", offset: " + offset + ", limit: " + limit + + ", serverIndex: " + serverStartIndex); + + String scope = setContexts(); + int searchStartIndex = offset; + CatalogueContentModeratorSystem cmsInstance = CatalogueCMSFactory.getFactory().getCMSPerScope(scope); + SearchedData searchedData = new SearchedData(offset, limit, searchStartIndex, false); + + Map filters = null; + if (restrictedToLoggedInUser) { + filters = new HashMap(1); + GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest()); + String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR); + filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails); + } + + long totalItemsForStatus = cmsInstance.countListItemsForStatus(status, filters); + LOG.info("totalItemsForStatus " + status + " are : " + totalItemsForStatus); + List listDataset = new ArrayList(); + try { + LOG.debug("getListItemsForStatus with searchStartIndex: " + searchStartIndex + ", limit: " + limit); + listDataset = getListItemsForStatus(status, searchStartIndex, limit, restrictedToLoggedInUser, + sortForField); + } catch (Exception e) { + String error = "Error occurred on getting items for status: " + status; + LOG.error(error, e); + throw new Exception(error + ". Cause: " + e.getMessage()); + } + + int listDatasetSize = listDataset.size(); + LOG.debug("Returned " + listDatasetSize + " with above parameters"); + searchedData.setData(listDataset); + searchedData.setTotalItems(totalItemsForStatus); + + if (listDatasetSize == limit || listDatasetSize == 0) { + LOG.debug("Page completed returning " + listDatasetSize + " items"); + int newOffset = searchStartIndex + offset; + searchedData.setServerSearchFinished(newOffset > totalItemsForStatus || listDatasetSize == 0); + LOG.debug("is Search finished: " + searchedData.isServerSearchFinished()); + return searchedData; + } + + LOG.debug("Returning: " + searchedData); + return searchedData; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorUtil.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorUtil.java new file mode 100644 index 0000000..161e17f --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorUtil.java @@ -0,0 +1,102 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.vomanagement.usermanagement.model.Email; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class CkanContentModeratorUtil. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 6, 2022 + */ +public class CkanContentModeratorUtil { + + private static Logger LOG = LoggerFactory.getLogger(CkanContentModeratorUtil.class); + + public static enum QUERY_OPERATOR { + AND, OR + } + + /** + * User query for emails. + * + * @param user the user + * @return the string representing the value of the query for filtering for User + * Mails + * @throws Exception the exception + */ + public static String userSOLRQueryForEmails(GCubeUser user, QUERY_OPERATOR operator) throws Exception { + LOG.debug("userQueryForEmails called for user {}", user); + + List listServerEmails = user.getEmailAddresses(); + LOG.debug("List server mails: {}", listServerEmails); + List emailsAddresses = new ArrayList(); + + boolean notFoundMail = listServerEmails == null || listServerEmails.isEmpty(); + + if (notFoundMail) { + LOG.warn("No list mail found in " + GCubeUser.class.getSimpleName() + " getEmailAddresses()"); + String mail = user.getEmail(); + LOG.debug("Read mail: " + mail); + if (mail != null && !mail.isEmpty()) { + LOG.info("Email found in " + GCubeUser.class.getSimpleName() + " getEmail()"); + emailsAddresses.add(mail); + } + } else { + for (Email email : listServerEmails) { + emailsAddresses.add(email.getEmail()); + } + } + + LOG.info("Email/s found for user {} is/are: {}", user.getUsername(), emailsAddresses); + + if (emailsAddresses.isEmpty()) { + throw new Exception("No email found for user: " + user.getUsername()); + } + + if (operator == null) + operator = QUERY_OPERATOR.OR; + + StringBuilder queryMails = new StringBuilder(); + String queryOperator = operator.name(); + // BUILDING EMAILS QUERY + int numberOfEmails = emailsAddresses.size(); + + String theQuery = ""; + + // case 1 email address + if (numberOfEmails == 1) { + theQuery = "'" + emailsAddresses.get(0) + "'"; + } else { + // case N > 1 email addresses + for (int i = 0; i < emailsAddresses.size() - 1; i++) { + String email = emailsAddresses.get(i); + if (i == 0) { + // opening the query and adding first email address + queryMails.append("('" + email + "'"); + } else { + // adding the operator and the email address + queryMails.append(" " + queryOperator + " '" + email + "'"); + } + } + + theQuery = queryMails.toString(); + + // to be sure that endsWith Operator + if (!theQuery.endsWith(queryOperator)) { + theQuery += " " + queryOperator + " "; + } + + // adding last email address and closing the query + theQuery += "'" + emailsAddresses.get(numberOfEmails - 1) + "')"; + } + + return theQuery; + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ContentModeratorSystem.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ContentModeratorSystem.java deleted file mode 100644 index cb2d8c1..0000000 --- a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/ContentModeratorSystem.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.gcube.portlets.widgets.ckancontentmoderator.server; - -import java.util.List; - -import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; - - -// TODO: Auto-generated Javadoc -/** - * The Interface ContentModeratorSystem. - * - * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it - * - * May 7, 2021 - */ -public interface ContentModeratorSystem { - - /** - * Checks if is content moderator enabled. - * - * @return true, if is content moderator enabled - */ - boolean isContentModeratorEnabled(); - - /** - * Sets the status. - * - * @param itemId the item id - * @param theStatus the the status - */ - void setStatus(String itemId, ItemStatus theStatus); - - - /** - * Gets the list items for status. - * - * @param theStatus the the status - * @return the list items for status - */ - List getListItemsForStatus(ItemStatus theStatus); - - /** - * Approve item. - * - * @param itemId the item id - */ - void approveItem(String itemId); - - /** - * Reject item. - * - * @param itemId the item id - * @param permanentlyDelete the permanently delete - * @param reasonMsg the reason msg - */ - void rejectItem(String itemId, boolean permanentlyDelete, String reasonMsg); - - /** - * Permanently delete. - * - * @param itemId the item id - */ - void permanentlyDelete(String itemId); - - /** - * The Enum ItemStatus. - * - * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it - * - * May 7, 2021 - */ - static enum ItemStatus { - PENDING("pending", "Pending"), APPROVED("approved", "Approved"), REJECTED("rejected", "Rejected"); - - private String id; - private String label; - - /** - * Instantiates a new item status. - * - * @param id the id - * @param label the label - */ - private ItemStatus(String id, String label) { - this.id = id; - this.label = label; - } - - /** - * Gets the id. - * - * @return the id - */ - public String getId() { - return id; - } - - /** - * Gets the label. - * - * @return the label - */ - public String getLabel() { - return label; - } - - } -} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/GcubeContextUtil.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/GcubeContextUtil.java new file mode 100644 index 0000000..3bedfb3 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/server/GcubeContextUtil.java @@ -0,0 +1,164 @@ +/** + * + */ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.gcube.common.portal.PortalContext; +import org.gcube.portlets.widgets.ckancontentmoderator.shared.CMSUserRole; +import org.gcube.vomanagement.usermanagement.RoleManager; +import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault; +import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; +import org.gcube.vomanagement.usermanagement.impl.LiferayRoleManager; +import org.gcube.vomanagement.usermanagement.model.GCubeRole; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.liferay.portal.service.UserLocalServiceUtil; + +/** + * The Class GcubeContextUtil. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Feb 21, 2022 + */ +public class GcubeContextUtil { + + protected static Logger LOG = LoggerFactory.getLogger(GcubeContextUtil.class); + + /** + * Checks if is within portal. + * + * @return true if you're running into the portal, false if in development + */ + public static boolean isWithinPortal() { + try { + UserLocalServiceUtil.getService(); + return true; + } catch (Exception ex) { + LOG.trace("Development Mode ON"); + return false; + } + } + + /** + * Gets the current user. + * + * @param httpServletRequest the http servlet request + * @return the current user + */ + public static GCubeUser getCurrentUser(HttpServletRequest httpServletRequest) { + return PortalContext.getConfiguration().getCurrentUser(httpServletRequest); + } + + /** + * Gets the current scope. + * + * @param httpServletRequest the http servlet request + * @return the current scope + */ + public static String getCurrentScope(HttpServletRequest httpServletRequest) { + return PortalContext.getConfiguration().getCurrentScope(httpServletRequest); + } + + /** + * Gets the current token. + * + * @param scope the scope + * @param username the username + * @return the current token + */ + public static String getCurrentToken(String scope, String username) { + return PortalContext.getConfiguration().getCurrentUserToken(scope, username); + } + + /** + * Gets the current group id. + * + * @param httpServletRequest the http servlet request + * @return the current group id + */ + public static long getCurrentGroupId(HttpServletRequest httpServletRequest) { + return PortalContext.getConfiguration().getCurrentGroupId(httpServletRequest); + } + + /** + * Gets the CMS user role for the logged user (in the current context) + * + * @param httpServletRequest the http servlet request + * @return the scopes with user roles for logged user + * @throws Exception the exception + */ + public static List getCMSRoleForUserInTheScope(HttpServletRequest httpServletRequest) throws Exception { + LOG.info("called getScopesWithThreddsRolesForLoggedUser"); + + // DEV MODE + if (!isWithinPortal()) { + //CMSUserRole userRole = CMSUserRole.CATALOGUE_MODERATOR; + CMSUserRole userRole = null; + LOG.warn("\n\n\nDevelopment MODE is enabled, returning CMS user role: "+userRole); + return Arrays.asList(userRole); + } + + GCubeUser user = null; + String scope = null; + Long groupId = null; + try { + + user = getCurrentUser(httpServletRequest); + scope = getCurrentScope(httpServletRequest); + groupId = getCurrentGroupId(httpServletRequest); + List cmsRoles = getCMSRoleForUserInTheGroupId(user, groupId); + LOG.info("in the context: " + scope + ", returning the role: " + cmsRoles + " for user " + + user.getUsername()); + return cmsRoles; + } catch (Exception e) { + String errorMsg = "An error occurred on checking user roles. Refresh the page and try again."; + LOG.error("An error occurred on checking user roles for user: " + user, e); + throw new Exception(errorMsg); + } + } + + /** + * Gets the CMS role for user in the scope. + * + * @param user the user + * @param groupId the group id + * @return the CMS role for user in the scope + */ + private static List getCMSRoleForUserInTheGroupId(GCubeUser user, Long groupId) { + if (user == null || groupId == null) { + LOG.warn("called getCMSRoleForUserInTheScope with invalid parameter user: " + user + ", in the groupId: " + + groupId, ", returning null"); + return null; + } + + LOG.info("called getCMSRoleForUserInTheScope user: " + user.getUsername() + ", in the groupId: " + groupId); + try { + RoleManager roleManager = new LiferayRoleManager(); + List roles = roleManager.listRolesByUserAndGroup(user.getUserId(), groupId); + List toReturn = new ArrayList(); + if (roles != null) { + for (GCubeRole gCubeRole : roles) { + if (gCubeRole.getRoleName().equalsIgnoreCase(CMSUserRole.CATALOGUE_MODERATOR.getRoleName())) { + toReturn.add(CMSUserRole.CATALOGUE_MODERATOR); + } + } + } + LOG.info("For user: " + user.getUsername() + " in the groupId: " + groupId + + " read and returing the role/s: " + toReturn); + return toReturn; + } catch (UserRetrievalFault | GroupRetrievalFault e) { + LOG.error("An error occurred during getVreRoleForUser: " + user, e); + return null; + } + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CMSUserRole.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CMSUserRole.java new file mode 100644 index 0000000..0c7a1dd --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CMSUserRole.java @@ -0,0 +1,17 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + + public enum CMSUserRole { + + CATALOGUE_MODERATOR("Catalogue-Moderator"); + + private String name; + + private CMSUserRole(String name) { + this.name = name; + } + + public String getRoleName() { + return this.name; + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CatalogueDataset.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CatalogueDataset.java new file mode 100644 index 0000000..d3110e5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/CatalogueDataset.java @@ -0,0 +1,228 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; + +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; + +import com.google.gwt.user.client.rpc.IsSerializable; + +/** + * The Class CatalogueDataset. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 14, 2021 + */ +public class CatalogueDataset implements Serializable, IsSerializable { + + /** + * + */ + private static final long serialVersionUID = 566645830900736239L; + private String author; + private String authorEmail; + private String id; + private String licenseId; + private String maintainer; + private String maintainerEmail; + private String name; + private String notes; + private String ownerOrg; + private ItemStatus status; + private String title; + private String url; + private String version; + private String extra_ItemURL; + private String extra_SystemType; + private long created; + private long lastUpdate; + + /** + * Instantiates a new ckan dataset base. + */ + public CatalogueDataset() { + } + + public String getAuthor() { + return author; + } + + public String getAuthorEmail() { + return authorEmail; + } + + public String getId() { + return id; + } + + public String getLicenseId() { + return licenseId; + } + + public String getMaintainer() { + return maintainer; + } + + public String getMaintainerEmail() { + return maintainerEmail; + } + + public String getName() { + return name; + } + + public String getNotes() { + return notes; + } + + public String getOwnerOrg() { + return ownerOrg; + } + + public ItemStatus getStatus() { + return status; + } + + public String getTitle() { + return title; + } + + public String getUrl() { + return url; + } + + public String getVersion() { + return version; + } + + public String getD4scienceItemURL() { + return extra_ItemURL; + } + + public long getCreated() { + return created; + } + + public void setAuthor(String author) { + this.author = author; + } + + public void setAuthorEmail(String authorEmail) { + this.authorEmail = authorEmail; + } + + public void setId(String id) { + this.id = id; + } + + public void setLicenseId(String licenseId) { + this.licenseId = licenseId; + } + + public void setMaintainer(String maintainer) { + this.maintainer = maintainer; + } + + public void setMaintainerEmail(String maintainerEmail) { + this.maintainerEmail = maintainerEmail; + } + + public void setName(String name) { + this.name = name; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public void setOwnerOrg(String ownerOrg) { + this.ownerOrg = ownerOrg; + } + + public void setStatus(ItemStatus status) { + this.status = status; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setVersion(String version) { + this.version = version; + } + + public void setCreated(long created) { + this.created = created; + } + + public void setLastUpdate(long time) { + this.lastUpdate = time; + + } + + public long getLastUpdate() { + return lastUpdate; + } + + public String getExtra_ItemURL() { + return extra_ItemURL; + } + + public void setExtra_ItemURL(String extra_ItemURL) { + this.extra_ItemURL = extra_ItemURL; + } + + public String getExtra_SystemType() { + return extra_SystemType; + } + + public void setExtra_SystemType(String extra_SystemType) { + this.extra_SystemType = extra_SystemType; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CatalogueDataset [author="); + builder.append(author); + builder.append(", authorEmail="); + builder.append(authorEmail); + builder.append(", id="); + builder.append(id); + builder.append(", licenseId="); + builder.append(licenseId); + builder.append(", maintainer="); + builder.append(maintainer); + builder.append(", maintainerEmail="); + builder.append(maintainerEmail); + builder.append(", name="); + builder.append(name); + builder.append(", notes="); + builder.append(notes); + builder.append(", ownerOrg="); + builder.append(ownerOrg); + builder.append(", status="); + builder.append(status); + builder.append(", title="); + builder.append(title); + builder.append(", url="); + builder.append(url); + builder.append(", version="); + builder.append(version); + builder.append(", extra_ItemURL="); + builder.append(extra_ItemURL); + builder.append(", extra_SystemType="); + builder.append(extra_SystemType); + builder.append(", created="); + builder.append(created); + builder.append(", lastUpdate="); + builder.append(lastUpdate); + builder.append("]"); + return builder.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/DISPLAY_FIELD.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/DISPLAY_FIELD.java new file mode 100644 index 0000000..d72ec9c --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/DISPLAY_FIELD.java @@ -0,0 +1,47 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +/** + * The Enum DISPLAY_FIELD. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 22, 2022 + */ +public enum DISPLAY_FIELD { + NAME("Name", "name"), TITLE("Title", "title"), AUTHOR("Author", "author_mail"), + CREATED("Created", "metadata_created"), LAST_UPDATE("Last Update", "metadata_modified"), + TYPE("Type", "extras_systemtype"); + + String label; + String jsonField; + + /** + * Instantiates a new display field. + * + * @param label the label + * @param jsonField the json field + */ + private DISPLAY_FIELD(String label, String jsonField) { + this.label = label; + this.jsonField = jsonField; + } + + /** + * Gets the label. + * + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * Gets the json field. + * + * @return the json field + */ + public String getJsonField() { + return jsonField; + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/FieldVerifier.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/FieldVerifier.java deleted file mode 100644 index 5143953..0000000 --- a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/FieldVerifier.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.gcube.portlets.widgets.ckancontentmoderator.shared; - -/** - *

- * FieldVerifier validates that the name the user enters is valid. - *

- *

- * This class is in the shared packing because we use it in both - * the client code and on the server. On the client, we verify that the name is - * valid before sending an RPC request so the user doesn't have to wait for a - * network round trip to get feedback. On the server, we verify that the name is - * correct to ensure that the input is correct regardless of where the RPC - * originates. - *

- *

- * When creating a class that is used on both the client and the server, be sure - * that all code is translatable and does not use native JavaScript. Code that - * is note translatable (such as code that interacts with a database or the file - * system) cannot be compiled into client side JavaScript. Code that uses native - * JavaScript (such as Widgets) cannot be run on the server. - *

- */ -public class FieldVerifier { - - /** - * Verifies that the specified name is valid for our service. - * - * In this example, we only require that the name is at least four - * characters. In your application, you can use more complex checks to ensure - * that usernames, passwords, email addresses, URLs, and other fields have the - * proper syntax. - * - * @param name the name to validate - * @return true if valid, false if invalid - */ - public static boolean isValidName(String name) { - if (name == null) { - return false; - } - return name.length() > 3; - } -} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ItemFieldDV.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ItemFieldDV.java new file mode 100644 index 0000000..542a332 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ItemFieldDV.java @@ -0,0 +1,165 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; +import java.util.List; + +/** + * The Class ItemFieldDV. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 22, 2022 + */ +public class ItemFieldDV implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 563269286444442608L; + private String displayName; + private List jsonFields; + private String operator; + private boolean displayAsResult; + private boolean sortable; + private boolean searchable; + + /** + * Instantiates a new item field. + */ + public ItemFieldDV() { + + } + + /** + * Gets the display name. + * + * @return the display name + */ + public String getDisplayName() { + return displayName; + } + + /** + * Gets the json fields. + * + * @return the json fields + */ + public List getJsonFields() { + return jsonFields; + } + + /** + * Gets the operator. + * + * @return the operator + */ + public String getOperator() { + return operator; + } + + /** + * Checks if is display as result. + * + * @return true, if is display as result + */ + public boolean isDisplayAsResult() { + return displayAsResult; + } + + /** + * Checks if is sortable. + * + * @return true, if is sortable + */ + public boolean isSortable() { + return sortable; + } + + /** + * Checks if is searchable. + * + * @return true, if is searchable + */ + public boolean isSearchable() { + return searchable; + } + + /** + * Sets the display name. + * + * @param displayName the new display name + */ + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + * Sets the json fields. + * + * @param jsonFields the new json fields + */ + public void setJsonFields(List jsonFields) { + this.jsonFields = jsonFields; + } + + /** + * Sets the operator. + * + * @param operator the new operator + */ + public void setOperator(String operator) { + this.operator = operator; + } + + /** + * Sets the display as result. + * + * @param displayAsResult the new display as result + */ + public void setDisplayAsResult(boolean displayAsResult) { + this.displayAsResult = displayAsResult; + } + + /** + * Sets the sortable. + * + * @param sortable the new sortable + */ + public void setSortable(boolean sortable) { + this.sortable = sortable; + } + + /** + * Sets the searchable. + * + * @param searchable the new searchable + */ + public void setSearchable(boolean searchable) { + this.searchable = searchable; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ItemFieldDV [displayName="); + builder.append(displayName); + builder.append(", jsonFields="); + builder.append(jsonFields); + builder.append(", operator="); + builder.append(operator); + builder.append(", displayAsResult="); + builder.append(displayAsResult); + builder.append(", sortable="); + builder.append(sortable); + builder.append(", searchable="); + builder.append(searchable); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ModerationUserRole.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ModerationUserRole.java new file mode 100644 index 0000000..3d40f60 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/ModerationUserRole.java @@ -0,0 +1,53 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; +import java.util.List; + +/** + * The Class ModerationUserRole. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Feb 21, 2022 + */ +public class ModerationUserRole implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 7002466635359684148L; + private String username; + private List roles; + + /** + * Instantiates a new moderation user role. + */ + public ModerationUserRole() { + } + + public ModerationUserRole(String username, List roles) { + super(); + this.username = username; + this.roles = roles; + } + + public String getUsername() { + return username; + } + + public List getRoles() { + return roles; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ModerationUserRole [username="); + builder.append(username); + builder.append(", roles="); + builder.append(roles); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/OperationReport.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/OperationReport.java new file mode 100644 index 0000000..4021f5f --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/OperationReport.java @@ -0,0 +1,66 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OperationReport implements Serializable { + + + /** + * + */ + private static final long serialVersionUID = 4960774282956107668L; + private String operationType; + private Map errorMapItems = new HashMap(); + private List passedListItems = new ArrayList(); + + public OperationReport() { + } + + public OperationReport(String operationType, List passedListItems, Map errorMapItems) { + this.operationType = operationType; + this.errorMapItems = errorMapItems; + this.passedListItems = passedListItems; + } + + public String getOperationType() { + return operationType; + } + + public Map getErrorMapItems() { + return errorMapItems; + } + + public List getPassedListItems() { + return passedListItems; + } + + public void setOperationType(String operationType) { + this.operationType = operationType; + } + + public void setErrorMapItems(Map errorMapItems) { + this.errorMapItems = errorMapItems; + } + + public void setPassedListItems(List passedListItems) { + this.passedListItems = passedListItems; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("OperationReport [operationType="); + builder.append(operationType); + builder.append(", errorMapItems="); + builder.append(errorMapItems); + builder.append(", passedListItems="); + builder.append(passedListItems); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchedData.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchedData.java new file mode 100644 index 0000000..f10d8c5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchedData.java @@ -0,0 +1,181 @@ +/** + * + */ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; +import java.util.List; + + +/** + * The Class SearchedFolder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jun 16, 2021 + */ +public class SearchedData implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 6800997954077785719L; + private List data; + private int clientStartIndex = 0; + private int limit; + private int serverEndIndex = 0; + private boolean isServerSearchFinished = false; + private long totalItems; + + /** + * Instantiates a new searched folder. + */ + public SearchedData() { + } + + /** + * Instantiates a new searched data. + * + * @param clientStartIndex the client start index + * @param limit the limit + * @param serverEndIndex the server end index + * @param isServerSearchFinished the is server search finished + */ + public SearchedData(int clientStartIndex, int limit, int serverEndIndex, boolean isServerSearchFinished) { + + this.clientStartIndex = clientStartIndex; + this.limit = limit; + this.serverEndIndex = serverEndIndex; + this.isServerSearchFinished = isServerSearchFinished; + } + + /** + * Gets the data. + * + * @return the data + */ + public List getData() { + return data; + } + + /** + * Gets the client start index. + * + * @return the client start index + */ + public int getClientStartIndex() { + return clientStartIndex; + } + + /** + * Gets the limit. + * + * @return the limit + */ + public int getLimit() { + return limit; + } + + /** + * Gets the server end index. + * + * @return the server end index + */ + public int getServerEndIndex() { + return serverEndIndex; + } + + /** + * Checks if is server search finished. + * + * @return true, if is server search finished + */ + public boolean isServerSearchFinished() { + return isServerSearchFinished; + } + + /** + * Sets the data. + * + * @param data the new data + */ + public void setData(List data) { + this.data = data; + } + + /** + * Sets the client start index. + * + * @param clientStartIndex the new client start index + */ + public void setClientStartIndex(int clientStartIndex) { + this.clientStartIndex = clientStartIndex; + } + + /** + * Sets the limit. + * + * @param limit the new limit + */ + public void setLimit(int limit) { + this.limit = limit; + } + + /** + * Sets the server end index. + * + * @param serverEndIndex the new server end index + */ + public void setServerEndIndex(int serverEndIndex) { + this.serverEndIndex = serverEndIndex; + } + + /** + * Sets the server search finished. + * + * @param isServerSearchFinished the new server search finished + */ + public void setServerSearchFinished(boolean isServerSearchFinished) { + this.isServerSearchFinished = isServerSearchFinished; + } + + /** + * Gets the total items. + * + * @return the total items + */ + public long getTotalItems() { + return totalItems; + } + + /** + * Sets the total items. + * + * @param totalItems the new total items + */ + public void setTotalItems(long totalItems) { + this.totalItems = totalItems; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SearchedData [data="); + builder.append(data); + builder.append(", clientStartIndex="); + builder.append(clientStartIndex); + builder.append(", limit="); + builder.append(limit); + builder.append(", serverEndIndex="); + builder.append(serverEndIndex); + builder.append(", isServerSearchFinished="); + builder.append(isServerSearchFinished); + builder.append(", totalItems="); + builder.append(totalItems); + builder.append("]"); + return builder.toString(); + } + + + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchingFilter.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchingFilter.java new file mode 100644 index 0000000..2c69657 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/SearchingFilter.java @@ -0,0 +1,191 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; +import java.util.List; + +/** + * The Class SearchingFilter. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 22, 2022 + */ +public class SearchingFilter implements Serializable { + + /** + * The Enum ORDER. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 22, 2022 + */ + public static enum ORDER { + ASC("asc"), DESC("desc"); + + String label; + + /** + * Instantiates a new order. + * + * @param label the label + */ + ORDER(String label) { + this.label = label; + } + + /** + * Gets the label. + * + * @return the label + */ + public String getLabel() { + return label; + } + } + + /** + * The Enum LOGICAL_OP. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Dec 15, 2021 + */ + public static enum LOGICAL_OP { + AND("AND"), OR("OR"); + + String operator; + + /** + * Instantiates a new order. + * + * @param operator the operator + */ + LOGICAL_OP(String operator) { + this.operator = operator; + } + + /** + * Gets the operator. + * + * @return the operator + */ + public String getOperator() { + return operator; + } + } + + /** + * + */ + private static final long serialVersionUID = -4004094263090373626L; + + private List orderByFields; + + private ORDER order = ORDER.ASC; + + private List conditions; + + /** + * Instantiates a new sort filter. + */ + public SearchingFilter() { + + } + + /** + * Instantiates a new sort filter. + * + * @param orderByFields the order by fields + * @param order the order + */ + public SearchingFilter(List orderByFields, ORDER order) { + this.orderByFields = orderByFields; + this.order = order; + } + + /** + * Instantiates a new sort filter. + * + * @param orderByFields the order by fields + * @param order the order + * @param conditions the conditions + */ + public SearchingFilter(List orderByFields, ORDER order, List conditions) { + this.orderByFields = orderByFields; + this.order = order; + this.conditions = conditions; + } + + /** + * Gets the conditions. + * + * @return the conditions + */ + public List getConditions() { + return conditions; + } + + /** + * Sets the conditions. + * + * @param conditions the new conditions + */ + public void setConditions(List conditions) { + this.conditions = conditions; + } + + /** + * Gets the order by fields. + * + * @return the order by fields + */ + public List getOrderByFields() { + return orderByFields; + } + + /** + * Gets the order. + * + * @return the order + */ + public ORDER getOrder() { + return order; + } + + /** + * Sets the order by fields. + * + * @param orderByFields the new order by fields + */ + public void setOrderByFields(List orderByFields) { + this.orderByFields = orderByFields; + } + + /** + * Sets the order. + * + * @param order the new order + */ + public void setOrder(ORDER order) { + this.order = order; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SearchingFilter [orderByFields="); + builder.append(orderByFields); + builder.append(", order="); + builder.append(order); + builder.append(", conditions="); + builder.append(conditions); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/WhereClause.java b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/WhereClause.java new file mode 100644 index 0000000..89e9a36 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckancontentmoderator/shared/WhereClause.java @@ -0,0 +1,98 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.shared; + +import java.io.Serializable; +import java.util.Map; + +import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchingFilter.LOGICAL_OP; + +/** + * The Class WhereClause. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 22, 2022 + */ +public class WhereClause implements Serializable { + + + /** + * + */ + private static final long serialVersionUID = -3354004449129217444L; + + private LOGICAL_OP operator = LOGICAL_OP.OR; + + private Map searchInto; + + /** + * Instantiates a new where clause. + */ + public WhereClause() { + + } + + /** + * Instantiates a new where clause. + * + * @param operator the operator + * @param searchInto the search into + */ + public WhereClause(LOGICAL_OP operator, Map searchInto) { + super(); + this.operator = operator; + this.searchInto = searchInto; + } + + /** + * Gets the operator. + * + * @return the operator + */ + public LOGICAL_OP getOperator() { + return operator; + } + + /** + * Gets the search into. + * + * @return the search into + */ + public Map getSearchInto() { + return searchInto; + } + + /** + * Sets the operator. + * + * @param operator the new operator + */ + public void setOperator(LOGICAL_OP operator) { + this.operator = operator; + } + + /** + * Sets the search into. + * + * @param searchInto the search into + */ + public void setSearchInto(Map searchInto) { + this.searchInto = searchInto; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("WhereClause [operator="); + builder.append(operator); + builder.append(", searchInto="); + builder.append(searchInto); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml b/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml index 309a748..0660eee 100644 --- a/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml +++ b/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/CkanContentModeratorWidget.gwt.xml @@ -1,22 +1,23 @@ - - + + - - - - - - + - + - - + - - - + + + + + + + + diff --git a/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/client/Messages_fr.properties b/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/client/Messages_fr.properties deleted file mode 100644 index b4a7627..0000000 --- a/src/main/resources/org/gcube/portlets/widgets/ckancontentmoderator/client/Messages_fr.properties +++ /dev/null @@ -1,2 +0,0 @@ -sendButton = Envoyer -nameField = Entrez votre nom \ No newline at end of file diff --git a/src/main/webapp/CkanContentModeratorWidget.css b/src/main/webapp/CkanContentModeratorWidget.css index 7aca7ac..6673fe4 100644 --- a/src/main/webapp/CkanContentModeratorWidget.css +++ b/src/main/webapp/CkanContentModeratorWidget.css @@ -32,3 +32,325 @@ h1 { #closeButton { margin: 15px 6px 6px; } + + + + +html{ + overflow-x: hidden !important; +} + +body { + padding-top: 70px; +} + +pre.prettyprint { + padding: 9.5px !important; + border: none !important; + margin-bottom: 0px !important; + background: transparent !important; + margin-bottom: 10px !important; +} + +.page-header { + margin-top: 0px !important; +} + +.progress{ + background-color: #E8F4FD; +} + +nav{ + width: calc(100% - 240px); +} + +nav .button-collapse i { + font-size: 24px !important; +} + +/* Styles for Affix/sidebar shamelessly copied from http://getbootstrap.com/assets/css/docs.css */ + +/* By default it's not affixed in mobile views, so undo that */ +.bs-sidebar.affix { + position: static; +} + +/* First level of nav */ +.bs-sidenav { + margin-top: 30px; + margin-bottom: 30px; + padding-top: 10px; + padding-bottom: 10px; + text-shadow: 0 1px 0 #fff; + background-color: #f7f5fa; + border-radius: 5px; +} + +/* All levels of nav */ +.bs-sidebar .nav > li > a { + display: block; + color: #716b7a; + padding: 5px 20px; +} + +.bs-sidebar .nav > li > a:hover, +.bs-sidebar .nav > li > a:focus { + text-decoration: none; + background-color: #e5e3e9; + border-right: 1px solid #dbd8e0; +} + +.bs-sidebar .nav > .active > a, +.bs-sidebar .nav > .active:hover > a, +.bs-sidebar .nav > .active:focus > a { + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-right: 1px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +.bs-sidebar .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + margin-bottom: 8px; +} + +.bs-sidebar .nav .nav > li > a { + padding-top: 3px; + padding-bottom: 3px; + padding-left: 30px; + font-size: 90%; +} + +/* Mobile down */ +@media only screen and (max-width: 600px) { + .panel { + padding: 0px !important; + } + pre.prettyprint { + width: calc(100vw - 80px); + } +} +@media only screen and (max-width: 992px) { + header { + width: 100% !important; + } +} +/* Tablets and up */ +@media screen and (min-width: 768px) { + + /* Show the docs nav */ + .bs-sidebar { + display: block; + } + + /* Show the hidden subnavs when space allows it */ + .bs-sidebar .nav > .active > ul { + display: block; + } +} + +/* Tablets/desktops and up */ +@media screen and (min-width: 992px) { + + /* Widen the fixed sidebar */ + .bs-sidebar.affix, + .bs-sidebar.affix-bottom { + width: 213px; + } + + .bs-sidebar.affix { + position: fixed; /* Undo the static from mobile-first approach */ + top: 60px; + } + + .bs-sidebar.affix-bottom { + position: absolute; /* Undo the static from mobile-first approach */ + } + + .bs-sidebar.affix-bottom .bs-sidenav, + .bs-sidebar.affix .bs-sidenav { + margin-top: 0; + margin-bottom: 0; + } +} + +/* Large desktops and up */ +@media screen and (min-width: 1200px) { + + /* Widen the fixed sidebar again */ + .bs-sidebar.affix-bottom, + .bs-sidebar.affix { + width: 270px; + } +} + +ul.side-nav.fixed li:hover,ul.side-nav.fixed li.active { + background-color: rgba(0, 0, 0, 0.05); +} + +.side-nav .collapsible-body li.active, .side-nav.fixed .collapsible-body li.active { + background-color: rgba(0, 0, 0, 0.05); +} + +/** Top Panel **/ +#customTable .top-panel { + background-color: white; + color: black; +} + +/** ToolPanel icons **/ +#customTable .top-panel .tool-panel i { + color: #e91e63; +} + +/** Hovering rows **/ +#customTable table tbody tr.data-row:hover { + background: rgba(33, 150, 243, 0.27); + color: #3f3f3f; +} + +/** Columns **/ +#customTable table tbody td:nth-child(3) { + background: #2196f3 !important; + color: #fff; + border-bottom: 2px solid #1976d2; +} + +/** Table Headers **/ +#customTable table thead tr th { + color: #1976d2; +} + +/** Scroll Navigated menu **/ +.table-of-contents.pinned { + top: 80px !important; +} + +.side-nav .collapsible-body li.active a, .side-nav.fixed .collapsible-body li.active a { + color: #000 !important; +} + +body { + background: #e9e9e9; +} + +main .panel { + margin-top: -40px; +} + +main .panel, main { + background: none; +} + +.code { + margin-bottom: 12px; +} + +.code > div:not(.empty-state) h4 { + font-size: 1.2em; + margin-top: 0px !important; +} + +.code div p.range-field { + margin-bottom: 0px; +} + +.code div p { + margin-bottom: 20px; +} + +.code { + padding: 20px; + margin-bottom: 12px; + background: #fff; + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); +} + +.TouchSplitter h4 { + padding-top: 100px; +} + +/** Set ids using widget.getElement().setId("idOfElement") */ +#closeButton { + margin: 15px 6px 6px; +} + +table tbody tr td img { + max-width: initial !important; +} + +.side-nav { + height: 100% !important; + box-sizing: border-box !important; + -moz-box-sizing: border-box !important; + -webkit-box-sizing: border-box !important +} + +pre { + padding-top: 20px; + white-space: pre; + background: #F3FBFF; + border: 1px solid rgba(51, 51, 51, .12); + font-size: 1.2em; + padding-left: 10px +} + +.tag { + color: #905 +} + +.attr { + color: #690 +} + +.comment { + color: #999 +} + +h1 { + font-size: 2em; + font-weight: 700; + color: #777; + margin: 40px 0 70px; + text-align: center +} + +.sendButton { + display: block; + font-size: 16pt +} + +.gwt-DialogBox { + width: 400px +} + +.dialogVPanel { + margin: 5px +} + +.serverResponseLabelError { + color: red +} + +#closeButton { + margin: 15px 6px 6px +} + +.gitter-open-chat-button, .gitter-open-chat-button:visited { + background: #2465c0 +} + +aside.gitter-chat-embed { + z-index: 9999 +} + +/** Carousel **/ +#demo-carousel-fixed { + bottom: 16%; + position: fixed; + text-align: center; + left: calc(50% - 90px); + z-index: 1; + z-index: 999; +} \ No newline at end of file diff --git a/src/main/webapp/CkanContentModeratorWidget.html b/src/main/webapp/CkanContentModeratorWidget.html index 5868fad..346b5b6 100644 --- a/src/main/webapp/CkanContentModeratorWidget.html +++ b/src/main/webapp/CkanContentModeratorWidget.html @@ -6,58 +6,47 @@ - - + + - - - - + + + + - - - - Web Application Starter Project + + + +Web Application Starter Project - - - - - - - + + + + + + + - - - - - - + + + + + + - - + + - - - -

Web Application Starter Project

- - - - - - - - - - - - -
Please enter your name:
- + + +
+ diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 98cafee..8603262 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,24 +1,23 @@ - + - + + ckanContentModeratorServlet + org.gcube.portlets.widgets.ckancontentmoderator.server.CkanContentModeratorServiceImpl + - - - greetServlet - org.gcube.portlets.widgets.ckancontentmoderator.server.GreetingServiceImpl - + + ckanContentModeratorServlet + /CkanContentModeratorWidget/ckanContentModeratorService + - - greetServlet - /CkanContentModeratorWidget/greet - - - - - CkanContentModeratorWidget.html - + + + CkanContentModeratorWidget.html + diff --git a/src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImplTest.java b/src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImplTest.java deleted file mode 100644 index 6b7c4ae..0000000 --- a/src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceAImplTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.gcube.portlets.widgets.ckancontentmoderator.server; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class CkanContentModeratorServiceAImplTest { - - @Test - public void test() { - fail("Not yet implemented"); - } - -} diff --git a/src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceTest.java b/src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceTest.java new file mode 100644 index 0000000..888e4e4 --- /dev/null +++ b/src/test/java/org/gcube/portlets/widgets/ckancontentmoderator/server/CkanContentModeratorServiceTest.java @@ -0,0 +1,53 @@ +package org.gcube.portlets.widgets.ckancontentmoderator.server; + +import static org.junit.Assert.fail; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.datacatalogue.utillibrary.gcat.GCatCaller; +import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorSystem; +import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; +import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants; +import org.slf4j.LoggerFactory; + +public class CkanContentModeratorServiceTest { + + //private String scope = "/gcube/devsec/devVRE"; + private String scope = "/pred4s/preprod/Dorne"; + private String testUser = "francesco.mangiacrapa"; + private String authorizationToken = ""; + + private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(CkanContentModeratorServiceTest.class); + + //@Test + public void test() { + fail("Not yet implemented"); + } + + //@Test + public void loadItemsForStatus() { + ScopeProvider.instance.set(scope); + SecurityTokenProvider.instance.set(authorizationToken); + ItemStatus itemStatus = ItemStatus.PENDING; + try { + CatalogueContentModeratorSystem cms = CatalogueCMSFactory.getFactory().getCMSPerScope(scope); + Map filters = new HashMap(1); + filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, "francesco.mangiacrapa@isti.cnr.it"); + List items = cms.getListItemsForStatus(itemStatus, 20, 0, filters, GCatCaller.DEFAULT_SORT_VALUE); + int i = 0; + System.out.println("Datasets with status "+itemStatus+" are: "+items.size()); + for (CkanDataset ckanDataset : items) { + System.out.println(i++ +")Read dataset: "+ckanDataset); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +}