This commit is contained in:
Massimiliano Assante 2019-05-22 14:12:35 +00:00
parent e2e3549ddc
commit 292812801d
122 changed files with 8441 additions and 0 deletions

45
2.8/.classpath Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/news-feed-2.8.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/news-feed-2.8.0-SNAPSHOT/WEB-INF/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</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="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="output" path="target/news-feed-2.8.0-SNAPSHOT/WEB-INF/classes"/>
</classpath>

0
2.8/.gwt/.gwt-log Normal file
View File

71
2.8/.project Normal file
View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>news-feed</name>
<comment>news-feed project</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</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>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
<nature>com.liferay.ide.core.liferayNature</nature>
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
</natures>
</projectDescription>

12
2.8/.settings/.jsdtscope Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="js/jquery.autosize.js|js/jquery.min.js" kind="src" path="src/main/webapp"/>
<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>

View File

@ -0,0 +1,3 @@
#Thu Jun 16 10:18:26 CEST 2011
eclipse.preferences.version=1
filesCopiedToWebInfLib=

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
jarsExcludedFromWebInfLib=
lastWarOutDir=/home/costantino/workspace/news-feed_good_trunk/target/news-feed-2.1.0-SNAPSHOT
warSrcDir=src/main/webapp
warSrcDirIsOutput=false

View File

@ -0,0 +1,5 @@
#Thu Jun 16 11:14:17 CEST 2011
eclipse.preferences.version=1
entryPointModules=
filesCopiedToWebInfLib=gwt-servlet.jar
gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgc3JjL21haW4vd2ViYXBwXV0+PC9leHRyYS1hcmdzPjx2bS1hcmdzPjwhW0NEQVRBWy1YbXg1MTJtXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLmNvbXBhbnkuU29tZU1vZHVsZTwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+

View File

@ -0,0 +1,4 @@
eclipse.preferences.version=1
lastWarOutDir=/Users/massi/Documents/workspace/news-feed/target/news-feed-2.8.0-SNAPSHOT
warSrcDir=src/main/webapp
warSrcDirIsOutput=false

View File

@ -0,0 +1,7 @@
#Tue Apr 02 15:52:18 CEST 2013
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,13 @@
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.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
validateFragments=false
validation.use-project-settings=true

View File

@ -0,0 +1,5 @@
#Tue Apr 02 15:52:17 CEST 2013
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,3 @@
#Tue Apr 02 16:00:18 CEST 2013
eclipse.preferences.version=1
org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="news-feed">
<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="/target/generated-sources/gwt"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<dependent-module archiveName="gcube-widgets-2.2.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/gcube-widgets/gcube-widgets">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="social-util-library-1.6.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/social-util-library/social-util-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="pickitem-widget-2.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/pickitem-widget/pickitem-widget">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="java-output-path" value="/${module}/target/www/WEB-INF/classes"/>
<property name="context-root" value="news-feed"/>
</wb-module>
</project-modules>

View File

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

View File

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

View File

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.JRE_CONTAINER

View File

@ -0,0 +1 @@
Global

View File

@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

View File

@ -0,0 +1,9 @@
#Thu Sep 02 10:42:12 CEST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

17
2.8/.tern-project Normal file
View File

@ -0,0 +1,17 @@
{
"plugins": {
"aui": {
},
"liferay": {
},
"yui": {
}
},
"libs": [
"ecma5",
"browser"
]
}

2
2.8/distro/LICENSE Normal file
View File

@ -0,0 +1,2 @@
${gcube.license}

64
2.8/distro/README Normal file
View File

@ -0,0 +1,64 @@
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@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Maintainers
-----------
* Massimiliano Assante (massimiliano.assante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
* Costantino Perciante (costantino.perciante@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
--------------------------------------------------
Installation documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}
Documentation
--------------------------------------------------
Documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}
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.

218
2.8/distro/changelog.xml Normal file
View File

@ -0,0 +1,218 @@
<ReleaseNotes>
<Changeset component="org.gcube.portlets-user.news-feed.2-8-0"
date="2019-05-22">
<Change>Bug #16724, Social networking: "See more" seems to reload a post with part of the old look and feel</Change>
<Change>Bug #16673, News Feed: comments with links between parenthesis not recognised</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-7-2"
date="2019-01-25">
<Change>Feature #16205: News Feed avoid refresh page when user is commenting</Change>
<Change>Minor CSS fix for anchors links font size</Change>
<Change>Bug fix #16225 mentions and replies http links not working in some email notifications</Change>
<Change>Feature #16452, Revise posts look and feel</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-6-1"
date="2018-04-12">
<Change>Removed previous jquery js load script and useless deprecated
pagebus</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-6-0"
date="2018-03-07">
<Change>Ported to GWT 2.8.2</Change>
<Change>Fix for Incident #11187 citing a people (with '@') in comments
is not working anymore
</Change>
<Change>
Feature #11189: Social-Networking - citing a people (with '@')
in comments loses the focus.
</Change>
<Change>Feature #10192 allow to sort feeds per recent comments
</Change>
<Change>Bug #7841 lack of blank space to separate the query term when
hashtag is used</Change>
<Change>Support for ticket #11139</Change>
<Change>Enhanced efficiency when retrieving mentioned users or groups
in comments</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-5-0"
date="2017-11-13">
<Change>fixes for Incident #10262: Cannot see who liked posts on VREs
of Parthenos
</Change>
<Change>Feature #10242: add comment taking up to 3 seconds sometime to
be delivered in the UI now shows a loader
</Change>
<Change>Ported to GWT 2.8.1</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-3-0"
date="2017-02-20">
<Change>fixes for changes to the underneath
common-notification-library
</Change>
<Change>Minor css fix </Change>
<Change>Refactored to the new version of elastic search client's
compliancy
</Change>
<Change>Feature #7212, do not apologies if no posts are present and
try to engage the user to post something.
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-2-0"
date="2016-12-02">
<Change>removed asl session</Change>
<Change>Increased general performance and bugfixes</Change>
<Change>fetching of users list to mention in comments loaded on demand
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-1-0"
date="2016-10-29">
<Change>Support to show feeds related to user's statistics added
</Change>
<Change>Fixed time for comments/posts: the year is present only if the
comment/post
was made before the current one
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.2-0-0"
date="2016-06-29">
<Change>Updated for Liferay 6.2.5</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.1-13-1"
date="2016-02-29">
<Change>Full-text search supported</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.news-feed.1-13-0"
date="2016-01-22">
<Change>Multi-attachment supported</Change>
<Change>Image preview available</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-12-0"
date="2015-11-12">
<Change>Fix for Bug #246, editing changes comment "metadata" namely
data
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-11-0"
date="2015-10-12">
<Change>Integrated workspace explorer widget and replace light tree
</Change>
<Change>Fix for Bug #195, Post dates lack the year
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-10-0"
date="2015-07-15">
<Change>Revised the way we shorten posts' text when this is very long,
better heuristic used
</Change>
<Change>Fixed bug #320, Users tagging does not work if @ is in the
middle of already typed text, works for hashtags too
</Change>
<Change>Revised mail notification message formatting, user text is now
more clear and visible
</Change>
<Change>Revised the way we provide back links for posts, removed
assumption that News Feed is always present the default community
page, good for single VRE portals support
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-9-0"
date="2015-04-27">
<Change>Integrated gwt-bootstrap and revised css</Change>
<Change>Ported to GWT 2.7.0</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-8-2"
date="2014-12-13">
<Change>added ClientScopeHandler to help prevent the back button cache
problem in Chrome and Firefox
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-8-1"
date="2014-11-18">
<Change>fixed see more problem with commercial ands (amps;) not being
converted
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-8-0"
date="2014-10-20">
<Change>Added support for hashtags</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-7-1"
date="2014-06-04">
<Change>Fixed bug that was allowing to like posts even if the user had
the session expired.
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-7-0"
date="2014-06-04">
<Change>
Fixed bug loosing session when messaging user from the news
feed
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-6-4"
date="2014-05-07">
<Change>Implemented the automatic scroll back in time for feeds (in
VRE scope)
</Change>
<Change>Added possibility to unlike alread liked posts</Change>
<Change>Added possibility to mention users in comments</Change>
<Change>Added default comment inputbox at the bottom of feed comments,
if any
</Change>
<Change>Added avatar replacement if user has no avatar</Change>
<Change>Fixed double notifications for post owner who commented his
post
</Change>
<Change>Fixed double notifications for post owner who liked his post
</Change>
<Change>Fixed user referral problem when post was deleted </Change>
<Change>Added session checking popup</Change>
<Change>Fixed paste problem on replies</Change>
<Change>Preserve new lines in comments implemented</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-5-0"
date="2014-02-13">
<Change>Moved to Java7</Change>
<Change>Added configuration file for VRE Labels</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-4-0"
date="2013-10-21">
<Change>Moved to GWT 2.5.1</Change>
<Change>Ported to Feather Weight Stack</Change>
<Change>Removed GCF Dependency</Change>
<Change>Logging with sl4j Enabled</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-2-0"
date="2013-07-08">
<Change>Fix for support Ticket #708</Change>
<Change>Fix for support Ticket #636</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-1-0"
date="2013-07-08">
<Change>Open single feed separately enhancement implemeented #1818
</Change>
<Change>links redirects correctly to user profiles</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.1-0-0"
date="2013-04-19">
<Change>Mavenized</Change>
<Change>Smart Refresh Support Added #1539</Change>
<Change>Show HTTP URL in replies as HTML anchor links #1542</Change>
<Change>Replies on App Feed exception fixed #580 prod. support
</Change>
<Change>Add Tag people in News Feed Portlet #1535</Change>
<Change>Notify people involved in post thread #1576</Change>
<Change>Scope Dependent News Feed #1561</Change>
<Change>Open single feed in new Window Support #1599</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.0-2-0"
date="2013-03-11">
<Change>User who favorite a post gets notified is someone comments on
that post
</Change>
</Changeset>
<Changeset component="org.gcube.portlets-user.newsfeed.0-1-0"
date="2012-10-31">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

31
2.8/distro/descriptor.xml Normal file
View File

@ -0,0 +1,31 @@
<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>

25
2.8/distro/profile.xml Normal file
View File

@ -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
2.8/log.txt Normal file
View File

390
2.8/pom.xml Normal file
View File

@ -0,0 +1,390 @@
<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.portlets.user</groupId>
<artifactId>news-feed</artifactId>
<packaging>war</packaging>
<version>2.8.0-SNAPSHOT</version>
<name>gCube News Feed Portlet</name>
<description>
gCube News Feed for exchanging updates with other users of VREs.
</description>
<scm>
<connection>scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId}</connection>
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId}</developerConnection>
<url>http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId}</url>
</scm>
<properties>
<!-- Convenience property to set the GWT version -->
<gwtVersion>2.8.2</gwtVersion>
<guavaVersion>18.0</guavaVersion>
<distroDirectory>distro</distroDirectory>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<liferay.version>6.2.5</liferay.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>maven-portal-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<dependency>
<groupId>org.gcube.portlets.user</groupId>
<artifactId>gcube-widgets</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common.portal</groupId>
<artifactId>portal-manager</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.dvos</groupId>
<artifactId>usermanagement-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.gwtbootstrap</groupId>
<artifactId>gwt-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.applicationsupportlayer</groupId>
<artifactId>aslsocial</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.resources.discovery</groupId>
<artifactId>ic-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google</groupId>
<artifactId>gwt-jsonmaker</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>common-authorization</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId>
<version>[1.16.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-thrift</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-cassandra</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-thrift</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.socialnetworking</groupId>
<artifactId>social-util-library</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.socialnetworking</groupId>
<artifactId>social-data-search-client</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.portlets.widgets</groupId>
<artifactId>pickitem-widget</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.portlets.widgets</groupId>
<artifactId>image-previewer-widget</artifactId>
<version>[1.1.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>notifications-common-library</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.portlets.widgets</groupId>
<artifactId>user-selection-dialog</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>compile</scope>
</dependency>
<!-- Please note that the elasticsearch client needs a compress-lzf version
>= 1.0.2 -->
<dependency>
<groupId>com.ning</groupId>
<artifactId>compress-lzf</artifactId>
<version>1.0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</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>javax.portlet</groupId>
<artifactId>portlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<!-- Generate compiled stuff in the folder used for developing mode -->
<outputDirectory>${webappDirectory}/WEB-INF/classes</outputDirectory>
<plugins>
<!-- GWT Maven Plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>${gwtVersion}</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<!-- <goal>test</goal> -->
</goals>
</execution>
</executions>
<!-- Plugin configuration. There are many available options, see gwt-maven-plugin
documentation at codehaus.org -->
<configuration>
<runTarget>NewsFeed.html</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
</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>

View File

@ -0,0 +1,5 @@
package org.gcube.portlets.user.newsfeed.client;
public enum FilterType {
ALL_UPDATES, CONNECTIONS, RECENT_COMMENTS, MINE;
}

View File

@ -0,0 +1,66 @@
package org.gcube.portlets.user.newsfeed.client;
import org.gcube.portal.databook.shared.ClientPost;
import org.gcube.portal.databook.shared.JSON;
import org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
/**
*
* @author Massimiliano Assante, CNR-ISTI
*
* This class uses Liferay's Client-side+Inter-Portlet-Communication for displaying post created in the Share Updates portlet
* @see https://web.liferay.com/community/wiki/-/wiki/Main/Client-side+Inter-Portlet-Communication+%28IPC%29%20using+Java+Script
*
*/
public class NewsFeed implements EntryPoint {
private final String UNIQUE_DIV = "newsfeedDIV";
private NewsFeedPanel mainPanel;
private static NewsFeedPanel instance;
public static NewsFeedPanel getInstance() {
if (instance == null) {
instance = new NewsFeedPanel();
}
return instance;
}
public void onModuleLoad() {
injectLiferayIPCEventReceiver();
exportReceiveEventJavascriptFunction();
mainPanel = getInstance();
RootPanel.get(UNIQUE_DIV).add(mainPanel);
}
/**
* this is a JSNI method that injects the Liferay Javascript function listening for events from ShareUpdates
*/
public static native void injectLiferayIPCEventReceiver() /*-{
try {
$wnd.Liferay.on('newPostCreated',function(event) {
$wnd.handleReceiveEvent(event.payload);
});
} catch(err) {
$wnd.console.log('error subscribing to newPostCreated events, acceptable in dev');
}
}-*/;
/**
* this is a JSNI method mapping the Javascript function handleReceiveEvent to the Java method handleReceiveEvent
*/
public static native void exportReceiveEventJavascriptFunction()/*-{
$wnd.handleReceiveEvent = @org.gcube.portlets.user.newsfeed.client.NewsFeed::handleReceiveEvent(*);
}-*/;
/**
* the Java method handleReceiveEvent
* @param jsonizedClientPostInstance the jsonized {@link ClientPost} sent by ShareUpdates
*/
public static void handleReceiveEvent(String jsonizedClientPostInstance) {
ClientPost cp = (ClientPost) JSON.parse(jsonizedClientPostInstance);
getInstance().addJustAddedFeed(cp);
}
}

View File

@ -0,0 +1,63 @@
package org.gcube.portlets.user.newsfeed.client;
import java.util.ArrayList;
import java.util.HashSet;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.EnhancedFeed;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.databook.shared.ShowUserStatisticAction;
import org.gcube.portlets.user.newsfeed.shared.MentionedDTO;
import org.gcube.portlets.user.newsfeed.shared.MorePostsBean;
import org.gcube.portlets.user.newsfeed.shared.OperationResult;
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
import org.gcube.portlets.widgets.pickitem.shared.ItemBean;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("newsServlet")
public interface NewsService extends RemoteService {
ArrayList<EnhancedFeed> getAllUpdateUserFeeds(int feedsNoPerCategory);
ArrayList<EnhancedFeed> getOnlyConnectionsUserPosts();
ArrayList<EnhancedFeed> getOnlyMyUserPosts();
ArrayList<EnhancedFeed> getOnlyLikedPosts();
ArrayList<EnhancedFeed> getPostsByHashtag(String hashtag);
ArrayList<EnhancedFeed> getPostsByQuery(String query, int from, int quantity);
ArrayList<EnhancedFeed> getPostsRelatedToUserStatistics(ShowUserStatisticAction action, int from, int quantity);
MorePostsBean getMorePosts(int from, int quantity);
boolean like(String postid, String postText, String postOwnerId);
boolean unlike(String postid, String postText, String postOwnerId);
boolean deleteComment(String commentid, String feedid);
boolean deletePost(String postid);
OperationResult comment(String feedid, String text,
HashSet<MentionedDTO> mentionedUsers, String feedOwnerId,
boolean isAppFeed);
OperationResult editComment(Comment toEdit);
ArrayList<Like> getAllLikesByPost(String postid);
ArrayList<Comment> getAllCommentsByPost(String feedid);
UserSettings getUserSettings();
EnhancedFeed getSinglePost(String postKey);
ArrayList<ItemBean> getOrganizationUsers();
}

View File

@ -0,0 +1,74 @@
package org.gcube.portlets.user.newsfeed.client;
import java.util.ArrayList;
import java.util.HashSet;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.EnhancedFeed;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.databook.shared.ShowUserStatisticAction;
import org.gcube.portlets.user.newsfeed.shared.MentionedDTO;
import org.gcube.portlets.user.newsfeed.shared.MorePostsBean;
import org.gcube.portlets.user.newsfeed.shared.OperationResult;
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
import org.gcube.portlets.widgets.pickitem.shared.ItemBean;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* The async counterpart of <code>NewsService</code>.
*/
public interface NewsServiceAsync {
void getAllUpdateUserFeeds(int feedsNoPerCategory,
AsyncCallback<ArrayList<EnhancedFeed>> callback);
void getOnlyConnectionsUserPosts(
AsyncCallback<ArrayList<EnhancedFeed>> callback);
void like(String postid, String postText, String postOwnerId,
AsyncCallback<Boolean> callback);
void getAllLikesByPost(String postid,
AsyncCallback<ArrayList<Like>> callback);
void getOnlyMyUserPosts(AsyncCallback<ArrayList<EnhancedFeed>> callback);
void getUserSettings(AsyncCallback<UserSettings> callback);
void comment(String feedid, String text, HashSet<MentionedDTO> mentionedUsers,
String feedOwnerId, boolean isAppFeed,
AsyncCallback<OperationResult> callback);
void getAllCommentsByPost(String postid,
AsyncCallback<ArrayList<Comment>> callback);
void deleteComment(String commentid, String feedid,
AsyncCallback<Boolean> callback);
void deletePost(String feedid, AsyncCallback<Boolean> callback);
void editComment(Comment toEdit, AsyncCallback<OperationResult> callback);
void getOnlyLikedPosts(AsyncCallback<ArrayList<EnhancedFeed>> callback);
void getSinglePost(String postKey, AsyncCallback<EnhancedFeed> callback);
void getMorePosts(int from, int quantity,
AsyncCallback<MorePostsBean> callback);
void unlike(String postid, String postText, String postOwnerId,
AsyncCallback<Boolean> callback);
void getOrganizationUsers(AsyncCallback<ArrayList<ItemBean>> callback);
void getPostsByHashtag(String hashtag,
AsyncCallback<ArrayList<EnhancedFeed>> callback);
void getPostsByQuery(String query, int from, int quantity,
AsyncCallback<ArrayList<EnhancedFeed>> callback);
void getPostsRelatedToUserStatistics(ShowUserStatisticAction action, int from, int quantity,
AsyncCallback<ArrayList<EnhancedFeed>> callback);
}

View File

@ -0,0 +1,46 @@
package org.gcube.portlets.user.newsfeed.client.event;
import java.util.HashSet;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import org.gcube.portlets.user.newsfeed.shared.MentionedDTO;
import com.google.gwt.event.shared.GwtEvent;
public class AddCommentEvent extends GwtEvent<AddCommentEventHandler> {
public static Type<AddCommentEventHandler> TYPE = new Type<AddCommentEventHandler>();
private TweetTemplate owner;
private String text;
private HashSet<MentionedDTO> mentionedUsers;
public AddCommentEvent(TweetTemplate owner, String text,HashSet<MentionedDTO> mentionedUsers) {
this.owner = owner;
this.text = text;
this.mentionedUsers = mentionedUsers;
}
public TweetTemplate getOwner() {
return owner;
}
public String getText() {
return text;
}
public HashSet<MentionedDTO> getMentionedUsers() {
return mentionedUsers;
}
@Override
public Type<AddCommentEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(AddCommentEventHandler handler) {
handler.onAddComment(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface AddCommentEventHandler extends EventHandler {
void onAddComment(AddCommentEvent event);
}

View File

@ -0,0 +1,36 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
public class AddLikeEvent extends GwtEvent<AddLikeEventHandler> {
public static Type<AddLikeEventHandler> TYPE = new Type<AddLikeEventHandler>();
private TweetTemplate owner;
private final String feedid;
public AddLikeEvent(TweetTemplate owner, String feedid) {
this.feedid = feedid;
this.owner = owner;
}
public String getFeedId() {
return feedid;
}
public TweetTemplate getOwner() {
return owner;
}
@Override
public Type<AddLikeEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(AddLikeEventHandler handler) {
handler.onAddLike(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface AddLikeEventHandler extends EventHandler {
void onAddLike(AddLikeEvent event);
}

View File

@ -0,0 +1,35 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
public class DeleteCommentEvent extends GwtEvent<DeleteCommentEventHandler> {
public static Type<DeleteCommentEventHandler> TYPE = new Type<DeleteCommentEventHandler>();
private TweetTemplate owner;
private String commentid;
public TweetTemplate getOwner() {
return owner;
}
public String getCommentId() {
return commentid;
}
public DeleteCommentEvent(TweetTemplate owner, String commentid) {
this.owner = owner;
this.commentid = commentid;
}
@Override
public Type<DeleteCommentEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(DeleteCommentEventHandler handler) {
handler.onDeleteComment(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface DeleteCommentEventHandler extends EventHandler {
void onDeleteComment(DeleteCommentEvent event);
}

View File

@ -0,0 +1,32 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
public class DeletePostEvent extends GwtEvent<DeletePostEventHandler> {
public static Type<DeletePostEventHandler> TYPE = new Type<DeletePostEventHandler>();
private TweetTemplate toDelete;
public TweetTemplate getToDelete() {
return toDelete;
}
public DeletePostEvent(TweetTemplate toDelete) {
this.toDelete = toDelete;
}
@Override
public Type<DeletePostEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(DeletePostEventHandler handler) {
handler.onDeletePost(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface DeletePostEventHandler extends EventHandler {
void onDeletePost(DeletePostEvent event);
}

View File

@ -0,0 +1,43 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.user.client.ui.HTMLPanel;
public class EditCommentEvent extends GwtEvent<EditCommentEventHandler> {
public static Type<EditCommentEventHandler> TYPE = new Type<EditCommentEventHandler>();
private TweetTemplate owner;
private Comment edited;
private HTMLPanel commentPanel;
public TweetTemplate getOwner() {
return owner;
}
public Comment getCommentInstance() {
return edited;
}
public HTMLPanel getCommentPanel() {
return commentPanel;
}
public EditCommentEvent(TweetTemplate owner, Comment editedComment, HTMLPanel commentPanel) {
this.owner = owner;
this.edited = editedComment;
this.commentPanel = commentPanel;
}
@Override
public Type<EditCommentEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(EditCommentEventHandler handler) {
handler.onEditComment(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface EditCommentEventHandler extends EventHandler {
void onEditComment(EditCommentEvent event);
}

View File

@ -0,0 +1,32 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
public class OpenPostEvent extends GwtEvent<OpenPostEventHandler> {
public static Type<OpenPostEventHandler> TYPE = new Type<OpenPostEventHandler>();
private TweetTemplate toShow;
public TweetTemplate getToShow() {
return toShow;
}
public OpenPostEvent(TweetTemplate toShow) {
this.toShow = toShow;
}
@Override
public Type<OpenPostEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(OpenPostEventHandler handler) {
handler.onOpenPost(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface OpenPostEventHandler extends EventHandler {
void onOpenPost(OpenPostEvent event);
}

View File

@ -0,0 +1,21 @@
package org.gcube.portlets.user.newsfeed.client.event;
/**
* This class contains the events (in a package like format) to which this portlet listens at.
* NOTE: these events are the same in the User-Statistics portlet and the share-updates one.
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
public class PageBusEvents {
// events in this portlet and user-statistics
public static final String postIncrement = "org.gcube.portal.incrementPostCount";
public static final String postDecrement = "org.gcube.portal.decrementPostCount";
public static final String likesIncrement = "org.gcube.portal.incrementLikesGot";
public static final String likesDecrement = "org.gcube.portal.decrementLikesGot";
public static final String commentsIncrement = "org.gcube.portal.incrementCommentsGot";
public static final String commentsDecrement = "org.gcube.portal.decrementCommentsGot";
// events in this portlet and the share-updates one
public static final String newPostCreated = "org.gcube.portal.databook.shared";
}

View File

@ -0,0 +1,37 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
public class SeeCommentsEvent extends GwtEvent<SeeCommentsEventHandler> {
public static Type<SeeCommentsEventHandler> TYPE = new Type<SeeCommentsEventHandler>();
private TweetTemplate owner;
private boolean commentForm2Add;
public TweetTemplate getOwner() {
return owner;
}
public boolean isCommentForm2Add() {
return commentForm2Add;
}
public SeeCommentsEvent(TweetTemplate owner, boolean commentForm2Add) {
this.owner = owner;
this.commentForm2Add = commentForm2Add;
}
@Override
public Type<SeeCommentsEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(SeeCommentsEventHandler handler) {
handler.onSeeComments(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface SeeCommentsEventHandler extends EventHandler {
void onSeeComments(SeeCommentsEvent event);
}

View File

@ -0,0 +1,28 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.GwtEvent;
public class SeeLikesEvent extends GwtEvent<SeeLikesEventHandler> {
public static Type<SeeLikesEventHandler> TYPE = new Type<SeeLikesEventHandler>();
private final String feedid;
public SeeLikesEvent(String feedid) {
this.feedid = feedid;
}
public String getFeedId() {
return feedid;
}
@Override
public Type<SeeLikesEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(SeeLikesEventHandler handler) {
handler.onSeeLikes(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface SeeLikesEventHandler extends EventHandler {
void onSeeLikes(SeeLikesEvent event);
}

View File

@ -0,0 +1,21 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.GwtEvent;
public class ShowMoreUpdatesEvent extends GwtEvent<ShowMoreUpdatesEventHandler> {
public static Type<ShowMoreUpdatesEventHandler> TYPE = new Type<ShowMoreUpdatesEventHandler>();
public ShowMoreUpdatesEvent() { }
@Override
public Type<ShowMoreUpdatesEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(ShowMoreUpdatesEventHandler handler) {
handler.onShowMoreUpdatesClick(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface ShowMoreUpdatesEventHandler extends EventHandler {
void onShowMoreUpdatesClick(ShowMoreUpdatesEvent event);
}

View File

@ -0,0 +1,21 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.GwtEvent;
public class ShowNewUpdatesEvent extends GwtEvent<ShowNewUpdatesEventHandler> {
public static Type<ShowNewUpdatesEventHandler> TYPE = new Type<ShowNewUpdatesEventHandler>();
public ShowNewUpdatesEvent() { }
@Override
public Type<ShowNewUpdatesEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(ShowNewUpdatesEventHandler handler) {
handler.onShowNewUpdatesClick(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface ShowNewUpdatesEventHandler extends EventHandler {
void onShowNewUpdatesClick(ShowNewUpdatesEvent event);
}

View File

@ -0,0 +1,36 @@
package org.gcube.portlets.user.newsfeed.client.event;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
public class UnLikeEvent extends GwtEvent<UnLikeEventHandler> {
public static Type<UnLikeEventHandler> TYPE = new Type<UnLikeEventHandler>();
private TweetTemplate owner;
private final String feedid;
public UnLikeEvent(TweetTemplate owner, String feedid) {
this.feedid = feedid;
this.owner = owner;
}
public String getFeedId() {
return feedid;
}
public TweetTemplate getOwner() {
return owner;
}
@Override
public Type<UnLikeEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(UnLikeEventHandler handler) {
handler.onUnLike(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import com.google.gwt.event.shared.EventHandler;
public interface UnLikeEventHandler extends EventHandler {
void onUnLike(UnLikeEvent event);
}

View File

@ -0,0 +1,260 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.gcubewidgets.client.elements.Div;
import org.gcube.portlets.user.newsfeed.client.event.AddCommentEvent;
import org.gcube.portlets.user.newsfeed.client.event.EditCommentEvent;
import com.github.gwtbootstrap.client.ui.Button;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
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.Window.ClosingHandler;
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.Image;
import com.google.gwt.user.client.ui.Widget;
public class AddCommentTemplate extends Composite {
interface CommentTemplateUiBinder extends UiBinder<Widget, AddCommentTemplate> {
}
private static CommentTemplateUiBinder uiBinder = GWT.create(CommentTemplateUiBinder.class);
public final static String COMMENT_TEXT = "Write a comment, use @ to mention someone";
public final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png";
private TweetTemplate owner;
private HandlerManager eventBus;
private boolean isEditing = false;
private HTMLPanel commentPanel;
private Comment toEdit;
private ClosingHandler closingHandler;
private HandlerRegistration handlerRegistration;
@UiField HTMLPanel mainPanel;
@UiField Image avatarImage;
@UiField SuperPosedTextArea commentTextArea;
@UiField Div highlighterDIV;
@UiField Button submitButton;
@UiField Button cancelButton; //obsolete
/**
* called on add comment
* @param caller
* @param myUserInfo
* @param eventBus
*/
public AddCommentTemplate(TweetTemplate caller, UserInfo myUserInfo, HandlerManager eventBus) {
initWidget(uiBinder.createAndBindUi(this));
this.eventBus = eventBus;
owner = caller;
avatarImage.setPixelSize(30, 30);
avatarImage.setUrl(myUserInfo.getAvatarId());
submitButton.setVisible(false);
cancelButton.setVisible(false);
commentTextArea.setHeight("30px");
commentTextArea.setContext(owner.getVREContext());
}
/**
* called on edit comment
* @param caller
* @param editText
*/
public AddCommentTemplate(TweetTemplate caller, Comment toEdit, HTMLPanel commentPanel) {
initWidget(uiBinder.createAndBindUi(this));
this.eventBus = caller.getEventBus();
this.commentPanel = commentPanel;
isEditing = true;
this.toEdit = toEdit;
String commentText = new HTML(toEdit.getText()).getText();
//replace the < & and >
commentText = commentText.replaceAll("&lt;","<").replaceAll("&gt;",">");
commentText = commentText.replaceAll("&amp;","&");
owner = caller;
commentTextArea.setContext(owner.getVREContext());
avatarImage.setPixelSize(30, 30);
avatarImage.setUrl(caller.getMyUserInfo().getAvatarId());
commentTextArea.setText(commentText);
mainPanel.removeStyleName("comment-hidden");
mainPanel.setStyleName("single-comment");
commentTextArea.addStyleName("comment-dark-color");
submitButton.setText("Edit");
closingHandler = new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
String currentText = commentTextArea.getText();
if(!currentText.isEmpty()){
closingEvent.setMessage("Do you really want to leave the page?");
}
}
};
handlerRegistration = Window.addWindowClosingHandler(closingHandler);
}
/** Used by AddCommentTemplate to instantiate SuperPosedTextArea */
@UiFactory SuperPosedTextArea build() {
return new SuperPosedTextArea(highlighterDIV);
}
public void setFocus() {
commentTextArea.setFocus(true);
submitButton.setVisible(true);
cancelButton.setVisible(true);
//it needs a timer otherwise it won't work
Timer t = new Timer() {
@Override
public void run() {
setCaretPositionToBegin(commentTextArea.getAreaId());
closingHandler = new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
String currentText = commentTextArea.getText();
if(!currentText.isEmpty()){
closingEvent.setMessage("Do you really want to leave the page?");
}
}
};
handlerRegistration = Window.addWindowClosingHandler(closingHandler);
}
};
t.schedule(200);
}
@UiHandler("submitButton")
void onSubmitClick(ClickEvent e) {
String userComment = commentTextArea.getText().trim();
if (userComment.equals(COMMENT_TEXT) || userComment.equals(ERROR_UPDATE_TEXT) || userComment.equals("")) {
commentTextArea.addStyleName("nwfeed-error");
commentTextArea.setText(ERROR_UPDATE_TEXT);
return;
}
if (isEditing) {
toEdit.setText(escapeHtml(commentTextArea.getText()));
eventBus.fireEvent(new EditCommentEvent(owner, toEdit, commentPanel));
}
else { //it is ok to add this comment
eventBus.fireEvent(new AddCommentEvent(owner, escapeHtml(commentTextArea.getText()), commentTextArea.getMentionedUsers()));
}
this.getWidget().setVisible(false);
owner.setCommentingDisabled(false);
handlerRegistration.removeHandler();
GWT.log(" handlerRegistration.removeHandler();");
}
/**
* called when pasting. it tries to avoid pasting long non spaced strings
* @param linkToCheck
*/
private boolean checkTextLength(String textToCheck) {
String [] parts = textToCheck.split("\\s");
// check the length of tokens
for( String item : parts ) {
if (!item.startsWith("http") && !item.startsWith("ftp")) { //url are accepted as they can be trunked
if (item.length() > 50) {
return false;
}
}
}
return true;
}
@UiHandler("cancelButton")
void onCancelClick(ClickEvent e) {
this.getWidget().setVisible(false);
owner.setCommentingDisabled(false);
if (isEditing) {
commentPanel.clear();
SingleComment sc = new SingleComment(toEdit, owner, true);
commentPanel.add(sc);
}
handlerRegistration.removeHandler();
}
@UiHandler("commentTextArea")
void onCommentClick(ClickEvent e) {
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
commentTextArea.setText("");
commentTextArea.addStyleName("comment-dark-color");
commentTextArea.removeStyleName("nwfeed-error");
}
submitButton.setVisible(true);
cancelButton.setVisible(true);
closingHandler = new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
String currentText = commentTextArea.getText();
if(!currentText.isEmpty()){
closingEvent.setMessage("Do you really want to leave the page?");
}
}
};
handlerRegistration = Window.addWindowClosingHandler(closingHandler);
}
@UiHandler("commentTextArea")
void onCommentKeyPress(KeyPressEvent e) {
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
commentTextArea.setText("");
commentTextArea.addStyleName("comment-dark-color");
commentTextArea.removeStyleName("nwfeed-error");
}
}
/**
* Escape an html string. Escaping data received from the client helps to
* prevent cross-site script vulnerabilities.
*
* @param html the html string to escape
* @return the escaped string
*/
private String escapeHtml(String html) {
if (html == null) {
return null;
}
return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
.replaceAll(">", "&gt;");
}
/**
* this position the caret at the begin in a TextArea
* @param myAreaId the unique identifier of the textarea
*/
public static native void setCaretPositionToBegin(String myAreaId) /*-{
var elem = $doc.getElementById(myAreaId);
if(elem != null) {
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', 0);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(0, 0);
}
else
elem.focus();
}
}
}-*/;
}

View File

@ -0,0 +1,35 @@
<!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:w="urn:import:org.gcube.portlets.user.gcubewidgets.client.elements"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:m="urn:import:org.gcube.portlets.user.newsfeed.client.ui">
<g:HTMLPanel styleName="comment-hidden" ui:field="mainPanel">
<table class="single-comment">
<tr>
<td width="30px" align="middle">
<g:Image styleName="member-photo" url="" ui:field="avatarImage"
width="30px" height="30px" />
</td>
<td>
<div id="comment-supercontainer">
<div id="comment-highlighterContainer">
<w:Div styleName="comment-highlighter" ui:field="highlighterDIV"></w:Div>
</div>
<div id="comment-inputContainer">
<m:SuperPosedTextArea styleName="post-comment" ui:field="commentTextArea" />
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<b:Button ui:field="cancelButton" text="Cancel" />
<b:Button ui:field="submitButton" text="Comment" />
</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,187 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import org.gcube.portal.databook.shared.Attachment;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.EnhancedImage;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.ui.Carousel;
import com.github.gwtbootstrap.client.ui.Image;
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.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
/**
* Class to show an attached file.
* @author Costantino Perciante at ISTI-CNR
*
*/
public class AttachmentPreviewer extends Composite {
private static AttachmentPreviewerUiBinder uiBinder = GWT
.create(AttachmentPreviewerUiBinder.class);
interface AttachmentPreviewerUiBinder extends
UiBinder<Widget, AttachmentPreviewer> {
}
public AttachmentPreviewer() {
initWidget(uiBinder.createAndBindUi(this));
}
@UiField
HTMLPanel attachmentContainer;
@UiField
Image imagePreview;
@UiField
Label fileNameLabel;
@UiField
Anchor downloadLabel;
@UiField
Anchor showPreviewLabel;
@UiField
Label labelSeparator;
// save attachment
private Attachment attachment;
// carousel reference
private Carousel carousel;
// enhanced image associated with this carousel
private EnhancedImage img;
public AttachmentPreviewer(Attachment a) {
// init
initWidget(uiBinder.createAndBindUi(this));
// save the attachment
attachment = a;
// set image preview
imagePreview.setUrl(a.getThumbnailURL());
imagePreview.setStyleName("image-preview-attachment");
// set file name (be careful on file name length)
String shownName = a.getName().length() > 21 ? a.getName().substring(0, 18) + "..." : a.getName();
fileNameLabel.setText(shownName);
fileNameLabel.setTitle(a.getName());
// download label
downloadLabel.setText("Download");
downloadLabel.setHref(attachment.getUri());
downloadLabel.setTarget("_blank");
// preview in case of an image
if(a.getMimeType().contains("image/")){
showPreviewLabel.setText("Show");
showPreviewLabel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(img != null)
carousel.show(img);
}
});
}else{
// hide the show button and the separator label
showPreviewLabel.setVisible(false);
labelSeparator.setVisible(false);
}
// style links
downloadLabel.addStyleName("link");
showPreviewLabel.addStyleName("link");
}
/**
* Change the width of this container.
* @param newWidth
* @param unit
*/
public void changeAttachmentWidth(int newWidth, Unit unit){
attachmentContainer.getElement().getStyle().setWidth(newWidth, unit);
}
/**
* Open the carousel when the user clicks on the preview's image.
* @param carousel
*/
public void onImageClickOpenCarousel(final Carousel carousel) {
// save it
this.carousel = carousel;
// change cursor type on hover
imagePreview.getElement().getStyle().setCursor(Cursor.POINTER);
// change tooltipe
imagePreview.setTitle("Click for a preview");
// add handler
imagePreview.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
carousel.show();
}
});
}
/**
* Open the carousel and show this enhancedImage when the user clicks on the preview's image.
* @param carousel
* @param enhancedImage the image to show
*/
public void onImageClickOpenCarousel(final Carousel carousel, final EnhancedImage enhancedImage) {
// save the carousel ref.
this.carousel = carousel;
// save img ref
this.img = enhancedImage;
// change cursor type on hover
imagePreview.getElement().getStyle().setCursor(Cursor.POINTER);
// change tooltipe
imagePreview.setTitle("Click for a preview");
// add handler
imagePreview.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(img != null)
carousel.show(img);
}
});
}
}

View File

@ -0,0 +1,54 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.container-style {
padding: 5px;
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
background-clip: border-box;
background-color: #FBFBFB;
background-image: none;
border: 1px solid #DDD;
border-radius: 4px;
margin: 5px;
display: inline-block;
width: 95%;
height: 60px;
overflow: hidden;
}
.label-filename-style {
overflow-x: hidden;
margin-left: 5px;
}
.label-show {
font-weight: bold;
margin-left: 5px;
}
.label-download {
font-weight: bold;
margin-left: 5px;
margin-right: 5px;
}
.display-inline-style {
display: inline-block;
margin-right: 5px;
}
</ui:style>
<g:HTMLPanel styleName="{style.container-style}" ui:field="attachmentContainer">
<g:HorizontalPanel width="100%'">
<b:Image ui:field="imagePreview"></b:Image>
<g:VerticalPanel styleName="{style.display-inline-style}">
<g:Label ui:field="fileNameLabel" styleName="{style.label-filename-style}"></g:Label>
<g:HorizontalPanel>
<g:Anchor ui:field="downloadLabel" styleName="{style.label-download}"></g:Anchor>
<g:Label ui:field="labelSeparator">-</g:Label>
<g:Anchor ui:field="showPreviewLabel" styleName="{style.label-show}"></g:Anchor>
</g:HorizontalPanel>
</g:VerticalPanel>
</g:HorizontalPanel>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,72 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import java.util.HashMap;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
public class AvatarReplacement extends Composite {
private static NoAvatarUiBinder uiBinder = GWT.create(NoAvatarUiBinder.class);
/**
* to maintain the color assigned to an avatar replacement, for each page load
* this hashmap maintain the assigned users color, chosen reandomly at the beginning
*/
public static final HashMap<String, String> avatarReplacementAssignedColors = new HashMap<String, String>();
interface NoAvatarUiBinder extends UiBinder<Widget, AvatarReplacement> {
}
@UiField HTML avatarBox;
/**
* the random colors
*/
private String[] randomColors = {
"#8e8e93",
"#ff2d55",
"#ff3b30",
"#ff9500",
"#ffcc00",
"#4cd964",
"#5ac8fa",
"#34aadc",
"#007aff",
"#5856d6"
};
public AvatarReplacement() {
initWidget(uiBinder.createAndBindUi(this));
}
public void setInitials(String username, String firstName, String lastName) {
pickRandomColor(username);
String first = "A";
if (firstName != null && firstName.trim().length() > 0)
first = firstName.trim().substring(0, 1);
String second = "Z";
if (lastName != null && lastName.trim().length() > 0)
second = lastName.trim().substring(0, 1);
avatarBox.setText(first+second);
}
/**
* randomize of does not find it, else color is maintained through all the session
* @param username
*/
private void pickRandomColor(String username) {
if (! avatarReplacementAssignedColors.containsKey(username)) {
String randomColor = randomColors[Random.nextInt(randomColors.length)];
avatarBox.getElement().getStyle().setBackgroundColor(randomColor);
avatarReplacementAssignedColors.put(username, randomColor);
} else
avatarBox.getElement().getStyle().setBackgroundColor(avatarReplacementAssignedColors.get(username));
}
}

View File

@ -0,0 +1,29 @@
<!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">
<ui:style>
.avatar-frame {
border-radius: 2em;
border: 1px solid #E6E6E6;
padding: 2px;
}
.avatar-replacement {
border-radius: 2em;
display: table-cell;
text-align: center;
vertical-align: middle;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
font-size: 22px;
padding: 0;
color: #FFF;
}
</ui:style>
<g:HTMLPanel width="40px" height="40px"
styleName="{style.avatar-frame}">
<g:HTML width="40px" height="40px"
styleName="{style.avatar-replacement}" ui:field="avatarBox"></g:HTML>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,64 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
public class AvatarReplacement4Comments extends Composite {
private static NoAvatarUiBinder uiBinder = GWT.create(NoAvatarUiBinder.class);
interface NoAvatarUiBinder extends UiBinder<Widget, AvatarReplacement4Comments> {
}
@UiField HTML avatarBox;
/**
* the random colors
*/
private String[] randomColors = {
"#8e8e93",
"#ff2d55",
"#ff3b30",
"#ff9500",
"#ffcc00",
"#4cd964",
"#5ac8fa",
"#34aadc",
"#007aff",
"#5856d6"
};
public AvatarReplacement4Comments() {
initWidget(uiBinder.createAndBindUi(this));
}
public void setInitials(String username, String firstName, String lastName) {
pickRandomColor(username);
String first = "A";
if (firstName != null && firstName.trim().length() > 0)
first = firstName.trim().substring(0, 1);
String second = "Z";
if (lastName != null && lastName.trim().length() > 0)
second = lastName.trim().substring(0, 1);
avatarBox.setText(first+second);
}
/**
* randomize of does not find it, else color is maintained through all the session
* @param username
*/
private void pickRandomColor(String username) {
if (! AvatarReplacement.avatarReplacementAssignedColors.containsKey(username)) {
String randomColor = randomColors[Random.nextInt(randomColors.length)];
avatarBox.getElement().getStyle().setBackgroundColor(randomColor);
AvatarReplacement.avatarReplacementAssignedColors.put(username, randomColor);
} else
avatarBox.getElement().getStyle().setBackgroundColor(AvatarReplacement.avatarReplacementAssignedColors.get(username));
}
}

View File

@ -0,0 +1,25 @@
<!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">
<ui:style>
.avatar-frame {
border-radius: 2em;
border: 1px solid #E6E6E6;
padding: 2px;
}
.avatar-replacement {
display: table-cell;
border-radius: 2em;
text-align: center;
vertical-align: middle;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
font-size: 12px;
padding: 0;
color: #FFF;
}
</ui:style>
<g:HTMLPanel width="30px" height="30px" styleName="{style.avatar-frame}">
<g:HTML width="30px" height="30px" styleName="{style.avatar-replacement}" ui:field="avatarBox"></g:HTML>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,83 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import org.gcube.portlets.user.newsfeed.client.FilterType;
import org.gcube.portlets.user.newsfeed.client.NewsServiceAsync;
import org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
import com.github.gwtbootstrap.client.ui.Dropdown;
import com.github.gwtbootstrap.client.ui.NavLink;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.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.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
public class FilterPanel extends Composite {
private static FilterPanelUiBinder uiBinder = GWT
.create(FilterPanelUiBinder.class);
interface FilterPanelUiBinder extends UiBinder<Widget, FilterPanel> {
}
protected static final String ERROR_MESSAGE = "Ops! we encountered some problems, server is not responding, please try again in a short while.";
protected static final String SESSION_EXPIRED = "Your session has expired, please log out and login again";
NewsFeedPanel caller;
NewsServiceAsync service;
@UiField NavLink allUpdatesLink;
@UiField NavLink recentCommentsLink;
@UiField Dropdown sortByDD;
public FilterPanel(NewsFeedPanel caller, NewsServiceAsync newsService) {
initWidget(uiBinder.createAndBindUi(this));
this.caller = caller;
this.service = newsService;
}
public void removeFilterSelected() {
allUpdatesLink.setActive(false);
recentCommentsLink.setActive(false);
}
@UiHandler("recentCommentsLink")
void onRecentCommentsLinkClick(ClickEvent e) {
allUpdatesLink.setDisabled(false);
recentCommentsLink.setDisabled(true);
sortByDD.setText("newest Comment");
caller.setCurrentFilter(FilterType.RECENT_COMMENTS);
int loadedPostsInView = caller.getAllUpdatesSize() + 1;
int quantity = loadedPostsInView < 100 ? 100 - loadedPostsInView : loadedPostsInView;
caller.loadMorePosts(quantity, true);
}
@UiHandler("allUpdatesLink")
void onAllUpdatesClick(ClickEvent e) {
allUpdatesLink.setDisabled(true);
recentCommentsLink.setDisabled(false);
sortByDD.setText("newest Post");
caller.setCurrentFilter(FilterType.ALL_UPDATES);
service.getUserSettings(new AsyncCallback<UserSettings>() {
@Override
public void onFailure(Throwable caught) {
Window.alert(ERROR_MESSAGE);
}
@Override
public void onSuccess(UserSettings result) {
if (result.getUserInfo().getUsername().equals("test.user")) {
Window.alert(SESSION_EXPIRED);
}
else
caller.showAllUpdatesFeeds();
}
});
}
}

View File

@ -0,0 +1,19 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.margin {
margin-bottom: 0 !important;
margin-top: -15px !important;
}
</ui:style>
<g:HTMLPanel ui:field="mainPanel">
<b:NavPills addStyleNames="{style.margin}">
<b:NavLink disabled="true">Show sorted by:</b:NavLink>
<b:Dropdown ui:field="sortByDD" text="newest Post">
<b:NavLink disabled="true" ui:field="allUpdatesLink">newest Post</b:NavLink>
<b:NavLink ui:field="recentCommentsLink">newest Comment</b:NavLink>
</b:Dropdown>
</b:NavPills>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,113 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.ui.Carousel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Cursor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
/**
* Link Previewer class to show a link a preview.
* @author Costantino Perciante at ISTI-CNR
* @author Massimiliano Assante at ISTI-CNR
*/
public class LinkPreviewer extends Composite {
// is the preview image still there ?
private boolean imageRemoved = false;
@UiField
HTML titleArea;
@UiField
HTML urlText;
@UiField
HTML descText;
@UiField
Image image;
// saved file name
private final String fileName;
private static LinkPreviewUiBinder uiBinder = GWT
.create(LinkPreviewUiBinder.class);
interface LinkPreviewUiBinder extends UiBinder<Widget, LinkPreviewer> {
}
public LinkPreviewer(String title, String titleDesc, String host, String linkThumbUrl, String url) {
initWidget(uiBinder.createAndBindUi(this));
if (linkThumbUrl == null || linkThumbUrl.equals("null")){
image.removeFromParent();
imageRemoved = true;
}
else {
image.setUrl(linkThumbUrl);
image.setWidth("80px");
}
// save the filename info
fileName = title;
titleArea.setHTML("<a class=\"link\" target=\"_blank\" href=\"" + url + "\">"+title+"</a> <span style=\"color: #333;\"> - " + host+ "</span>");
urlText.setHTML((url.length() > 70) ? url.substring(0, 70)+"..." : url);
String desc = titleDesc;
descText.setHTML((desc.length() > 256) ? desc.substring(0, 256)+"..." : desc);
}
/**
* Open the carousel when the user clicks on the preview's image.
* @param carousel
*/
public void onImageClickOpenCarousel(final Carousel carousel) {
if(imageRemoved)
return;
// change cursor type on hover
image.getElement().getStyle().setCursor(Cursor.POINTER);
// add handler
image.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
carousel.show();
}
});
}
/**
* Open the carousel when the user clicks on the previews' file name.
* @param carousel
*/
public void onFileNameClickOpenCarousel(final Carousel carousel) {
String nameToShow = fileName.length() > 40 ? fileName.substring(0, 40) + "..." : fileName;
titleArea.setHTML("<a class=\"link\" >"+ nameToShow +"</a>");
titleArea.setTitle(fileName);
titleArea.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
carousel.show();
}
});
}
}

