git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/message-conversations@154393 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
21eea1df57
commit
fd563a702e
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="target/messages-2.0.0-SNAPSHOT/WEB-INF/classes" path="src/main/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry excluding="**" kind="src" output="target/messages-2.0.0-SNAPSHOT/WEB-INF/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/messages-2.0.0-SNAPSHOT/WEB-INF/classes" path="target/generated-sources/gwt">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="com.gwtplugins.gwt.eclipse.core.GWT_CONTAINER/gwt-2.8.1"/>
|
||||||
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/messages-2.0.0-SNAPSHOT/WEB-INF/classes"/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>message-conversations</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||||
|
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||||
|
<nature>com.liferay.ide.core.liferayNature</nature>
|
||||||
|
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src/main/webapp"/>
|
||||||
|
<classpathentry excluding="**/bower_components/*|**/node_modules/*|**/*.min.js" kind="src" path="target/m2e-wtp/web-resources"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="hide" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
|
||||||
|
<classpathentry kind="output" path=""/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1,4 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
lastWarOutDir=/Users/massi/Documents/workspace/message-conversations/target/message-conversations-0.0.1-SNAPSHOT
|
||||||
|
warSrcDir=src/main/webapp
|
||||||
|
warSrcDirIsOutput=false
|
|
@ -0,0 +1,3 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
entryPointModules=
|
||||||
|
filesCopiedToWebInfLib=
|
|
@ -0,0 +1,3 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
warSrcDir=src/main/webapp
|
||||||
|
warSrcDirIsOutput=false
|
|
@ -0,0 +1,3 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
entryPointModules=
|
||||||
|
filesCopiedToWebInfLib=
|
|
@ -0,0 +1,5 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding//src/main/java=UTF-8
|
||||||
|
encoding//src/main/resources=UTF-8
|
||||||
|
encoding//target/generated-sources/gwt=UTF-8
|
||||||
|
encoding/<project>=UTF-8
|
|
@ -0,0 +1,8 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,3 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
validateFragments=false
|
||||||
|
validation.use-project-settings=true
|
|
@ -0,0 +1,4 @@
|
||||||
|
activeProfiles=
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
resolveWorkspaceProjects=true
|
||||||
|
version=1
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||||
|
<wb-module deploy-name="message-conversations-portlet">
|
||||||
|
<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="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||||
|
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||||
|
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
|
||||||
|
<dependent-module archiveName="client-context-library-1.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/client-context-library/client-context-library">
|
||||||
|
<dependency-type>uses</dependency-type>
|
||||||
|
</dependent-module>
|
||||||
|
<property name="java-output-path" value="/message-conversations/target/message-conversations-0.0.1-SNAPSHOT/WEB-INF/classes"/>
|
||||||
|
<property name="context-root" value="messages"/>
|
||||||
|
</wb-module>
|
||||||
|
</project-modules>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<faceted-project>
|
||||||
|
<fixed facet="wst.jsdt.web"/>
|
||||||
|
<installed facet="java" version="1.8"/>
|
||||||
|
<installed facet="jst.web" version="3.0"/>
|
||||||
|
<installed facet="wst.jsdt.web" version="1.0"/>
|
||||||
|
<installed facet="liferay.portlet" version="6.0"/>
|
||||||
|
</faceted-project>
|
|
@ -0,0 +1 @@
|
||||||
|
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
|
|
@ -0,0 +1 @@
|
||||||
|
Window
|
|
@ -0,0 +1,2 @@
|
||||||
|
disabled=06target
|
||||||
|
eclipse.preferences.version=1
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"plugins": {
|
||||||
|
"guess-types": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"outline": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"liferay": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"yui3": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"aui2.0.x": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libs": [
|
||||||
|
"ecma5",
|
||||||
|
"browser"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
${gcube.license}
|
|
@ -0,0 +1,61 @@
|
||||||
|
The gCube System - ${name}
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
${description}
|
||||||
|
|
||||||
|
|
||||||
|
${gcube.description}
|
||||||
|
|
||||||
|
${gcube.funding}
|
||||||
|
|
||||||
|
|
||||||
|
Version
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
${version} (${buildDate})
|
||||||
|
|
||||||
|
Please see the file named "changelog.xml" in this directory for the release notes.
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
* Massimiliano Assante (massimiliano.assante-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
|
||||||
|
Maintainers
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Francesco Mangiacrapa (francesco.mangiacrapa-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
* Massimiliano Assante (massimiliano.assante-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
|
||||||
|
Download information
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Source code is available from SVN:
|
||||||
|
${scm.url}
|
||||||
|
|
||||||
|
Binaries can be downloaded from the gCube website:
|
||||||
|
${gcube.website}
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Documentation is available on-line in the gCube Wiki:
|
||||||
|
${gcube.wikiRoot}/Workspace
|
||||||
|
|
||||||
|
Support
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Bugs and support requests can be reported in the gCube issue tracking tool:
|
||||||
|
${gcube.issueTracking}
|
||||||
|
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.
|
|
@ -0,0 +1,50 @@
|
||||||
|
<ReleaseNotes>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.2-0-0"
|
||||||
|
date="2017-09-21">
|
||||||
|
<Change>Improved look and feel</Change>
|
||||||
|
<Change>Responsive, works on mobile</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.1-3-0"
|
||||||
|
date="2016-11-28">
|
||||||
|
<Change>Removed ASL Session</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-8-0"
|
||||||
|
date="2015-10-08">
|
||||||
|
<Change>[Feature #879] Message Improvements</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-7-0"
|
||||||
|
date="2015-06-05">
|
||||||
|
<Change>Upgraded to GWT 2.7</Change>
|
||||||
|
<Change>[Feature #129] Porting to HL 2.0</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-6-0"
|
||||||
|
date="2013-06-04">
|
||||||
|
<Change>Fixed bug on "reply all"</Change>
|
||||||
|
<Change>Changed icons</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-5-0"
|
||||||
|
date="2013-06-04">
|
||||||
|
<Change>Updated pom to support new gcube core (gcube release 3.2)
|
||||||
|
</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-4-0"
|
||||||
|
date="2013-10-21">
|
||||||
|
<Change>#Ticket 2223. This project was enhancements to gwt 2.5.1
|
||||||
|
</Change>
|
||||||
|
<Change>GCF dependency was removed</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-3-0"
|
||||||
|
date="2013-07-08">
|
||||||
|
<Change>Updated show attachments: this functionality now calls the
|
||||||
|
servlet contained in ws-tree
|
||||||
|
</Change>
|
||||||
|
<Change>Error management for attachments: it was added redirect
|
||||||
|
functionality in download servlet
|
||||||
|
</Change>
|
||||||
|
<Change>Fixed Ticket #1348</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.portlets-user.messages.0-1-0"
|
||||||
|
date="2013-01-13">
|
||||||
|
<Change>First Release</Change>
|
||||||
|
</Changeset>
|
||||||
|
</ReleaseNotes>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<assembly
|
||||||
|
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||||
|
<id>servicearchive</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<baseDirectory>/</baseDirectory>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${distroDirectory}</directory>
|
||||||
|
<outputDirectory>/</outputDirectory>
|
||||||
|
<useDefaultExcludes>true</useDefaultExcludes>
|
||||||
|
<includes>
|
||||||
|
<include>README</include>
|
||||||
|
<include>LICENSE</include>
|
||||||
|
<include>changelog.xml</include>
|
||||||
|
<include>profile.xml</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>755</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>target/${build.finalName}.${project.packaging}</source>
|
||||||
|
<outputDirectory>/${artifactId}</outputDirectory>
|
||||||
|
</file>
|
||||||
|
|
||||||
|
</files>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<ID></ID>
|
||||||
|
<Type>Service</Type>
|
||||||
|
<Profile>
|
||||||
|
<Description>${description}</Description>
|
||||||
|
<Class>PortletUser</Class>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>${version}</Version>
|
||||||
|
<Packages>
|
||||||
|
<Software>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>${version}</Version>
|
||||||
|
<MavenCoordinates>
|
||||||
|
<groupId>${groupId}</groupId>
|
||||||
|
<artifactId>${artifactId}</artifactId>
|
||||||
|
<version>${version}</version>
|
||||||
|
</MavenCoordinates>
|
||||||
|
<Files>
|
||||||
|
<File>target/${build.finalName}.war</File>
|
||||||
|
</Files>
|
||||||
|
</Software>
|
||||||
|
</Packages>
|
||||||
|
</Profile>
|
||||||
|
</Resource>
|
|
@ -0,0 +1,308 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>maven-parent</artifactId>
|
||||||
|
<groupId>org.gcube.tools</groupId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath />
|
||||||
|
</parent>
|
||||||
|
<groupId>org.gcube.portets.user</groupId>
|
||||||
|
<artifactId>messages</artifactId>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<description>
|
||||||
|
gCube Messages Portlet for exchanging messages with other users.
|
||||||
|
</description>
|
||||||
|
<scm>
|
||||||
|
<connection>scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/message-conversations</connection>
|
||||||
|
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/message-conversations</developerConnection>
|
||||||
|
<url>http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/message-conversations</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- Convenience property to set the GWT version -->
|
||||||
|
<gwt.version>2.8.1</gwt.version>
|
||||||
|
<distroDirectory>distro</distroDirectory>
|
||||||
|
<!-- GWT 2.8 requires 1.8 -->
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<gwt-material.version>2.0-rc6</gwt-material.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.distribution</groupId>
|
||||||
|
<artifactId>maven-portal-bom</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.gwt</groupId>
|
||||||
|
<artifactId>gwt</artifactId>
|
||||||
|
<version>${gwt.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.portlets.widgets</groupId>
|
||||||
|
<artifactId>workspace-explorer</artifactId>
|
||||||
|
<version>[1.8.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.applicationsupportlayer</groupId>
|
||||||
|
<artifactId>aslsocial</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common.portal</groupId>
|
||||||
|
<artifactId>portal-manager</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.portal</groupId>
|
||||||
|
<artifactId>client-context-library</artifactId>
|
||||||
|
<version>[1.0.0-SNAPSHOT,)</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.portlet</groupId>
|
||||||
|
<artifactId>portlet-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.gwt</groupId>
|
||||||
|
<artifactId>gwt-servlet</artifactId>
|
||||||
|
<version>${gwt.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.gwt</groupId>
|
||||||
|
<artifactId>gwt-user</artifactId>
|
||||||
|
<version>${gwt.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.gwt</groupId>
|
||||||
|
<artifactId>gwt-dev</artifactId>
|
||||||
|
<version>${gwt.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- FWS -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.core</groupId>
|
||||||
|
<artifactId>common-scope-maps</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- GwtMaterial -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.gwtmaterialdesign</groupId>
|
||||||
|
<artifactId>gwt-material</artifactId>
|
||||||
|
<version>${gwt-material.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.gwtmaterialdesign</groupId>
|
||||||
|
<artifactId>gwt-material-themes</artifactId>
|
||||||
|
<version>${gwt-material.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.gwtmaterialdesign</groupId>
|
||||||
|
<artifactId>gwt-material-addins</artifactId>
|
||||||
|
<version>${gwt-material.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.portal</groupId>
|
||||||
|
<artifactId>notifications-common-library</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- HOME LIBRARY -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>home-library-jcr</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>home-library-model</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>home-library</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>asm-all</artifactId>
|
||||||
|
<groupId>asm</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>xml-apis</groupId>
|
||||||
|
<artifactId>xml-apis</artifactId>
|
||||||
|
<version>1.4.01</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<!-- <version>3.1.0</version> -->
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.dvos</groupId>
|
||||||
|
<artifactId>usermanagement-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>authorization-client</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>common-authorization</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.liferay.portal</groupId>
|
||||||
|
<artifactId>portal-service</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.liferay.portal</groupId>
|
||||||
|
<artifactId>util-java</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<!-- Output classes directly into the webapp, so that IDEs and "mvn process-classes"
|
||||||
|
update them in DevMode -->
|
||||||
|
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<!-- Mojo's Maven Plugin for GWT -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>gwt-maven-plugin</artifactId>
|
||||||
|
<version>2.8.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
<goal>generateAsync</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<!-- Plugin configuration. There are many available options, see gwt-maven-plugin
|
||||||
|
documentation at codehaus.org -->
|
||||||
|
<configuration>
|
||||||
|
<runTarget>MessageConversations.html</runTarget>
|
||||||
|
<modules>
|
||||||
|
<module>org.gcube.portets.user.message_conversations.MessageConversations</module>
|
||||||
|
</modules>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.0.0-M1</version>
|
||||||
|
<configuration>
|
||||||
|
<additionalparam>-Xdoclint:none</additionalparam>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- Copy static web files before executing gwt:run -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>2.1.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>exploded</goal>
|
||||||
|
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<webappDirectory>${webappDirectory}</webappDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<target>${maven.compiler.target}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- SA Plugin -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>${distroDirectory}/descriptor.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>servicearchive</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</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>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.client.ui.ApplicationView;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.EntryPoint;
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||||
|
import com.google.gwt.user.client.ui.RootPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point classes define <code>onModuleLoad()</code>.
|
||||||
|
*/
|
||||||
|
public class MessageConversations implements EntryPoint {
|
||||||
|
public static final String DIV_CONTAINER_ID = "create-users-container";
|
||||||
|
/**
|
||||||
|
* Create a remote service proxy to talk to the server-side Greeting service.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private final MessageServiceAsync convService = GWT.create(MessageService.class);
|
||||||
|
private ApplicationView ap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the entry point method.
|
||||||
|
*/
|
||||||
|
public void onModuleLoad() {
|
||||||
|
((ServiceDefTarget) convService).setServiceEntryPoint("/delegate/message-conversations");
|
||||||
|
ap = new ApplicationView();
|
||||||
|
RootPanel.get(DIV_CONTAINER_ID).add(ap);
|
||||||
|
ap.readUserMessages(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.CurrUserAndPortalUsersWrapper;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.WSUser;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.rpc.RemoteService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client side stub for the RPC service.
|
||||||
|
*/
|
||||||
|
public interface MessageService extends RemoteService {
|
||||||
|
|
||||||
|
ArrayList<ConvMessage> getMessages(boolean sent);
|
||||||
|
ConvMessage getMessageById(String messageId, boolean sent);
|
||||||
|
CurrUserAndPortalUsersWrapper getWorkspaceUsers();
|
||||||
|
ArrayList<WSUser> searchUsers(String keyword);
|
||||||
|
boolean sendToById(ArrayList<String> recipientIds, ArrayList<String> listAttachmentsId, String subject, String body);
|
||||||
|
boolean deleteMessageById(String messageId, boolean sent);
|
||||||
|
String getAttachmentDownloadURL(String itemId);
|
||||||
|
boolean saveAttachmentToWorkspaceFolder(String itemId, String destinationFolderId);
|
||||||
|
boolean markMessageUnread(String messageId);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.google.gwt.i18n.client.DateTimeFormat;
|
||||||
|
import com.google.gwt.user.client.Random;
|
||||||
|
import com.google.gwt.user.client.ui.RootPanel;
|
||||||
|
import com.google.gwt.user.datepicker.client.CalendarUtil;
|
||||||
|
|
||||||
|
import gwt.material.design.client.constants.Color;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
public static DateTimeFormat fmCurrentYear = DateTimeFormat.getFormat("MMM d H:mm");
|
||||||
|
public static DateTimeFormat fmPastYears = DateTimeFormat.getFormat("MMM d H:mm ''yy");
|
||||||
|
|
||||||
|
public static Color getRandomColor() {
|
||||||
|
Color toReturn = Color.values()[Random.nextInt(Color.values().length)];
|
||||||
|
while (toReturn.name().startsWith("WHITE") ||
|
||||||
|
toReturn.name().startsWith("GREY") ||
|
||||||
|
toReturn.name().startsWith("TRANSPARENT") ||
|
||||||
|
toReturn.name().startsWith("BROWN") ||
|
||||||
|
toReturn.name().contains("LIGHTEN") ||
|
||||||
|
toReturn.name().contains("ACCENT")) {
|
||||||
|
toReturn = Color.values()[Random.nextInt(Color.values().length)];
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isMobile() {
|
||||||
|
int screenWidth = RootPanel.get(MessageConversations.DIV_CONTAINER_ID).getOffsetWidth();
|
||||||
|
return (screenWidth <= 768);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static String getFormatteDate(Date date) {
|
||||||
|
Date now = new Date();
|
||||||
|
int dayInBetween = CalendarUtil.getDaysBetween(now, date);
|
||||||
|
switch (dayInBetween) {
|
||||||
|
case 0:
|
||||||
|
return"Today at " + (DateTimeFormat.getFormat("H:mm").format(date));
|
||||||
|
case -1:
|
||||||
|
return "Yesterday, " + (DateTimeFormat.getFormat("H:mm").format(date));
|
||||||
|
case -2:
|
||||||
|
return "2 days ago, " + (DateTimeFormat.getFormat("H:mm").format(date));
|
||||||
|
default:
|
||||||
|
return(now.getYear() == date.getYear()) ? fmCurrentYear.format(date) : fmPastYears.format(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,706 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.autocomplete;
|
||||||
|
|
||||||
|
import com.google.gwt.dom.client.Document;
|
||||||
|
import com.google.gwt.event.dom.client.*;
|
||||||
|
import com.google.gwt.event.logical.shared.*;
|
||||||
|
import com.google.gwt.event.shared.HandlerRegistration;
|
||||||
|
import com.google.gwt.user.client.DOM;
|
||||||
|
import com.google.gwt.user.client.ui.*;
|
||||||
|
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
|
||||||
|
import gwt.material.design.addins.client.MaterialAddins;
|
||||||
|
import gwt.material.design.addins.client.autocomplete.constants.AutocompleteType;
|
||||||
|
import gwt.material.design.addins.client.base.constants.AddinsCssName;
|
||||||
|
import gwt.material.design.client.MaterialDesignBase;
|
||||||
|
import gwt.material.design.client.base.*;
|
||||||
|
import gwt.material.design.client.base.mixin.*;
|
||||||
|
import gwt.material.design.client.constants.CssName;
|
||||||
|
import gwt.material.design.client.constants.IconType;
|
||||||
|
import gwt.material.design.client.constants.ProgressType;
|
||||||
|
import gwt.material.design.client.ui.MaterialChip;
|
||||||
|
import gwt.material.design.client.ui.MaterialLabel;
|
||||||
|
import gwt.material.design.client.ui.html.Label;
|
||||||
|
import gwt.material.design.client.ui.html.ListItem;
|
||||||
|
import gwt.material.design.client.ui.html.UnorderedList;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author kevzlou7979
|
||||||
|
* @author gilberto-torrezan
|
||||||
|
* @author M. Assante, CNR-ISTI
|
||||||
|
* @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#!autocomplete">Material AutoComplete</a>
|
||||||
|
*/
|
||||||
|
// @formatter:on
|
||||||
|
public class MaterialAutoComplete extends AbstractValueWidget<List<? extends Suggestion>> implements HasPlaceholder,
|
||||||
|
HasProgress, HasType<AutocompleteType>, HasSelectionHandlers<Suggestion>, HasReadOnly {
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (MaterialAddins.isDebug()) {
|
||||||
|
MaterialDesignBase.injectCss(MaterialAutocompleteDebugClientBundle.INSTANCE.autocompleteCssDebug());
|
||||||
|
} else {
|
||||||
|
MaterialDesignBase.injectCss(MaterialAutocompleteClientBundle.INSTANCE.autocompleteCss());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Suggestion, Widget> suggestionMap = new LinkedHashMap<>();
|
||||||
|
private Label placeholderLabel = new Label();
|
||||||
|
|
||||||
|
private List<ListItem> itemsHighlighted = new ArrayList<>();
|
||||||
|
private FlowPanel panel = new FlowPanel();
|
||||||
|
private UnorderedList list = new UnorderedList();
|
||||||
|
private SuggestOracle suggestions;
|
||||||
|
private TextBox itemBox = new TextBox();
|
||||||
|
private SuggestBox suggestBox;
|
||||||
|
private int limit = 0;
|
||||||
|
private MaterialLabel errorLabel = new MaterialLabel();
|
||||||
|
private final ProgressMixin<MaterialAutoComplete> progressMixin = new ProgressMixin<>(this);
|
||||||
|
|
||||||
|
private String selectedChipStyle = "blue white-text";
|
||||||
|
private boolean directInputAllowed = true;
|
||||||
|
private MaterialChipProvider chipProvider = new DefaultMaterialChipProvider();
|
||||||
|
|
||||||
|
private final ErrorMixin<AbstractValueWidget, MaterialLabel> errorMixin = new ErrorMixin<>(this, errorLabel, list, placeholderLabel);
|
||||||
|
|
||||||
|
private FocusableMixin<MaterialWidget> focusableMixin;
|
||||||
|
private ReadOnlyMixin<MaterialAutoComplete, TextBox> readOnlyMixin;
|
||||||
|
|
||||||
|
public final CssTypeMixin<AutocompleteType, MaterialAutoComplete> typeMixin = new CssTypeMixin<>(this, this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use MaterialAutocomplete to search for matches from local or remote data
|
||||||
|
* sources.
|
||||||
|
*/
|
||||||
|
public MaterialAutoComplete() {
|
||||||
|
super(Document.get().createDivElement(), AddinsCssName.AUTOCOMPLETE, CssName.INPUT_FIELD);
|
||||||
|
add(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MaterialAutoComplete(AutocompleteType type) {
|
||||||
|
this();
|
||||||
|
setType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MaterialAutoComplete(String placeholder) {
|
||||||
|
this();
|
||||||
|
setPlaceholder(placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use MaterialAutocomplete to search for matches from local or remote data
|
||||||
|
* sources.
|
||||||
|
*
|
||||||
|
* @see #setSuggestions(SuggestOracle)
|
||||||
|
*/
|
||||||
|
public MaterialAutoComplete(SuggestOracle suggestions) {
|
||||||
|
this();
|
||||||
|
build(suggestions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate and build the List Items to be set on Auto Complete box.
|
||||||
|
*/
|
||||||
|
protected void build(SuggestOracle suggestions) {
|
||||||
|
list.setStyleName(AddinsCssName.MULTIVALUESUGGESTBOX_LIST);
|
||||||
|
this.suggestions = suggestions;
|
||||||
|
final ListItem item = new ListItem();
|
||||||
|
|
||||||
|
item.setStyleName(AddinsCssName.MULTIVALUESUGGESTBOX_INPUT_TOKEN);
|
||||||
|
suggestBox = new SuggestBox(suggestions, itemBox);
|
||||||
|
setLimit(this.limit);
|
||||||
|
String autocompleteId = DOM.createUniqueId();
|
||||||
|
itemBox.getElement().setId(autocompleteId);
|
||||||
|
|
||||||
|
item.add(suggestBox);
|
||||||
|
item.add(placeholderLabel);
|
||||||
|
list.add(item);
|
||||||
|
|
||||||
|
list.addDomHandler(event -> suggestBox.showSuggestionList(), ClickEvent.getType());
|
||||||
|
|
||||||
|
itemBox.addBlurHandler(blurEvent -> {
|
||||||
|
if (getValue().size() > 0) {
|
||||||
|
placeholderLabel.addStyleName(CssName.ACTIVE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
itemBox.addKeyDownHandler(event -> {
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
switch (event.getNativeKeyCode()) {
|
||||||
|
case KeyCodes.KEY_ENTER:
|
||||||
|
if (directInputAllowed) {
|
||||||
|
String value = itemBox.getValue();
|
||||||
|
if (value != null && !(value = value.trim()).isEmpty()) {
|
||||||
|
gwt.material.design.client.base.Suggestion directInput = new gwt.material.design.client.base.Suggestion();
|
||||||
|
directInput.setDisplay(value);
|
||||||
|
directInput.setSuggestion(value);
|
||||||
|
changed = addItem(directInput);
|
||||||
|
if (getType() == AutocompleteType.TEXT) {
|
||||||
|
itemBox.setText(value);
|
||||||
|
} else {
|
||||||
|
itemBox.setValue("");
|
||||||
|
}
|
||||||
|
itemBox.setFocus(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KeyCodes.KEY_BACKSPACE:
|
||||||
|
if (itemBox.getValue().trim().isEmpty()) {
|
||||||
|
if (itemsHighlighted.isEmpty()) {
|
||||||
|
if (suggestionMap.size() > 0) {
|
||||||
|
ListItem li = (ListItem) list.getWidget(list.getWidgetCount() - 2);
|
||||||
|
|
||||||
|
if (tryRemoveSuggestion(li.getWidget(0))) {
|
||||||
|
li.removeFromParent();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case KeyCodes.KEY_DELETE:
|
||||||
|
if (itemBox.getValue().trim().isEmpty()) {
|
||||||
|
for (ListItem li : itemsHighlighted) {
|
||||||
|
if (tryRemoveSuggestion(li.getWidget(0))) {
|
||||||
|
li.removeFromParent();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itemsHighlighted.clear();
|
||||||
|
}
|
||||||
|
itemBox.setFocus(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
ValueChangeEvent.fire(MaterialAutoComplete.this, getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
itemBox.addClickHandler(event -> suggestBox.showSuggestionList());
|
||||||
|
|
||||||
|
suggestBox.addSelectionHandler(selectionEvent -> {
|
||||||
|
Suggestion selectedItem = selectionEvent.getSelectedItem();
|
||||||
|
itemBox.setValue("");
|
||||||
|
if (addItem(selectedItem)) {
|
||||||
|
ValueChangeEvent.fire(MaterialAutoComplete.this, getValue());
|
||||||
|
}
|
||||||
|
itemBox.setFocus(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.add(list);
|
||||||
|
panel.getElement().setAttribute("onclick",
|
||||||
|
"document.getElementById('" + autocompleteId + "').focus()");
|
||||||
|
panel.add(errorLabel);
|
||||||
|
suggestBox.setFocus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean tryRemoveSuggestion(Widget widget) {
|
||||||
|
Set<Entry<Suggestion, Widget>> entrySet = suggestionMap.entrySet();
|
||||||
|
for (Entry<Suggestion, Widget> entry : entrySet) {
|
||||||
|
if (widget.equals(entry.getValue())) {
|
||||||
|
if (chipProvider.isChipRemovable(entry.getKey())) {
|
||||||
|
suggestionMap.remove(entry.getKey());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding the item value using Material Chips added on auto complete box
|
||||||
|
*/
|
||||||
|
public boolean addItem(final Suggestion suggestion) {
|
||||||
|
SelectionEvent.fire(MaterialAutoComplete.this, suggestion);
|
||||||
|
if (getLimit() > 0) {
|
||||||
|
if (suggestionMap.size() >= getLimit()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suggestionMap.containsKey(suggestion)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ListItem displayItem = new ListItem();
|
||||||
|
displayItem.setStyleName(AddinsCssName.MULTIVALUESUGGESTBOX_TOKEN);
|
||||||
|
|
||||||
|
if (getType() == AutocompleteType.TEXT) {
|
||||||
|
suggestionMap.clear();
|
||||||
|
itemBox.setText(suggestion.getDisplayString());
|
||||||
|
} else {
|
||||||
|
final MaterialChip chip = chipProvider.getChip(suggestion);
|
||||||
|
if (chip == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
chip.addClickHandler(event -> {
|
||||||
|
if (chipProvider.isChipSelectable(suggestion)) {
|
||||||
|
if (itemsHighlighted.contains(displayItem)) {
|
||||||
|
chip.removeStyleName(selectedChipStyle);
|
||||||
|
itemsHighlighted.remove(displayItem);
|
||||||
|
} else {
|
||||||
|
chip.addStyleName(selectedChipStyle);
|
||||||
|
itemsHighlighted.add(displayItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (chip.getIcon() != null) {
|
||||||
|
chip.getIcon().addClickHandler(event -> {
|
||||||
|
if (chipProvider.isChipRemovable(suggestion)) {
|
||||||
|
suggestionMap.remove(suggestion);
|
||||||
|
list.remove(displayItem);
|
||||||
|
itemsHighlighted.remove(displayItem);
|
||||||
|
ValueChangeEvent.fire(MaterialAutoComplete.this, getValue());
|
||||||
|
suggestBox.showSuggestionList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
suggestionMap.put(suggestion, chip);
|
||||||
|
displayItem.add(chip);
|
||||||
|
list.insert(displayItem, list.getWidgetCount() - 1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the chip items on the autocomplete box
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
itemBox.setValue("");
|
||||||
|
placeholderLabel.removeStyleName(CssName.ACTIVE);
|
||||||
|
|
||||||
|
Collection<Widget> values = suggestionMap.values();
|
||||||
|
for (Widget widget : values) {
|
||||||
|
Widget parent = widget.getParent();
|
||||||
|
if (parent instanceof ListItem) {
|
||||||
|
parent.removeFromParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suggestionMap.clear();
|
||||||
|
|
||||||
|
clearErrorOrSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FocusableMixin<MaterialWidget> getFocusableMixin() {
|
||||||
|
if (focusableMixin == null) {
|
||||||
|
focusableMixin = new FocusableMixin<>(new MaterialWidget(itemBox.getElement()));
|
||||||
|
}
|
||||||
|
return focusableMixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the item values on autocomplete
|
||||||
|
* @see #getValue()
|
||||||
|
*/
|
||||||
|
public List<String> getItemValues() {
|
||||||
|
Set<Suggestion> keySet = suggestionMap.keySet();
|
||||||
|
List<String> values = new ArrayList<>(keySet.size());
|
||||||
|
for (Suggestion suggestion : keySet) {
|
||||||
|
values.add(suggestion.getReplacementString());
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param itemValues the itemsSelected to set
|
||||||
|
* @see #setValue(Object)
|
||||||
|
*/
|
||||||
|
public void setItemValues(List<String> itemValues) {
|
||||||
|
setItemValues(itemValues, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param itemValues the itemsSelected to set
|
||||||
|
* @param fireEvents will fire value change event if true
|
||||||
|
* @see #setValue(Object)
|
||||||
|
*/
|
||||||
|
public void setItemValues(List<String> itemValues, boolean fireEvents) {
|
||||||
|
if (itemValues == null) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Suggestion> list = new ArrayList<>(itemValues.size());
|
||||||
|
for (String value : itemValues) {
|
||||||
|
Suggestion suggestion = new gwt.material.design.client.base.Suggestion(value, value);
|
||||||
|
list.add(suggestion);
|
||||||
|
}
|
||||||
|
setValue(list, fireEvents);
|
||||||
|
if (itemValues.size() > 0) {
|
||||||
|
placeholderLabel.addStyleName(CssName.ACTIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the itemsHighlighted
|
||||||
|
*/
|
||||||
|
public List<ListItem> getItemsHighlighted() {
|
||||||
|
return itemsHighlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param itemsHighlighted the itemsHighlighted to set
|
||||||
|
*/
|
||||||
|
public void setItemsHighlighted(List<ListItem> itemsHighlighted) {
|
||||||
|
this.itemsHighlighted = itemsHighlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the suggestion oracle
|
||||||
|
*/
|
||||||
|
public SuggestOracle getSuggestions() {
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the SuggestOracle to be used to provide suggestions. Also setups the
|
||||||
|
* component with the needed event handlers and UI elements.
|
||||||
|
*
|
||||||
|
* @param suggestions the suggestion oracle to set
|
||||||
|
*/
|
||||||
|
public void setSuggestions(SuggestOracle suggestions) {
|
||||||
|
this.suggestions = suggestions;
|
||||||
|
build(suggestions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSuggestions(SuggestOracle suggestions, AutocompleteType type) {
|
||||||
|
setType(type);
|
||||||
|
setSuggestions(suggestions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLimit() {
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLimit(int limit) {
|
||||||
|
this.limit = limit;
|
||||||
|
if (this.suggestBox != null) {
|
||||||
|
this.suggestBox.setLimit(limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the number of suggestions to be displayed to the user. This differs from
|
||||||
|
* setLimit() which set both the suggestions displayed AND the limit of values
|
||||||
|
* allowed within the autocomplete.
|
||||||
|
* @param limit
|
||||||
|
*/
|
||||||
|
public void setAutoSuggestLimit(int limit) {
|
||||||
|
if (this.suggestBox != null) {
|
||||||
|
this.suggestBox.setLimit(limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPlaceholder() {
|
||||||
|
return placeholderLabel.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlaceholder(String placeholder) {
|
||||||
|
placeholderLabel.setText(placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current {@link MaterialChipProvider}. By default, the class uses
|
||||||
|
* an instance of {@link DefaultMaterialChipProvider}.
|
||||||
|
*/
|
||||||
|
public MaterialChipProvider getChipProvider() {
|
||||||
|
return chipProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a {@link MaterialChipProvider} that can customize how the
|
||||||
|
* {@link MaterialChip} is created for each selected {@link Suggestion}.
|
||||||
|
*/
|
||||||
|
public void setChipProvider(MaterialChipProvider chipProvider) {
|
||||||
|
this.chipProvider = chipProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set to <code>false</code>, only {@link Suggestion}s from the
|
||||||
|
* SuggestionOracle are accepted. Direct input create by the user is
|
||||||
|
* ignored. By default, direct input is allowed.
|
||||||
|
*/
|
||||||
|
public void setDirectInputAllowed(boolean directInputAllowed) {
|
||||||
|
this.directInputAllowed = directInputAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if {@link Suggestion}s created by direct input from the user
|
||||||
|
* should be allowed. By default directInputAllowed is
|
||||||
|
* <code>true</code>.
|
||||||
|
*/
|
||||||
|
public boolean isDirectInputAllowed() {
|
||||||
|
return directInputAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the style class applied to chips when they are selected.
|
||||||
|
* <p>
|
||||||
|
* Defaults to "blue white-text".
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param selectedChipStyle The class or classes to be applied to selected chips
|
||||||
|
*/
|
||||||
|
public void setSelectedChipStyle(String selectedChipStyle) {
|
||||||
|
this.selectedChipStyle = selectedChipStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the style class applied to chips when they are selected.
|
||||||
|
* <p>
|
||||||
|
* Defaults to "blue white-text".
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public String getSelectedChipStyle() {
|
||||||
|
return selectedChipStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showProgress(ProgressType type) {
|
||||||
|
progressMixin.showProgress(ProgressType.INDETERMINATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPercent(double percent) {
|
||||||
|
progressMixin.setPercent(percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideProgress() {
|
||||||
|
progressMixin.hideProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerRegistration addKeyUpHandler(final KeyUpHandler handler) {
|
||||||
|
return itemBox.addKeyUpHandler(event -> {
|
||||||
|
if (isEnabled()) {
|
||||||
|
handler.onKeyUp(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setType(AutocompleteType type) {
|
||||||
|
typeMixin.setType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AutocompleteType getType() {
|
||||||
|
return typeMixin.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerRegistration addSelectionHandler(final SelectionHandler<Suggestion> handler) {
|
||||||
|
return addHandler(new SelectionHandler<Suggestion>() {
|
||||||
|
@Override
|
||||||
|
public void onSelection(SelectionEvent<Suggestion> event) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
handler.onSelection(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, SelectionEvent.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyMixin<MaterialAutoComplete, TextBox> getReadOnlyMixin() {
|
||||||
|
if (readOnlyMixin == null) {
|
||||||
|
readOnlyMixin = new ReadOnlyMixin<>(this, itemBox);
|
||||||
|
}
|
||||||
|
return readOnlyMixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadOnly(boolean value) {
|
||||||
|
getReadOnlyMixin().setReadOnly(value);
|
||||||
|
if (value) {
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return getReadOnlyMixin().isReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setToggleReadOnly(boolean toggle) {
|
||||||
|
getReadOnlyMixin().setToggleReadOnly(toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isToggleReadOnly() {
|
||||||
|
return getReadOnlyMixin().isToggleReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface that defines how a {@link MaterialChip} is created, given a
|
||||||
|
* {@link Suggestion}.
|
||||||
|
*
|
||||||
|
* @see MaterialAutoComplete#setChipProvider(MaterialChipProvider)
|
||||||
|
*/
|
||||||
|
public static interface MaterialChipProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a {@link MaterialChip} based on the selected
|
||||||
|
* {@link Suggestion}.
|
||||||
|
*
|
||||||
|
* @param suggestion the selected {@link Suggestion}
|
||||||
|
* @return the created MaterialChip, or <code>null</code> if the
|
||||||
|
* suggestion should be ignored.
|
||||||
|
*/
|
||||||
|
MaterialChip getChip(Suggestion suggestion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the chip defined by the suggestion should be selected when the user clicks on it.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* Selecion of chips is used to batch remove suggestions, for example.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param suggestion the selected {@link Suggestion}
|
||||||
|
* @see MaterialAutoComplete#setSelectedChipStyle(String)
|
||||||
|
*/
|
||||||
|
boolean isChipSelectable(Suggestion suggestion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the chip defined by the suggestion should be removed from the autocomplete when clicked on its icon.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* Override this method returning <code>false</code> to implement your own logic when the user clicks on the chip icon.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param suggestion the selected {@link Suggestion}
|
||||||
|
*/
|
||||||
|
boolean isChipRemovable(Suggestion suggestion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of the {@link MaterialChipProvider} interface,
|
||||||
|
* used by the {@link MaterialAutoComplete}.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* By default all chips are selectable and removable. The default {@link IconType} used by the chips provided is the {@link IconType#CLOSE}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see MaterialAutoComplete#setChipProvider(MaterialChipProvider)
|
||||||
|
*/
|
||||||
|
public static class DefaultMaterialChipProvider implements MaterialChipProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MaterialChip getChip(Suggestion suggestion) {
|
||||||
|
final MaterialChip chip = new MaterialChip();
|
||||||
|
|
||||||
|
String imageChip = suggestion.getDisplayString();
|
||||||
|
String textChip = imageChip;
|
||||||
|
|
||||||
|
String s = "<img src=\"";
|
||||||
|
if (imageChip.contains(s)) {
|
||||||
|
int ix = imageChip.indexOf(s) + s.length();
|
||||||
|
imageChip = imageChip.substring(ix, imageChip.indexOf("\"", ix + 1));
|
||||||
|
chip.setUrl(imageChip);
|
||||||
|
textChip = textChip.replaceAll("[<](/)?img[^>]*[>]", "");
|
||||||
|
}
|
||||||
|
chip.setText(textChip);
|
||||||
|
chip.setIconType(IconType.CLOSE);
|
||||||
|
|
||||||
|
return chip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChipRemovable(Suggestion suggestion) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChipSelectable(Suggestion suggestion) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<List<? extends Suggestion>> handler) {
|
||||||
|
return addHandler(new ValueChangeHandler<List<? extends Suggestion>>() {
|
||||||
|
@Override
|
||||||
|
public void onValueChange(ValueChangeEvent<List<? extends Suggestion>> event) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
handler.onValueChange(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, ValueChangeEvent.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerRegistration addBlurHandler(BlurHandler handler) {
|
||||||
|
return itemBox.addHandler(blurEvent -> {
|
||||||
|
if (isEnabled()) {
|
||||||
|
handler.onBlur(blurEvent);
|
||||||
|
}
|
||||||
|
}, BlurEvent.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerRegistration addFocusHandler(FocusHandler handler) {
|
||||||
|
return itemBox.addHandler(focusEvent -> {
|
||||||
|
if (isEnabled()) {
|
||||||
|
handler.onFocus(focusEvent);
|
||||||
|
}
|
||||||
|
}, FocusEvent.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the selected {@link Suggestion}s. Modifications to the list are
|
||||||
|
* not propagated to the component.
|
||||||
|
*
|
||||||
|
* @return the list of selected {@link Suggestion}s, or empty if none was
|
||||||
|
* selected (never <code>null</code>).
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<? extends Suggestion> getValue() {
|
||||||
|
return new ArrayList<>(suggestionMap.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(List<? extends Suggestion> value, boolean fireEvents) {
|
||||||
|
clear();
|
||||||
|
if (value != null) {
|
||||||
|
placeholderLabel.addStyleName(CssName.ACTIVE);
|
||||||
|
for (Suggestion suggestion : value) {
|
||||||
|
addItem(suggestion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.setValue(value, fireEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
super.setEnabled(enabled);
|
||||||
|
itemBox.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ErrorMixin<AbstractValueWidget, MaterialLabel> getErrorMixin() {
|
||||||
|
return errorMixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label getPlaceholderLabel() {
|
||||||
|
return placeholderLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextBox getItemBox() {
|
||||||
|
return itemBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MaterialLabel getErrorLabel() {
|
||||||
|
return errorLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuggestBox getSuggestBox() {
|
||||||
|
return suggestBox;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.autocomplete;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.resources.client.ClientBundle;
|
||||||
|
import com.google.gwt.resources.client.TextResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client Bundle for Autocomplete component
|
||||||
|
*
|
||||||
|
* @author kevzlou7979
|
||||||
|
*/
|
||||||
|
interface MaterialAutocompleteClientBundle extends ClientBundle {
|
||||||
|
|
||||||
|
MaterialAutocompleteClientBundle INSTANCE = GWT.create(MaterialAutocompleteClientBundle.class);
|
||||||
|
|
||||||
|
@Source("autocomplete.min.css")
|
||||||
|
TextResource autocompleteCss();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.autocomplete;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.resources.client.ClientBundle;
|
||||||
|
import com.google.gwt.resources.client.TextResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client Bundle for Autocomplete component
|
||||||
|
*
|
||||||
|
* @author kevzlou7979
|
||||||
|
*/
|
||||||
|
interface MaterialAutocompleteDebugClientBundle extends ClientBundle {
|
||||||
|
|
||||||
|
MaterialAutocompleteDebugClientBundle INSTANCE = GWT.create(MaterialAutocompleteDebugClientBundle.class);
|
||||||
|
|
||||||
|
@Source("autocomplete.css")
|
||||||
|
TextResource autocompleteCssDebug();
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
ul.multiValueSuggestBox-list {
|
||||||
|
overflow: hidden;
|
||||||
|
height: auto !important;
|
||||||
|
height: 1%;
|
||||||
|
cursor: text;
|
||||||
|
min-height: 1px;
|
||||||
|
z-index: 999;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
list-style-type: none;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border-bottom: 1px solid #9e9e9e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete.disabled ul.multiValueSuggestBox-list {
|
||||||
|
border-bottom: 1px dotted rgba(0, 0, 0, 0.26);
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete.disabled .chip i {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-text .multiValueSuggestBox-input-token, .autocomplete-text .multiValueSuggestBox-input-token input {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete.read-only ul.multiValueSuggestBox-list {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete.disabled .chip {
|
||||||
|
color: rgba(0,0,0,0.6) !important;
|
||||||
|
background-color: #e4e4e4 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gwt-SuggestBoxPopup .item {
|
||||||
|
padding-left: 20px !important;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gwt-SuggestBoxPopup .item img {
|
||||||
|
border-radius: 12px;
|
||||||
|
float: left;
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
.gwt-SuggestBoxPopup {
|
||||||
|
z-index: 9999;
|
||||||
|
min-width: 300px !important;
|
||||||
|
background: white;
|
||||||
|
border-radius: 2px;
|
||||||
|
-webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
-moz-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
.gwt-SuggestBoxPopup tr {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.gwt-SuggestBoxPopup .item-selected {
|
||||||
|
background: rgba(0,0,0,.03) !important;
|
||||||
|
}
|
||||||
|
.suggestPopupMiddleCenter {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.suggestPopupMiddle {
|
||||||
|
width: 100%;
|
||||||
|
left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestPopupTop, .suggestPopupBottom, .suggestPopupMiddleLeft, .suggestPopupMiddleRight {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.multiValueSuggestBox-list li input {
|
||||||
|
border: 0;
|
||||||
|
width: 200px;
|
||||||
|
background-color: transparent;
|
||||||
|
margin: 0px;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.multiValueSuggestBox-list input[type=text]:focus:not([readonly]) {
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: 0 1px 0 0 #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.multiValueSuggestBox-token {
|
||||||
|
cursor: default;
|
||||||
|
float: left;
|
||||||
|
margin: 8px 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.multiValueSuggestBox-input-token {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row .autocomplete label {
|
||||||
|
left: 0.75rem !important;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
.autocomplete.disabled .chip i,.suggestPopupBottom,.suggestPopupMiddleLeft,.suggestPopupMiddleRight,.suggestPopupTop{display:none}ul.multiValueSuggestBox-list{overflow:hidden;height:auto!important;height:1%;cursor:text;min-height:1px;z-index:999;margin:0 0 15px;padding:0;border:none;width:100%;list-style-type:none;border-bottom:1px solid #9e9e9e}.autocomplete.disabled ul.multiValueSuggestBox-list{border-bottom:1px dotted rgba(0,0,0,.26)}.autocomplete-text .multiValueSuggestBox-input-token,.autocomplete-text .multiValueSuggestBox-input-token input{width:100%!important}.autocomplete.read-only ul.multiValueSuggestBox-list{border:none!important}.autocomplete.disabled .chip{color:rgba(0,0,0,.6)!important;background-color:#e4e4e4!important}.gwt-SuggestBoxPopup .item{padding-left:20px!important;padding:12px}.gwt-SuggestBoxPopup .item img{border-radius:12px;float:left;height:24px;width:24px;margin-right:12px}.gwt-SuggestBoxPopup{z-index:9999;min-width:300px!important;background:#fff;border-radius:2px;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);-moz-box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12)}.gwt-SuggestBoxPopup tr{white-space:nowrap}.gwt-SuggestBoxPopup .item-selected{background:rgba(0,0,0,.03)!important}.suggestPopupMiddleCenter{width:100%;padding:0!important}.suggestPopupMiddle{width:100%;left:0!important}ul.multiValueSuggestBox-list li input{width:200px;background-color:transparent;margin:0;border:none!important}ul.multiValueSuggestBox-list input[type=text]:focus:not([readonly]){border:none!important;box-shadow:0 1px 0 0 #fff!important}li.multiValueSuggestBox-token{cursor:default;float:left;margin:8px 0 0 8px}li.multiValueSuggestBox-input-token{float:left}.row .autocomplete label{left:.75rem!important}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.event;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
|
||||||
|
import com.google.gwt.event.shared.GwtEvent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class DeleteMessageEvent extends GwtEvent<DeleteMessageEventHandler> {
|
||||||
|
public static Type<DeleteMessageEventHandler> TYPE = new Type<DeleteMessageEventHandler>();
|
||||||
|
|
||||||
|
private ConvMessage m;
|
||||||
|
private boolean sent;
|
||||||
|
public DeleteMessageEvent(ConvMessage m, boolean sent) {
|
||||||
|
this.m = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConvMessage getMessage() {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSent() {
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type<DeleteMessageEventHandler> getAssociatedType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatch(DeleteMessageEventHandler handler) {
|
||||||
|
handler.onDeleteMessage(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.event;
|
||||||
|
|
||||||
|
import com.google.gwt.event.shared.EventHandler;
|
||||||
|
|
||||||
|
public interface DeleteMessageEventHandler extends EventHandler {
|
||||||
|
void onDeleteMessage(DeleteMessageEvent event);
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.event;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import com.google.gwt.event.shared.GwtEvent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class NewMessageEvent extends GwtEvent<NewMessageEventHandler> {
|
||||||
|
public static Type<NewMessageEventHandler> TYPE = new Type<NewMessageEventHandler>();
|
||||||
|
|
||||||
|
|
||||||
|
private String text;
|
||||||
|
private HashSet<String> mentionedUsers;
|
||||||
|
|
||||||
|
public NewMessageEvent() {
|
||||||
|
|
||||||
|
this.text = text;
|
||||||
|
this.mentionedUsers = mentionedUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<String> getMentionedUsers() {
|
||||||
|
return mentionedUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type<NewMessageEventHandler> getAssociatedType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatch(NewMessageEventHandler handler) {
|
||||||
|
handler.onNewMessage(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.event;
|
||||||
|
|
||||||
|
import com.google.gwt.event.shared.EventHandler;
|
||||||
|
|
||||||
|
public interface NewMessageEventHandler extends EventHandler {
|
||||||
|
void onNewMessage(NewMessageEvent event);
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.oracle;
|
||||||
|
import gwt.material.design.addins.client.autocomplete.base.MaterialSuggestionOracle;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageService;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageServiceAsync;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.CurrUserAndPortalUsersWrapper;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.WSUser;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||||
|
|
||||||
|
public class UserOracle extends MaterialSuggestionOracle{
|
||||||
|
private final MessageServiceAsync convService = GWT.create(MessageService.class);
|
||||||
|
|
||||||
|
private List<WSUser> contacts = new LinkedList<>();
|
||||||
|
|
||||||
|
public void addContacts(List<WSUser> users) {
|
||||||
|
contacts.addAll(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserOracle() {
|
||||||
|
((ServiceDefTarget) convService).setServiceEntryPoint("/delegate/message-conversations");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestSuggestions(Request request, Callback callback) {
|
||||||
|
Response resp = new Response();
|
||||||
|
if(contacts.isEmpty()){
|
||||||
|
callback.onSuggestionsReady(request, resp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String text = request.getQuery();
|
||||||
|
text = text.toLowerCase();
|
||||||
|
|
||||||
|
final List<UserSuggestion> list = new ArrayList<>();
|
||||||
|
convService.searchUsers(text, new AsyncCallback<ArrayList<WSUser>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable arg0) {
|
||||||
|
GWT.log("error");
|
||||||
|
callback.onSuggestionsReady(request, resp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ArrayList<WSUser> results) {
|
||||||
|
for (WSUser contact : results){
|
||||||
|
list.add(new UserSuggestion(contact));
|
||||||
|
}
|
||||||
|
resp.setSuggestions(list);
|
||||||
|
callback.onSuggestionsReady(request, resp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.oracle;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.WSUser;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.ui.SuggestOracle;
|
||||||
|
|
||||||
|
public class UserSuggestion implements SuggestOracle.Suggestion {
|
||||||
|
|
||||||
|
private WSUser user;
|
||||||
|
|
||||||
|
public UserSuggestion(WSUser user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayString() {
|
||||||
|
return getReplacementString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReplacementString() {
|
||||||
|
return user.getFullName() + " ("+user.getEmail()+")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public WSUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,380 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageService;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageServiceAsync;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.Utils;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.event.DeleteMessageEvent;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.ui.resources.MessagesResources;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.MessageUserModel;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* GwtMaterial
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2015 - 2016 GwtMaterialDesign
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
|
import com.google.gwt.event.logical.shared.ResizeEvent;
|
||||||
|
import com.google.gwt.event.logical.shared.ResizeHandler;
|
||||||
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
|
import com.google.gwt.uibinder.client.UiField;
|
||||||
|
import com.google.gwt.uibinder.client.UiHandler;
|
||||||
|
import com.google.gwt.user.client.Window;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||||
|
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.RootPanel;
|
||||||
|
import com.google.gwt.user.client.ui.ScrollPanel;
|
||||||
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
|
import gwt.material.design.client.constants.IconType;
|
||||||
|
import gwt.material.design.client.constants.Position;
|
||||||
|
import gwt.material.design.client.ui.MaterialAnchorButton;
|
||||||
|
import gwt.material.design.client.ui.MaterialBadge;
|
||||||
|
import gwt.material.design.client.ui.MaterialCollection;
|
||||||
|
import gwt.material.design.client.ui.MaterialFAB;
|
||||||
|
import gwt.material.design.client.ui.MaterialLink;
|
||||||
|
import gwt.material.design.client.ui.MaterialProgress;
|
||||||
|
import gwt.material.design.client.ui.MaterialRow;
|
||||||
|
import gwt.material.design.client.ui.MaterialToast;
|
||||||
|
import gwt.material.design.client.ui.animate.MaterialAnimation;
|
||||||
|
import gwt.material.design.client.ui.animate.Transition;
|
||||||
|
|
||||||
|
public class ApplicationView extends Composite {
|
||||||
|
|
||||||
|
interface Binder extends UiBinder<Widget, ApplicationView> {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Binder uiBinder = GWT.create(Binder.class);
|
||||||
|
private final MessageServiceAsync convService = GWT.create(MessageService.class);
|
||||||
|
|
||||||
|
|
||||||
|
private boolean toggle = false;
|
||||||
|
private boolean toggleSwitch = false;
|
||||||
|
private int unreadMessages = 0;
|
||||||
|
private int totalMessages = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@UiField ScrollPanel scrollerPanel;
|
||||||
|
@UiField MaterialRow rightPanel;
|
||||||
|
@UiField HTMLPanel htmlPanel;
|
||||||
|
@UiField MaterialFAB FAB;
|
||||||
|
@UiField MaterialLink menu, newMessage, switcher;
|
||||||
|
@UiField MaterialAnchorButton replyAll, reply, forward;
|
||||||
|
@UiField MaterialCollection messagesCollection;
|
||||||
|
@UiField MaterialProgress messageLoader, messagesLoader;
|
||||||
|
@UiField MaterialBadge badge;
|
||||||
|
|
||||||
|
private ConvMessage currentSelected;
|
||||||
|
private DisplayMessage displayMessage;
|
||||||
|
private WriteMessage newMessageDisplay;
|
||||||
|
|
||||||
|
|
||||||
|
public ApplicationView() {
|
||||||
|
initWidget(uiBinder.createAndBindUi(this));
|
||||||
|
((ServiceDefTarget) convService).setServiceEntryPoint("/delegate/message-conversations");
|
||||||
|
displayMessage = new DisplayMessage(convService, this);
|
||||||
|
newMessageDisplay = new WriteMessage(convService, this);
|
||||||
|
Window.addResizeHandler(new ResizeHandler() {
|
||||||
|
@Override
|
||||||
|
public void onResize(ResizeEvent event) {
|
||||||
|
int height = event.getHeight() - 100;
|
||||||
|
scrollerPanel.setHeight(height+"px");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scrollerPanel.add(displayMessage);
|
||||||
|
if (! Utils.isMobile()) {
|
||||||
|
reply.setTooltip("Reply");
|
||||||
|
reply.setTooltipPosition(Position.LEFT);
|
||||||
|
replyAll.setTooltip("Reply All");
|
||||||
|
replyAll.setTooltipPosition(Position.LEFT);
|
||||||
|
forward.setTooltip("Forward");
|
||||||
|
forward.setTooltipPosition(Position.LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param sent
|
||||||
|
*/
|
||||||
|
public void readUserMessages(final boolean sent) {
|
||||||
|
messagesLoader.setVisible(true);
|
||||||
|
convService.getMessages(sent, new AsyncCallback<ArrayList<ConvMessage>>() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable arg0) {
|
||||||
|
RootPanel.get("create-users-container").add(new HTML("ERROR "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ArrayList<ConvMessage> messages) {
|
||||||
|
if (messages != null) {
|
||||||
|
showMessages(messages, sent);
|
||||||
|
if (messages.size() > 0)
|
||||||
|
readUserMessage(messages.get(0).getId(), sent);
|
||||||
|
else {
|
||||||
|
writeWelcomeMessage();
|
||||||
|
messageLoader.setVisible(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RootPanel.get("create-users-container").add(new HTML("It is impossible to read your messages at this time. "
|
||||||
|
+ "This could be a server error, please try to reload the page"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param messages
|
||||||
|
* @param sent
|
||||||
|
*/
|
||||||
|
public void showMessages(ArrayList<ConvMessage> messages, boolean sent) {
|
||||||
|
messagesCollection.clear();
|
||||||
|
messagesLoader.setVisible(false);
|
||||||
|
messagesCollection.setVisible(true);
|
||||||
|
int scrollerHeight = Window.getClientHeight() - 100;
|
||||||
|
scrollerPanel.setHeight(scrollerHeight+"px");
|
||||||
|
for (ConvMessage convMessage : messages) {
|
||||||
|
messagesCollection.add(new MessageItem(convMessage, messagesCollection, this, sent));
|
||||||
|
if (! (sent || convMessage.isRead()))
|
||||||
|
unreadMessages++;
|
||||||
|
totalMessages++;
|
||||||
|
}
|
||||||
|
if (messages.size() > 0) {
|
||||||
|
MessageItem first = (MessageItem) messagesCollection.getChildrenList().get(0);
|
||||||
|
first.setSelected(true);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
updateBadge(sent);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
public void deleteMessage(final DeleteMessageEvent event) {
|
||||||
|
final ConvMessage toDelete = event.getMessage();
|
||||||
|
boolean sent = event.isSent();
|
||||||
|
convService.deleteMessageById(toDelete.getId(), sent, new AsyncCallback<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable caught) {
|
||||||
|
MaterialToast.fireToast("Message Deleted Failed for ("+toDelete.getSubject()+")");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Boolean result) {
|
||||||
|
MaterialToast.fireToast("Message Deleted ("+toDelete.getSubject()+")");
|
||||||
|
totalMessages = totalMessages - 1;
|
||||||
|
updateBadge(event.isSent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
public void setMessageUnread(ConvMessage toSet) {
|
||||||
|
convService.markMessageUnread(toSet.getId(), new AsyncCallback<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable caught) {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Boolean result) {
|
||||||
|
unreadMessages++;
|
||||||
|
updateBadge(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param messageId
|
||||||
|
* @param sent
|
||||||
|
*/
|
||||||
|
public void readUserMessage(String messageId, final boolean sent) {
|
||||||
|
messageLoader.setColor(Utils.getRandomColor());
|
||||||
|
messageLoader.setVisible(true);
|
||||||
|
scrollerPanel.clear();
|
||||||
|
convService.getMessageById(messageId, toggleSwitch, new AsyncCallback<ConvMessage>() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable arg0) {
|
||||||
|
RootPanel.get("create-users-container").add(new HTML("ERROR getting message "));
|
||||||
|
messageLoader.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ConvMessage toShow) {
|
||||||
|
messageLoader.setVisible(false);
|
||||||
|
displayMessage.showMessage(toShow);
|
||||||
|
scrollerPanel.add(displayMessage);
|
||||||
|
setCurrentSelectedMessage(toShow);
|
||||||
|
if (!sent)
|
||||||
|
decreaseUnreadCounter(toShow);
|
||||||
|
FAB.setVisible(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private void updateBadge(boolean sent) {
|
||||||
|
String badgeText = totalMessages + (sent ? " sent" : " (" + unreadMessages + " unread" + ")");
|
||||||
|
if (unreadMessages == 0 && !sent)
|
||||||
|
badgeText = totalMessages+" received";
|
||||||
|
badge.setText(badgeText);
|
||||||
|
badge.setVisible(true);
|
||||||
|
}
|
||||||
|
private void decreaseUnreadCounter(ConvMessage toShow) {
|
||||||
|
if (unreadMessages > 0 && !toShow.isRead())
|
||||||
|
unreadMessages--;
|
||||||
|
updateBadge(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetCounters() {
|
||||||
|
badge.setVisible(false);
|
||||||
|
unreadMessages = 0;
|
||||||
|
totalMessages = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@UiHandler("switcher")
|
||||||
|
void onSwitchSentInbox(ClickEvent e) {
|
||||||
|
resetCounters();
|
||||||
|
MaterialAnimation animation = new MaterialAnimation();
|
||||||
|
animation.setDelay(0);
|
||||||
|
animation.setDuration(1000);
|
||||||
|
animation.transition(Transition.FLIPINX);
|
||||||
|
animation.animate(switcher);
|
||||||
|
if(!toggleSwitch){
|
||||||
|
switcher.setIconType(IconType.SEND);
|
||||||
|
}else{
|
||||||
|
switcher.setIconType(IconType.INBOX);
|
||||||
|
}
|
||||||
|
toggleSwitch = ! toggleSwitch;
|
||||||
|
readUserMessages(toggleSwitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("menu")
|
||||||
|
void onHideShowSidebar(ClickEvent e) {
|
||||||
|
if(toggle){
|
||||||
|
showSidePanel();
|
||||||
|
}else{
|
||||||
|
hideSidePanel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void displayNewOrReplyMessage() {
|
||||||
|
FAB.setVisible(false);
|
||||||
|
messagesCollection.clearActive();
|
||||||
|
scrollerPanel.clear();
|
||||||
|
scrollerPanel.add(newMessageDisplay);
|
||||||
|
newMessageDisplay.setFocusOnUsersInput();
|
||||||
|
if (Utils.isMobile())
|
||||||
|
hideSidePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("newMessage")
|
||||||
|
void onNewMessage(ClickEvent e) {
|
||||||
|
newMessageDisplay = new WriteMessage(convService, this);
|
||||||
|
displayNewOrReplyMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("reply")
|
||||||
|
void onReplyMessage(ClickEvent e) {
|
||||||
|
if (currentSelected != null) {
|
||||||
|
newMessageDisplay = new WriteMessage(convService, this);
|
||||||
|
ConvMessage msg = currentSelected;
|
||||||
|
newMessageDisplay.setIsReply(msg);
|
||||||
|
displayNewOrReplyMessage();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Window.alert("Cannot find which message to reply, please report the issue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@UiHandler("replyAll")
|
||||||
|
void onReplyAllMessage(ClickEvent e) {
|
||||||
|
if (currentSelected != null) {
|
||||||
|
newMessageDisplay = new WriteMessage(convService, this);
|
||||||
|
ConvMessage msg = currentSelected;
|
||||||
|
newMessageDisplay.setIsReplyAll(msg);
|
||||||
|
displayNewOrReplyMessage();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Window.alert("Cannot find which message to reply all, please report the issue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@UiHandler("forward")
|
||||||
|
void onForwardMessage(ClickEvent e) {
|
||||||
|
if (currentSelected != null) {
|
||||||
|
newMessageDisplay = new WriteMessage(convService, this);
|
||||||
|
ConvMessage msg = currentSelected;
|
||||||
|
newMessageDisplay.setIsForward(msg);
|
||||||
|
displayNewOrReplyMessage();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Window.alert("Cannot find which message to forward, please report the issue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected void showSidePanel() {
|
||||||
|
displayMessage.getMainPanel().setLeft(350);
|
||||||
|
displayMessage.getMainPanel().setGrid("l8 m12 s12");
|
||||||
|
newMessageDisplay.getMainPanel().setLeft(350);
|
||||||
|
newMessageDisplay.getMainPanel().setGrid("l8 m12 s12");
|
||||||
|
rightPanel.setLeft(0);
|
||||||
|
toggle = ! toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void hideSidePanel() {
|
||||||
|
displayMessage.getMainPanel().setLeft(0);
|
||||||
|
displayMessage.getMainPanel().setGrid("l12 s12 m12");
|
||||||
|
newMessageDisplay.getMainPanel().setLeft(0);
|
||||||
|
newMessageDisplay.getMainPanel().setGrid("l12 s12 m12");
|
||||||
|
|
||||||
|
rightPanel.setLeft(-350);
|
||||||
|
toggle = ! toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCurrentSelectedMessage(ConvMessage msg) {
|
||||||
|
currentSelected = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeWelcomeMessage() {
|
||||||
|
MessagesResources images = GWT.create(MessagesResources.class);
|
||||||
|
List<MessageUserModel> recipients = Arrays.asList(new MessageUserModel(0, "you", "You", ""));
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
MessageUserModel sender = new MessageUserModel(0, "jarvis", "D4Science Team", images.d4scienceTeam().getURL(), "", "");
|
||||||
|
ConvMessage welcomeMessage = new ConvMessage("0", "Welcome to your Messages", sender, recipients , new Date(), MessagesResources.WELCOME_MESSAGE, true);
|
||||||
|
FAB.setVisible(false);
|
||||||
|
displayMessage.showMessage(welcomeMessage);
|
||||||
|
welcomeMessage.setContent(MessagesResources.WELCOME_MESSAGE.substring(0, 102)+ " ...");
|
||||||
|
MessageItem item = new MessageItem(welcomeMessage, messagesCollection, this, false);
|
||||||
|
item.hideMessageMenu();
|
||||||
|
messagesCollection.add(item);
|
||||||
|
totalMessages++;
|
||||||
|
updateBadge(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||||
|
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:m="urn:import:gwt.material.design.client.ui"
|
||||||
|
xmlns:ma="urn:import:gwt.material.design.addins.client"
|
||||||
|
xmlns:mc="urn:import:org.gcube.portets.user.message_conversations.client.autocomplete">
|
||||||
|
|
||||||
|
<ui:style>
|
||||||
|
.animation {
|
||||||
|
transition: 0.4s all;
|
||||||
|
-webkit-transition: 0.4s all;
|
||||||
|
-moz-transition: 0.4s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.borderRight {
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topBar {
|
||||||
|
height: 60px;
|
||||||
|
overflow-y: hidden !important; /* needed in windows */
|
||||||
|
border-bottom: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marginTop {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflowXHidden {
|
||||||
|
overflow-x: hidden !important; /* needed in windows */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalTitle {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alignCenter {
|
||||||
|
text-align: center;
|
||||||
|
padding: 50px;
|
||||||
|
}
|
||||||
|
</ui:style>
|
||||||
|
<g:HTMLPanel ui:field="htmlPanel">
|
||||||
|
<!-- TOP BAR -->
|
||||||
|
<m:MaterialHeader ui:field="header">
|
||||||
|
<m:MaterialNavBar ui:field="navBar" layoutPosition="FIXED"
|
||||||
|
addStyleNames="{style.topBar}" height="60" backgroundColor="WHITE">
|
||||||
|
<m:MaterialNavSection float="LEFT" showOn="SHOW_ON_MED_DOWN">
|
||||||
|
<m:MaterialLink iconType="MENU" iconColor="LIGHT_BLUE_DARKEN_2"
|
||||||
|
paddingLeft="25" waves="DEFAULT" ui:field="menu" hideOn="HIDE_ON_MED_DOWN" />
|
||||||
|
<m:MaterialLink iconType="INBOX" textColor="LIGHT_BLUE_DARKEN_2"
|
||||||
|
ui:field="switcher" waves="DEFAULT" paddingLeft="25">
|
||||||
|
<m:MaterialBadge text="22 unread" backgroundColor="LIGHT_BLUE_DARKEN_2"
|
||||||
|
textColor="WHITE" circle="false" ui:field="badge" visible="false"
|
||||||
|
hideOn="HIDE_ON_MED_DOWN" />
|
||||||
|
</m:MaterialLink>
|
||||||
|
<m:MaterialLink ui:field="newMessage" text="New"
|
||||||
|
showOn="SHOW_ON_MED_DOWN" iconType="MESSAGE" textColor="LIGHT_BLUE_DARKEN_2"
|
||||||
|
waves="LIGHT" />
|
||||||
|
</m:MaterialNavSection>
|
||||||
|
</m:MaterialNavBar>
|
||||||
|
</m:MaterialHeader>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- SIDE PANEL -->
|
||||||
|
<m:MaterialRow ui:field="rightPanel" overflow="AUTO"
|
||||||
|
depth="995" grid="l3 m3 s12" padding="0" backgroundColor="WHITE"
|
||||||
|
height="100%" layoutPosition="FIXED" top="60" left="0" width="350px"
|
||||||
|
addStyleNames="{style.animation} {style.borderRight}">
|
||||||
|
<m:MaterialProgress type="INDETERMINATE" ui:field="messagesLoader"
|
||||||
|
color="BLUE" />
|
||||||
|
<m:MaterialCollection ui:field="messagesCollection"
|
||||||
|
addStyleNames="{style.marginTop}" visible="false">
|
||||||
|
</m:MaterialCollection>
|
||||||
|
</m:MaterialRow>
|
||||||
|
|
||||||
|
<!-- MAIN WINDOW -->
|
||||||
|
<m:MaterialContainer fontSize="0.8em">
|
||||||
|
<m:MaterialRow layoutPosition="RELATIVE" grid="l8 s12 m12"
|
||||||
|
top="65">
|
||||||
|
<m:MaterialProgress type="INDETERMINATE"
|
||||||
|
ui:field="messageLoader" color="TEAL" />
|
||||||
|
<g:ScrollPanel height="600px" ui:field="scrollerPanel"
|
||||||
|
addStyleNames="{style.overflowXHidden}"></g:ScrollPanel>
|
||||||
|
</m:MaterialRow>
|
||||||
|
</m:MaterialContainer>
|
||||||
|
|
||||||
|
<!-- FAB -->
|
||||||
|
<m:MaterialFAB ui:field="FAB">
|
||||||
|
<m:MaterialButton type="FLOATING" backgroundColor="RED"
|
||||||
|
iconType="REPLY" size="LARGE" />
|
||||||
|
<m:MaterialFABList>
|
||||||
|
<m:MaterialAnchorButton type="FLOATING"
|
||||||
|
waves="LIGHT" backgroundColor="BLUE" ui:field="forward" iconType="FORWARD" />
|
||||||
|
<m:MaterialAnchorButton type="FLOATING"
|
||||||
|
waves="LIGHT" backgroundColor="AMBER" ui:field="replyAll" iconType="REPLY_ALL" />
|
||||||
|
<m:MaterialAnchorButton type="FLOATING"
|
||||||
|
waves="LIGHT" backgroundColor="TEAL" ui:field="reply" iconType="REPLY" />
|
||||||
|
</m:MaterialFABList>
|
||||||
|
</m:MaterialFAB>
|
||||||
|
</g:HTMLPanel>
|
||||||
|
</ui:UiBinder>
|
|
@ -0,0 +1,134 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.ui;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageServiceAsync;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.FileModel;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.client.notification.WorkspaceExplorerSaveNotification.WorskpaceExplorerSaveNotificationListener;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.client.save.WorkspaceExplorerSaveDialog;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.shared.Item;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.dom.client.Style.Unit;
|
||||||
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
|
import com.google.gwt.uibinder.client.UiField;
|
||||||
|
import com.google.gwt.uibinder.client.UiHandler;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
import com.google.gwt.user.client.ui.Composite;
|
||||||
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
|
import gwt.material.design.client.ui.MaterialButton;
|
||||||
|
import gwt.material.design.client.ui.MaterialDropDown;
|
||||||
|
import gwt.material.design.client.ui.MaterialLink;
|
||||||
|
import gwt.material.design.client.ui.MaterialLoader;
|
||||||
|
import gwt.material.design.client.ui.MaterialToast;
|
||||||
|
|
||||||
|
public class AttachmentMenu extends Composite {
|
||||||
|
|
||||||
|
private static AttachmentMenuUiBinder uiBinder = GWT.create(AttachmentMenuUiBinder.class);
|
||||||
|
|
||||||
|
interface AttachmentMenuUiBinder extends UiBinder<Widget, AttachmentMenu> {
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum DownloadStatus { FAILED, IN_PROGRESS, COMPLETE };
|
||||||
|
|
||||||
|
@UiField MaterialDropDown menu;
|
||||||
|
@UiField MaterialLink downloadButton;
|
||||||
|
@UiField MaterialLink saveWSButton;
|
||||||
|
|
||||||
|
private FileModel item;
|
||||||
|
private MaterialButton parentButton;
|
||||||
|
private MessageServiceAsync convService;
|
||||||
|
private DownloadStatus generatingDownloadURL = DownloadStatus.IN_PROGRESS;
|
||||||
|
|
||||||
|
public AttachmentMenu(MessageServiceAsync convService, MaterialButton parent, FileModel item) {
|
||||||
|
initWidget(uiBinder.createAndBindUi(this));
|
||||||
|
this.item = item;
|
||||||
|
this.parentButton = parent;
|
||||||
|
this.convService = convService;
|
||||||
|
convService.getAttachmentDownloadURL(item.getIdentifier(), new AsyncCallback<String>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String result) {
|
||||||
|
if (result != null) {
|
||||||
|
downloadButton.setHref(result);
|
||||||
|
generatingDownloadURL = DownloadStatus.COMPLETE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generatingDownloadURL = DownloadStatus.FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable caught) {
|
||||||
|
GWT.log("onFailure");
|
||||||
|
generatingDownloadURL = DownloadStatus.FAILED;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeparator(boolean separator) {
|
||||||
|
menu.setSeparator(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActivator(String activator) {
|
||||||
|
menu.setActivator(activator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("downloadButton")
|
||||||
|
void onFileDownload(ClickEvent e) {
|
||||||
|
switch (generatingDownloadURL) {
|
||||||
|
case IN_PROGRESS:
|
||||||
|
e.stopPropagation();
|
||||||
|
MaterialToast.fireToast("Generating link is in progress, please retry in few seconds", "rounded");
|
||||||
|
break;
|
||||||
|
case COMPLETE:
|
||||||
|
MaterialToast.fireToast("Download in progress ... ", "rounded");
|
||||||
|
break;
|
||||||
|
case FAILED:
|
||||||
|
e.stopPropagation();
|
||||||
|
downloadButton.setHref("#");
|
||||||
|
MaterialToast.fireToast("Warning: could not generate a download link, some error occurred in the server", "rounded");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("saveWSButton")
|
||||||
|
void onSave2WS(ClickEvent e) {
|
||||||
|
final WorkspaceExplorerSaveDialog navigator = new WorkspaceExplorerSaveDialog(item.getName(), true);
|
||||||
|
navigator.addStyleName("BS-Navigator");;
|
||||||
|
navigator.getElement().getStyle().setLeft(50, Unit.PCT);
|
||||||
|
WorskpaceExplorerSaveNotificationListener listener = new WorskpaceExplorerSaveNotificationListener(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaving(Item parent, String fileName) {
|
||||||
|
GWT.log("onSaving parent: "+parent +", fileName" +fileName);
|
||||||
|
navigator.hide();
|
||||||
|
MaterialLoader.showProgress(true, parentButton);
|
||||||
|
convService.saveAttachmentToWorkspaceFolder(item.getIdentifier(), parent.getId(), new AsyncCallback<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable caught) {
|
||||||
|
MaterialLoader.showProgress(false, parentButton);
|
||||||
|
MaterialToast.fireToast("Warning: could not save this file to the selected Workspace folder, please retry", "rounded");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Boolean result) {
|
||||||
|
MaterialLoader.showProgress(false, parentButton);
|
||||||
|
MaterialToast.fireToast("File " +fileName+" Saved succesfully");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAborted() {
|
||||||
|
GWT.log("onAborted");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed(Throwable throwable) {
|
||||||
|
GWT.log("onFailed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
navigator.addWorkspaceExplorerSaveNotificationListener(listener);
|
||||||
|
navigator.show();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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:m="urn:import:gwt.material.design.client.ui">
|
||||||
|
<m:MaterialDropDown activator="dp-4" constrainWidth="true"
|
||||||
|
gutter="5" backgroundColor="WHITE" separator="true" ui:field="menu"
|
||||||
|
belowOrigin="true">
|
||||||
|
<m:MaterialLink textColor="BLUE" iconType="FOLDER_SHARED"
|
||||||
|
ui:field="saveWSButton" iconPosition="LEFT" text="Save in Workspace"
|
||||||
|
separator="true" />
|
||||||
|
<m:MaterialLink textColor="BLUE" iconType="FILE_DOWNLOAD"
|
||||||
|
ui:field="downloadButton" iconPosition="LEFT" text="Download"/>
|
||||||
|
</m:MaterialDropDown>
|
||||||
|
</ui:UiBinder>
|
|
@ -0,0 +1,107 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.ui;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageServiceAsync;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.Utils;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.FileModel;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.MessageUserModel;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.dom.client.Style.TextTransform;
|
||||||
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
|
import com.google.gwt.uibinder.client.UiField;
|
||||||
|
import com.google.gwt.uibinder.client.UiHandler;
|
||||||
|
import com.google.gwt.user.client.ui.Composite;
|
||||||
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
|
import gwt.material.design.client.constants.Color;
|
||||||
|
import gwt.material.design.client.constants.IconPosition;
|
||||||
|
import gwt.material.design.client.constants.IconType;
|
||||||
|
import gwt.material.design.client.constants.WavesType;
|
||||||
|
import gwt.material.design.client.ui.MaterialButton;
|
||||||
|
import gwt.material.design.client.ui.MaterialLabel;
|
||||||
|
import gwt.material.design.client.ui.MaterialPanel;
|
||||||
|
import gwt.material.design.client.ui.MaterialRow;
|
||||||
|
import gwt.material.design.client.ui.MaterialTextArea;
|
||||||
|
import gwt.material.design.client.ui.MaterialTitle;
|
||||||
|
|
||||||
|
public class DisplayMessage extends Composite {
|
||||||
|
|
||||||
|
private static DisplayMessageUiBinder uiBinder = GWT.create(DisplayMessageUiBinder.class);
|
||||||
|
|
||||||
|
interface DisplayMessageUiBinder extends UiBinder<Widget, DisplayMessage> {
|
||||||
|
}
|
||||||
|
@UiField MaterialPanel mainPanel;
|
||||||
|
|
||||||
|
@UiField MaterialRow messageAttachmentsBody;
|
||||||
|
@UiField MaterialButton showMessages;
|
||||||
|
@UiField MaterialTextArea messageContent;
|
||||||
|
@UiField MaterialTitle messageSender, messageSubject, messageRecipients;
|
||||||
|
private ApplicationView ap;
|
||||||
|
private MessageServiceAsync convService;
|
||||||
|
|
||||||
|
public DisplayMessage(MessageServiceAsync convService, ApplicationView ap) {
|
||||||
|
initWidget(uiBinder.createAndBindUi(this));
|
||||||
|
this.convService = convService;
|
||||||
|
this.ap = ap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the message in the main panel
|
||||||
|
* @param m message to display
|
||||||
|
*/
|
||||||
|
public void showMessage(ConvMessage m) {
|
||||||
|
String recipientsLabel = "";
|
||||||
|
|
||||||
|
for (MessageUserModel r : m.getRecipients()) {
|
||||||
|
String fullName = (r.getFullName() == null) ? r.getUsername() : r.getFullName();
|
||||||
|
recipientsLabel+= fullName+"; ";
|
||||||
|
}
|
||||||
|
String fullName = (m.getOwner().getFullName() == null) ? m.getOwner().getUsername() : m.getOwner().getFullName();
|
||||||
|
messageSender.setTitle(fullName + ", " + Utils.getFormatteDate(m.getDate()));
|
||||||
|
messageSubject.setTitle(m.getSubject());
|
||||||
|
messageRecipients.setTitle("To: "+recipientsLabel);
|
||||||
|
messageContent.setText(m.getContent());
|
||||||
|
messageRecipients.setVisible(true);
|
||||||
|
messageContent.setVisible(true);
|
||||||
|
|
||||||
|
messageAttachmentsBody.clear();
|
||||||
|
messageAttachmentsBody.setVisible(m.hasAttachments());
|
||||||
|
messageAttachmentsBody.add(new MaterialLabel("Attachments: "));
|
||||||
|
int i = 0;
|
||||||
|
for (FileModel item : m.getAttachments()) {
|
||||||
|
String activator = "item"+i;
|
||||||
|
String attachmentName = (item.getName().length() > 25) ? item.getName().substring(0, 20) + "..." : item.getName();
|
||||||
|
MaterialButton toAdd = new MaterialButton(attachmentName, IconType.ARROW_DROP_DOWN);
|
||||||
|
toAdd.setTitle(item.getName());
|
||||||
|
|
||||||
|
AttachmentMenu dd = new AttachmentMenu(convService, toAdd, item);
|
||||||
|
dd.setActivator(activator);
|
||||||
|
dd.setSeparator(true);
|
||||||
|
|
||||||
|
toAdd.setMargin(5);
|
||||||
|
toAdd.setPaddingRight(5);
|
||||||
|
toAdd.setPaddingLeft(5);
|
||||||
|
toAdd.setWaves(WavesType.DEFAULT);
|
||||||
|
toAdd.setActivates(activator);
|
||||||
|
toAdd.setIconPosition(IconPosition.RIGHT);
|
||||||
|
toAdd.setBackgroundColor(Color.RED_DARKEN_1);
|
||||||
|
toAdd.getElement().getStyle().setBackgroundImage("none");
|
||||||
|
toAdd.getElement().getStyle().setTextTransform(TextTransform.NONE);
|
||||||
|
|
||||||
|
messageAttachmentsBody.add(toAdd);
|
||||||
|
messageAttachmentsBody.add(dd);
|
||||||
|
i = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("showMessages")
|
||||||
|
void onShowMessages(ClickEvent e) {
|
||||||
|
ap.showSidePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialPanel getMainPanel() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!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:m="urn:import:gwt.material.design.client.ui"
|
||||||
|
xmlns:ma="urn:import:gwt.material.design.addins.client">
|
||||||
|
<ui:style>
|
||||||
|
.animation {
|
||||||
|
transition: 0.4s all;
|
||||||
|
-webkit-transition: 0.4s all;
|
||||||
|
-moz-transition: 0.4s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflowXHidden {
|
||||||
|
overflow-x: hidden !important; /* needed in windows */
|
||||||
|
}
|
||||||
|
</ui:style>
|
||||||
|
<m:MaterialPanel ui:field="mainPanel" backgroundColor="WHITE"
|
||||||
|
layoutPosition="RELATIVE" marginBottom="0" grid="l8 m12 s12"
|
||||||
|
paddingLeft="10" paddingRight="60" marginLeft="5"
|
||||||
|
addStyleNames="{style.animation} message-metadata" left="350">
|
||||||
|
<m:MaterialButton type="FLAT" text="Back" waves="LIGHT"
|
||||||
|
ui:field="showMessages" iconType="FAST_REWIND" hideOn="HIDE_ON_MED_UP"
|
||||||
|
textColor="BLUE" paddingLeft="0" />
|
||||||
|
<m:MaterialTitle ui:field="messageSender"
|
||||||
|
addStyleNames="message-sender" marginTop="0"></m:MaterialTitle>
|
||||||
|
<m:MaterialTitle ui:field="messageSubject" marginTop="0"></m:MaterialTitle>
|
||||||
|
<m:MaterialTitle ui:field="messageRecipients" visible="false"
|
||||||
|
addStyleNames="message-recipients" marginTop="0"></m:MaterialTitle>
|
||||||
|
<m:MaterialRow ui:field="messageAttachmentsBody"></m:MaterialRow>
|
||||||
|
<m:MaterialTextArea ui:field="messageContent"
|
||||||
|
resizeRule="AUTO" visible="false" readOnly="true" />
|
||||||
|
</m:MaterialPanel>
|
||||||
|
|
||||||
|
</ui:UiBinder>
|
|
@ -0,0 +1,195 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.ui;
|
||||||
|
|
||||||
|
import org.gcube.portets.user.message_conversations.client.Utils;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.event.DeleteMessageEvent;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.ui.resources.MessagesResources;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.dom.client.Style.Cursor;
|
||||||
|
import com.google.gwt.dom.client.Style.Unit;
|
||||||
|
import com.google.gwt.dom.client.Style.Visibility;
|
||||||
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
|
import com.google.gwt.event.dom.client.ClickHandler;
|
||||||
|
import com.google.gwt.event.dom.client.MouseOutEvent;
|
||||||
|
import com.google.gwt.event.dom.client.MouseOutHandler;
|
||||||
|
import com.google.gwt.event.dom.client.MouseOverEvent;
|
||||||
|
import com.google.gwt.event.dom.client.MouseOverHandler;
|
||||||
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
|
import com.google.gwt.uibinder.client.UiField;
|
||||||
|
import com.google.gwt.uibinder.client.UiHandler;
|
||||||
|
import com.google.gwt.user.client.Random;
|
||||||
|
import com.google.gwt.user.client.ui.Composite;
|
||||||
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
|
import gwt.material.design.client.constants.Color;
|
||||||
|
import gwt.material.design.client.ui.MaterialCollection;
|
||||||
|
import gwt.material.design.client.ui.MaterialCollectionItem;
|
||||||
|
import gwt.material.design.client.ui.MaterialDropDown;
|
||||||
|
import gwt.material.design.client.ui.MaterialIcon;
|
||||||
|
import gwt.material.design.client.ui.MaterialImage;
|
||||||
|
import gwt.material.design.client.ui.MaterialLabel;
|
||||||
|
import gwt.material.design.client.ui.MaterialLink;
|
||||||
|
import gwt.material.design.client.ui.MaterialToast;
|
||||||
|
|
||||||
|
public class MessageItem extends Composite {
|
||||||
|
|
||||||
|
private static MessageItemUiBinder uiBinder = GWT.create(MessageItemUiBinder.class);
|
||||||
|
|
||||||
|
interface MessageItemUiBinder extends UiBinder<Widget, MessageItem> {
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static Color HOVER_MESSAGE_COLOR = Color.GREY_LIGHTEN_4;
|
||||||
|
|
||||||
|
private boolean deleteClicked = true;
|
||||||
|
|
||||||
|
private ApplicationView ap;
|
||||||
|
private MaterialCollection parentCollection;
|
||||||
|
private ConvMessage myMessage;
|
||||||
|
private boolean sent;
|
||||||
|
|
||||||
|
|
||||||
|
@UiField MaterialCollectionItem item;
|
||||||
|
@UiField MaterialImage avatarImage;
|
||||||
|
@UiField MaterialLabel senderNameLabel;
|
||||||
|
@UiField MaterialLabel subjectLabel;
|
||||||
|
@UiField MaterialLabel previewLabel;
|
||||||
|
@UiField MaterialLabel timeLabel;
|
||||||
|
@UiField MaterialIcon attachmentsIcon;
|
||||||
|
@UiField MaterialIcon messageActionIcon;
|
||||||
|
|
||||||
|
@UiField MaterialLink deleteButton;
|
||||||
|
@UiField MaterialDropDown dd;
|
||||||
|
|
||||||
|
MessagesResources images = GWT.create(MessagesResources.class);
|
||||||
|
|
||||||
|
|
||||||
|
public MessageItem(final ConvMessage m, MaterialCollection parentCollection, ApplicationView ap, boolean sent) {
|
||||||
|
initWidget(uiBinder.createAndBindUi(this));
|
||||||
|
item.getElement().getStyle().setCursor(Cursor.POINTER);
|
||||||
|
this.sent = sent;
|
||||||
|
this.myMessage = m;
|
||||||
|
this.ap = ap;
|
||||||
|
this.parentCollection = parentCollection;
|
||||||
|
if (m.hasAttachments())
|
||||||
|
attachmentsIcon.setVisibility(Visibility.VISIBLE);
|
||||||
|
if (!m.isRead())
|
||||||
|
item.addStyleName("unread-message");
|
||||||
|
if (m.getOwner().getAvatarURL() == null || m.getOwner().getAvatarURL().compareTo("")== 0) {
|
||||||
|
if (sent)
|
||||||
|
avatarImage.setResource(
|
||||||
|
m.getRecipients().size() > 1 ? images.group() : images.user());
|
||||||
|
else {
|
||||||
|
avatarImage.setResource(images.user());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (sent && m.getRecipients().size() > 1)
|
||||||
|
avatarImage.setResource(images.group());
|
||||||
|
else
|
||||||
|
avatarImage.setUrl(m.getOwner().getAvatarURL());
|
||||||
|
}
|
||||||
|
String fullName = (m.getOwner().getFullName() == null) ? m.getOwner().getUsername() : m.getOwner().getFullName();
|
||||||
|
senderNameLabel.setText(fullName);
|
||||||
|
subjectLabel.setText(m.getSubject());
|
||||||
|
previewLabel.setText(m.getContent());
|
||||||
|
timeLabel.setText(Utils.getFormatteDate(m.getDate()));
|
||||||
|
|
||||||
|
if (sent)
|
||||||
|
item.setBackgroundColor(Color.WHITE);
|
||||||
|
|
||||||
|
//because on tablet and on mobile cause problems
|
||||||
|
if (!Utils.isMobile()) {
|
||||||
|
item.addMouseOverHandler(new MouseOverHandler() {
|
||||||
|
@Override
|
||||||
|
public void onMouseOver(MouseOverEvent event) {
|
||||||
|
messageActionIcon.setVisibility(Visibility.VISIBLE);
|
||||||
|
item.setBackgroundColor(HOVER_MESSAGE_COLOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
item.addMouseOutHandler(new MouseOutHandler() {
|
||||||
|
@Override
|
||||||
|
public void onMouseOut(MouseOutEvent event) {
|
||||||
|
messageActionIcon.setVisibility(Visibility.HIDDEN);
|
||||||
|
item.setBackgroundColor(Color.WHITE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {//on mobile
|
||||||
|
messageActionIcon.setVisibility(Visibility.VISIBLE);
|
||||||
|
dd.setHoverable(false);
|
||||||
|
}
|
||||||
|
messageActionIcon.addClickHandler(new ClickHandler() {
|
||||||
|
@Override
|
||||||
|
public void onClick(ClickEvent event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteButton.addClickHandler(new ClickHandler() {
|
||||||
|
@Override
|
||||||
|
public void onClick(ClickEvent event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
MaterialLink link = new MaterialLink("UNDO");
|
||||||
|
link.addClickHandler(new ClickHandler() {
|
||||||
|
@Override
|
||||||
|
public void onClick(ClickEvent event) {
|
||||||
|
deleteClicked = false;
|
||||||
|
MaterialToast.fireToast("UNDO DONE");
|
||||||
|
item.setVisible(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new MaterialToast(()->{doDelete(m.getSubject());}, link).toast("Deleting Message ("+m.getSubject()+")");
|
||||||
|
item.setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dd.getElement().getStyle().setWidth(300, Unit.PX);
|
||||||
|
String activator = "activate"+Random.nextInt();
|
||||||
|
dd.setActivator(activator);
|
||||||
|
messageActionIcon.setActivates(activator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@UiHandler("setUnreadButton")
|
||||||
|
void onSetUnread(ClickEvent e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
ap.setMessageUnread(myMessage);
|
||||||
|
myMessage.setRead(false);
|
||||||
|
item.addStyleName("unread-message");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDelete(String subject) {
|
||||||
|
if (deleteClicked) {
|
||||||
|
GWT.log("is sent?"+ this.sent);
|
||||||
|
ap.deleteMessage(new DeleteMessageEvent(myMessage, this.sent));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
deleteClicked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(boolean active) {
|
||||||
|
item.setBackgroundColor(Color.WHITE);
|
||||||
|
item.removeStyleName("unread-message");
|
||||||
|
item.setActive(active);
|
||||||
|
myMessage.setRead(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("item")
|
||||||
|
void onClickedMessage(ClickEvent e) {
|
||||||
|
checkHideSideBarOnMobile();
|
||||||
|
parentCollection.clearActive();
|
||||||
|
ap.readUserMessage(myMessage.getId(), this.sent);
|
||||||
|
setSelected(true);
|
||||||
|
myMessage.setRead(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkHideSideBarOnMobile() {
|
||||||
|
if (Utils.isMobile())
|
||||||
|
ap.hideSidePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideMessageMenu() {
|
||||||
|
messageActionIcon.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
<!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:m="urn:import:gwt.material.design.client.ui">
|
||||||
|
|
||||||
|
<m:MaterialCollectionItem type="AVATAR"
|
||||||
|
ui:field="item" paddingLeft="55" paddingTop="5" paddingBottom="0"
|
||||||
|
lineHeight="18">
|
||||||
|
<m:MaterialImage ui:field="avatarImage" type="CIRCLE"
|
||||||
|
top="5" left="5" />
|
||||||
|
<m:MaterialLabel ui:field="senderNameLabel"
|
||||||
|
paddingLeft="0" fontSize="1.5em" textColor="BLACK" />
|
||||||
|
<m:MaterialLabel ui:field="subjectLabel" paddingLeft="0"
|
||||||
|
textColor="BLACK" />
|
||||||
|
<m:MaterialLabel ui:field="previewLabel" paddingLeft="0"
|
||||||
|
paddingRight="10" textColor="GREY" />
|
||||||
|
<m:MaterialCollectionSecondary top="0"
|
||||||
|
textAlign="RIGHT" right="2">
|
||||||
|
<m:MaterialLabel ui:field="timeLabel" textColor="GREY"
|
||||||
|
fontSize=".8em" />
|
||||||
|
<m:MaterialIcon iconType="KEYBOARD_ARROW_DOWN"
|
||||||
|
iconSize="SMALL" visibility="HIDDEN" ui:field="messageActionIcon"
|
||||||
|
iconColor="GREY" marginTop="5" />
|
||||||
|
<m:MaterialIcon iconType="ATTACHMENT" iconColor="GREY"
|
||||||
|
marginLeft="10" ui:field="attachmentsIcon" visibility="HIDDEN"
|
||||||
|
iconSize="TINY" title="This message has attachments" />
|
||||||
|
|
||||||
|
</m:MaterialCollectionSecondary>
|
||||||
|
<m:MaterialDropDown ui:field="dd" activator=""
|
||||||
|
constrainWidth="false" gutter="-100" hover="true" belowOrigin="true">
|
||||||
|
<m:MaterialLink textColor="BLUE_DARKEN_1" ui:field="deleteButton"
|
||||||
|
text="Delete Message" />
|
||||||
|
<m:MaterialLink textColor="BLUE_DARKEN_1" ui:field="setUnreadButton"
|
||||||
|
text="Mark as unread" />
|
||||||
|
</m:MaterialDropDown>
|
||||||
|
</m:MaterialCollectionItem>
|
||||||
|
|
||||||
|
</ui:UiBinder>
|
|
@ -0,0 +1,338 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.portal.clientcontext.client.GCubeClientContext;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageServiceAsync;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.Utils;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.autocomplete.MaterialAutoComplete;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.oracle.UserOracle;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.oracle.UserSuggestion;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.MessageUserModel;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.WSUser;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.client.notification.WorkspaceExplorerSelectNotification.WorskpaceExplorerSelectNotificationListener;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.client.select.WorkspaceExplorerSelectDialog;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.shared.FilterCriteria;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.shared.Item;
|
||||||
|
import org.gcube.portlets.widgets.wsexplorer.shared.ItemType;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.dom.client.Style.Unit;
|
||||||
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
|
import com.google.gwt.uibinder.client.UiField;
|
||||||
|
import com.google.gwt.uibinder.client.UiHandler;
|
||||||
|
import com.google.gwt.user.client.Timer;
|
||||||
|
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.SuggestOracle;
|
||||||
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
|
import gwt.material.design.client.constants.Color;
|
||||||
|
import gwt.material.design.client.constants.IconSize;
|
||||||
|
import gwt.material.design.client.constants.IconType;
|
||||||
|
import gwt.material.design.client.ui.MaterialButton;
|
||||||
|
import gwt.material.design.client.ui.MaterialChip;
|
||||||
|
import gwt.material.design.client.ui.MaterialIcon;
|
||||||
|
import gwt.material.design.client.ui.MaterialLabel;
|
||||||
|
import gwt.material.design.client.ui.MaterialLink;
|
||||||
|
import gwt.material.design.client.ui.MaterialPanel;
|
||||||
|
import gwt.material.design.client.ui.MaterialPreLoader;
|
||||||
|
import gwt.material.design.client.ui.MaterialRow;
|
||||||
|
import gwt.material.design.client.ui.MaterialTextArea;
|
||||||
|
import gwt.material.design.client.ui.MaterialTextBox;
|
||||||
|
|
||||||
|
public class WriteMessage extends Composite {
|
||||||
|
|
||||||
|
private static MessageWindowUiBinder uiBinder = GWT.create(MessageWindowUiBinder.class);
|
||||||
|
|
||||||
|
interface MessageWindowUiBinder extends UiBinder<Widget, WriteMessage> {
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiField MaterialPanel mainPanel;
|
||||||
|
@UiField MaterialTextBox txtBoxSubject;
|
||||||
|
// @UiField MaterialWindow modal;
|
||||||
|
@UiField MaterialAutoComplete acModal;
|
||||||
|
@UiField MaterialButton btnSendModal, btnCloseModal;
|
||||||
|
@UiField MaterialPanel modalContent, sendingLoader;
|
||||||
|
@UiField MaterialRow attachmentsRow;
|
||||||
|
@UiField MaterialLink attachButton;
|
||||||
|
@UiField MaterialLabel sendingFeedback;
|
||||||
|
@UiField MaterialPreLoader sendingSpinner;
|
||||||
|
@UiField MaterialTextArea txtArea;
|
||||||
|
|
||||||
|
private ApplicationView ap;
|
||||||
|
private MessageServiceAsync convService;
|
||||||
|
|
||||||
|
public WriteMessage(MessageServiceAsync convService, ApplicationView ap) {
|
||||||
|
initWidget(uiBinder.createAndBindUi(this));
|
||||||
|
this.convService = convService;
|
||||||
|
this.ap = ap;
|
||||||
|
UserOracle oracle = new UserOracle();
|
||||||
|
oracle.addContacts(getAllUsers());
|
||||||
|
acModal.setSuggestions(oracle);
|
||||||
|
btnSendModal.getElement().getStyle().setBackgroundImage("none");
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialPanel getMainPanel() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsReply(ConvMessage msg) {
|
||||||
|
acModal.addItem(new UserSuggestion(
|
||||||
|
new WSUser(
|
||||||
|
msg.getOwner().getUsername(),
|
||||||
|
msg.getOwner().getUsername(),
|
||||||
|
msg.getOwner().getFullName(),
|
||||||
|
msg.getOwner().getEmail()
|
||||||
|
)
|
||||||
|
));
|
||||||
|
String subject = getReplySubject(msg.getSubject());
|
||||||
|
|
||||||
|
txtBoxSubject.setText(subject);
|
||||||
|
txtBoxSubject.setReadOnly(true);
|
||||||
|
|
||||||
|
txtArea.setText(getReplyHeaderMessage(msg));
|
||||||
|
focusOnBody();
|
||||||
|
}
|
||||||
|
public void setIsReplyAll(ConvMessage msg) {
|
||||||
|
setIsReply(msg);
|
||||||
|
long currUserId = 0;
|
||||||
|
try {
|
||||||
|
currUserId = Long.parseLong(GCubeClientContext.getCurrentUserId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log("Could not read userId client context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (MessageUserModel u : msg.getRecipients()) {
|
||||||
|
if (u.getUserId() != currUserId)
|
||||||
|
acModal.addItem(new UserSuggestion(
|
||||||
|
new WSUser(
|
||||||
|
u.getUserId()+"",
|
||||||
|
u.getUsername(),
|
||||||
|
u.getFullName(),
|
||||||
|
u.getEmail()
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
focusOnBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsForward(ConvMessage msg) {
|
||||||
|
String subject = "Fwd: " + msg.getSubject();
|
||||||
|
txtBoxSubject.setText(subject);
|
||||||
|
txtBoxSubject.setReadOnly(true);
|
||||||
|
txtArea.setText(getForwardHeaderMessage(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
//need to defer this
|
||||||
|
private void focusOnBody() {
|
||||||
|
Timer t = new Timer() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (! Utils.isMobile()) {
|
||||||
|
txtArea.setCursorPos(0);
|
||||||
|
txtArea.setFocus(true);
|
||||||
|
txtArea.setActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t.schedule(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getReplySubject(String subject) {
|
||||||
|
if (subject != null) {
|
||||||
|
return subject.startsWith("Re:") ? subject : "Re: " + subject;
|
||||||
|
} else
|
||||||
|
return "No subject";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getReplyHeaderMessage(ConvMessage msg) {
|
||||||
|
String toReturn = "\n\n---\n on " + msg.getDate() + " " + msg.getOwner().getFullName() + " wrote:";
|
||||||
|
toReturn += "\n\n"+msg.getContent();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native void log(String msg) /*-{
|
||||||
|
$wnd.console.log(msg);
|
||||||
|
}-*/;
|
||||||
|
|
||||||
|
private String getForwardHeaderMessage(ConvMessage msg) {
|
||||||
|
String toReturn = "\n\n---\nBegin forwarded message:";
|
||||||
|
toReturn += "\nFrom: " + msg.getOwner().getFullName();
|
||||||
|
toReturn += "\nDate: " + msg.getDate();
|
||||||
|
toReturn += "\nTo: ";
|
||||||
|
if (msg.getRecipients() != null) {
|
||||||
|
for (MessageUserModel recipient : msg.getRecipients()) {
|
||||||
|
toReturn += recipient.getFullName() + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toReturn += "\nSubject: " +msg.getSubject();
|
||||||
|
toReturn += "\n\n"+msg.getContent();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WriteMessage setFocusOnUsersInput() {
|
||||||
|
if (!Utils.isMobile())
|
||||||
|
acModal.setFocus(true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//just used in devlopment
|
||||||
|
private List<WSUser> getAllUsers() {
|
||||||
|
List<WSUser> toReturn = new ArrayList<>();
|
||||||
|
toReturn.add(new WSUser("testing", "username testing", "Andrea testing", "@gmail.com"));
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
@UiHandler("attachButton")
|
||||||
|
void onAttach(ClickEvent e) {
|
||||||
|
List<ItemType> types = new ArrayList<>();
|
||||||
|
ItemType[] theTypes = ItemType.values();
|
||||||
|
for (int i = 0; i < theTypes.length; i++) {
|
||||||
|
if (theTypes[i] != ItemType.FOLDER)
|
||||||
|
types.add(theTypes[i]);
|
||||||
|
}
|
||||||
|
FilterCriteria criteria = null;
|
||||||
|
final WorkspaceExplorerSelectDialog wpTreepopup = new WorkspaceExplorerSelectDialog("Select an item", criteria, types);
|
||||||
|
wpTreepopup.getElement().getStyle().setLeft(50, Unit.PCT);
|
||||||
|
wpTreepopup.setZIndex(10010);
|
||||||
|
WorskpaceExplorerSelectNotificationListener listener = new WorskpaceExplorerSelectNotificationListener() {
|
||||||
|
@Override
|
||||||
|
public void onSelectedItem(Item item) {
|
||||||
|
attachmentsRow.add(getChip(item.getId(), item.getName(), item.isFolder(), true));
|
||||||
|
wpTreepopup.hide();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onFailed(Throwable throwable) {
|
||||||
|
Window.alert("There are networks problem, please check your connection.");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onAborted() {}
|
||||||
|
@Override
|
||||||
|
public void onNotValidSelection() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
wpTreepopup.addWorkspaceExplorerSelectNotificationListener(listener);
|
||||||
|
wpTreepopup.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//for the attachments we distinguish between folder and files
|
||||||
|
private MaterialChip getChip(String itemId, String itemName, boolean isFolder, boolean deletable) {
|
||||||
|
MaterialChip chip = new MaterialChip(itemName);
|
||||||
|
if (deletable)
|
||||||
|
chip.setIconType(IconType.CLOSE);
|
||||||
|
chip.setMargin(5);
|
||||||
|
chip.setId(itemId);
|
||||||
|
if (isFolder) {
|
||||||
|
chip.setLetter("F");
|
||||||
|
chip.setLetterBackgroundColor(Color.AMBER);
|
||||||
|
chip.setBackgroundColor(Color.YELLOW);
|
||||||
|
chip.setTextColor(Color.GREY_DARKEN_2);
|
||||||
|
} else {
|
||||||
|
chip.setLetter("D");
|
||||||
|
chip.setLetterBackgroundColor(Color.RED);
|
||||||
|
chip.setTextColor(Color.GREY_DARKEN_2);
|
||||||
|
}
|
||||||
|
return chip;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private ArrayList<String> getSelectedFilesAndFoldersId() {
|
||||||
|
ArrayList<String> toReturn = new ArrayList<>();
|
||||||
|
int n = attachmentsRow.getWidgetCount();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
Widget w = attachmentsRow.getWidget(i);
|
||||||
|
if (w instanceof MaterialChip) {
|
||||||
|
toReturn.add(((MaterialChip) w).getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@UiHandler("btnSendModal")
|
||||||
|
void onSendMessage(ClickEvent e) {
|
||||||
|
|
||||||
|
if (getSelectedUsers().isEmpty()) {
|
||||||
|
acModal.setError("Look empty to me");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
acModal.reset();
|
||||||
|
}
|
||||||
|
if (txtBoxSubject.getText().isEmpty()) {
|
||||||
|
txtBoxSubject.setError("Subject is mandatory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
txtBoxSubject.reset();
|
||||||
|
}
|
||||||
|
if (txtArea.getText().isEmpty()) {
|
||||||
|
txtArea.setError("The body of the message is mandatory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
txtArea.reset();
|
||||||
|
}
|
||||||
|
GWT.log(getSelectedUsers()+"");
|
||||||
|
GWT.log(getSelectedFilesAndFoldersId()+"");
|
||||||
|
ArrayList<String> recipientIds = new ArrayList<>();
|
||||||
|
for (WSUser u : getSelectedUsers()) {
|
||||||
|
recipientIds.add(u.getScreenname());
|
||||||
|
}
|
||||||
|
modalContent.setVisible(false);
|
||||||
|
sendingLoader.setVisible(true);
|
||||||
|
|
||||||
|
btnSendModal.setEnabled(false);
|
||||||
|
convService.sendToById(recipientIds, getSelectedFilesAndFoldersId(), txtBoxSubject.getText(), txtArea.getText(), new AsyncCallback<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable caught) {
|
||||||
|
sendingSpinner.removeFromParent();
|
||||||
|
sendingFeedback.setText("We're sorry an error occurred! Please try again");
|
||||||
|
modalContent.setVisible(true);
|
||||||
|
btnSendModal.setEnabled(true);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Boolean result) {
|
||||||
|
sendingSpinner.removeFromParent();
|
||||||
|
if (result) {
|
||||||
|
sendingFeedback.setText("Your message has been sent");
|
||||||
|
MaterialIcon okIcon = new MaterialIcon(IconType.DONE, Color.GREEN, Color.WHITE);
|
||||||
|
okIcon.setIconSize(IconSize.MEDIUM);
|
||||||
|
sendingLoader.add(okIcon);
|
||||||
|
btnCloseModal.setText("Close");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sendingFeedback.setText("We're sorry an error occurred in the server! Please try again");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiHandler("btnCloseModal")
|
||||||
|
void onClose(ClickEvent e) {
|
||||||
|
if (Utils.isMobile())
|
||||||
|
ap.showSidePanel();
|
||||||
|
mainPanel.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WSUser> getSelectedUsers() {
|
||||||
|
List<? extends SuggestOracle.Suggestion> values = acModal.getValue();
|
||||||
|
List<WSUser> users = new ArrayList<>(values.size());
|
||||||
|
for(SuggestOracle.Suggestion value : values){
|
||||||
|
if(value instanceof UserSuggestion){
|
||||||
|
UserSuggestion us = (UserSuggestion) value;
|
||||||
|
WSUser user = us.getUser();
|
||||||
|
users.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
<!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:m="urn:import:gwt.material.design.client.ui"
|
||||||
|
xmlns:ma="urn:import:gwt.material.design.addins.client"
|
||||||
|
xmlns:mc="urn:import:org.gcube.portets.user.message_conversations.client.autocomplete">
|
||||||
|
<ui:style>
|
||||||
|
.modalTitle {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alignCenter {
|
||||||
|
text-align: center;
|
||||||
|
padding: 50px;
|
||||||
|
}
|
||||||
|
.animation {
|
||||||
|
transition: 0.4s all;
|
||||||
|
-webkit-transition: 0.4s all;
|
||||||
|
-moz-transition: 0.4s all;
|
||||||
|
}
|
||||||
|
</ui:style>
|
||||||
|
<!-- Modal -->
|
||||||
|
<m:MaterialPanel ui:field="mainPanel" backgroundColor="WHITE" shadow="1"
|
||||||
|
layoutPosition="RELATIVE" marginBottom="0" grid="l8 m12 s12"
|
||||||
|
paddingLeft="10" paddingRight="60" marginLeft="5" marginTop="-5"
|
||||||
|
addStyleNames="{style.animation} message-metadata" left="350">
|
||||||
|
<m:MaterialModalFooter textAlign="RIGHT">
|
||||||
|
<m:MaterialButton ui:field="btnCloseModal" text="Cancel"
|
||||||
|
type="FLAT" textColor="BLACK" waves="DEFAULT"/>
|
||||||
|
<m:MaterialButton text="Send" type="FLAT" textColor="WHITE"
|
||||||
|
backgroundColor="BLUE" waves="DEFAULT" ui:field="btnSendModal" />
|
||||||
|
</m:MaterialModalFooter>
|
||||||
|
<m:MaterialPanel ui:field="sendingLoader" visible="false"
|
||||||
|
addStyleNames="{style.alignCenter}">
|
||||||
|
<m:MaterialLabel text="Sending message ..."
|
||||||
|
addStyleNames="{style.modalTitle}" marginBottom="50" ui:field="sendingFeedback" />
|
||||||
|
<m:MaterialPreLoader size="BIG" ui:field="sendingSpinner">
|
||||||
|
<m:MaterialSpinner />
|
||||||
|
</m:MaterialPreLoader>
|
||||||
|
</m:MaterialPanel>
|
||||||
|
<m:MaterialPanel ui:field="modalContent" padding="5">
|
||||||
|
<mc:MaterialAutoComplete placeholder="To:"
|
||||||
|
ui:field="acModal" directInputAllowed="false"></mc:MaterialAutoComplete>
|
||||||
|
<m:MaterialRow>
|
||||||
|
<m:MaterialTextBox label="Subject" ui:field="txtBoxSubject"
|
||||||
|
marginBottom="0" />
|
||||||
|
</m:MaterialRow>
|
||||||
|
<m:MaterialRow marginBottom="0">
|
||||||
|
<m:MaterialLink href="#attach" text="Select files to attach"
|
||||||
|
textColor="BLACK" iconType="ATTACHMENT" iconPosition="LEFT"
|
||||||
|
ui:field="attachButton" />
|
||||||
|
</m:MaterialRow>
|
||||||
|
<m:MaterialRow ui:field="attachmentsRow" marginBottom="0" />
|
||||||
|
<m:MaterialRow>
|
||||||
|
<m:MaterialTextArea ui:field="txtArea" label="Body" resizeRule="AUTO"/>
|
||||||
|
</m:MaterialRow>
|
||||||
|
</m:MaterialPanel>
|
||||||
|
</m:MaterialPanel>
|
||||||
|
</ui:UiBinder>
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.client.ui.resources;
|
||||||
|
|
||||||
|
import com.google.gwt.resources.client.ClientBundle;
|
||||||
|
import com.google.gwt.resources.client.ImageResource;
|
||||||
|
|
||||||
|
public interface MessagesResources extends ClientBundle {
|
||||||
|
public static final String WELCOME_MESSAGE = "Welcome to your Messages.\nMessages lets you stay connected, organized, and productive at work, at home, and everywhere in between. "+
|
||||||
|
"Also, you can easily attach very large files to your messages from Workspace." +
|
||||||
|
"\n\nThis message will automatically be deleted as soon you'll receive another one.";
|
||||||
|
|
||||||
|
@Source("group.png")
|
||||||
|
ImageResource group();
|
||||||
|
|
||||||
|
@Source("user.png")
|
||||||
|
ImageResource user();
|
||||||
|
|
||||||
|
@Source("d4science.png")
|
||||||
|
ImageResource d4scienceTeam();
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,514 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
|
||||||
|
import org.gcube.applicationsupportlayer.social.NotificationsManager;
|
||||||
|
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
|
||||||
|
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser;
|
||||||
|
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||||
|
import org.gcube.common.homelibary.model.items.type.WorkspaceItemType;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeLibrary;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeManager;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeManagerFactory;
|
||||||
|
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.Workspace;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.exceptions.ItemNotFoundException;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.folder.FolderItem;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.sharing.WorkspaceMessage;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.sharing.WorkspaceMessageManager;
|
||||||
|
import org.gcube.common.portal.PortalContext;
|
||||||
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
|
import org.gcube.portal.notifications.bean.GenericItemBean;
|
||||||
|
import org.gcube.portal.notifications.thread.MessageNotificationsThread;
|
||||||
|
import org.gcube.portets.user.message_conversations.client.MessageService;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.ConvMessage;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.CurrUserAndPortalUsersWrapper;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.FileModel;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.MessageUserModel;
|
||||||
|
import org.gcube.portets.user.message_conversations.shared.WSUser;
|
||||||
|
import org.gcube.vomanagement.usermanagement.GroupManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.UserManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
|
||||||
|
import org.gcube.vomanagement.usermanagement.util.ManagementUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
|
||||||
|
import com.liferay.portal.kernel.dao.orm.QueryUtil;
|
||||||
|
import com.liferay.portal.kernel.exception.PortalException;
|
||||||
|
import com.liferay.portal.kernel.exception.SystemException;
|
||||||
|
import com.liferay.portal.kernel.util.OrderByComparator;
|
||||||
|
import com.liferay.portal.kernel.util.OrderByComparatorFactoryUtil;
|
||||||
|
import com.liferay.portal.model.User;
|
||||||
|
import com.liferay.portal.service.GroupLocalServiceUtil;
|
||||||
|
import com.liferay.portal.service.UserLocalServiceUtil;
|
||||||
|
import com.liferay.portal.util.PortalUtil;
|
||||||
|
/**
|
||||||
|
* The server side implementation of the RPC service.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ConvServiceImpl extends RemoteServiceServlet implements MessageService {
|
||||||
|
private static final Logger _log = LoggerFactory.getLogger(ConvServiceImpl.class);
|
||||||
|
|
||||||
|
private PortalContext pContext;
|
||||||
|
private UserManager um;
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
um = new LiferayUserManager();
|
||||||
|
pContext = PortalContext.getConfiguration();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true if you're running into the portal, false if in development
|
||||||
|
*/
|
||||||
|
private boolean isWithinPortal() {
|
||||||
|
try {
|
||||||
|
UserLocalServiceUtil.getService();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (com.liferay.portal.kernel.bean.BeanLocatorException ex) {
|
||||||
|
_log.trace("Development Mode ON");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GCubeUser getCurrentUser(HttpServletRequest httpServletRequest) {
|
||||||
|
if (isWithinPortal()) {
|
||||||
|
try {
|
||||||
|
long userId = PortalUtil.getUser(httpServletRequest).getUserId();
|
||||||
|
long groupId = pContext.getCurrentGroupId(httpServletRequest);
|
||||||
|
if (GroupLocalServiceUtil.hasUserGroup(userId, groupId))
|
||||||
|
return um.getUserById(userId);
|
||||||
|
else {
|
||||||
|
_log.error("User not authorised in Group, the logged user id=" + userId + " does not belong to group " + groupId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.warn("Could not read user from LR PortalUtil in delegate servlet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return pContext.getCurrentUser(getThreadLocalRequest());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<ConvMessage> getMessages(boolean sent) {
|
||||||
|
ArrayList<ConvMessage> toReturn = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
GCubeUser user = getCurrentUser(getThreadLocalRequest());
|
||||||
|
pContext = PortalContext.getConfiguration();
|
||||||
|
_log.debug("*** Reading user = " +user.getFullname());
|
||||||
|
String scope = pContext.getCurrentScope(getThreadLocalRequest());
|
||||||
|
ScopeProvider.instance.set(scope);
|
||||||
|
String token = pContext.getCurrentUserToken(scope, user.getUserId());
|
||||||
|
SecurityTokenProvider.instance.set(token);
|
||||||
|
Workspace workspace = null;
|
||||||
|
try {
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
workspace = manager.getHome().getWorkspace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WorkspaceMessage> listMessages = (sent) ?
|
||||||
|
workspace.getWorkspaceMessageManager().getSentMessages() : workspace.getWorkspaceMessageManager().getReceivedMessages();
|
||||||
|
_log.debug("Got messages of " + user.getFullname() + " how many? " + listMessages.size());
|
||||||
|
//the messages are returned from the oldest to the new one, so we reverse them
|
||||||
|
Collections.reverse(listMessages);
|
||||||
|
LiferayUserManager um = new LiferayUserManager();
|
||||||
|
|
||||||
|
for (WorkspaceMessage m : listMessages) {
|
||||||
|
String previewBody = m.getBody().length() > 80 ? m.getBody().substring(0, 79) + " ..." : m.getBody();
|
||||||
|
MessageUserModel mu = null;
|
||||||
|
GCubeUser sender = null;
|
||||||
|
try {
|
||||||
|
if (sent) {
|
||||||
|
if (m.getAddresses().size() < 2) {
|
||||||
|
GCubeUser recipient = um.getUserByUsername(m.getAddresses().get(0));
|
||||||
|
mu = new MessageUserModel(recipient.getUserId(), recipient.getUsername(), recipient.getFullname(), recipient.getUserAvatarURL(), "", "");
|
||||||
|
} else {
|
||||||
|
//we have at least 2 recipients
|
||||||
|
GCubeUser recipient1 = um.getUserByUsername(m.getAddresses().get(0));
|
||||||
|
GCubeUser recipient2 = um.getUserByUsername(m.getAddresses().get(1));
|
||||||
|
String label2Display = recipient1.getFirstName() + " & " + recipient2.getFirstName();
|
||||||
|
if (m.getAddresses().size() > 2)
|
||||||
|
label2Display += " & ...";
|
||||||
|
mu = new MessageUserModel(recipient1.getUserId(), recipient1.getUsername(), label2Display, null, "", "");
|
||||||
|
|
||||||
|
}
|
||||||
|
} else { //received message
|
||||||
|
sender = um.getUserByUsername(m.getSender().getPortalLogin());
|
||||||
|
mu = new MessageUserModel(sender.getUserId(), sender.getUsername(), sender.getFullname(), sender.getUserAvatarURL(), "", "");
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
if (!sent) {
|
||||||
|
mu = new MessageUserModel(m.getSender().getPortalLogin());
|
||||||
|
} else {
|
||||||
|
mu = new MessageUserModel(m.getAddresses().get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sent) { //received messages
|
||||||
|
boolean hasAttachments = !m.getAttachmentsIds().isEmpty();
|
||||||
|
toReturn.add(new ConvMessage(
|
||||||
|
m.getId(),
|
||||||
|
m.getSubject(),
|
||||||
|
mu,
|
||||||
|
new Date(m.getSendTime().getTimeInMillis()),
|
||||||
|
previewBody,
|
||||||
|
m.isRead(),
|
||||||
|
hasAttachments));
|
||||||
|
} else { //sent messages
|
||||||
|
ArrayList<MessageUserModel> recipients = new ArrayList<>();
|
||||||
|
for (String rec : m.getAddresses()) {
|
||||||
|
recipients.add(new MessageUserModel(rec));
|
||||||
|
}
|
||||||
|
toReturn.add(new ConvMessage(
|
||||||
|
m.getId(),
|
||||||
|
m.getSubject(),
|
||||||
|
mu,
|
||||||
|
recipients,
|
||||||
|
new Date(m.getSendTime().getTimeInMillis()),
|
||||||
|
previewBody,
|
||||||
|
m.isRead()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
_log.trace("get All Messages Received ");
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean markMessageUnread(String messageId) {
|
||||||
|
GCubeUser user = getCurrentUser(getThreadLocalRequest());
|
||||||
|
String scope = pContext.getCurrentScope(getThreadLocalRequest());
|
||||||
|
SecurityTokenProvider.instance.set(pContext.getCurrentUserToken(scope, user.getUserId()));
|
||||||
|
try {
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
Workspace workspace = manager.getHome().getWorkspace();
|
||||||
|
workspace.getWorkspaceMessageManager().getReceivedMessage(messageId).setStatus(false);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConvMessage getMessageById(String messageId, boolean sent) {
|
||||||
|
ConvMessage toReturn = null;
|
||||||
|
try {
|
||||||
|
GCubeUser user = getCurrentUser(getThreadLocalRequest());
|
||||||
|
_log.debug("*** Reading user from liferay session = " +user.getFullname());
|
||||||
|
String scope = pContext.getCurrentScope(getThreadLocalRequest());
|
||||||
|
SecurityTokenProvider.instance.set(pContext.getCurrentUserToken(scope, user.getUserId()));
|
||||||
|
LiferayUserManager um = new LiferayUserManager();
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
Workspace workspace = manager.getHome().getWorkspace();
|
||||||
|
WorkspaceMessage m = (sent) ?
|
||||||
|
workspace.getWorkspaceMessageManager().getSentMessage(messageId): workspace.getWorkspaceMessageManager().getReceivedMessage(messageId);
|
||||||
|
MessageUserModel mu = null;
|
||||||
|
GCubeUser sender = null;
|
||||||
|
try {
|
||||||
|
sender = um.getUserByUsername(m.getSender().getPortalLogin());
|
||||||
|
mu = new MessageUserModel(sender.getUserId(), sender.getUsername(), sender.getFullname(), extractDomainFromEmail(sender.getEmail()));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
mu = new MessageUserModel(m.getSender().getPortalLogin());
|
||||||
|
}
|
||||||
|
ArrayList<MessageUserModel> recipients = new ArrayList<>();
|
||||||
|
for (String recipient : m.getAddresses()) {
|
||||||
|
try {
|
||||||
|
GCubeUser toAdd = um.getUserByUsername(recipient);
|
||||||
|
recipients.add(new MessageUserModel(toAdd.getUserId(), toAdd.getUsername(), toAdd.getFullname(), extractDomainFromEmail(toAdd.getEmail())));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
recipients.add(new MessageUserModel(recipient));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<FileModel> attachments = new ArrayList<>();
|
||||||
|
List<String> attachItems = m.getAttachmentsIds();
|
||||||
|
for (String itemId : attachItems) {
|
||||||
|
WorkspaceItem item = workspace.getItem(itemId);
|
||||||
|
String downloadURL = null; //removed for performanc issue and done on demand
|
||||||
|
attachments.add(new FileModel(item.getId(), item.getName(), null, item.isFolder(), downloadURL));
|
||||||
|
}
|
||||||
|
boolean hasAttachments = !attachItems.isEmpty();
|
||||||
|
toReturn = new ConvMessage(
|
||||||
|
m.getId(),
|
||||||
|
m.getSubject(),
|
||||||
|
mu,
|
||||||
|
recipients,
|
||||||
|
new Date(m.getSendTime().getTimeInMillis()),
|
||||||
|
m.getBody(),
|
||||||
|
m.isRead(),
|
||||||
|
attachments,
|
||||||
|
hasAttachments);
|
||||||
|
if (!sent)
|
||||||
|
m.setStatus(true); //marked as read
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttachmentDownloadURL(String itemId) {
|
||||||
|
GCubeUser user = getCurrentUser(getThreadLocalRequest());
|
||||||
|
String scope = pContext.getCurrentScope(getThreadLocalRequest());
|
||||||
|
SecurityTokenProvider.instance.set(pContext.getCurrentUserToken(scope, user.getUserId()));
|
||||||
|
try {
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
Workspace workspace = manager.getHome().getWorkspace();
|
||||||
|
WorkspaceItem item = workspace.getItem(itemId);
|
||||||
|
String downladURL = item.getPublicLink(false);
|
||||||
|
downladURL = (downladURL.startsWith("https")) ? downladURL : downladURL.replace("http", "https");
|
||||||
|
return downladURL;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean saveAttachmentToWorkspaceFolder(String itemId, String destinationFolderId) {
|
||||||
|
GCubeUser user = getCurrentUser(getThreadLocalRequest());
|
||||||
|
String scope = pContext.getCurrentScope(getThreadLocalRequest());
|
||||||
|
SecurityTokenProvider.instance.set(pContext.getCurrentUserToken(scope, user.getUserId()));
|
||||||
|
try {
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
Workspace workspace = manager.getHome().getWorkspace();
|
||||||
|
WorkspaceItem copied = workspace.copy(itemId, destinationFolderId);
|
||||||
|
return (copied != null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteMessageById(String messageId, boolean sent) {
|
||||||
|
GCubeUser user = getCurrentUser(getThreadLocalRequest());
|
||||||
|
_log.debug("deleteMessageById reading user from liferay session = " +user.getFullname() + " m id = " + messageId);
|
||||||
|
String scope = pContext.getCurrentScope(getThreadLocalRequest());
|
||||||
|
SecurityTokenProvider.instance.set(pContext.getCurrentUserToken(scope, user.getUserId()));
|
||||||
|
try {
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
WorkspaceMessageManager workspaceMessanger = manager.getHome().getWorkspace().getWorkspaceMessageManager();
|
||||||
|
if (sent)
|
||||||
|
workspaceMessanger.deleteSentMessage(messageId);
|
||||||
|
else {
|
||||||
|
workspaceMessanger.deleteReceivedMessage(messageId);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<WSUser> searchUsers(String keyword) {
|
||||||
|
ArrayList<WSUser> toReturn = new ArrayList<>();
|
||||||
|
if (isWithinPortal()) {
|
||||||
|
OrderByComparator comparator = OrderByComparatorFactoryUtil.create("User_", "screenname", true);
|
||||||
|
try {
|
||||||
|
_log.debug("Searching " + keyword);
|
||||||
|
List<User> lrUsers = UserLocalServiceUtil.search(ManagementUtils.getCompany().getCompanyId(), keyword, 0, null, QueryUtil.ALL_POS, QueryUtil.ALL_POS, comparator);
|
||||||
|
for (User user : lrUsers) {
|
||||||
|
toReturn.add(new WSUser(""+user.getUserId(), user.getScreenName(), user.getFullName(), extractDomainFromEmail(user.getEmailAddress())));
|
||||||
|
}
|
||||||
|
} catch (SystemException | PortalException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else { //development
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
toReturn.add(new WSUser("andrea.rossi", "andrea.rossi", "Andrea Rossi", "m.assante@gmail.com"));
|
||||||
|
if (i % 2 == 0)
|
||||||
|
toReturn.add(new WSUser(""+i, "username"+i, "userGetFullname()"+i, "user.getEmail()"+i));
|
||||||
|
else
|
||||||
|
toReturn.add(new WSUser(""+i, "ciccio"+i, "ciccioNome"+i, "ciccioEMail"+i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sendToById(ArrayList<String> recipientIds, ArrayList<String> listAttachmentsId, String subject, String body) {
|
||||||
|
PortalContext pContext = PortalContext.getConfiguration();
|
||||||
|
GCubeUser currentUser = pContext.getCurrentUser(getThreadLocalRequest());
|
||||||
|
|
||||||
|
if (listAttachmentsId == null)
|
||||||
|
listAttachmentsId = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
Workspace workspace = HomeLibrary.getUserWorkspace(currentUser.getUsername());
|
||||||
|
_log.info("Sending message to: " + recipientIds.toString());
|
||||||
|
String checkedSubject = subject;
|
||||||
|
String checkedBody = body;
|
||||||
|
String messageId = workspace.getWorkspaceMessageManager().sendMessageToPortalLogins(checkedSubject, checkedBody, listAttachmentsId, recipientIds);
|
||||||
|
try {
|
||||||
|
body += getPublicLinksForAttachs(workspace, listAttachmentsId);
|
||||||
|
}
|
||||||
|
catch (InternalErrorException|ItemNotFoundException e) {
|
||||||
|
_log.error("Ops, could not generate publick link for some of the attachments");
|
||||||
|
}
|
||||||
|
_log.debug("Sending message notification to: " + recipientIds.toString());
|
||||||
|
|
||||||
|
List<GenericItemBean> recipients = getUsersbyUserId(recipientIds);
|
||||||
|
|
||||||
|
NotificationsManager nm = new ApplicationNotificationsManager(new SocialNetworkingSite(getThreadLocalRequest()), pContext.getCurrentScope(getThreadLocalRequest()),
|
||||||
|
new SocialNetworkingUser(
|
||||||
|
currentUser.getUsername(),
|
||||||
|
currentUser.getEmail(),
|
||||||
|
currentUser.getFullname(),
|
||||||
|
currentUser.getUserAvatarURL()
|
||||||
|
));
|
||||||
|
Thread thread = new Thread(new MessageNotificationsThread(recipients, messageId, checkedSubject, body, nm));
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
return (messageId != null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.error("While Sending message to: " + recipientIds.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* utility method extract the @domain.com from an email address
|
||||||
|
* return @unknown-domain in case of no emails
|
||||||
|
*/
|
||||||
|
private String extractDomainFromEmail(String email) {
|
||||||
|
int index = email.indexOf('@');
|
||||||
|
if (index > 0)
|
||||||
|
return email.substring(index);
|
||||||
|
else
|
||||||
|
return "@unknown-domain";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* return the User instance given his id
|
||||||
|
* @param recipientIds
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<GenericItemBean> getUsersbyUserId(List<String> recipientIds) {
|
||||||
|
List<GenericItemBean> recipients = new ArrayList<GenericItemBean>();
|
||||||
|
for (String userid : recipientIds) {
|
||||||
|
GCubeUser user = null;
|
||||||
|
try {
|
||||||
|
user = new LiferayUserManager().getUserByUsername(userid);
|
||||||
|
recipients.add(new GenericItemBean(""+user.getUserId(), user.getUsername(), user.getFullname(), ""));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param workspace
|
||||||
|
* @param listAttachmentsId
|
||||||
|
* @return
|
||||||
|
* @throws ItemNotFoundException
|
||||||
|
* @throws InternalErrorException
|
||||||
|
*/
|
||||||
|
private String getPublicLinksForAttachs(Workspace workspace, ArrayList<String> listAttachmentsId) throws ItemNotFoundException, InternalErrorException{
|
||||||
|
|
||||||
|
if (listAttachmentsId != null && (!listAttachmentsId.isEmpty()) ) {
|
||||||
|
List<WorkspaceItem> attachments = new ArrayList<WorkspaceItem>();
|
||||||
|
for (String itemId : listAttachmentsId) {
|
||||||
|
attachments.add(workspace.getItem(itemId));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
if(attachments!=null && attachments.size() > 0){
|
||||||
|
builder.append("\n\n\nThe following ");
|
||||||
|
String msg = attachments.size()>1?"files were attached to this message:":"file was attached to this message:";
|
||||||
|
builder.append(msg+"\n");
|
||||||
|
for (WorkspaceItem workspaceItem : attachments) {
|
||||||
|
|
||||||
|
if(workspaceItem.getType().equals(WorkspaceItemType.FOLDER_ITEM)) {
|
||||||
|
FolderItem folderItem = (FolderItem) workspaceItem;
|
||||||
|
String publicLink = "";
|
||||||
|
String itemName = "";
|
||||||
|
try {
|
||||||
|
itemName = workspaceItem.getName();
|
||||||
|
publicLink = folderItem.getPublicLink(true);
|
||||||
|
}
|
||||||
|
catch (InternalErrorException e) {
|
||||||
|
_log.warn("An error occurred when creating public link for attachment, skipping file: " + itemName);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
builder.append(itemName + " ("+publicLink+")");
|
||||||
|
builder.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_log.debug("returning public links: "+builder.toString());
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
else return "";
|
||||||
|
}
|
||||||
|
else return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the list of workspace users
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CurrUserAndPortalUsersWrapper getWorkspaceUsers() {
|
||||||
|
|
||||||
|
PortalContext pContext = PortalContext.getConfiguration();
|
||||||
|
GCubeUser currentUser = pContext.getCurrentUser(getThreadLocalRequest());
|
||||||
|
_log.debug("trying to get WorkspaceUsers ..");
|
||||||
|
WSUser currUser = null;
|
||||||
|
ArrayList<WSUser> portalUsers = new ArrayList<WSUser>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isWithinPortal()) {
|
||||||
|
UserManager um = new LiferayUserManager();
|
||||||
|
GroupManager gm = new LiferayGroupManager();
|
||||||
|
List<GCubeUser> users = um.listUsersByGroup(gm.getRootVO().getGroupId());
|
||||||
|
for (GCubeUser user : users) {
|
||||||
|
_log.trace("Trying to get additional info for "+user.getUsername());
|
||||||
|
portalUsers.add(new WSUser(user.getUserId()+"", user.getUsername(), user.getFullname(), user.getEmail()));
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
portalUsers.add(new WSUser(""+i, "username"+i, "userGetFullname()"+i, "user.getEmail()"+i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currUser = new WSUser(currentUser.getUsername(), currentUser.getUsername(), currentUser.getFullname(), currentUser.getEmail());
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.error("Error in server get all contacts ", e);
|
||||||
|
}
|
||||||
|
CurrUserAndPortalUsersWrapper toReturn = new CurrUserAndPortalUsersWrapper(currUser, portalUsers);
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.gcube.portets.user.message_conversations.server.portlet;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.portlet.GenericPortlet;
|
||||||
|
import javax.portlet.PortletException;
|
||||||
|
import javax.portlet.PortletRequestDispatcher;
|
||||||
|
import javax.portlet.RenderRequest;
|
||||||
|
import javax.portlet.RenderResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MessagesPortlet extends GenericPortlet {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSP folder name
|
||||||
|
*/
|
||||||
|
public static final String JSP_FOLDER = "/WEB-INF/jsp/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String VIEW_JSP = JSP_FOLDER + "Messages_view.jsp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param request .
|
||||||
|
* @param response .
|
||||||
|
* @throws IOException .
|
||||||
|
* @throws PortletException .
|
||||||
|
*/
|
||||||
|
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
|
||||||
|
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_JSP);
|
||||||
|
rd.include(request,response);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.shared;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||||
|
|
||||||
|
|
||||||
|
public class ConvMessage implements IsSerializable{
|
||||||
|
private String id;
|
||||||
|
private String subject;
|
||||||
|
private MessageUserModel owner;
|
||||||
|
private List<MessageUserModel> recipients;
|
||||||
|
private Date date;
|
||||||
|
private String content;
|
||||||
|
private boolean isRead;
|
||||||
|
private ArrayList<FileModel> attachments;
|
||||||
|
private boolean hasAttachments;
|
||||||
|
|
||||||
|
public ConvMessage() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//full constructors
|
||||||
|
public ConvMessage(String id, String subject, MessageUserModel owner, List<MessageUserModel> recipients,
|
||||||
|
Date date, String content, boolean isRead, ArrayList<FileModel> attachments, boolean hasAttachments) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.subject = subject;
|
||||||
|
this.owner = owner;
|
||||||
|
this.recipients = recipients;
|
||||||
|
this.date = date;
|
||||||
|
this.content = content;
|
||||||
|
this.isRead = isRead;
|
||||||
|
this.attachments = attachments;
|
||||||
|
this.hasAttachments = hasAttachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//without recipients
|
||||||
|
public ConvMessage(String id, String subject, MessageUserModel owner, Date date,
|
||||||
|
String content, boolean isRead, boolean hasAttachments) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.subject = subject;
|
||||||
|
this.owner = owner;
|
||||||
|
this.recipients = null;
|
||||||
|
this.date = date;
|
||||||
|
this.content = content;
|
||||||
|
this.isRead = isRead;
|
||||||
|
this.hasAttachments = hasAttachments;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//without attchment
|
||||||
|
public ConvMessage(String id, String subject, MessageUserModel owner, List<MessageUserModel> recipients, Date date,
|
||||||
|
String content, boolean isRead) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.subject = subject;
|
||||||
|
this.owner = owner;
|
||||||
|
this.recipients = recipients;
|
||||||
|
this.date = date;
|
||||||
|
this.content = content;
|
||||||
|
this.isRead = isRead;
|
||||||
|
attachments = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<MessageUserModel> getRecipients() {
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecipients(ArrayList<MessageUserModel> recipients) {
|
||||||
|
this.recipients = recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageUserModel getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(MessageUserModel owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRead() {
|
||||||
|
return isRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRead(boolean isRead) {
|
||||||
|
this.isRead = isRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<FileModel> getAttachments() {
|
||||||
|
return attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setAttachments(ArrayList<FileModel> attachments) {
|
||||||
|
this.attachments = attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean hasAttachments() {
|
||||||
|
return hasAttachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setHasAttachments(boolean hasAttachments) {
|
||||||
|
this.hasAttachments = hasAttachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ConvMessage [id=" + id + ", subject=" + subject + ", owner=" + owner + ", recipients=" + recipients
|
||||||
|
+ ", date=" + date + ", content=" + content + ", isRead=" + isRead + ", attachments=" + attachments
|
||||||
|
+ ", hasAttachments=" + hasAttachments + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.shared;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class CurrUserAndPortalUsersWrapper implements Serializable {
|
||||||
|
|
||||||
|
private WSUser currentUser;
|
||||||
|
private ArrayList<WSUser> users;
|
||||||
|
|
||||||
|
public CurrUserAndPortalUsersWrapper() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrUserAndPortalUsersWrapper(WSUser currentUser, ArrayList<WSUser> users) {
|
||||||
|
super();
|
||||||
|
this.currentUser = currentUser;
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WSUser getCurrentUser() {
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentUser(WSUser currentUser) {
|
||||||
|
this.currentUser = currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<WSUser> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsers(ArrayList<WSUser> users) {
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.shared;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||||
|
|
||||||
|
public class FileModel implements IsSerializable{
|
||||||
|
private String identifier, name;
|
||||||
|
private String parentId;
|
||||||
|
boolean isDirectory;
|
||||||
|
private String downloadLink;
|
||||||
|
|
||||||
|
public FileModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public FileModel(String identifier, String name, String parentId, boolean isDirectory, String downloadLink) {
|
||||||
|
super();
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.name = name;
|
||||||
|
this.parentId = parentId;
|
||||||
|
this.isDirectory = isDirectory;
|
||||||
|
this.downloadLink = downloadLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public FileModel(String identifier, String name, String parentId, boolean isDirectory) {
|
||||||
|
super();
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.name = name;
|
||||||
|
this.parentId = parentId;
|
||||||
|
this.isDirectory = isDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentifier(String identifier) {
|
||||||
|
this.identifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentId() {
|
||||||
|
return parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDirectory() {
|
||||||
|
return isDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirectory(boolean isDirectory) {
|
||||||
|
this.isDirectory = isDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDownloadLink() {
|
||||||
|
return downloadLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setDownloadLink(String downloadLink) {
|
||||||
|
this.downloadLink = downloadLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentId(String parentId) {
|
||||||
|
this.parentId = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FileModel [identifier=" + identifier + ", name=" + name + ", parentId=" + parentId + ", isDirectory="
|
||||||
|
+ isDirectory + ", downloadLink=" + downloadLink + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.shared;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||||
|
|
||||||
|
|
||||||
|
public class MessageUserModel implements IsSerializable {
|
||||||
|
private long userId;
|
||||||
|
private String username;
|
||||||
|
private String fullName;
|
||||||
|
private String avatarURL;
|
||||||
|
private String accountURL;
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
//this constructor is used only for development purposes
|
||||||
|
public MessageUserModel(String username) {
|
||||||
|
super();
|
||||||
|
this.userId = username.length();
|
||||||
|
this.username = username;
|
||||||
|
this.fullName = username.toUpperCase();
|
||||||
|
this.email = "test@gmail.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageUserModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* @param username
|
||||||
|
* @param fullName
|
||||||
|
* @param email
|
||||||
|
*/
|
||||||
|
public MessageUserModel(long userId, String username, String fullName, String email) {
|
||||||
|
super();
|
||||||
|
this.userId = userId;
|
||||||
|
this.username = username;
|
||||||
|
this.fullName = fullName;
|
||||||
|
this.avatarURL = "";
|
||||||
|
this.accountURL = "";
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* @param username
|
||||||
|
* @param fullName
|
||||||
|
* @param avatarURL
|
||||||
|
* @param accountURL
|
||||||
|
* @param email
|
||||||
|
*/
|
||||||
|
public MessageUserModel(long userId, String username, String fullName, String avatarURL, String accountURL, String email) {
|
||||||
|
super();
|
||||||
|
this.userId = userId;
|
||||||
|
this.username = username;
|
||||||
|
this.fullName = fullName;
|
||||||
|
this.avatarURL = avatarURL;
|
||||||
|
this.accountURL = accountURL;
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatarURL() {
|
||||||
|
return avatarURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarURL(String avatarURL) {
|
||||||
|
this.avatarURL = avatarURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccountURL() {
|
||||||
|
return accountURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountURL(String accountURL) {
|
||||||
|
this.accountURL = accountURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MessageUserModel [userId=" + userId + ", username=" + username + ", fullName=" + fullName
|
||||||
|
+ ", avatarURL=" + avatarURL + ", accountURL=" + accountURL + ", email=" + email + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.gcube.portets.user.message_conversations.shared;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Massimiliano Assante, ISTI-CNR
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class WSUser implements IsSerializable{
|
||||||
|
private String id;
|
||||||
|
private String screenname;
|
||||||
|
private String fullName;
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
public WSUser() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WSUser(String id, String screenname, String fullName, String email) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.screenname = screenname;
|
||||||
|
this.fullName = fullName;
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
public String getScreenname() {
|
||||||
|
return screenname;
|
||||||
|
}
|
||||||
|
public void setScreenname(String screenname) {
|
||||||
|
this.screenname = screenname;
|
||||||
|
}
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "\nid="+id+" \nlogin="+screenname+" \nfullname="+fullName+" \nemail="+email;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
log4j.rootLogger=INFO, A1
|
||||||
|
log4j.appender.A1=org.apache.log4j.ConsoleAppender
|
||||||
|
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
|
||||||
|
|
||||||
|
# Print the date in ISO 8601 format
|
||||||
|
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
|
||||||
|
|
||||||
|
# Print only messages of level TRACE or above in the package org.gcube
|
||||||
|
log4j.logger.org.gcube=DEBUG
|
||||||
|
log4j.logger.org.gcube.application.framework.core.session=INFO
|
||||||
|
log4j.logger.org.gcube.common.scope.impl.DefaultScopeProvider=ERROR
|
||||||
|
log4j.logger.com.netflix.astyanax.connectionpool.impl.CountingConnectionPoolMonitor=ERROR
|
||||||
|
log4j.logger.org.gcube.common.homelibrary=WARN
|
||||||
|
log4j.logger.org.gcube.common.authorization=WARN
|
||||||
|
log4j.logger.org.gcube.common.clients=WARN
|
||||||
|
log4j.logger.org.gcube.resources.clients=WARN
|
||||||
|
log4j.logger.org.gcube.contentmanager=WARN
|
||||||
|
log4j.logger.org.gcube.resources.discovery=WARN
|
|
@ -0,0 +1,5 @@
|
||||||
|
<service-map scope='/gcube/devNext' version="1.0.7-SNAPSHOT">
|
||||||
|
<services>
|
||||||
|
<service name='XQueryAccessService' endpoint='http://node22.d.d4science.research-infrastructures.eu:8080/wsrf/services/gcube/informationsystem/collector/XQueryAccess' />
|
||||||
|
</services>
|
||||||
|
</service-map>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<service-map scope='/gcube/devsec' version="1.0.7-SNAPSHOT">
|
||||||
|
<services>
|
||||||
|
<service name='XQueryAccessService' endpoint='http://dlib01.isti.cnr.it:8080/wsrf/services/gcube/informationsystem/collector/XQueryAccess' />
|
||||||
|
</services>
|
||||||
|
</service-map>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<service-map scope='/gcube' version="1.0.7-SNAPSHOT">
|
||||||
|
<services>
|
||||||
|
<service name='XQueryAccessService' endpoint='http://node5.d.d4science.research-infrastructures.eu:8000/wsrf/services/gcube/informationsystem/collector/XQueryAccess' />
|
||||||
|
</services>
|
||||||
|
</service-map>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module rename-to='MessageConversations'>
|
||||||
|
<!-- Inherit the core Web Toolkit stuff. -->
|
||||||
|
<inherits name='com.google.gwt.user.User' />
|
||||||
|
|
||||||
|
<!-- Inherit the default GWT style sheet. You can change -->
|
||||||
|
<!-- the theme of your GWT application by uncommenting -->
|
||||||
|
<!-- 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'/> -->
|
||||||
|
<inherits name='org.gcube.portlets.widgets.wsexplorer.WorkspaceExplorer' />
|
||||||
|
<!-- Other module inherits -->
|
||||||
|
<!-- GWT Material -->
|
||||||
|
<inherits name="gwt.material.design.GwtMaterialWithJQueryDebug" />
|
||||||
|
|
||||||
|
<!--Inherit the GCubeClientContext widget code -->
|
||||||
|
<inherits name='org.gcube.portal.clientcontext.GCubeClientContext' />
|
||||||
|
<inherits name="gwt.material.design.addins.GwtMaterialAddins" />
|
||||||
|
<!-- Specify the app entry point class. -->
|
||||||
|
<entry-point
|
||||||
|
class='org.gcube.portets.user.message_conversations.client.MessageConversations' />
|
||||||
|
|
||||||
|
<!-- Specify the paths for translatable code -->
|
||||||
|
<source path='client' />
|
||||||
|
<source path='shared' />
|
||||||
|
|
||||||
|
</module>
|
|
@ -0,0 +1,46 @@
|
||||||
|
.unread-message {
|
||||||
|
border-left: 3px solid #2196f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collection .collection-item.active {
|
||||||
|
background-color: #0277bd !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collection .collection-item.active span.black-text {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collection .collection-item.active span.grey-text {
|
||||||
|
color: #ccc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-metadata > div:not(.empty-state) h4 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin-top: 10px !important;
|
||||||
|
font-weight: 400 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-metadata > div.message-sender h4 {
|
||||||
|
font-size: 2.2em;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-metadata > div.message-recipients h4 {
|
||||||
|
font-size: 1.6em;
|
||||||
|
color: #555;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px solid grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gwt-SuggestBoxPopup .item-selected {
|
||||||
|
color: #1565c0 !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
.breadcrumb {
|
||||||
|
padding: 2px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.modal.BS-Navigator.in div.modal-body {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!doctype html>
|
||||||
|
<!-- The DOCTYPE declaration above will set the -->
|
||||||
|
<!-- browser's rendering engine into -->
|
||||||
|
<!-- "Standards Mode". Replacing this declaration -->
|
||||||
|
<!-- with a "Quirks Mode" doctype may lead to some -->
|
||||||
|
<!-- differences in layout. -->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
|
||||||
|
<link type="text/css" rel="stylesheet" href="MessageConversations.css">
|
||||||
|
|
||||||
|
<title>Messages Web</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/gcube-context.js"></script>
|
||||||
|
<script type="text/javascript" src="MessageConversations/MessageConversations.nocache.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" src="js/iframe-context.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
injectClientContext();
|
||||||
|
</script>
|
||||||
|
<div id="create-users-container"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
|
||||||
|
<%@ page
|
||||||
|
import="org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager"%>
|
||||||
|
<%@ page
|
||||||
|
import="org.gcube.common.authorization.library.provider.UserInfo"%>
|
||||||
|
<%@ page import="org.gcube.common.portal.PortalContext"%>
|
||||||
|
|
||||||
|
|
||||||
|
<%
|
||||||
|
long groupId = com.liferay.portal.util.PortalUtil.getScopeGroupId(request);
|
||||||
|
long userId = com.liferay.portal.util.PortalUtil.getUser(request).getUserId();
|
||||||
|
|
||||||
|
String strURL = response.encodeURL(
|
||||||
|
request.getContextPath() + "/MessageConversations.html?gid=" + groupId + "&uid=" + userId);
|
||||||
|
%>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
function resizeIFrameToFitContent( iFrame ) {
|
||||||
|
var dockBarHeight = (window.innerWidth > 768) ? 90 : 0;
|
||||||
|
iFrame.height = window.innerHeight - dockBarHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', function(e) {
|
||||||
|
var iFrame = document.getElementById( 'myIframe' );
|
||||||
|
resizeIFrameToFitContent( iFrame );
|
||||||
|
} );
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<iframe id="myIframe" src='<%=strURL%>' width="100%" marginwidth="0"
|
||||||
|
marginheight="0" frameborder="0" scrolling="no" style=" overflow-x: hidden; "> </iframe>
|
||||||
|
|
||||||
|
<!-- iFrame resize handler -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
var resizeDelay = 200;
|
||||||
|
var doResize = true;
|
||||||
|
var resizer = function() {
|
||||||
|
if (doResize) {
|
||||||
|
var iFrame = document.getElementById('myIframe');
|
||||||
|
resizeIFrameToFitContent(iFrame);
|
||||||
|
doResize = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var resizerInterval = setInterval(resizer, resizeDelay);
|
||||||
|
resizer();
|
||||||
|
|
||||||
|
$(window).resize(function() {
|
||||||
|
doResize = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE display PUBLIC "-//Liferay//DTD Display 6.2.0//EN" "http://www.liferay.com/dtd/liferay-display_6_2_0.dtd">
|
||||||
|
|
||||||
|
<display>
|
||||||
|
<category name="gCube Enabling Apps">
|
||||||
|
<portlet id="MessageConv" />
|
||||||
|
</category>
|
||||||
|
</display>
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=MessageConv
|
||||||
|
module-group-id=liferay
|
||||||
|
module-incremental-version=1
|
||||||
|
tags=
|
||||||
|
short-description=
|
||||||
|
change-log=
|
||||||
|
page-url=http://www.d4science.org
|
||||||
|
author=D4Science.org
|
||||||
|
licenses=EUPL
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_2_0.dtd">
|
||||||
|
|
||||||
|
<liferay-portlet-app>
|
||||||
|
<portlet>
|
||||||
|
<portlet-name>MessageConv</portlet-name>
|
||||||
|
<layout-cacheable>false</layout-cacheable>
|
||||||
|
<instanceable>false</instanceable>
|
||||||
|
<ajaxable>false</ajaxable>
|
||||||
|
<header-portlet-css>/MessageConversations.css</header-portlet-css>
|
||||||
|
</portlet>
|
||||||
|
<role-mapper>
|
||||||
|
<role-name>administrator</role-name>
|
||||||
|
<role-link>Administrator</role-link>
|
||||||
|
</role-mapper>
|
||||||
|
<role-mapper>
|
||||||
|
<role-name>guest</role-name>
|
||||||
|
<role-link>Guest</role-link>
|
||||||
|
</role-mapper>
|
||||||
|
<role-mapper>
|
||||||
|
<role-name>power-user</role-name>
|
||||||
|
<role-link>Power User</role-link>
|
||||||
|
</role-mapper>
|
||||||
|
<role-mapper>
|
||||||
|
<role-name>user</role-name>
|
||||||
|
<role-link>User</role-link>
|
||||||
|
</role-mapper>
|
||||||
|
</liferay-portlet-app>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<portlet-app
|
||||||
|
version="2.0"
|
||||||
|
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
|
||||||
|
>
|
||||||
|
<portlet>
|
||||||
|
<portlet-name>MessageConv</portlet-name>
|
||||||
|
<display-name>MessageConv</display-name>
|
||||||
|
<portlet-class>org.gcube.portets.user.message_conversations.server.portlet.MessagesPortlet</portlet-class>
|
||||||
|
<init-param>
|
||||||
|
<name>view-jsp</name>
|
||||||
|
<value>/view.jsp</value>
|
||||||
|
</init-param>
|
||||||
|
<expiration-cache>0</expiration-cache>
|
||||||
|
<supports>
|
||||||
|
<mime-type>text/html</mime-type>
|
||||||
|
</supports>
|
||||||
|
<portlet-info>
|
||||||
|
<title>MessageConv Sent</title>
|
||||||
|
<short-title>MessageConv Sent</short-title>
|
||||||
|
<keywords>MessageConv Sent</keywords>
|
||||||
|
</portlet-info>
|
||||||
|
<portlet-preferences>
|
||||||
|
<preference>
|
||||||
|
<name>portletSetupShowBorders</name>
|
||||||
|
<value>false</value>
|
||||||
|
</preference>
|
||||||
|
</portlet-preferences>
|
||||||
|
<security-role-ref>
|
||||||
|
<role-name>administrator</role-name>
|
||||||
|
</security-role-ref>
|
||||||
|
</portlet>
|
||||||
|
</portlet-app>
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||||
|
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||||
|
version="3.0">
|
||||||
|
|
||||||
|
<!-- Servlets -->
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>convServlet</servlet-name>
|
||||||
|
<servlet-class>org.gcube.portets.user.message_conversations.server.ConvServiceImpl</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>convServlet</servlet-name>
|
||||||
|
<url-pattern>/delegate/message-conversations</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>message-conversations</servlet-name>
|
||||||
|
<servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>servlet-class</param-name>
|
||||||
|
<param-value>org.gcube.portets.user.message_conversations.server.ConvServiceImpl</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>sub-context</param-name>
|
||||||
|
<param-value>message-conversations</param-value>
|
||||||
|
</init-param>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<!-- Workspace Explorer -->
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>workspaceExplorer</servlet-name>
|
||||||
|
<servlet-class>org.gcube.portlets.widgets.wsexplorer.server.WorkspaceExplorerServiceImpl</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>workspaceExplorer</servlet-name>
|
||||||
|
<url-pattern>/MessageConversations/WorkspaceExplorerService</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<!-- Default page to serve -->
|
||||||
|
<welcome-file-list>
|
||||||
|
<welcome-file>MessageConversations.html</welcome-file>
|
||||||
|
</welcome-file-list>
|
||||||
|
|
||||||
|
</web-app>
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Author: Massimiliano Assante, CNR-ISTI
|
||||||
|
* */
|
||||||
|
|
||||||
|
/*The following function simply injects the Liferay object field scopeGroupId in the XMLHttpRequest header.
|
||||||
|
* So that every ajax call performed in the page has those parameters set.*/
|
||||||
|
function injectClientContext() {
|
||||||
|
if (Liferay != null) {
|
||||||
|
var userId;
|
||||||
|
var groupId;
|
||||||
|
if (Liferay.ThemeDisplay.isSignedIn()) {
|
||||||
|
userId = Liferay.ThemeDisplay.getUserId();
|
||||||
|
groupId = Liferay.ThemeDisplay.getScopeGroupId();
|
||||||
|
console.log("groupid is = " + groupId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
groupId = Liferay.ThemeDisplay.getScopeGroupId();
|
||||||
|
//console.log('Not logged in, injecting groupId only');
|
||||||
|
}
|
||||||
|
//attach the 3 header params in all the XHR sends
|
||||||
|
(function(send) {
|
||||||
|
XMLHttpRequest.prototype.send = function(data) {
|
||||||
|
this.setRequestHeader("gcube-userId", userId);
|
||||||
|
this.setRequestHeader("gcube-vreid", groupId);
|
||||||
|
this.setRequestHeader("gcube-request-url", location.href);
|
||||||
|
send.call(this, data);
|
||||||
|
};
|
||||||
|
})(XMLHttpRequest.prototype.send);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Author: Massimiliano Assante, CNR-ISTI
|
||||||
|
* */
|
||||||
|
|
||||||
|
function getParameterByName(name, url) {
|
||||||
|
if (!url) url = window.location.href;
|
||||||
|
name = name.replace(/[\[\]]/g, "\\$&");
|
||||||
|
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
|
||||||
|
results = regex.exec(url);
|
||||||
|
if (!results) return null;
|
||||||
|
if (!results[2]) return '';
|
||||||
|
return decodeURIComponent(results[2].replace(/\+/g, " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var ThemeDisplayObject = {
|
||||||
|
userId : getParameterByName('uid'),
|
||||||
|
groupId : getParameterByName('gid'),
|
||||||
|
getUserId : function () {
|
||||||
|
return this.userId
|
||||||
|
},
|
||||||
|
getScopeGroupId : function () {
|
||||||
|
return this.groupId
|
||||||
|
},
|
||||||
|
isSignedIn : function () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Liferay = new Object();
|
||||||
|
Liferay.ThemeDisplay = ThemeDisplayObject;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Insert title here</title>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
ciao
|
||||||
|
<iframe id="IframeMessage" src='MessageConversations.html' width="100%" onload="this.style.height=this.contentDocument.body.scrollHeight +'px';"
|
||||||
|
marginwidth="0" marginheight="0" frameborder="1" scrolling="no" ></iframe>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue