task_21363 #1

Closed
francesco.mangiacrapa wants to merge 53 commits from task_21363 into master
100 changed files with 8764 additions and 403 deletions

View File

@ -11,17 +11,9 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
@ -29,10 +21,19 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes> <attributes>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="/home/francescomangiacrapa/.m2/repository/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar"/>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -1,4 +1,4 @@
eclipse.preferences.version=1 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 warSrcDir=src/main/webapp
warSrcDirIsOutput=false warSrcDirIsOutput=false

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
entryPointModules=

View File

@ -1,11 +1,16 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 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.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.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.compiler.source=1.8

View File

@ -1,11 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0"> <?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="ckan-content-moderator-widget-0.0.1-SNAPSHOT">
<wb-module deploy-name="ckan-content-moderator-widget-0.1.0-SNAPSHOT">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/> <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/> <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<dependent-module archiveName="catalogue-util-library-1.1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/catalogue-util-library/catalogue-util-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="context-root" value="ckan-content-moderator-widget"/> <property name="context-root" value="ckan-content-moderator-widget"/>
<property name="java-output-path" value="/ckan-content-moderator-widget/target/ckan-content-moderator-widget-0.0.1-SNAPSHOT/WEB-INF/classes"/>
<property name="java-output-path" value="/ckan-content-moderator-widget/target/ckan-content-moderator-widget-0.1.0-SNAPSHOT/WEB-INF/classes"/>
</wb-module> </wb-module>
</project-modules> </project-modules>

View File

@ -0,0 +1,7 @@
<root>
<facet id="jst.jaxrs">
<node name="libprov">
<attribute name="provider-id" value="jaxrs-no-op-library-provider"/>
</node>
</facet>
</root>

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<faceted-project> <faceted-project>
<fixed facet="wst.jsdt.web"/> <fixed facet="wst.jsdt.web"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.web" version="2.3"/> <installed facet="jst.web" version="2.3"/>
<installed facet="com.gwtplugins.gwt.facet" version="1.0"/> <installed facet="com.gwtplugins.gwt.facet" version="1.0"/>
<installed facet="wst.jsdt.web" version="1.0"/> <installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.jaxrs" version="2.0"/>
</faceted-project> </faceted-project>

View File

@ -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). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.0.0] - 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

152
pom.xml
View File

@ -14,7 +14,7 @@
<groupId>org.gcube.portlets.widgets</groupId> <groupId>org.gcube.portlets.widgets</groupId>
<artifactId>ckan-content-moderator-widget</artifactId> <artifactId>ckan-content-moderator-widget</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<name>gCube Ckan Content Moderator Widget</name> <name>gCube Ckan Content Moderator Widget</name>
<description> <description>
@ -30,12 +30,11 @@
<properties> <properties>
<!-- Convenience property to set the GWT version --> <!-- Convenience property to set the GWT version -->
<gwtVersion>2.7.0</gwtVersion> <gwtVersion>2.9.0</gwtVersion>
<!-- <webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory> -->
<distroDirectory>distro</distroDirectory> <distroDirectory>distro</distroDirectory>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
</properties> </properties>
@ -44,48 +43,123 @@
<dependency> <dependency>
<groupId>org.gcube.distribution</groupId> <groupId>org.gcube.distribution</groupId>
<artifactId>maven-portal-bom</artifactId> <artifactId>maven-portal-bom</artifactId>
<version>3.6.1-SNAPSHOT</version> <version>3.6.3-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt</artifactId>
<version>${gwtVersion}</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
<exclusions>
<exclusion>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<dependencies> <dependencies>
<!-- needed to compile/run in devMode with gwt > 2.7 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- needed to compile/run in devMode with gwt > 2.7 -->
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>com.google.gwt</groupId> <groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId> <artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version> <version>${gwtVersion}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>${gwtVersion}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>com.github.gwtbootstrap</groupId> <groupId>com.github.gwtbootstrap</groupId>
<artifactId>gwt-bootstrap</artifactId> <artifactId>gwt-bootstrap</artifactId>
<version>2.3.2.0</version> <version>2.3.2.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
</dependency>
<!-- FWS -->
<dependency>
<groupId>org.gcube.resources.discovery</groupId>
<artifactId>ic-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.gcube.datacatalogue</groupId> <groupId>org.gcube.datacatalogue</groupId>
<artifactId>catalogue-util-library</artifactId> <artifactId>catalogue-util-library</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0)</version> <version>[1.0.0-SNAPSHOT, 2.0.0)</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- PORTAL MANAGER -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.gcube.common.portal</groupId>
<artifactId>slf4j-log4j12</artifactId> <artifactId>portal-manager</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>portal-service</artifactId>
<scope>provided</scope>
</dependency>
<!-- User Management Core -->
<dependency>
<groupId>org.gcube.dvos</groupId>
<artifactId>usermanagement-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
@ -95,8 +169,6 @@
</dependencies> </dependencies>
<build> <build>
<!-- Generate compiled stuff in the folder used for developing mode -->
<!-- <outputDirectory>${webappDirectory}/WEB-INF/classes</outputDirectory> -->
<resources> <resources>
<resource> <resource>
<directory>src/main/java</directory> <directory>src/main/java</directory>
@ -107,13 +179,11 @@
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<includes> <includes>
<include>**/*.*</include> <include>**/*</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>
<plugins> <plugins>
<!-- GWT Maven Plugin --> <!-- GWT Maven Plugin -->
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
@ -123,22 +193,18 @@
<execution> <execution>
<goals> <goals>
<goal>compile</goal> <goal>compile</goal>
<goal>test</goal> <!-- <goal>run</goal> -->
</goals> </goals>
</execution> </execution>
</executions> </executions>
<!-- Plugin configuration. There are many available options, see gwt-maven-plugin
documentation at codehaus.org -->
<configuration>
<runTarget>CkanContentModeratorWidget.html</runTarget>
<modules>
<module>org.gcube.portlets.widgets.ckancontentmoderator.CkanContentModeratorWidget</module>
</modules>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin> </plugin>
<!-- SA Plugin --> <!-- SA Plugin -->
<plugin> <plugin>
@ -159,7 +225,33 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-profile</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<directory>${distroDirectory}</directory>
<filtering>true</filtering>
<includes>
<include>profile.xml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='CkanContentModeratorWidget'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<inherits
name="org.gcube.datacatalogue.utillibrary.CkanUtilLibrary" />
<inherits name="com.github.gwtbootstrap.Bootstrap" />
<!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<!-- <entry-point class='org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorWidget'
/> -->
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
<stylesheet src='content-moderator-widget.css' />
</module>