View File

@ -0,0 +1,26 @@
<!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">
<g:HTMLPanel styleName="link-preview">
<table>
<tr>
<td valign="top">
<div class="linkpreview-image">
<g:Image ui:field="image" />
</div>
</td>
<td valign="top">
<div class="linkpreview-title">
<g:HTML styleName="" ui:field="titleArea" />
</div>
<div class="linkpreview-url">
<g:HTML styleName="" ui:field="urlText" />
</div>
<div class="linkpreview-desc">
<g:HTML styleName="" ui:field="descText" />
</div>
</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,19 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
public class LoadingText extends Composite {
private static LoadingTextUiBinder uiBinder = GWT
.create(LoadingTextUiBinder.class);
interface LoadingTextUiBinder extends UiBinder<Widget, LoadingText> {
}
public LoadingText() {
initWidget(uiBinder.createAndBindUi(this));
}
}

View File

@ -0,0 +1,13 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<g:VerticalPanel horizontalAlignment="CENTER" width="100%">
<b:Icon type="GEAR" size="FOUR_TIMES" spin="true" />
<b:Caption>
<b:Heading size="2">Please wait</b:Heading>
<b:Paragraph>
Contacting infrastructure services ...
</b:Paragraph>
</b:Caption>
</g:VerticalPanel>
</ui:UiBinder>

View File

@ -0,0 +1,73 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import org.gcube.portlets.user.newsfeed.client.event.ShowNewUpdatesEvent;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Timer;
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.Widget;
public class NewFeedsAvailable extends Composite {
private static NewFeedsAvailableUiBinder uiBinder = GWT
.create(NewFeedsAvailableUiBinder.class);
interface NewFeedsAvailableUiBinder extends
UiBinder<Widget, NewFeedsAvailable> {
}
private HandlerManager eventBus;
@UiField HTML caption;
@UiField HTMLPanel panel;
public NewFeedsAvailable(int newUpdatesNo, HandlerManager eventBus) {
initWidget(uiBinder.createAndBindUi(this));
this.eventBus = eventBus;
if (newUpdatesNo > 0) {
updateNewUpdatesNo(newUpdatesNo);
//create the fade transition effect
Timer t = new Timer() {
@Override
public void run() {
caption.addStyleName("new-feeds-show");
}
};
t.schedule(100);
}
else throw new IllegalArgumentException("newUpdatesNo must be greater than 0");
}
public void updateNewUpdatesNo(int newUpdatesNo) {
String messageToShow = newUpdatesNo > 1 ? "See " + newUpdatesNo + " new Updates" : "See 1 new Update";
caption.setHTML(messageToShow);
setBrowserWindowTitle(newUpdatesNo);
}
public static void setBrowserWindowTitle (int newUpdatesNo) {
if (Document.get() != null) {
String currTitle = Document.get().getTitle();
if (currTitle.startsWith("(")) {
String newTitle = "(" + newUpdatesNo + currTitle.substring(2);
Document.get().setTitle(newTitle);
}
else
Document.get().setTitle ("("+newUpdatesNo+") " + currTitle);
}
}
@UiHandler("caption")
void onClick(ClickEvent e) {
eventBus.fireEvent(new ShowNewUpdatesEvent());
}
}

View File

@ -0,0 +1,7 @@
<!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">
<g:HTMLPanel ui:field="panel" styleName="new-feeds-container">
<g:HTML ui:field="caption" styleName="new-feeds-available" />
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,101 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.WidgetCollection;
/**
* This panel will contain the attachments/previews
* @author Massimiliano Assante at ISTI CNR
* @author Costantino Perciante at ISTI CNR
*
*/
public class Placeholder extends FlowPanel {
private static final String SHOW_OTHER_ATTACHMENTS_LABEL = "Show All";
// check if we need to show more attachments
private boolean appendShowMoreLabel;
/**
* Modified version of the add method.
*/
public void add(AttachmentPreviewer atPrev){
// retrieve the list of children
WidgetCollection listOfChildren = this.getChildren();
// check the size
int size = listOfChildren.size();
// look at NewsFeed.css ...
if(Window.getClientWidth() <= 1128){
add((Widget)atPrev);
atPrev.changeAttachmentWidth(92, Unit.PCT);
}
else if(size % 2 == 0){
// in this case the next attachment we are going to add remains with the same width
add((Widget)atPrev);
GWT.log("added without changing size");
}
else{
// we need to change the length of the last element added and of this new one
((AttachmentPreviewer) listOfChildren.get(size -1)).changeAttachmentWidth(45, Unit.PCT);
atPrev.changeAttachmentWidth(45, Unit.PCT);
// add it finally
add((Widget)atPrev);
}
if(size >= 4){
// ok, we are going to add the 5th attachment and so forth but we hide them..
atPrev.setVisible(false);
// remember to add the button to let the user show them later
appendShowMoreLabel = true;
}
}
/**
* Append "Show All" label to the post template.
*/
public void appendShowMoreLabel(){
if(appendShowMoreLabel){
final WidgetCollection listOfChildren = this.getChildren();
final SimplePanel sp = new SimplePanel();
sp.setStyleName("centered");
final Anchor showMoreAttachments = new Anchor(SHOW_OTHER_ATTACHMENTS_LABEL);
showMoreAttachments.setTitle("Show all the attached files");
showMoreAttachments.setStyleName("link");
sp.add(showMoreAttachments);
showMoreAttachments.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
// retrieve the list of attachmentPreviewers and show them
for(Widget w: listOfChildren){
w.setVisible(true);
}
sp.setVisible(false);
}
});
// show the panel
this.add(sp);
}
}
}

View File

@ -0,0 +1,40 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Cursor;
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.Window.Location;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
public class ResultsFor extends Composite {
private static ResultsForUiBinder uiBinder = GWT
.create(ResultsForUiBinder.class);
interface ResultsForUiBinder extends UiBinder<Widget, ResultsFor> {
}
@UiField HTML allUpdatesLink;
@UiField HTML resultForDiv;
public ResultsFor(String prefix, String hashtag) {
initWidget(uiBinder.createAndBindUi(this));
allUpdatesLink.setHTML("<a class=\"link\">All Posts</a>");
allUpdatesLink.getElement().getStyle().setCursor(Cursor.POINTER);
resultForDiv.setHTML(prefix + " <b>" + hashtag + "</b>");
resultForDiv.setStyleName("filter-selected");
}
@UiHandler("allUpdatesLink")
void onAllUpdatesClick(ClickEvent e) {
String href = Location.getHref();
if (href.contains("?"))
href = href.substring(0, href.indexOf("?"));
Location.assign(href);
}
}

View File

@ -0,0 +1,16 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:HTMLPanel>
<div class="feed-filters">
<ul>
<li class="feed-breadcrumb">
<g:HTML ui:field="allUpdatesLink"></g:HTML>
</li>
<li class="final">
<g:HTML ui:field="resultForDiv"></g:HTML>
</li>
</ul>
</div>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,53 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.ListBox;
import com.github.gwtbootstrap.client.ui.Modal;
import com.google.gwt.core.client.GWT;
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.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
public class SharePostDialog extends Composite {
private static SharePostDialogUiBinder uiBinder = GWT
.create(SharePostDialogUiBinder.class);
interface SharePostDialogUiBinder extends UiBinder<Widget, SharePostDialog> {
}
public SharePostDialog(TweetTemplate toShare) {
initWidget(uiBinder.createAndBindUi(this));
input.addItem("devVRE", "devVRE");
input.addItem("devVRE2", "devVRE");
input.addItem("devVRE3", "devVRE");
}
@UiField Button sharePostButton;
@UiField Button cancel;
@UiField Modal modalWindow;
@UiField ListBox input;
@UiHandler("sharePostButton")
void onClick(ClickEvent e) {
Window.alert("Hello!");
}
@UiHandler("cancel")
void onCancelClick(ClickEvent e) {
modalWindow.hide();
}
public void openModal() {
GWT.log("OpenModal");
modalWindow.show();
}
}

View File

@ -0,0 +1,23 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel>
<b:Modal ui:field="modalWindow" title="Share this post"
backdrop="STATIC" keyboard="true" animation="true">
<b:Form type="VERTICAL">
<b:ListBox alternateSize="XLARGE" ui:field="input"></b:ListBox>
</b:Form>
<b:ModalFooter>
<b:Button ui:field="cancel">Cancel</b:Button>
<b:Button ui:field="sharePostButton" type="PRIMARY">Send Invite</b:Button>
</b:ModalFooter>
</b:Modal>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,38 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
public class ShowMoreFeeds extends Composite {
private static NewFeedsAvailableUiBinder uiBinder = GWT
.create(NewFeedsAvailableUiBinder.class);
interface NewFeedsAvailableUiBinder extends
UiBinder<Widget, ShowMoreFeeds> {
}
@UiField HTML caption;
@UiField HTMLPanel panel;
public ShowMoreFeeds(HandlerManager eventBus) {
initWidget(uiBinder.createAndBindUi(this));
panel.getElement().getStyle().setMarginTop(10, Unit.PX);
caption.addStyleName("new-feeds-show");
caption.getElement().getStyle().setBackgroundColor("transparent");
caption.getElement().getStyle().setFontSize(14, Unit.PX);
caption.setHTML("Show more feeds");
//done after
//panel.getElement().getStyle().setVisibility(Visibility.HIDDEN);
}
}

View File