View File

@ -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;
}
}

View File

@ -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<Boolean>() {
@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<Boolean>() {
@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<Boolean>() {
@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;
}
}

View File

@ -2,28 +2,135 @@ package org.gcube.portlets.widgets.ckancontentmoderator.client;
import java.util.List; import java.util.List;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; import org.gcube.datacatalogue.utillibrary.shared.ItemStatus;
import org.gcube.portlets.widgets.ckancontentmoderator.server.ContentModeratorSystem.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.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; 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 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<String> 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<String> itemNames, boolean permanentlyDelete, String reasonMsg)
throws Exception;
public List<CkanDataset> getListItemsForStatus(ItemStatus theStatus); /**
* Permanently delete.
*
* @param itemNames the item names
* @return the operation report
* @throws Exception the exception
*/
public OperationReport permanentlyDelete(List<String> 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<CatalogueDataset> 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<String> 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;
} }

View File

@ -2,23 +2,128 @@ package org.gcube.portlets.widgets.ckancontentmoderator.client;
import java.util.List; import java.util.List;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; import org.gcube.datacatalogue.utillibrary.shared.ItemStatus;
import org.gcube.portlets.widgets.ckancontentmoderator.server.ContentModeratorSystem.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; 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 { public interface CkanContentModeratorServiceAsync {
void isContentModeratorEnabled(AsyncCallback<Boolean> 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<String> itemNames, boolean permanentlyDelete, String reasonMsg,
AsyncCallback<OperationReport> callback);
void approveItem(String itemId, AsyncCallback<Void> 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<List<CatalogueDataset>> callback);
void getListItemsForStatus(ItemStatus theStatus, AsyncCallback<List<CkanDataset>> 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<SearchedData> asyncCallback);
void permanentlyDelete(String itemId, AsyncCallback<Void> callback); /**
* Approve item.
*
* @param itemNames the item names
* @param moderatorMessage the moderator message
* @param callback the callback
*/
void approveItem(List<String> itemNames, String moderatorMessage, AsyncCallback<OperationReport> callback);
void rejectItem(String itemId, boolean permanentlyDelete, String reasonMsg, AsyncCallback<Void> callback); /**
* Permanently delete.
*
* @param itemNames the item names
* @param callback the callback
*/
void permanentlyDelete(List<String> itemNames, AsyncCallback<OperationReport> callback);
void setStatus(String itemId, ItemStatus theStatus, AsyncCallback<Void> callback); /**
* Sets the status.
*
* @param theStatus the the status
* @param itemNames the item names
* @param callback the callback
*/
void setStatus(ItemStatus theStatus, List<String> itemNames, AsyncCallback<OperationReport> 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<ModerationUserRole> callback);
/**
* Checks if is moderation enabled.
*
* @param reloadConfig the reload config
* @param callback the callback
*/
void isModerationEnabled(boolean reloadConfig, AsyncCallback<Boolean> callback);
/**
* Checks if is moderator role assigned.
*
* @param callback the callback
*/
void isModeratorRoleAssigned(AsyncCallback<Boolean> 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<Boolean> 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<CatalogueDataset> callback);
} }

View File

@ -1,53 +1,93 @@
package org.gcube.portlets.widgets.ckancontentmoderator.client; 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 com.github.gwtbootstrap.client.ui.Modal;
import org.gcube.portlets.widgets.ckancontentmoderator.server.ContentModeratorSystem.ItemStatus; import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
/** /**
* Entry point classes define <code>onModuleLoad()</code>. * The Class CkanContentModeratorWidget.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Apr 7, 2022
*/ */
public class CkanContentModeratorWidget implements EntryPoint { public class CkanContentModeratorWidget {
/**
* 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.";
/** private MainPanel mainPanel = new MainPanel();
* Create a remote service proxy to talk to the server-side Greeting service.
*/
private final CkanContentModeratorServiceAsync greetingService = GWT.create(CkanContentModeratorService.class);
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);
/** boolean isModeratorRoleAssigned = false;
* This is the entry point method. try {
*/ isModeratorRoleAssigned = ccux.getModeratorCheckConfig().isModeratorRoleAssigned();
public void onModuleLoad() { } catch (Exception e) {
greetingService.getListItemsForStatus(ItemStatus.PENDING, new AsyncCallback<List<CkanDataset>>() {
@Override
public void onSuccess(List<CkanDataset> result) {
// TODO Auto-generated method stub
} }
@Override if (isModeratorRoleAssigned) {
public void onFailure(Throwable caught) { mainPanel.setLoggedLabelText("Logged in as Moderator");
// TODO Auto-generated method stub
} }
}); }
}
/**
* 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();
}
} }

View File

@ -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<String, CkanShowItemFrame> mapOfItemsTabDisplayed = new HashMap<String, CkanShowItemFrame>();
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<ItemFieldDV> 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<CatalogueDataset>() {
@Override
public void onSuccess(CatalogueDataset result) {
GWT.log("CatalogueDataset read is: " + result);
if (result != null) {
eventBus.fireEvent(new ShowItemEvent<CatalogueDataset>(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<ItemFieldDV> displayFieldsToItemFields(DISPLAY_FIELD[] sortByFields) {
List<ItemFieldDV> listSortByIF = new ArrayList<ItemFieldDV>(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 <T> void onClick(ClickItemEvent<T> clickItemEvent) {
if (clickItemEvent.getSelectItems() != null) {
List<T> 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 <T> void onShowItemClicked(ShowItemEvent<T> showItemEvent) {
GWT.log("onShowItemClicked fired");
if (showItemEvent.getSelectItems() != null) {
List<T> 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 <T> void onValueChanged(CheckBoxSelectIemsEvent<T> onValueChangedEvent) {
howeView.markItemsAsChecked(onValueChangedEvent.isChecked(), true);
}
});
eventBus.addHandler(TableRangeViewChangedEvent.TYPE, new TableRangeViewChangedEventHandler() {
@Override
public <T> void onRangeChanged(TableRangeViewChangedEvent<T> 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;
}
}

View File

@ -0,0 +1,22 @@
//package org.gcube.portlets.widgets.ckancontentmoderator.client;
//
//import com.google.gwt.core.client.EntryPoint;
//
///**
// * Entry point classes define <code>onModuleLoad()</code>.
// */
//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() {
// }
//
//}