@ -0,0 +1,7 @@
<!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">
<g:HTMLPanel ui:field="panel" styleName="new-feeds-container">
<g:HTML ui:field="caption" styleName="new-feeds-available" />
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,186 @@
package org.gcube.portlets.user.newsfeed.client.ui;
import java.util.Date;
import org.gcube.common.portal.GCubePortalConstants;
import org.gcube.portal.databook.client.GCubeSocialNetworking;
import org.gcube.portal.databook.client.util.Encoder;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portlets.user.newsfeed.client.event.DeleteCommentEvent;
import org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
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.Event;
import com.google.gwt.user.client.Window.Location;
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.Image;
import com.google.gwt.user.client.ui.Widget;
public class SingleComment extends Composite {
private static SingleCommentUiBinder uiBinder = GWT
.create(SingleCommentUiBinder.class);
interface SingleCommentUiBinder extends UiBinder<Widget, SingleComment> {
}
private static final int MAX_SHOWTEXT_LENGTH = 450;
private boolean isUsers = false;
private TweetTemplate owner;
private String myCommentid;
private Comment myComment;
@UiField HTMLPanel mainPanel;
@UiField Image avatarImage;
@UiField AvatarReplacement4Comments avatarReplacement;
@UiField HTML commentText;
@UiField HTML timeArea;
@UiField HTML closeImage;
@UiField HTML editImage;
@UiField HTML seeMore;
public SingleComment(Comment toShow, TweetTemplate owner, boolean isUsers) {
initWidget(uiBinder.createAndBindUi(this));
sinkEvents(Event.ONPASTE);
this.owner = owner;
this.isUsers = isUsers;
this.myComment = toShow;
myCommentid = toShow.getKey();
avatarImage.setPixelSize(30, 30);
avatarImage.setUrl(toShow.getThumbnailURL());
//check if the user has his own avatar
if (toShow.getThumbnailURL().endsWith("img_id=0") || !toShow.getThumbnailURL().contains("?")) { //it means no avatar is set
avatarImage.setVisible(false);
String f = "A";
String s = "Z";
if (toShow.getFullName() != null) {
String[] parts = toShow.getFullName().split("\\s");
if (parts.length > 0) {
f = parts[0].toUpperCase();
s = parts[parts.length-1].toUpperCase();
} else {
f = toShow.getFullName().substring(0,1);
s = toShow.getFullName().substring(1,2);
}
}
avatarReplacement.setInitials(toShow.getUserid(), f, s);
avatarReplacement.setVisible(true);
}
String commentToShow = toShow.getText();
//replace the < & and >
commentToShow = commentToShow.replaceAll("&lt;","<").replaceAll("&gt;",">");
commentToShow = commentToShow.replaceAll("&amp;","&");
if (commentToShow.length() > MAX_SHOWTEXT_LENGTH) {
final int TEXT_TO_SHOW_LENGHT = (commentToShow.length() < 700) ? (commentToShow.length() - (commentToShow.length() / 3)) : 700;
commentToShow = commentToShow.substring(0, TEXT_TO_SHOW_LENGHT) + "...";
seeMore.setHTML("<a class=\"seemore\"> See More </a>");
}
final String profilePageURL = GCubePortalConstants.PREFIX_GROUP_URL + NewsFeedPanel.extractOrgFriendlyURL(Location.getHref()) +GCubePortalConstants.USER_PROFILE_FRIENDLY_URL;
commentText.setHTML("<a class=\"link\" href=\"" + profilePageURL + "?"+
Encoder.encode(GCubeSocialNetworking.USER_PROFILE_OID)+"="+
Encoder.encode(toShow.getUserid())+"\">"+toShow.getFullName()+
"</a> " + commentToShow);
// Comment's data
Date now = new Date();
String formattedTime;
String formattedTimeEdit = null;
if(now.getYear() != toShow.getTime().getYear())
formattedTime = DateTimeFormat.getFormat("MMMM dd yyyy, h:mm a").format(toShow.getTime());
else
formattedTime = DateTimeFormat.getFormat("MMMM dd, h:mm a").format(toShow.getTime());
if(toShow.isEdit()){
if(now.getYear() != toShow.getLastEditTime().getYear())
formattedTimeEdit = DateTimeFormat.getFormat("MMMM dd yyyy, h:mm a").format(toShow.getLastEditTime());
else
formattedTimeEdit = DateTimeFormat.getFormat("MMMM dd, h:mm a").format(toShow.getLastEditTime());
}
if(toShow.isEdit())
timeArea.setHTML(formattedTime +
" (Last edit on " + formattedTimeEdit + ")");
else
timeArea.setHTML(formattedTime);
if (isUsers) {
closeImage.setStyleName("closeImage");
closeImage.setTitle("Delete");
editImage.setStyleName("editImage");
editImage.setTitle("Edit");
}
}
@UiHandler("seeMore")
void onSeeMoreClick(ClickEvent e) {
String commentToShow = myComment.getText();
//replace the < & and >
commentToShow = commentToShow.replaceAll("&lt;","<").replaceAll("&gt;",">");
commentToShow = commentToShow.replaceAll("&amp;","&");
final String profilePageURL = GCubePortalConstants.PREFIX_GROUP_URL + NewsFeedPanel.extractOrgFriendlyURL(Location.getHref()) +GCubePortalConstants.USER_PROFILE_FRIENDLY_URL;
commentText.setHTML("<a class=\"link\" href=\"" + profilePageURL + "?"+
Encoder.encode(GCubeSocialNetworking.USER_PROFILE_OID)+"="+
Encoder.encode(myComment.getUserid())+"\">"+
myComment.getFullName()+"</a> " + commentToShow);
seeMore.setHTML("");
}
@UiHandler("closeImage")
void onDeleteCommentClick(ClickEvent e) {
if (isUsers)
owner.getEventBus().fireEvent(new DeleteCommentEvent(owner, myCommentid));
}
@UiHandler("editImage")
void onEditCommentClick(ClickEvent e) {
if (isUsers) {
AddCommentTemplate addComm = new AddCommentTemplate(owner, myComment, mainPanel);
mainPanel.getElement().setInnerHTML("");
mainPanel.add(addComm);
}
}
@UiHandler("commentText")
public void onHover(MouseOverEvent event) {
if (isUsers) {
closeImage.addStyleName("uiCloseButton");
editImage.addStyleName("uiEditButton");
}
}
@UiHandler("commentText")
public void onHover(MouseOutEvent event) {
if (isUsers) {
closeImage.removeStyleName("uiCloseButton");
editImage.removeStyleName("uiEditButton");
}
}
public String getCommentKey() {
return myCommentid;
}
}

View File

@ -0,0 +1,34 @@
<!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:org.gcube.portlets.user.newsfeed.client.ui">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel ui:field="mainPanel">
<table class="single-comment">
<tr>
<td width="36px" align="middle">
<g:Image styleName="member-photo" url="" ui:field="avatarImage"
width="30px" height="30px" />
<m:AvatarReplacement4Comments visible="false"
ui:field="avatarReplacement"></m:AvatarReplacement4Comments>
</td>
<td>
<div class="commentsPanel">
<g:HTML styleName="user-comment" ui:field="commentText" />
<g:HTML styleName="" ui:field="seeMore" />
<g:HTML styleName="user-comment-time" ui:field="timeArea" />
</div>
</td>
<td width="15px" valign="top" class="comment-bgcolor">
<g:HTML height="15px" width="15px" ui:field="editImage"></g:HTML>
</td>
<td width="15px" valign="top" class="comment-bgcolor">
<g:HTML height="15px" width="15px" ui:field="closeImage"></g:HTML>
</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,233 @@
/**
*
*/
package org.gcube.portlets.user.newsfeed.client.ui;
import java.util.HashSet;
import org.gcube.portlets.user.gcubewidgets.client.elements.Div;
import org.gcube.portlets.user.newsfeed.client.NewsService;
import org.gcube.portlets.user.newsfeed.client.NewsServiceAsync;
import org.gcube.portlets.user.newsfeed.shared.MentionedDTO;
import org.gcube.portlets.widgets.pickitem.client.dialog.PickItemsDialog;
import org.gcube.portlets.widgets.pickitem.client.events.PickedItemEvent;
import org.gcube.portlets.widgets.pickitem.client.events.PickedItemEventHandler;
import org.gcube.portlets.widgets.pickitem.shared.ItemBean;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.TextArea;
/**
* @author massi
*
*/
public class SuperPosedTextArea extends TextArea {
private final NewsServiceAsync newsService = GWT.create(NewsService.class);
private final HandlerManager eventBus = new HandlerManager(null);
private PickItemsDialog pickUserDlg = null;
private Div highlighterDIV;
public final static int ARROW_UP = 38;
public final static int ARROW_DOWN = 40;
private String context;
private HashSet<MentionedDTO> mentionedUsers = new HashSet<MentionedDTO>();
private String areaId;
/**
*
*/
public SuperPosedTextArea(Div highlighterDIV) {
sinkEvents(Event.ONPASTE);
sinkEvents(Event.ONCONTEXTMENU);
sinkEvents(Event.ONKEYDOWN);
sinkEvents(Event.ONKEYUP);
setText(AddCommentTemplate.COMMENT_TEXT);
this.highlighterDIV = highlighterDIV;
//needed to give unique identifiers to the Area (for the jQuery plugin)
areaId = "postTextArea"+Random.nextInt();
getElement().setAttribute("id", areaId);
bind();
Timer t = new Timer() {
@Override
public void run() {
myAutoSize(areaId);
}
};
t.schedule(200);
this.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(KeyPressEvent event) {
if (pickUserDlg != null) {
int top = getAbsoluteTop();
int offset = getOffsetHeight();
int y = getAbsoluteTop()+getOffsetHeight();
GWT.log("top=" + top + " - offset = " +offset);
pickUserDlg.onKeyPress(getCursorPos(), event.getUnicodeCharCode(), getAbsoluteLeft(), y, getText());
}
}
});
this.addFocusHandler(new FocusHandler() {
@Override
public void onFocus(FocusEvent event) {
pickUserDlg = new PickItemsDialog('@', eventBus, 430, context);
pickUserDlg.withPhoto();
}
});
}
/**
* This is the way to wrap jQuery plugins into GWT, wrap it in a function and call it.
*/
public static native void myAutoSize(String myAreaId) /*-{
function autoSizeArea() {
$wnd.jQuery('#'+myAreaId).autosize();
}
autoSizeArea();
}-*/;
/**
* @param element
*/
public SuperPosedTextArea(Element element) {
super(element);
}
/**
*
* @param context e.g. /gcube/devNext/NextNext
*/
public void setContext(String context) {
this.context = context;
}
/**
* paste event overridden
*/
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE: {
if (getText().equals(AddCommentTemplate.COMMENT_TEXT) || getText().equals(AddCommentTemplate.ERROR_UPDATE_TEXT) ) {
setText("");
addStyleName("dark-color");
removeStyleName("nwfeed-error");
}
break;
}
case Event.ONKEYUP: {
injectInDiv(getText());
pickUserDlg.onKeyUp(event.getKeyCode());
break;
}
case Event.ONCONTEXTMENU: {
removeSampleText();
break;
}
case Event.ONKEYDOWN: {
if (pickUserDlg.isShowing()) {
//avoid the arrow up to move the cursor at the beginning of the textbox and the TAB to move around inputs and enter to go newline
if (event.getKeyCode() == ARROW_UP || event.getKeyCode() == KeyCodes.KEY_TAB || event.getKeyCode() == KeyCodes.KEY_ENTER) {
DOM.eventCancelBubble(event, true);
event.preventDefault();
return;
}
}
break;
}
}
}
protected void removeSampleText() {
if (getText().equals(AddCommentTemplate.COMMENT_TEXT) || getText().equals(AddCommentTemplate.ERROR_UPDATE_TEXT) ) {
setText("");
addStyleName("darker-color");
removeStyleName("nwfeed-error");
}
}
protected void cleanHighlighterDiv() {
//DOM.getElementById("comment-highlighter").setInnerHTML("");
highlighterDIV.getElement().setInnerHTML("");
}
/**
* copy what is being written in the text area in the underneath DIV
* @param textAreaText
*/
private void injectInDiv(String textAreaText) {
String text;
// parse the text:
// replace all the line braks by <br/>, and all the double spaces by the html version &nbsp;
text = textAreaText.replaceAll("(\r\n|\n)","<br />");
text = text.replaceAll("\\s\\s","&nbsp;&nbsp;");
for (MentionedDTO mentionedUser : mentionedUsers) {
text = text.replaceAll(mentionedUser.value,
"<span id=\""+ mentionedUser.id +"\" title=\""+ mentionedUser.type +"\" class=\"highlightedUser\">"+mentionedUser.value+"</span>");
}
// re-inject the processed text into the div
highlighterDIV.getElement().setInnerHTML(text);
}
/**
* events binder
*/
private void bind() {
eventBus.addHandler(PickedItemEvent.TYPE, new PickedItemEventHandler() {
@Override
public void onSelectedItem(PickedItemEvent event) {
String toAdd = event.getSelectedItem().getAlternativeName();
ItemBean ib = event.getSelectedItem();
String type = ib.isItemGroup() ? "team" : "user";
MentionedDTO mToAdd = new MentionedDTO(ib.getId(), ib.getAlternativeName(), type);
mentionedUsers.add(mToAdd);
String preceedingPart = getText().substring(0, event.getItemCursorIndexStart());
String afterPart = getText().substring(event.getItemCursorIndexEnd()+1);
setText(preceedingPart + toAdd + " " + afterPart);
injectInDiv(getText());
}
});
}
public HashSet<MentionedDTO> getMentionedUsers() {
NodeList<Element> elems = highlighterDIV.getElement().getElementsByTagName("span");
HashSet<MentionedDTO> toReturn = new HashSet<MentionedDTO>();
if (elems != null && elems.getLength() > 0) {
int elemsNo = elems.getLength();
for (int i = 0; i < elemsNo; i++) {
Element el = elems.getItem(i);
String id = el.getId();
String type = el.getTitle();
String value = el.getInnerText();
MentionedDTO toAdd = new MentionedDTO(id, value, type);
toReturn.add(toAdd);
GWT.log(toAdd.toString());
}
}
return toReturn;
}
/**
* return the unique identifier of this textarea, useful for getElementById JS method
* @return
*/
public String getAreaId() {
return areaId;
}
}

View File

@ -0,0 +1,727 @@
/**
*
*/
package org.gcube.portlets.user.newsfeed.client.ui;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import org.gcube.common.portal.GCubePortalConstants;
import org.gcube.portal.databook.client.GCubeSocialNetworking;
import org.gcube.portal.databook.client.util.Encoder;
import org.gcube.portal.databook.shared.Attachment;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.EnhancedFeed;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.newsfeed.client.event.AddLikeEvent;
import org.gcube.portlets.user.newsfeed.client.event.DeletePostEvent;
import org.gcube.portlets.user.newsfeed.client.event.OpenPostEvent;
import org.gcube.portlets.user.newsfeed.client.event.SeeCommentsEvent;
import org.gcube.portlets.user.newsfeed.client.event.SeeLikesEvent;
import org.gcube.portlets.user.newsfeed.client.event.UnLikeEvent;
import org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.EnhancedImage;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.ui.Carousel;
import com.github.gwtbootstrap.client.ui.Button;
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.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.i18n.client.DateTimeFormat;
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.Location;
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.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* @author Massimiliano Assante at ISTI-CNR
* @author Costantino Perciante at ISTI-CNR
*
*/
public class TweetTemplate extends Composite {
private static TweetTemplateUiBinder uiBinder = GWT
.create(TweetTemplateUiBinder.class);
interface TweetTemplateUiBinder extends UiBinder<Widget, TweetTemplate> {
}
public static final String loading = GWT.getModuleBaseURL() + "../images/loading-comments.gif";
private static final int MAX_SHOWTEXT_LENGTH = 612;
private EnhancedFeed myPost;
private UserInfo myUserInfo;
private HandlerManager eventBus;
private ArrayList<SingleComment> myComments;
private boolean commentingDisabled = false;
private boolean commentsFetched = false;
private int totalComments = 0;
private HTML showAllComments = new HTML();
private boolean isAppPost = false;
private HTML submitCommentPreloader = new HTML("<div class=\"more-comment\"><img style=\"padding-right:15px;\"src=\""+ loading +"\" /></div>");
private TweetTemplate myInstance;
// Carousel from the image-previewer widget
private Carousel carousel;
/**
* tell if this tweet is belonging to the current user
*/
private boolean isUsers = false;
@UiField
HTML contentArea;
@UiField
HTML postOwnerArea;
@UiField
HTML seeMore;
@UiField
InlineLabel timeArea;
@UiField
InlineLabel separator;
@UiField
InlineLabel vreSourceInMetadata;
@UiField
HTML likeArea;
@UiField
HTML commentArea;
@UiField
Image avatarImage;
@UiField
AvatarReplacement avatarReplacement;
@UiField
HTMLPanel mainHTML;
@UiField
Button likesNo;
@UiField
Button commentsNo;
@UiField
VerticalPanel commentsPanel;
@UiField
HTML closeImage;
@UiField
HTML openImage;
@UiField
VerticalPanel previewPanel;
@UiField
Placeholder attachmentPreviewPanel;
@UiField
Label messageSeparator;
/**
* used when fetching tweets from server
* @param myUserInfo
* @param myPost
* @param isUsers
* @param displaySingle tells if you're displaying a single fedd or not
* @param eventBus
*/
public TweetTemplate(boolean displaySingle, boolean showTimelineSource, UserInfo myUserInfo, EnhancedFeed myPost, HandlerManager eventBus) {
initWidget(uiBinder.createAndBindUi(this));
commentsNo.getElement().getStyle().setPaddingTop(0, Unit.PX);
likesNo.getElement().getStyle().setPaddingTop(0, Unit.PX);
likesNo.getElement().getStyle().setPaddingRight(2, Unit.PX);
commentsNo.getElement().getStyle().setPaddingRight(2, Unit.PX);
likesNo.getElement().getStyle().setPaddingLeft(2, Unit.PX);
commentsNo.getElement().getStyle().setPaddingLeft(2, Unit.PX);
myInstance = this;
this.myUserInfo = myUserInfo;
this.vreSourceInMetadata.setVisible(false);
this.separator.setVisible(false);
this.myPost = myPost;
isAppPost = myPost.getFeed().isApplicationFeed();
Feed post = myPost.getFeed();
this.eventBus = eventBus;
this.isUsers = myPost.isUsers();
this.carousel = new Carousel();
myComments = new ArrayList<SingleComment>();
if (isUsers || myUserInfo.isAdmin()) {
closeImage.setStyleName("closeImage");
closeImage.setTitle(myUserInfo.isAdmin() ? "Delete (Administrator Mode)" : "delete");
} else {
closeImage.removeFromParent();
}
// if there is one attachment or a link preview, maintain backward compatibility
if (post.getUri() != null && post.getUri().compareTo("") != 0 && post.getLinkTitle() != null && post.getLinkTitle().compareTo("") != 0 && !post.isMultiFileUpload()) {
// hide the attachments panel
attachmentPreviewPanel.setVisible(false);
LinkPreviewer linkPreviewer = new LinkPreviewer(post.getLinkTitle(), post.getLinkDescription(), post.getLinkHost(), post.getUriThumbnail(), post.getUri());
// enable the image previewer if it is an image (mime)
if(post.getLinkHost().contains("image/")){
ArrayList<EnhancedImage> listOfEnhancedImages;
EnhancedImage enhancedImage = new EnhancedImage(
post.getUri(),
post.getLinkTitle() +
" (" + post.getLinkDescription() + ", type:" + post.getLinkHost() +")",
post.getLinkTitle(),
post.getUri()
);
listOfEnhancedImages = new ArrayList<EnhancedImage>();
listOfEnhancedImages.add(enhancedImage);
carousel.updateImages(listOfEnhancedImages);
// set handler on the linkpreviewer image to show this carousel and on the image title too
linkPreviewer.onImageClickOpenCarousel(carousel);
linkPreviewer.onFileNameClickOpenCarousel(carousel);
// remove next and prev buttons of the carousel since we have only an image
carousel.hideArrows();
}
// add link preview to the preview panel
previewPanel.add(linkPreviewer);
}
// in case there are attachments, we have to fill attachmentPreviewPanel instead of the previewPanel
if(post.isMultiFileUpload()){
// set style to the attachment container
attachmentPreviewPanel.setStyleName("attachment-preview-container");
// hide link preview panel
previewPanel.setVisible(false);
// prepare the carousel
ArrayList<EnhancedImage> listOfEnhancedImages = new ArrayList<EnhancedImage>();
// remember that one attachment is stored in the fields: uri, uriThumbnail, linkTitle, linkDescription, linkHost
Attachment firstAttachment = new Attachment(
post.getKey(), // it is meaningless but it's needed
post.getUri(),
post.getLinkTitle(),
post.getLinkDescription(),
post.getUriThumbnail(),
post.getLinkHost());
// create first attachment previewer and pass it the carousel
AttachmentPreviewer firstAttachmentPreviewer = new AttachmentPreviewer(firstAttachment);
// determine if the left/right arrows must be removed
int imagesAvailableInCarousel = 0;
// check if it is an image
if(firstAttachment.getMimeType().contains("image/")){
EnhancedImage enhancedImage = new EnhancedImage(
post.getUri(),
post.getLinkTitle() +
" (" + post.getLinkDescription() + ", type:" + post.getLinkHost() +")",
post.getLinkTitle(),
post.getUri()
);
listOfEnhancedImages.add(enhancedImage);
firstAttachmentPreviewer.onImageClickOpenCarousel(carousel, enhancedImage);
// increment the images
imagesAvailableInCarousel ++;
}
// add the first attachment to the panel
attachmentPreviewPanel.add(firstAttachmentPreviewer);
// check the others
for (Attachment otherAttachment : myPost.getAttachments()) {
AttachmentPreviewer attachmentPreviewer = new AttachmentPreviewer(otherAttachment);
if(otherAttachment.getMimeType().contains("image/")){
EnhancedImage enhancedImage = new EnhancedImage(
otherAttachment.getUri(),
otherAttachment.getName() +
" (" + otherAttachment.getDescription() + ", type:" + post.getLinkHost() +")",
otherAttachment.getName(),
otherAttachment.getUri()
);
listOfEnhancedImages.add(enhancedImage);
// pass the carousel
attachmentPreviewer.onImageClickOpenCarousel(carousel, enhancedImage);
// increment the images
imagesAvailableInCarousel ++;
}
// try to build the attachment viewer
attachmentPreviewPanel.add(attachmentPreviewer);
// hide arrows if there is no more than 1 image
if(imagesAvailableInCarousel <= 1)
carousel.hideArrows();
}
// update the carousel's images
carousel.updateImages(listOfEnhancedImages);
// invoke append label
attachmentPreviewPanel.appendShowMoreLabel();
}
openImage.setStyleName("openImage");
openImage.setTitle("Open this feed separately");
//show if the user has already liked this or not
setFavoritedUI(myPost.isLiked());
commentArea.setHTML("<a>" + NewsFeedPanel.COMMENT_LABEL + "</a>");
String postText = post.getDescription();
String descWithoutHTML = new HTML(postText).getText();
if ( (! postText.startsWith("<span")) && descWithoutHTML.length() > MAX_SHOWTEXT_LENGTH && !displaySingle) {
final int TEXT_TO_SHOW_LENGHT = (descWithoutHTML.length() < 600) ? (postText.length() - (postText.length() / 3)) : 600;
postText = postText.substring(0, TEXT_TO_SHOW_LENGHT) + "...";
seeMore.setHTML("<a class=\"seemore\"> See More </a>");
}
avatarImage.setUrl(post.getThumbnailURL());
avatarImage.setPixelSize(40, 40);
//replace the < & and >
postText = postText.replaceAll("&lt;","<").replaceAll("&gt;",">");
postText = postText.replaceAll("&amp;","&");
final String profilePageURL = GCubePortalConstants.PREFIX_GROUP_URL + NewsFeedPanel.extractOrgFriendlyURL(Location.getHref()) +GCubePortalConstants.USER_PROFILE_FRIENDLY_URL;
if (showTimelineSource && post.getVreid() != null && post.getVreid().compareTo("") != 0) {
this.vreSourceInMetadata.setVisible(true);
this.separator.setVisible(true);
String vreName = post.getVreid().substring(post.getVreid().lastIndexOf("/")+1);
vreSourceInMetadata.setText(vreName);
vreSourceInMetadata.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Location.assign("/group/"+vreName.toLowerCase());
}
});
}
if (! isAppPost) {
// sharePostArea.setHTML("<a>" + NewsFeedPanel.SHARE_FWD_LABEL + "</a>");
postOwnerArea.setHTML("<a class=\"linkProfile\" href=\""+profilePageURL
+"?"+
Encoder.encode(GCubeSocialNetworking.USER_PROFILE_OID)+"="+
Encoder.encode(post.getEntityId())+"\">"+post.getFullName()+"</a>");
contentArea.setHTML(postText);
//check if the user has his own avatar
if (post.getThumbnailURL().contains("img_id=0") || !post.getThumbnailURL().contains("?")) { //it means no avatar is set
avatarImage.setVisible(false);
String f = "A";
String s = "Z";
if (post.getFullName() != null) {
String[] parts = post.getFullName().split("\\s");
if (parts.length > 0) {
f = parts[0].toUpperCase();
s = parts[parts.length-1].toUpperCase();
} else {
f = post.getFullName().substring(0,1);
s = post.getFullName().substring(1,2);
}
}
avatarReplacement.setInitials(post.getEntityId(), f, s);
avatarReplacement.setVisible(true);
}
}
else {
// messageSeparator.setVisible(false);
postOwnerArea.setHTML("<a class=\"linkProfile\" href=\""+post.getUri()+"\">"+post.getFullName()+"</a>");
contentArea.setHTML(postText);
if (isAppPost) {
if (myUserInfo.isAdmin())
closeImage.setTitle("Delete this Application feed (Administrator Only)");
else
closeImage.removeFromParent();
}
}
try {
Date now = new Date();
String formattedTime;
// TODO java.util.Calendar is not yet available in GWT
if(now.getYear() != post.getTime().getYear())
formattedTime = DateTimeFormat.getFormat("MMMM dd yyyy, h:mm a").format(post.getTime());
else
formattedTime = DateTimeFormat.getFormat("MMMM dd, h:mm a").format(post.getTime());
timeArea.setText(formattedTime);
String formattedTimeWithYear = DateTimeFormat.getFormat("dd MMMM yyyy h:mm a ").format(post.getTime());
timeArea.setTitle(formattedTimeWithYear);
if (! post.getCommentsNo().equals("0")) {
commentsNo.setVisible(true);
commentsNo.setText(post.getCommentsNo());
commentsNo.setTitle(post.getCommentsNo() + " people commented this.");
}
if (! post.getLikesNo().equals("0")) {
likesNo.setVisible(true);
likesNo.setText(post.getLikesNo());
likesNo.setTitle("Show People who have " + NewsFeedPanel.LIKED_LABEL + " this.");
}
totalComments = Integer.parseInt(post.getCommentsNo());
}
catch (NumberFormatException e) {
totalComments = 0;
}
catch (Exception e) {
timeArea.setText("just now");
}
commentsPanel.setStyleName("commentsPanel");
if (myPost.getComments() != null && myPost.getComments().size() > 0) {
if (totalComments > 2 && !displaySingle) {
showAllComments = getShowAllCommentsLink(totalComments);
commentsPanel.add(showAllComments);
commentsNo.setVisible(true);
}
for (Comment comment : myPost.getComments()) {
addComment(new SingleComment(comment, this, (comment.getUserid().equals(myUserInfo.getUsername()))));
}
showAddCommentForm(false);
}
}
/**
* used when getting tweets from the client
* @param myUserInfo
* @param feed
* @param eventBus
* @param hidden
*/
public TweetTemplate(UserInfo myUserInfo, EnhancedFeed feed, HandlerManager eventBus, boolean hidden) {
this(false, false, myUserInfo, feed, eventBus);
contentArea.getElement().getParentElement().getParentElement().setClassName("div-table-col content hidden");
}
@UiHandler("contentArea")
public void onHover(MouseOutEvent event) {
if (isUsers)
closeImage.removeStyleName("uiCloseButton");
openImage.removeStyleName("uiOpenButton");
}
@UiHandler("contentArea")
public void onHover(MouseOverEvent event) {
if (isUsers) {
closeImage.addStyleName("uiCloseButton");
GWT.log("this belong to user");
}
openImage.addStyleName("uiOpenButton");
}
@UiHandler("closeImage")
void onDeleteFeedClick(ClickEvent e) {
if (isUsers || myUserInfo.isAdmin()){
eventBus.fireEvent(new DeletePostEvent(this));
}
else {
GWT.log("not belong to user");
}
}
@UiHandler("openImage")
void onOpenFeedClick(ClickEvent e) {
eventBus.fireEvent(new OpenPostEvent(this));
}
@UiHandler("seeMore")
void onSeeMoreClick(ClickEvent e) {
String postText = myPost.getFeed().getDescription();
//replace the < & and >
postText = postText.replaceAll("&lt;","<").replaceAll("&gt;",">");
postText = postText.replaceAll("&amp;","&");
contentArea.setHTML(postText);
seeMore.setHTML("");
}
private void setFavoritedUI(boolean favorited) {
if (favorited) {
likeArea.setHTML("<a style=\"color:#6E8CCC;\">" + NewsFeedPanel.LIKED_LABEL + "</a>");
likeArea.setTitle("Unlike this");
}
else {
likeArea.setHTML("<a>" + NewsFeedPanel.LIKE_LABEL + "</a>");
}
}
@UiHandler("likeArea")
void onLikeClick(ClickEvent e) {
//if is not liked
if (!likeArea.getText().equals(NewsFeedPanel.LIKED_LABEL)) {
try {
int cur = Integer.parseInt(myPost.getFeed().getLikesNo());
cur++;
if (cur == 1) {
myPost.getFeed().setLikesNo("1");
likesNo.setText("1");
likesNo.setTitle("People who have " + NewsFeedPanel.LIKED_LABEL + " this");
likesNo.setVisible(true);
} else {
myPost.getFeed().setLikesNo(""+cur);
likesNo.setText(""+cur);
likesNo.setVisible(true);
}
eventBus.fireEvent(new AddLikeEvent(this, myPost.getFeed().getKey()));
setFavoritedUI(true);
}
catch (NumberFormatException ex) {
likeArea.setHTML("Error on the server");
}
} else {
//it is liked
int cur = Integer.parseInt(myPost.getFeed().getLikesNo());
cur--;
if (cur == 0) {
myPost.getFeed().setLikesNo("0");
likesNo.setText("");
likesNo.setVisible(false);
likesNo.setTitle("");
} else {
myPost.getFeed().setLikesNo(""+cur);
likesNo.setText(""+cur);
likesNo.setVisible(true);
}
eventBus.fireEvent(new UnLikeEvent(this, myPost.getFeed().getKey()));
setFavoritedUI(false);
}
}
@UiHandler("commentArea")
void onAddCommentClick(ClickEvent e) {
if (! commentingDisabled) {
if (! commentsFetched && totalComments > 2) { //if so, need to load all comments before adding a comment
fireSeeComments(true);
}
else {
showAddCommentForm(true);
}
}
else
GWT.log("Commenting disabled");
}
public void showAddCommentForm(boolean focus) {
final AddCommentTemplate toAdd = new AddCommentTemplate(this, myUserInfo, eventBus);
commentsPanel.add(toAdd);
commentingDisabled = true;
final Timer t = new Timer() {
@Override
public void run() {
toAdd.setStyleName("comment-show");
}
};
if (focus)
toAdd.setFocus();
t.schedule(10);
}
private HTML getShowAllCommentsLink(int commentsNo) {
final HTML toReturn = new HTML("<div class=\"more-comment\"><a class=\"link\" style=\"font-size:11px;\">Show all " + commentsNo + " comments<a/></div>");
toReturn.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
fireSeeComments(false);
}
});
return toReturn;
}
private void fireSeeComments(boolean commentForm2Add) {
eventBus.fireEvent(new SeeCommentsEvent(this, commentForm2Add));
}
@UiHandler("likesNo")
void onSeeLikes(ClickEvent e) {
eventBus.fireEvent(new SeeLikesEvent(myPost.getFeed().getKey()));
}
@UiHandler("commentsNo")
void onSeeComments(ClickEvent e) {
fireSeeComments(false);
}
public void setcontentAreaStyle(String cssclass) {
contentArea.getElement().getParentElement().getParentElement().setClassName("div-table-col content visible");
}
public boolean isCommenting() {
return commentingDisabled;
}
public void setCommentingDisabled(boolean commenting) {
this.commentingDisabled = commenting;
}
public String getFeedKey() {
return myPost.getFeed().getKey();
}
public void remove(Widget w) {
mainHTML.remove(w);
}
public void addComment(SingleComment comment) {
commentsPanel.add(comment);
myComments.add(comment);
}
/**
*
* @param show true to show a preloader, false to hide it.
* display a preloader userful when the user is wating for the comment operation to be confirmed by the server
*/
public void showCommentingPreloader(boolean show) {
if (show)
commentsPanel.add(submitCommentPreloader);
else
commentsPanel.remove(submitCommentPreloader);
}
public void updateSingleComment(Comment edited, HTMLPanel commentPanel){
commentPanel.clear();
SingleComment sc = new SingleComment(edited, this, true);
commentPanel.add(sc);
// replace the new SingleComment in the list
int index = 0;
Iterator<SingleComment> iterator = this.myComments.iterator();
for (;iterator.hasNext();) {
SingleComment singleComment = (SingleComment) iterator.next();
if(singleComment.getCommentKey().equals(edited.getKey())){
iterator.remove();
this.myComments.add(index, sc);
break;
}
index ++;
}
}
public void clearComments() {
myComments.clear();
commentsPanel.clear();
}
public void showLoadingComments() {
showAllComments.setHTML("<div class=\"more-comment\"><img style=\"padding-right:15px;\"src=\""+ loading +"\" /></div>");
}
public boolean isCommentsFetched() {
return commentsFetched;
}
public void setCommentsFetched(boolean commentsFetched) {
this.commentsFetched = commentsFetched;
}
public HandlerManager getEventBus() {
return eventBus;
}
public void updateCommentsNumberCount() {
if (myComments.size() == 1) {
//commentsNo.setStyleName("show-comments-number");
commentsNo.setTitle("Persons who have commented this.");
}
//commentsNo.setHTML(commentIcon.getElement().toString()+"<span>&nbsp;</span>"+myComments.size());
commentsNo.setText(""+myComments.size());
}
public UserInfo getMyUserInfo() {
return myUserInfo;
}
public String getMyFeedUserId() {
return myPost.getFeed().getEntityId();
}
public String getMyFeedText() {
return myPost.getFeed().getDescription();
}
public boolean isAppFeed() {
return isAppPost;
}
public boolean isUser() {
return isUsers;
}
/**
* Returns the number of comments this post has
* @return
*/
public int numberOfComments(){
return myComments.size();
}
/**
* Returns the context of the Post
* @return the context (scope) of the Post
*/
public String getVREContext() {
return this.myPost.getFeed().getVreid();
}
/**
* Returns the number of likes this post has
* @return
*/
public int numberOfLikes(){
// not so easy
int ret = 0;
try{
ret = Integer.parseInt(likesNo.getText());
}catch(NumberFormatException e){
GWT.log(e.toString());
}
return ret;
}
}