View File

@ -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();
}
}

View File

@ -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 };
}

View File

@ -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 <T> the generic type
*/
public class CheckBoxSelectIemsEvent<T> extends GwtEvent<CheckBoxSelectIemsEventHandler> {
public static Type<CheckBoxSelectIemsEventHandler> TYPE = new Type<CheckBoxSelectIemsEventHandler>();
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<CheckBoxSelectIemsEventHandler> 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;
}
}

View File

@ -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 <T> the generic type
* @param onValueChangedEvent the on value changed event
*/
<T> void onValueChanged(CheckBoxSelectIemsEvent<T> onValueChangedEvent);
}

View File

@ -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 <T> the generic type
*/
public class ClickItemEvent<T> extends GwtEvent<ClickItemEventHandler> {
public static Type<ClickItemEventHandler> TYPE = new Type<ClickItemEventHandler>();
private List<T> selectItems;
/**
* Instantiates a new click item event.
*
* @param selectItems the select items
*/
public ClickItemEvent(List<T> 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<ClickItemEventHandler> 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<T> getSelectItems() {
return selectItems;
}
}

View File

@ -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 <T> the generic type
* @param moreInfoShowEvent the more info show event
*/
<T> void onClick(ClickItemEvent<T> moreInfoShowEvent);
}

View File

@ -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<CloseAllTabsEventHandler> {
public static Type<CloseAllTabsEventHandler> TYPE = new Type<CloseAllTabsEventHandler>();
/**
* Instantiates a new close all tabs event.
*/
public CloseAllTabsEvent() {
}
/**
* Gets the associated type.
*
* @return the associated type
*/
@Override
public Type<CloseAllTabsEventHandler> getAssociatedType() {
return TYPE;
}
/**
* Dispatch.
*
* @param handler the handler
*/
@Override
protected void dispatch(CloseAllTabsEventHandler handler) {
handler.onClick(this);
}
}

View File

@ -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);
}

View File

@ -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<IFrameInstanciedEventHandler> {
public static Type<IFrameInstanciedEventHandler> TYPE = new Type<IFrameInstanciedEventHandler>();
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<IFrameInstanciedEventHandler> 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;
}
}

View File

@ -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);
}

View File

@ -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<SelectItemsWithItemStatusEventHandler> {
public static Type<SelectItemsWithItemStatusEventHandler> TYPE = new Type<SelectItemsWithItemStatusEventHandler>();
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<SelectItemsWithItemStatusEventHandler> 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;
}
}

View File

@ -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);
}

View File

@ -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 <T> the generic type
*/
public class ShowItemEvent<T> extends GwtEvent<ShowItemEventHandler> {
public static Type<ShowItemEventHandler> TYPE = new Type<ShowItemEventHandler>();
private List<T> 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<T> 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<ShowItemEventHandler> 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<T> getSelectItems() {
return selectItems;
}
/**
* Checks if is focus on displaying.
*
* @return true, if is focus on displaying
*/
public boolean isFocusOnDisplaying() {
return focusOnDisplaying;
}
}

View File

@ -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 <T> the generic type
* @param showItemEvent the show item event
*/
<T> void onShowItemClicked(ShowItemEvent<T> showItemEvent);
}

View File

@ -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<ShowMessageEventHandler> {
public static Type<ShowMessageEventHandler> TYPE = new Type<ShowMessageEventHandler>();
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<ShowMessageEventHandler> 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;
}
}

View File

@ -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);
}

View File

@ -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 <T> the generic type
*/
public class TableRangeViewChangedEvent<T> extends GwtEvent<TableRangeViewChangedEventHandler> {
public static Type<TableRangeViewChangedEventHandler> TYPE = new Type<TableRangeViewChangedEventHandler>();
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<TableRangeViewChangedEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(TableRangeViewChangedEventHandler handler) {
handler.onRangeChanged(this);
}
public int getStartIndex() {
return startIndex;
}
public int getLimitIndex() {
return limitIndex;
}
}

View File

@ -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 {
<T> void onRangeChanged(TableRangeViewChangedEvent<T> tableRangeViewChangedEvent);
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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());
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

View File