View File

@ -0,0 +1,83 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:m="urn:import:org.gcube.portlets.user.newsfeed.client.ui">
<g:HTMLPanel ui:field="mainHTML">
<div class="div-table">
<div class="div-table-row">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td align="left" style="vertical-align: top;">
<g:Image title="" styleName="member-photo" url=""
ui:field="avatarImage" width="40" height="40" />
<m:AvatarReplacement visible="false"
ui:field="avatarReplacement"></m:AvatarReplacement>
</td>
<td align="left" style="vertical-align: middle">
<div style="margin-left: 10px;">
<g:HTML styleName="" ui:field="postOwnerArea" />
<g:InlineLabel styleName="timeStampContent"
ui:field="timeArea"></g:InlineLabel>
<g:InlineLabel styleName="timeStampContent"
ui:field="separator"> · </g:InlineLabel>
<g:InlineLabel styleName="vreSourceInMetadata"
ui:field="vreSourceInMetadata"></g:InlineLabel>
</div>
</td>
</tr>
</tbody>
</table>
<div class="div-table-col nf-post-remove">
<g:HTML height="15px" ui:field="closeImage"></g:HTML>
<g:HTML height="15px" ui:field="openImage"></g:HTML>
</div>
</div>
<div class="div-table-row">
<div class="div-table-col content">
<div class="tweet-content">
<g:HTML styleName="" ui:field="contentArea" />
<g:HTML styleName="" ui:field="seeMore" />
</div>
<g:VerticalPanel ui:field="previewPanel"
width="100%"></g:VerticalPanel>
<m:Placeholder ui:field="attachmentPreviewPanel"></m:Placeholder>
<div class="tweet-actions">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td align="left" style="vertical-align: top;">
<g:HTML styleName="comment" ui:field="commentArea" />
</td>
<td align="left" style="vertical-align: top;">
<g:Label styleName="tweet-separator">-</g:Label>
</td>
<td align="left" style="vertical-align: top;">
<g:HTML styleName="like" ui:field="likeArea" />
</td>
<td align="left" style="vertical-align: top;">
<g:Label ui:field="messageSeparator"
styleName="tweet-separator"></g:Label>
</td>
<td align="left" style="vertical-align: top;">
<b:Button width="45px" icon="COMMENTS" type="LINK"
ui:field="commentsNo" visible="false"></b:Button>
</td>
<td align="left" style="vertical-align: top;">
<b:Button width="45px" icon="THUMBS_UP_ALT"
type="LINK" ui:field="likesNo" visible="false"></b:Button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="tweet-content">
<g:VerticalPanel ui:field="commentsPanel"></g:VerticalPanel>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,51 @@
package org.gcube.portlets.user.newsfeed.server;
/**
* custom class to read propety file once
* @author massi
*
*/
public class CustomConfiguration {
private int refreshTime;
private String vreLabel;
private boolean showTimelineSource;
public CustomConfiguration(int refreshTime, String vreLabel,
boolean showTimelineSource) {
super();
this.refreshTime = refreshTime;
this.vreLabel = vreLabel;
this.showTimelineSource = showTimelineSource;
}
public int getRefreshTime() {
return refreshTime;
}
public void setRefreshTime(int refreshTime) {
this.refreshTime = refreshTime;
}
public String getVreLabel() {
return vreLabel;
}
public void setVreLabel(String vreLabel) {
this.vreLabel = vreLabel;
}
public boolean isShowTimelineSource() {
return showTimelineSource;
}
public void setShowTimelineSource(boolean showTimelineSource) {
this.showTimelineSource = showTimelineSource;
}
@Override
public String toString() {
return "CustomConfiguration [refreshTime=" + refreshTime
+ ", vreLabel=" + vreLabel + ", showTimelineSource="
+ showTimelineSource + "]";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
package org.gcube.portlets.user.newsfeed.server.portlet;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
public class NewsFeedPortlet extends GenericPortlet {
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
response.setContentType("text/html");
PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/NewsFeed_view.jsp");
dispatcher.include(request, response);
}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
}
}

View File

@ -0,0 +1,48 @@
package org.gcube.portlets.user.newsfeed.shared;
import com.google.gwt.user.client.rpc.IsSerializable;
public class MentionedDTO implements IsSerializable{
public String id, value, type;
public MentionedDTO() {
super();
}
public MentionedDTO(String id, String value, String type) {
super();
this.id = id;
this.value = value;
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "MentionedDTO [id=" + id + ", value=" + value + ", type=" + type + "]";
}
}

View File

@ -0,0 +1,51 @@
package org.gcube.portlets.user.newsfeed.shared;
import java.io.Serializable;
import java.util.ArrayList;
import org.gcube.portal.databook.shared.EnhancedFeed;
@SuppressWarnings("serial")
public class MorePostsBean implements Serializable {
private int lastReturnedPostTimelineIndex;
private ArrayList<EnhancedFeed> posts;
public MorePostsBean() {
super();
}
public MorePostsBean(int lastReturnedFeedTimelineIndex,
ArrayList<EnhancedFeed> feeds) {
super();
this.lastReturnedPostTimelineIndex = lastReturnedFeedTimelineIndex;
this.posts = feeds;
}
public int getLastReturnedFeedTimelineIndex() {
return lastReturnedPostTimelineIndex;
}
public void setLastReturnedFeedTimelineIndex(int lastReturnedFeedTimelineIndex) {
this.lastReturnedPostTimelineIndex = lastReturnedFeedTimelineIndex;
}
public ArrayList<EnhancedFeed> getPosts() {
return posts;
}
public void setPosts(ArrayList<EnhancedFeed> posts) {
this.posts = posts;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("MorePostsBean [lastReturnedPostTimelineIndex=");
builder.append(lastReturnedPostTimelineIndex);
builder.append(", posts=");
builder.append(posts);
builder.append("]");
return builder.toString();
}
}

View File

@ -0,0 +1,12 @@
package org.gcube.portlets.user.newsfeed.shared;
public class NewsConstants {
/**
* Feeds Number to who per VRE/Category
*/
public static final int FEEDS_NO_PER_CATEGORY = 9;
public static final int FEEDS_MAX_PER_CATEGORY = 30;
public static final String TEST_USER = "test.user";
}

View File

@ -0,0 +1,47 @@
package org.gcube.portlets.user.newsfeed.shared;
import org.gcube.portal.databook.shared.Comment;
import com.google.gwt.user.client.rpc.IsSerializable;
public class OperationResult implements IsSerializable {
private Boolean success;
private String message;
private Comment comment;
public OperationResult() {
super();
}
public OperationResult(Boolean success, String message, Comment comment) {
super();
this.success = success;
this.message = message;
this.comment = comment;
}
public Boolean isSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Comment getComment() {
return comment;
}
public void setComment(Comment comment) {
this.comment = comment;
}
}

View File

@ -0,0 +1,90 @@
package org.gcube.portlets.user.newsfeed.shared;
import org.gcube.portal.databook.shared.UserInfo;
import com.google.gwt.user.client.rpc.IsSerializable;
@SuppressWarnings("serial")
public class UserSettings implements IsSerializable {
private UserInfo userInfo;
private int refreshingTimeInMillis;
private String currentScope;
//indicate the
private String vreLabel;
//indicate whether the webapp is running at infrasturcture level
boolean isInfrastructure;
//indicate whether to indicate the feed timeline source or not (From whicn VRE/Channel this feed come from)
boolean showTimelineSourceLabel;
public UserSettings() {
super();
}
public UserSettings(UserInfo userInfo, int refreshingTimeInMillis,
String currentScope, String vreLabel, boolean isInfrastructure,
boolean showTimelineSourceLabel) {
super();
this.userInfo = userInfo;
this.refreshingTimeInMillis = refreshingTimeInMillis;
this.currentScope = currentScope;
this.vreLabel = vreLabel;
this.isInfrastructure = isInfrastructure;
this.showTimelineSourceLabel = showTimelineSourceLabel;
}
public boolean isShowTimelineSourceLabel() {
return showTimelineSourceLabel;
}
public void setShowTimelineSourceLabel(boolean showTimelineSourceLabel) {
this.showTimelineSourceLabel = showTimelineSourceLabel;
}
public UserInfo getUserInfo() {
return userInfo;
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
public int getRefreshingTimeInMillis() {
return refreshingTimeInMillis;
}
public void setRefreshingTimeInMillis(int refreshingTimeInMillis) {
this.refreshingTimeInMillis = refreshingTimeInMillis;
}
public String getCurrentScope() {
return currentScope;
}
public void setCurrentScope(String currentScope) {
this.currentScope = currentScope;
}
public boolean isInfrastructure() {
return isInfrastructure;
}
public void setInfrastructure(boolean isInfrastructure) {
this.isInfrastructure = isInfrastructure;
}
public String getVreLabel() {
return vreLabel;
}
public void setVreLabel(String channelName) {
this.vreLabel = channelName;
}
@Override
public String toString() {
return "UserSettings [userInfo=" + userInfo
+ ", refreshingTimeInMillis=" + refreshingTimeInMillis
+ ", currentScope=" + currentScope + ", vreLabel=" + vreLabel
+ ", isInfrastructure=" + isInfrastructure
+ ", showTimelineSourceLabel=" + showTimelineSourceLabel + "]";
}
}

View File

@ -0,0 +1,42 @@
# gCube Portal custom log4j Logger
#Author: Massimiliano Assante, ISTI-CNR
log4j.rootLogger=INFO, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=[PORTAL] %-4r [%t] %-5p %c %x - %m%n
# Display any warnings generated by our code
#log4j.category.org.globus=WARN
# Comment out the line below if you want to log every authorization
# decision the notification consumer makes.
#log4j.category.org.globus.wsrf.impl.security.authorization.ServiceAuthorizationChain=ERROR
log4j.logger.org.gcube=TRACE, GCUBE
log4j.appender.GCUBE.threshold=DEBUG
log4j.appender.GCUBE=org.apache.log4j.ConsoleAppender
log4j.appender.GCUBE.layout=org.apache.log4j.PatternLayout
log4j.appender.GCUBE.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} [%t,%M:%L] %
m%n
log4j.logger.org.apache.jasper.compiler.TldLocationsCache.level=ERROR, CA
#AVOID LOGGING EHCACHE Hearbeat problem
log4j.logger.net.sf.ehcache.distribution.PayloadUtil=OFF, CA
log4j.logger.org.eclipse.jetty=ERROR, CA
log4j.logger.org.gcube.portal.notifications=INFO, CA
log4j.logger.org.gcube.common.scope.impl=INFO, CA
log4j.logger.org.gcube.common.core.utils.events=INFO, CA
log4j.logger.org.gcube.portlets.user.homelibrary=INFO CA
log4j.logger.org.gcube.common.resources.kxml=ERROR, CA
log4j.logger.org.gcube.application.aquamaps.enhabling.Impl.ISCrawler=ERROR, CA
log4j.logger.com.netflix.astyanax.connectionpool.impl=ERROR, CA
log4j.logger.org.gcube.common.scope.impl=INFO, CA
log4j.logger.com.couchbase.client=ERROR, CA
log4j.logger.org.gcube.smartgears.handlers=INFO, CA
log4j.logger.org.gcube.informationsystem.publisher=INFO, CA
log4j.logger.org.gcube.application.framework.core.session=INFO, CA

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='newsfeed'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<!-- To Comment out -->
<!-- <set-property name="user.agent" value="safari" /> -->
<inherits name="org.jsonmaker.gwt.Gwt_jsonmaker" />
<!-- <inherits -->
<!-- name="net.eliasbalasis.tibcopagebus4gwt.testsubscriber.TestSubscriber" /> -->
<inherits name="com.google.gwt.json.JSON" />
<inherits name="com.github.gwtbootstrap.Bootstrap" />
<!-- inherits gCube Widgets Library -->
<inherits name='org.gcube.portlets.user.gcubewidgets.WidgetFactory' />
<inherits name='org.gcube.portlets.widgets.userselection.UserSelection' />
<inherits name='org.gcube.portlets.widgets.pickitem.PickItem' />
<inherits name='org.gcube.portal.databook.GCubeSocialNetworking' />
<inherits name="org.gcube.portlets.widgets.imagepreviewerwidget.ImagePreviewer" />
<!-- Specify the app entry point class. -->
<entry-point class='org.gcube.portlets.user.newsfeed.client.NewsFeed' />
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
</module>

View File

@ -0,0 +1,667 @@
/* Media queries for phones at the bottom pf this page */
table {
border-collapse: separate !important;
border-spacing: 0;
}
a.linkProfile {
font-size: 14px;
font-weight: 600;
height: auto;
line-height: 19px;
cursor: pointer;
}
.timeStampContent {
color: rgb(97, 103, 112);
font-size: 12px;
font-weight: normal;
height: auto;
line-height: 16px;
}
.vreSourceInMetadata {
color: rgb(97, 103, 112);
font-size: 12px;
font-weight: normal;
height: auto;
line-height: 16px;
cursor: pointer;
}
.vreSourceInMetadata:hover {
text-decoration: underline;
cursor: pointer;
}
img.member-photo {
border-radius: 2em;
display: block;
padding: 2px;
border: 1px solid #E6E6E6;
}
.result-hashtag {
color: #555;
font-size: 20px;
}
#newsfeedDIV .nav .dropdown-toggle .caret {
margin-top: 5px !important;
border-top: 7px solid #000;
border-right: 7px solid transparent;
border-left: 7px solid transparent;
border-top-color: #08c;
order-bottom-color: #08c;
}
#newsfeedDIV .nav-pills>li.disabled>a {
padding-right: 0;
}
.image-preview-attachment {
align: left !important;
margin: 5px !important;
display: inline !important;
height: 40px !important;
width: 40px !important;
overflow: hidden !important;
float: left !important;
border: 1px solid #DDD !important;
border-radius: 4px !important;
}
/* Superpose TextArea and Highlight DIV trick starts here */
#comment-supercontainer {
position: relative;
background-color: #EFF3F5;
}
#comment-highlighterContainer {
position: absolute;
left: 0;
top: 0;
cursor: text;
width: 100%;
height: 50px;
}
#comment-inputContainer {
position: relative;
}
.comment-highlighter {
padding: 4px 2px;
color: #ffffff;
background-color: #FFF;
margin-top: 0;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 11px;
letter-spacing: normal;
line-height: normal;
border: 1px solid transparent;
margin-left: 5px;
width: 98%;
min-height: 30px;
word-wrap: break-word;
/* this is very important when usere paste long links*/
}
div#comment-inputContainer textarea.post-comment {
padding: 4px 2px;
color: #999;
background-color: transparent;
margin-top: 0px;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 11px;
letter-spacing: normal;
line-height: normal;
border: 1px solid #C3CDE7;
margin-left: 5px;
width: 98%;
min-height: 30px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
div#comment-inputContainer textarea.post-comment.comment-dark-color {
color: #333;
background-color: transparent;
transition: background .25s ease-in-out;
-moz-transition: background .25s ease-in-out;
-webkit-transition: background .25s ease-in-out;
}
.highlightedUser {
background-color: #D8DFEA !important;
}
/* DIV trick ends here */
.new-feeds-container {
position: relative;
}
.new-feeds-available {
color: #444;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
text-align: center;
font-size: 13px;
width: 576px;
margin: 0px 25px 0px 8px;
padding: 3px;
border: 1px solid #75AAD0;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
height: 0px;
opacity: 0;
transition-property: opacity, height;
transition-duration: .40s;
transition-timing-function: ease-out;
-moz-transition-property: opacity, height;
-moz-transition-duration: .40s;
-moz-transition-timing-function: ease-out;
-webkit-transition-property: opacity, height;
-webkit-transition-duration: .40s;
-webkit-transition-timing-function: ease-out;
-ms-transition-property: opacity, height;
-ms-transition-duration: .40s;
-ms-transition-timing-function: ease-out;
}
.new-feeds-show {
opacity: 1;
background: #D6E2FC;
height: 20px;
width: 95%;
}
.new-feeds-available:hover {
background: #EDEFF4;
cursor: pointer;
cursor: hand;
text-decoration: underline;
}
.nofeed-message {
line-height: 40px;
font-family: 'Architects Daughter', arial, sans-serif;
font-size: 15px;
}
.feed-filters {
margin-top: -5px;
width: 500px
}
.feed-filters ul {
list-style: none;
margin: 0;
padding-left: 0;
}
.feed-filters li a {
color: #3B5998;
text-decoration: none;
}
.feed-filters li a:hover {
text-decoration: underline;
transition: color .25s ease-in-out;
-moz-transition: color .25s ease-in-out;
-webkit-transition: color .25s ease-in-out;
}
.feed-filters li {
color: #444;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 15px;
float: left;
height: 2em;
line-height: 2em;
display: block;
text-decoration: none;
text-align: center;
padding-left: 10px;
padding-right: 25px;
background-attachment: scroll;
background-color: transparent;
background-image: url("images/grid_small_dot.png");
background-position: 100% 50%;
background-repeat: no-repeat;
background-size: auto auto;
}
.feed-filters li.final {
background-image: none;
}
.feed-filters li.feed-breadcrumb {
background-image: url("images/arrow-right.png");
}
.filter-selected a {
color: #444 !important;
font-weight: bold;
}
/* Other */
.attachment-preview-container {
padding: 5px;
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
background-clip: border-box;
background-color: #FBFBFB;
background-image: none;
border: 1px solid #DDD;
border-radius: 4px;
width: 97%;
margin-top: 5px;
margin-left: 5px;
}
.centered {
width: 100%;
text-align: center;
}
.linkpreview-image {
margin: 3px;
width: 80px;
}
.link-preview {
padding: 5px;
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
background-clip: border-box;
background-color: #FBFBFB;
background-image: none;
border: 1px solid #DDD;
border-radius: 4px;
width: 97%;
margin-top: 5px;
margin-left: 5px;
}
.linkpreview-bgcolor {
background-color: #FBFBFB;
}
.linkpreview-title {
margin-top: 3px;
font-size: 12px;
font-weight: bold;
line-height: 15px;
}
.linkpreview-url {
margin-top: 10px;
color: #666;
font-size: 10px;
}
.linkpreview-desc {
padding-top: 5px;
color: #333;
font-size: 10px;
line-height: 14px;
}
.comment-hidden {
opacity: 0;
}
.comment-show {
background-color: #EFF3F5;
opacity: 1;
transition: opacity .45s ease-in-out;
-moz-transition: opacity .45s ease-in-out;
-webkit-transition: opacity .45s ease-in-out;
-ms-transition: opacity .45s ease-in-out;
width: 100%;
}
.commentsPanel {
width: 99%;
margin: 4px 0 0 4px;
}
.more-comment, .more-comment:hover {
background-color: #EFF3F5;
width: 100%;
text-align: center;
padding-top: 3px;
border-bottom-color: #FFF;
border-bottom-style: solid;
border-bottom-width: 1px;
cursor: pointer;
}
div>table.single-comment, .single-comment {
background-color: #EFF3F5;
border-bottom-color: #FFF;
border-bottom-style: solid;
border-bottom-width: 1px;
border-left: 2px solid #DDD;
padding-left: 3px;
width: 100%;
}
.comment-bgcolor {
background-color: #EFF3F5;
}
.uiCloseButton {
background: url(images/close.png) 0px 0px no-repeat;
height: 15px;
width: 15px;
}
.uiOpenButton {
background: url(images/open-sep.png) 0px 2px no-repeat;
height: 15px;
width: 15px;
}
.closeImage {
float: right;
height: 15px;
width: 15px;
}
.closeImage:hover {
background: url(images/close.png) 0px -16px no-repeat;
cursor: pointer;
cursor: hand;
}
.closeImage:active {
background: url(images/close.png) 0px -32px no-repeat;
}
.openImage {
float: right;
height: 15px;
width: 15px;
}
.openImage:hover {
background: url(images/open-sep.png) 0px -14px no-repeat;
cursor: pointer;
cursor: hand;
}
.openImage:active {
background: url(images/open-sep.png) 0px -30px no-repeat;
}
.uiEditButton {
background: url(images/edit.png) 0px 0px no-repeat;
height: 15px;
width: 15px;
}
.editImage {
height: 15px;
width: 15px;
}
.editImage:hover {
background: url(images/edit.png) 0px -16px no-repeat;
cursor: pointer;
cursor: hand;
}
.editImage:active {
background: url(images/edit.png) 0px -32px no-repeat;
}
.user-comment {
width: 99%;
color: #333;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 11px;
border-color: #999;
border-width: 1px;
letter-spacing: normal;
}
.user-comment-time {
width: 99%;
color: #999;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 11px;
white-space: nowrap;
}
a.seemore, .seemore:hover {
font-size: 9px;
cursor: pointer;
cursor: hand;
}
.like:hover {
cursor: pointer;
cursor: hand;
}
.comment:hover {
cursor: pointer;
cursor: hand;
}
a.person-link {
font-size: 16x;
}
.tweet-content {
font-family: 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
line-height: 18px;
color: #333;
width: 100%;
word-wrap: break-word;
-ms-word-break: break-all;
/* Non standard for webkit */
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
}
.tweet-separator {
padding-left: 5px;
padding-right: 5px;
}
.tweet-actions {
width: 99%;
padding-top: 5px;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 11px;
text-align: left;
overflow: hidden;
clear: both;
}
.tweet-actions .time {
padding-left: 15px;
padding-right: 15px;
white-space: nowrap;
}
.tweet-actions div {
color: #666;
}
/* TABLES */
.div-table-400 {
display: table;
width: 400px;
background-clip: border-box;
background-image: none;
background-origin: padding-box;
border-bottom-color: #DADADA;
border-bottom-style: solid;
border-bottom-width: 1px;
padding: 12px 7px 3px 7px;
}
.div-table {
display: table;
width: 98%;
background-clip: border-box;
background-image: none;
background-origin: padding-box;
border-bottom-color: #DADADA;
border-bottom-style: solid;
border-bottom-width: 1px;
padding: 10px 7px 3px 7px;
}
.div-table-row {
display: table-row;
text-align: left;
}
.div-table-col {
display: table-cell;
text-align: left;
}
.div-table-col.content {
padding-top: 7px;
vertical-align: top;
}
.div-table-col.edit {
padding-left: 5px;
vertical-align: top;
width: 15px;
}
.div-table-col.nf-post-remove {
padding-left: 5px;
vertical-align: top;
width: 30px;
}
.div-table-col.photo {
width: 60px;
}
.div-table-col.labels {
width: 60px;
}
.div-table-col.smallphoto {
width: 40px;
}
.visible {
background-color: #FFF;
transition: background .75s ease-in-out;
-moz-transition: background .75s ease-in-out;
-webkit-transition: background .75s ease-in-out;
}
.hidden {
background-color: #fdffcc;
}
.nwfeed-error {
color: #FFF;
background-color: pink;
transition: background .45s ease-in-out;
-moz-transition: background .45s ease-in-out;
-webkit-transition: background .45s ease-in-out;
}
div.tweet-content a.link {
font-size: 14px;
}
/* For phones*/
@media screen and (max-width: 520px) {
.commentsPanel {
width: 260px;
}
#comment-highlighterContainer {
width: 260px;
}
.comment-highlighter {
width: 230px;
}
div#comment-inputContainer textarea.post-comment {
width: 230px;
}
.link-preview {
width: 260px;
}
/* div.attachment-preview-container { */
/* width: 300px; */
/* } */
.linkpreview-desc, .linkpreview-url, .linkpreview-image {
display: none;
}
.image-preview-attachment {
display: none !important;
}
.new-feeds-show {
width: 260px;
}
.div-table {
padding-left: 0;
padding-right: 0;
margin-left: -15px;
}
.tweet-actions {
width: 330px;
}
.feed-filters {
width: 320px;
}
}
@media screen and (max-width: 1128px) {
.commentsPanel {
width: 300px;
}
.link-preview {
width: 260px;
}
/* div.attachment-preview-container { */
/* width: 300px; */
/* } */
.new-feeds-show {
width: 260px;
}
.linkpreview-desc, .linkpreview-url, .linkpreview-image {
display: none;
}
.image-preview-attachment {
display: none !important;
}
.div-table-col {
display: block;
padding-left: 10px;
padding-bottom: 5px;
}
.div-table {
padding-left: 0;
padding-right: 0;
margin-left: -10px;
}
.tweet-actions {
width: 330px;
}
.feed-filters {
width: 320px;
}
}

View File

@ -0,0 +1,38 @@
<!doctype html>
<!-- The DOCTYPE declaration above will set the -->
<!-- browser's rendering engine into -->
<!-- "Standards Mode". Replacing this declaration -->
<!-- with a "Quirks Mode" doctype is not supported. -->
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link href='https://fonts.googleapis.com/css?family=Architects+Daughter' rel='stylesheet' type='text/css'>
<!-- -->
<!-- Consider inlining CSS to reduce the number of requested files -->
<!-- -->
<link type="text/css" rel="stylesheet" href="NewsFeed.css">
<!-- -->
<!-- Any title is fine -->
<!-- -->
<title>News Feed</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src='js/jquery.autosize.js'></script>
</head>
<script type="text/javascript" src="newsfeed/newsfeed.nocache.js"></script>
</head>
<!-- -->
<!-- The body can have arbitrary html, or -->
<!-- you can leave the body empty if you want -->
<!-- to create a completely dynamic UI. -->
<!-- -->
<body>
<div id="newsfeedDIV"></div>
</body>
</html>

View File

@ -0,0 +1,18 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%-- Uncomment below lines to add portlet taglibs to jsp
<%@ page import="javax.portlet.*"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<portlet:defineObjects />
--%>
<link href='https://fonts.googleapis.com/css?family=Architects+Daughter' rel='stylesheet' type='text/css'>
<script type="text/javascript" language="javascript"
src='<%=request.getContextPath()%>/newsfeed/newsfeed.nocache.js'></script>
<script type="text/javascript" src='<%=request.getContextPath()%>/js/jquery.autosize.js'></script>
<div id="newsfeedDIV"></div>

View File

@ -0,0 +1,7 @@
<?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 Social Apps">
<portlet id="NewsFeed" />
</category>
</display>

View File

@ -0,0 +1,9 @@
name=NewsFeed
module-group-id=liferay
module-incremental-version=1
tags=
short-description=
change-log=
page-url=http://www.d4science.org
author=D4Science.org
licenses=EUPL

View File

@ -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>NewsFeed</portlet-name>
<layout-cacheable>false</layout-cacheable>
<instanceable>false</instanceable>
<ajaxable>false</ajaxable>
<header-portlet-css>/NewsFeed.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>

Some files were not shown because too many files have changed in this diff Show More