@ -0,0 +1,11 @@
.table-container {
width: 90% !important;
/*width: 700px;*/
margin: auto !important;
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12);
}
.active-header {
background-color: #e1f5fe !important;
color: #2196F3 !important;
border-bottom: none !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -0,0 +1,73 @@
/**
*
*/
package org.gcube.portlets.widgets.ckancontentmoderator.client.ui;
import com.github.gwtbootstrap.client.ui.FluidRow;
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.Widget;
/**
* The Class BaseViewTemplate.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* Feb 19, 2015
*/
public class BaseViewTemplate extends Composite{
@UiField
FluidRow top_container;
@UiField
FluidRow base_container;
@UiField
FluidRow bottom_container;
private static BaseViewTemplateUiBinder uiBinder = GWT.create(BaseViewTemplateUiBinder.class);
/**
* The Interface BaseViewTemplateUiBinder.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* Feb 19, 2015
*/
interface BaseViewTemplateUiBinder extends UiBinder<Widget, BaseViewTemplate> {
}
/**
* 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);
}
}

View File

@ -0,0 +1,13 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<g:FlowPanel>
<b:FluidRow ui:field="top_container">
</b:FluidRow>
<b:FluidRow ui:field="base_container">
</b:FluidRow>
<b:FluidRow ui:field="bottom_container">
</b:FluidRow>
</g:FlowPanel>
</ui:UiBinder>

View File

@ -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<Widget, CkanShowItemFrame> {
}
/**
* 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);
}
}

View File

@ -0,0 +1,22 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.important {
font-weight: bold;
}
.as_simple_link {
background: none;
border: none;
}
</ui:style>
<g:HTMLPanel>
<b:AlertBlock close="false" addStyleNames="as_simple_link" ui:field="alertBlockNav">
<b:Button ui:field="button_reload" title="Reload the page" type="LINK">Reload</b:Button>
</b:AlertBlock>
<g:HTMLPanel ui:field="panel_container">
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -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<CatalogueDataset> itemsTable;
private MyCustomDataProvider<CatalogueDataset> dataProvider = new MyCustomDataProvider<CatalogueDataset>();
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<CatalogueDataset>(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<CatalogueDataset> getAsycnDataProvider() {
return (AsyncDataProvider<CatalogueDataset>) getCellTable().getDataProvider();
}
/**
* Gets the cell tale.
*
* @return the cell tale
*/
private SortedCellTable<CatalogueDataset> 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<? super CatalogueDataset> sm = getCellTable().getSelectionModel();
if (sm instanceof SingleSelectionModel) {
SingleSelectionModel<CatalogueDataset> ssm = (SingleSelectionModel<CatalogueDataset>) sm;
ssm.clear();
} else if (sm instanceof MultiSelectionModel) {
MultiSelectionModel<CatalogueDataset> msm = (MultiSelectionModel<CatalogueDataset>) sm;
msm.clear();
}
getAsycnDataProvider().updateRowCount((int) result.getTotalItems(), true);
getAsycnDataProvider().updateRowData(result.getClientStartIndex(), result.getData());
/*
* MOCK-UP int total = 35; List<CatalogueDataset> listData = new
* ArrayList<CatalogueDataset>(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<SearchedData>() {
@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<CatalogueDataset> 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<CatalogueDataset> getSelectItems() {
return itemsTable.getSelectedItems();
}
/**
* A custom {@link AsyncDataProvider}.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jul 5, 2017
* @param <T> the generic type
*/
public class MyCustomDataProvider<T> extends AsyncDataProvider<T> {
/**
* {@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<T> 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<T>(start, length));
}
}
public void hideSelectableRow(boolean bool) {
Element tableEl = itemsTable.getCellTable().getElement();
if (bool)
tableEl.addClassName("hide_checkbox");
else
tableEl.removeClassName("hide_checkbox");
}
}

View File

@ -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;
}
}

View File

@ -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<Widget, ContentModeratorToolbar> {
}
@UiField
Dropdown dropdownSelectStatus;
@UiField
Dropdown dropdownSortBy;
@UiField
NavLink closeAllTabs;
@UiField
Label statusInfo;
@UiField
Label orderInfo;
private HandlerManager eventBus;
private ItemStatus activeStatus;
private List<ItemFieldDV> sortByList;
private ItemFieldDV activeSortBy;
public ContentModeratorToolbar(HandlerManager eventBus, ItemStatus status, List<ItemFieldDV> 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;
}
}

View File

@ -0,0 +1,44 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.important {
font-weight: bold;
}
.margin-top-12 {
margin-top: 12px;
}
.margin-left-20 {
margin-left: 20px;
}
</ui:style>
<g:HTMLPanel>
<b:Navbar>
<b:Nav>
<b:Dropdown text="Select Items with status..."
ui:field="dropdownSelectStatus">
</b:Dropdown>
</b:Nav>
<b:Nav>
<b:Label ui:field="statusInfo" type="INFO"
addStyleNames="{style.margin-top-12}"></b:Label>
</b:Nav>
<b:Nav>
<b:Dropdown text="Order By" ui:field="dropdownSortBy"
addStyleNames="{style.margin-left-20}">
</b:Dropdown>
</b:Nav>
<b:Nav>
<b:Label ui:field="orderInfo" type="DEFAULT" addStyleNames="{style.margin-top-12}"></b:Label>
</b:Nav>
<b:Nav alignment="RIGHT">
<b:NavLink ui:field="closeAllTabs" visible="false">Close All Tabs
</b:NavLink>
</b:Nav>
</b:Navbar>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -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<Widget, DoActionCMSView> {
}
@UiField
HTML htmlDisplayMessage;
@UiField
CheckBox checkBoxPermDelete;
@UiField
TextArea txtMsgReason;
@UiField
Button buttonActionConfirmYES;
@UiField
Button buttonActionConfirmNO;
@UiField
AlertBlock alertBlockDoAction;
@UiField
HelpBlock helpPermDelete;
private List<CatalogueDataset> 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<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
helpPermDelete.setVisible(false);
if(event.getValue()) {
helpPermDelete.setVisible(true);
}
}
});
}
public void updateStatus(ItemStatus fromStatus, ItemStatus toStatus, List<CatalogueDataset> 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 <b>" + fromStatus.getLabel() + "</b> to <b>" + toStatus.getLabel() + "</b>. 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<CatalogueDataset> 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<CatalogueDataset> 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;
}
}

View File

@ -0,0 +1,46 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.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;
}
</ui:style>
<g:HTMLPanel>
<b:AlertBlock ui:field="alertBlockDoAction">
<g:HTML ui:field="htmlDisplayMessage"
addStyleNames="{style.fontsize-16}"></g:HTML>
<b:Form type="VERTICAL" addStyleNames="{style.margin-top-15}">
<b:TextArea placeholder="Rejecting reason..." addStyleNames="{style.text-area-message}"
ui:field="txtMsgReason" />
<b:CheckBox ui:field="checkBoxPermDelete"
title="Permanently removes the selected item/s from Catalogue">Permanently Delete</b:CheckBox>
<b:HelpBlock ui:field="helpPermDelete" visible="false">This operation cannot be undone. The selected items will be permantently deleted from Catalogue</b:HelpBlock>
<b:Paragraph addStyleNames="{style.margin-top-15}">
<b:Button type="PRIMARY" ui:field="buttonActionConfirmYES"
addStyleNames="{style.margin-left-10}">YES</b:Button>
<b:Button ui:field="buttonActionConfirmNO"
addStyleNames="{style.margin-left-10}">NO</b:Button>
</b:Paragraph>
</b:Form>
</b:AlertBlock>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -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<NavLink> setStatusOptions = new ArrayList<NavLink>();
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<Widget, HomeView> {
}
/**
* 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<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
GWT.log("Is checked: " + cbSelectAll.getValue());
eventBus.fireEvent(new CheckBoxSelectIemsEvent<CatalogueDataset>(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<CatalogueDataset> selectedItems = paginatedView.getSelectItems();
doActionCMS.updateStatus(fromStatus, toStatus, selectedItems);
final AlertBlock newAlertBlock = doActionCMS.getAlertBlockDoAction();
newAlertBlock.addClosedHandler(new ClosedHandler<AlertBase>() {
@Override
public void onClosed(ClosedEvent<AlertBase> 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<CatalogueDataset> selectedItems = paginatedView.getSelectItems();
doActionCMS.permanentlyDelete(selectedItems);
final AlertBlock newAlertBlock = doActionCMS.getAlertBlockDoAction();
newAlertBlock.addClosedHandler(new ClosedHandler<AlertBase>() {
@Override
public void onClosed(ClosedEvent<AlertBase> event) {
confirmPanelContainer.clear();
}
});
Button buttActionConfirmYes = doActionCMS.getButtonActionConfirmYES();
buttActionConfirmYes.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
confirmPanelContainer.clear();
showActionLoader(true);
List<String> listDatasetNames = UtilFunct.toListDatasetNames(doActionCMS.getListSelectItems());
CkanContentModeratorWidgetController.contentModeratorService.permanentlyDelete(listDatasetNames,
new AsyncCallback<OperationReport>() {
@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 += " <br/>Error occurred on deleting permanently " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> " + 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<String> listDatasetNames = UtilFunct.toListDatasetNames(doActionCMSView.getListSelectItems());
switch (toStatus) {
case PENDING:
CkanContentModeratorWidgetController.contentModeratorService.setStatus(toStatus, listDatasetNames,
new AsyncCallback<OperationReport>() {
@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 += " <br/>Error occurred on updating status to " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> " + 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<OperationReport>() {
@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 += " <br/>Error occurred on approving " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> " + 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<OperationReport>() {
@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 += " <br/>Error occurred on rejecting " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> " + 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;
}
}

View File

@ -0,0 +1,61 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.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;
}
</ui:style>
<g:HTMLPanel>
<b:Heading ui:field="pageHeader" size="4"
addStyleNames="{style.headinghome}">Items with status: </b:Heading>
<g:HorizontalPanel
addStyleNames="{style.font-size-14}" ui:field="updateStatusActionPanel">
<b:CheckBox ui:field="cbSelectAll"
addStyleNames="{style.margin-left-5}"></b:CheckBox>
<b:Nav>
<b:Dropdown text="Update status as..."
ui:field="dropdownSetStatus" addStyleNames="{style.margin-left-20}">
</b:Dropdown>
</b:Nav>
<b:Button ui:field="permanentlyDelete"
addStyleNames="{style.button-style}" type="LINK" visible="false">Permanently
Delete</b:Button>
</g:HorizontalPanel>
<g:HTMLPanel ui:field="actionLoaderPanel"></g:HTMLPanel>
<g:HTMLPanel ui:field="confirmPanel"></g:HTMLPanel>
<g:HTMLPanel ui:field="panelContainer"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -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<Widget, MainPanel> {
}
@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;
}
}

View File

@ -0,0 +1,19 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.important {
font-weight: bold;
}
.margin-bottom-2 {
margin-bottom: 2px;
}
</ui:style>
<g:HTMLPanel ui:field="mainPanel">
<b:Label ui:field="labelLoggedIn"
addStyleNames="{style.margin-bottom-2}"></b:Label>
<g:HTMLPanel ui:field="mainPanelContainer"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -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<Widget, MainTabPanel> {
}
private List<Tab> results = new ArrayList<Tab>();
@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);)
}
}

View File

@ -0,0 +1,16 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel>
<b:TabPanel tabPosition="above" ui:field="mainTabPanel">
<b:Tab icon="HOME" heading="Home" active="true" ui:field="homeTab">
</b:Tab>
</b:TabPanel>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -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 <T> the generic type
* @return the selected items
*/
<T> List<T> getSelectedItems();
}

View File

@ -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 <T> the generic type
*/
public abstract class AbstractItemsCellTable<T> {
protected SortedCellTable<T> sortedCellTable;
protected T itemContextMenu = null;
protected boolean fireEventOnClick = true;
protected SelectionModel<T> 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<T> 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<T> dataProvider,
SelectionModel<T> selectionModel, int pageSize) {
this.eventBus = eventBus;
this.fireEventOnClick = fireOnClick;
this.theSelectionModel = selectionModel;
sortedCellTable = new SortedCellTable<T>(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<T> checkBoxManager = DefaultSelectionEventManager.<T> createCheckboxManager();
sortedCellTable.setSelectionModel(theSelectionModel,checkBoxManager);
theSelectionModel.addSelectionChangeHandler(new Handler() {
@Override
public void onSelectionChange(final SelectionChangeEvent event) {
if (theSelectionModel instanceof SingleSelectionModel) {
SingleSelectionModel<T> ssm = (SingleSelectionModel<T>) theSelectionModel;
final T selectedObject = ssm.getSelectedObject();
if (selectedObject != null) {
GWT.log("Clicked: " + selectedObject);
// selectedItem(selectedObject);
if (fireEventOnClick)
AbstractItemsCellTable.this.eventBus.fireEvent(new ClickItemEvent<T>(Arrays.asList(selectedObject)));
}
}else if (theSelectionModel instanceof MultiSelectionModel) {
Set<T> selected = ((MultiSelectionModel<T>) theSelectionModel).getSelectedSet();
GWT.log("Selected are:" +selected);
if (fireEventOnClick)
AbstractItemsCellTable.this.eventBus.fireEvent(new ClickItemEvent<T>(new ArrayList<T>(selected)));
}
}
});
sortedCellTable.addDomHandler(new DoubleClickHandler() {
@Override
public void onDoubleClick(final DoubleClickEvent event) {
if (theSelectionModel instanceof SingleSelectionModel) {
SingleSelectionModel<T> ssm = (SingleSelectionModel<T>) 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<T>(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<T>(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<T> items, boolean removeOldItems) {
//
// if (removeOldItems) {
// if (theSelectionModel instanceof SingleSelectionModel) {
// ((SingleSelectionModel<T>) theSelectionModel).clear();
// } else if (theSelectionModel instanceof MultiSelectionModel) {
// ((MultiSelectionModel<T>) theSelectionModel).clear();
// }
// }
// sortedCellTable.setList(items);
// sortedCellTable.setPageSize(items.size() + 1);
// sortedCellTable.redraw();
// }
/**
* Gets the cell tables.
*
* @return the cell tables
*/
public SortedCellTable<T> 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<T> items) {
AbstractDataProvider<T> dataProvider = sortedCellTable.getDataProvider();
if (dataProvider instanceof ListDataProvider) {
List<T> ldp = ((ListDataProvider<T>) 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 ???
}
}
}

View File

@ -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 <T> the generic type
*/
public class ItemsTable<T extends CatalogueDataset> extends AbstractItemsCellTable<T> implements SelectionItems {
private TextColumn<T> type;
private TextColumn<T> name;
private TextColumn<T> title;
private TextColumn<T> author;
public DateTimeFormat dtformat = DateTimeFormat.getFormat("dd MMM hh:mm aaa yyyy");
public ImageResource info = ContentModeratorWidgetResources.ICONS.infoSquare();
private AbstractDataProvider<T> dataProvider;
private List<DISPLAY_FIELD> displayFields;
private Column<T, Date> createdColumn;
private Column<T, Date> 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<T> 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<T> dataProvider) {
this.dataProvider = dataProvider;
this.theSelectionModel = new MultiSelectionModel<T>();
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<T, Boolean> checkColumn = new Column<T, Boolean>(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<T, String> showdItemColumn = new Column<T, String>(previewButton) {
public String getValue(T object) {
return "Show";
}
};
showdItemColumn.setFieldUpdater(new FieldUpdater<T, String>() {
@Override
public void update(int index, T object, String value) {
GWT.log("clicked show");
eventBus.fireEvent(new ShowItemEvent<T>(Arrays.asList(object), false));
}
});
sortedCellTable.addColumn(showdItemColumn);
sortedCellTable.setColumnWidth(showdItemColumn, 80, Unit.PX);
if (this.displayFields.contains(DISPLAY_FIELD.NAME)) {
// NAME
name = new TextColumn<T>() {
@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("<div title=\"" + ((CatalogueDataset) object).getName() + "\">");
super.render(context, object, sb);
sb.appendHtmlConstant("</div>");
};
};
sortedCellTable.addColumn(name, "Name", true);
if (!isAsyncronusTable) {
Comparator<T> c = new Comparator<T>() {
@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<T>() {
@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<T> c = new Comparator<T>() {
@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<T>() {
@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<T> c = new Comparator<T>() {
@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<T, Date>(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<T> c = new Comparator<T>() {
@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<T, Date>(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<T> c = new Comparator<T>() {
@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<T>() {
@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("<div title=\"" + type + "\">");
super.render(context, object, sb);
sb.appendHtmlConstant("</div>");
};
};
sortedCellTable.addColumn(type, "Type", true);
if (!isAsyncronusTable) {
Comparator<T> c = new Comparator<T>() {
@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 <code>true</code> for ascending icon, <code>false</code>
* for descending icon
*/
public void setSortedColumn(int columnIndex, boolean ascending) {
GWT.log("Column index: " + columnIndex);
GWT.log("ascending: " + ascending);
Column<T, ?> 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<DISPLAY_FIELD> 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<T> getSelectedItems() {
if (theSelectionModel instanceof SingleSelectionModel) {
T selected = ((SingleSelectionModel<T>) theSelectionModel).getSelectedObject();
if (selected != null) {
return Arrays.asList(selected);
}
} else if (theSelectionModel instanceof MultiSelectionModel) {
Set<T> selected = ((MultiSelectionModel<T>) theSelectionModel).getSelectedSet();
if (selected != null) {
return new ArrayList<T>(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<T> getSelectionModel() {
return theSelectionModel;
}
}

View File

@ -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 <T> the generic type
* @param <C> the generic type
*/
public abstract class MyToolTipColumn<T, C> extends Column<T, C> {
/**
* 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("<div title=\"{0}\">")
SafeHtml startToolTip(String toolTipText);
/**
* End tool tip.
*
* @return the safe html
*/
@Template("</div>")
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<C> 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());
}
}

View File

@ -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 <T> the generic type
*/
public class SortedCellTable<T> extends CellTable<T> {
/**
* To keep track of the currently sorted column
*/
private Column<T, ?> currentlySortedColumn;
/**
* Tells us which way to sort a column initially
*/
private Map<Column<T, ?>, Boolean> defaultSortOrderMap = new HashMap<Column<T, ?>, Boolean>();
/**
* Comparators associated with their columns
*/
private Map<Column<T, ?>, Comparator<T>> comparators = new HashMap<Column<T, ?>, Comparator<T>>();
/**
* Column to sort when the data provider's list is refreshed using
* {@link SortedCellTable#setList(List)}
*/
private Column<T, ?> initialSortColumn;
/**
* Data provider we will attach to this table
*/
private AbstractDataProvider<T> 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<T> dataProv) {
super(pageSize, CellTableResources.INSTANCE);
this.dataProvider = dataProv;
if (this.dataProvider instanceof ListDataProvider) {
ListDataProvider<T> listDataProvider = (ListDataProvider<T>) this.dataProvider;
ListHandler<T> listSortHandler = new ListHandler<T>((listDataProvider).getList()) {
@Override
public void onColumnSort(ColumnSortEvent event) {
@SuppressWarnings("unchecked")
Column<T, ?> column = (Column<T, ?>) 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<T> 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<T>() {
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<T, ?> column, Comparator<T> 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<T, ?> column = (Column<T, ?>) 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<T> 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<T>() {
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<T, ?> 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<T, ?> 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<T, ?> 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<T, ?> 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<T, ?> column, Comparator<T> 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<T, ?> 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<T> list) {
if (dataProvider instanceof ListDataProvider) {
List<T> 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<T>() {
@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<T> getDataProvider() {
return dataProvider;
}
}

View File

@ -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 <code>true</code> 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 <code>true</code> if the widget should be animated.
* @param dynamicSafe <code>true</code> 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();
}
}
});
}
}

View File

@ -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);
}
}

View File

@ -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<String> toListDatasetNames(List<CatalogueDataset> itemsSelected) {
List<String> listDatasetNames = new ArrayList<String>(itemsSelected.size());
for (CatalogueDataset catalogueDataset : itemsSelected) {
listDatasetNames.add(catalogueDataset.getName());
}
return listDatasetNames;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}-*/;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<CkanDataset, CatalogueDataset> toCatalogueDataset = new Function<CkanDataset, CatalogueDataset>() {
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<String, String> 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;
}
};
}

View File

@ -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<String, CacheBean> 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<String, CacheBean>();
}
/**
* 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());
}
}

View File

@ -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<CkanDataset> 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
}
}

View File

@ -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<String, String> params = new HashMap<String, String>(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<String> 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<CMSUserRole> 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<CatalogueDataset> 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<CatalogueDataset> datasetList = null;
try {
String scope = setContexts();
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
Map<String, String> filters = null;
if (restrictedToLoggedInUser) {
filters = new HashMap<String, String>(1);
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR);
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails);
}
List<CkanDataset> datasets = cmsInstance.getListItemsForStatus(theStatus, limit, offset, filters,
sortForField);
if (datasets != null) {
int size = datasets.size();
datasetList = new ArrayList<CatalogueDataset>(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<String> 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<String, String> errorMapItems = new HashMap<String, String>();
List<String> changedStatusListItems = new ArrayList<String>();
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<String> 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<String, String> errorMapItems = new HashMap<String, String>();
List<String> approvedListItems = new ArrayList<String>();
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<String> 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<String, String> errorMapItems = new HashMap<String, String>();
List<String> passedListItems = new ArrayList<String>();
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<String> 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<String, String> errorMapItems = new HashMap<String, String>();
List<String> passedListItems = new ArrayList<String>();
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<String, String> filters = null;
if (restrictedToLoggedInUser) {
filters = new HashMap<String, String>(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<CatalogueDataset> listDataset = new ArrayList<CatalogueDataset>();
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;
}
}

View File

@ -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<Email> listServerEmails = user.getEmailAddresses();
LOG.debug("List server mails: {}", listServerEmails);
List<String> emailsAddresses = new ArrayList<String>();
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;
}
}

View File

@ -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<CkanDataset> 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;
}
}
}

View File

@ -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<CMSUserRole> 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<CMSUserRole> 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<CMSUserRole> 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<GCubeRole> roles = roleManager.listRolesByUserAndGroup(user.getUserId(), groupId);
List<CMSUserRole> toReturn = new ArrayList<CMSUserRole>();
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;
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -1,42 +0,0 @@
package org.gcube.portlets.widgets.ckancontentmoderator.shared;
/**
* <p>
* FieldVerifier validates that the name the user enters is valid.
* </p>
* <p>
* This class is in the <code>shared</code> 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.
* </p>
* <p>
* 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.
* </p>
*/
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;
}
}

View File

@ -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<String> 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<String> 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<String> 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();
}
}

View File

@ -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<CMSUserRole> roles;
/**
* Instantiates a new moderation user role.
*/
public ModerationUserRole() {
}
public ModerationUserRole(String username, List<CMSUserRole> roles) {
super();
this.username = username;
this.roles = roles;
}
public String getUsername() {
return username;
}
public List<CMSUserRole> 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();
}
}

View File

@ -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<String, String> errorMapItems = new HashMap<String, String>();
private List<String> passedListItems = new ArrayList<String>();
public OperationReport() {
}
public OperationReport(String operationType, List<String> passedListItems, Map<String, String> errorMapItems) {
this.operationType = operationType;
this.errorMapItems = errorMapItems;
this.passedListItems = passedListItems;
}
public String getOperationType() {
return operationType;
}
public Map<String, String> getErrorMapItems() {
return errorMapItems;
}
public List<String> getPassedListItems() {
return passedListItems;
}
public void setOperationType(String operationType) {
this.operationType = operationType;
}
public void setErrorMapItems(Map<String, String> errorMapItems) {
this.errorMapItems = errorMapItems;
}
public void setPassedListItems(List<String> 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();
}
}

View File

@ -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<CatalogueDataset> 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<CatalogueDataset> 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<CatalogueDataset> 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();
}
}

View File

@ -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<ItemFieldDV> orderByFields;
private ORDER order = ORDER.ASC;
private List<WhereClause> 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<ItemFieldDV> 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<ItemFieldDV> orderByFields, ORDER order, List<WhereClause> conditions) {
this.orderByFields = orderByFields;
this.order = order;
this.conditions = conditions;
}
/**
* Gets the conditions.
*
* @return the conditions
*/
public List<WhereClause> getConditions() {
return conditions;
}
/**
* Sets the conditions.
*
* @param conditions the new conditions
*/
public void setConditions(List<WhereClause> conditions) {
this.conditions = conditions;
}
/**
* Gets the order by fields.
*
* @return the order by fields
*/
public List<ItemFieldDV> 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<ItemFieldDV> 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();
}
}

View File

@ -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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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();
}
}

View File

@ -1,22 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module rename-to='CkanContentModeratorWidget'> <module rename-to='CkanContentModeratorWidget'>
<!-- Inherit the core Web Toolkit stuff. --> <!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' /> <inherits name='com.google.gwt.user.User' />
<!-- Inherit the default GWT style sheet. You can change --> <inherits
<!-- the theme of your GWT application by uncommenting --> name="org.gcube.datacatalogue.utillibrary.CkanUtilLibrary" />
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.standard.Standard' />
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits --> <inherits name="com.github.gwtbootstrap.Bootstrap" />
<!-- Specify the app entry point class. --> <!-- Other module inherits -->
<entry-point class='org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorWidget' />
<!-- Specify the paths for translatable code --> <!-- Specify the app entry point class. -->
<source path='client' /> <!-- <entry-point class='org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorWidget'
<source path='shared' /> /> -->
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
<stylesheet src='content-moderator-widget.css' />
</module> </module>

View File

@ -1,2 +0,0 @@
sendButton = Envoyer
nameField = Entrez votre nom

View File

@ -32,3 +32,325 @@ h1 {
#closeButton { #closeButton {
margin: 15px 6px 6px; 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;
}

View File

@ -6,58 +6,47 @@
<!-- differences in layout. --> <!-- differences in layout. -->
<html> <html>
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!-- --> <!-- -->
<!-- Consider inlining CSS to reduce the number of requested files --> <!-- Consider inlining CSS to reduce the number of requested files -->
<!-- --> <!-- -->
<link type="text/css" rel="stylesheet" href="CkanContentModeratorWidget.css"> <link type="text/css" rel="stylesheet"
href="CkanContentModeratorWidget.css">
<!-- --> <!-- -->
<!-- Any title is fine --> <!-- Any title is fine -->
<!-- --> <!-- -->
<title>Web Application Starter Project</title> <title>Web Application Starter Project</title>
<!-- --> <!-- -->
<!-- This script loads your compiled module. --> <!-- This script loads your compiled module. -->
<!-- If you add any GWT meta tags, they must --> <!-- If you add any GWT meta tags, they must -->
<!-- be added before this line. --> <!-- be added before this line. -->
<!-- --> <!-- -->
<script type="text/javascript" language="javascript" src="CkanContentModeratorWidget/CkanContentModeratorWidget.nocache.js"></script> <script type="text/javascript" language="javascript"
</head> src="CkanContentModeratorWidget/CkanContentModeratorWidget.nocache.js"></script>
</head>
<!-- --> <!-- -->
<!-- The body can have arbitrary html, or --> <!-- The body can have arbitrary html, or -->
<!-- you can leave the body empty if you want --> <!-- you can leave the body empty if you want -->
<!-- to create a completely dynamic UI. --> <!-- to create a completely dynamic UI. -->
<!-- --> <!-- -->
<body> <body>
<!-- OPTIONAL: include this if you want history support --> <!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
style="position: absolute; width: 0; height: 0; border: 0"></iframe>
<!-- RECOMMENDED if your web app will not function without JavaScript enabled --> <!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
<noscript> <noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif"> <div
Your web browser must have JavaScript enabled style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
in order for this application to display correctly. Your web browser must have JavaScript enabled in order for this
</div> application to display correctly.</div>
</noscript> </noscript>
<div id="theContentModeratorDiv"></div>
<h1>Web Application Starter Project</h1> </body>
<table align="center">
<tr>
<td colspan="2" style="font-weight:bold;">Please enter your name:</td>
</tr>
<tr>
<td id="nameFieldContainer"></td>
<td id="sendButtonContainer"></td>
</tr>
<tr>
<td colspan="2" style="color:red;" id="errorLabelContainer"></td>
</tr>
</table>
</body>
</html> </html>

View File

@ -1,24 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app <web-app xmlns="http://java.sun.com/xml/ns/javaee"
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
"http://java.sun.com/dtd/web-app_2_3.dtd"> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<web-app> <servlet>
<servlet-name>ckanContentModeratorServlet</servlet-name>
<servlet-class>org.gcube.portlets.widgets.ckancontentmoderator.server.CkanContentModeratorServiceImpl</servlet-class>
</servlet>
<!-- Servlets --> <servlet-mapping>
<servlet> <servlet-name>ckanContentModeratorServlet</servlet-name>
<servlet-name>greetServlet</servlet-name> <url-pattern>/CkanContentModeratorWidget/ckanContentModeratorService</url-pattern>
<servlet-class>org.gcube.portlets.widgets.ckancontentmoderator.server.GreetingServiceImpl</servlet-class> </servlet-mapping>
</servlet>
<servlet-mapping> <!-- Default page to serve -->
<servlet-name>greetServlet</servlet-name> <welcome-file-list>
<url-pattern>/CkanContentModeratorWidget/greet</url-pattern> <welcome-file>CkanContentModeratorWidget.html</welcome-file>
</servlet-mapping> </welcome-file-list>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>CkanContentModeratorWidget.html</welcome-file>
</welcome-file-list>
</web-app> </web-app>

View File

@ -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");
}
}

View File

@ -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<String, String> filters = new HashMap<String, String>(1);
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, "francesco.mangiacrapa@isti.cnr.it");
List<CkanDataset> 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();
}
}
}

8
src/test/resources/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/devNext.gcubekey
/devVRE.gcubekey
/devsec.gcubekey
/gCubeApps.gcubekey
/gcube.gcubekey
/log4j.properties
/pred4s.gcubekey
/preprod.gcubekey