updated for displaying topic seach results

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/news-feed@100484 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Massimiliano Assante 2014-10-07 14:41:08 +00:00
parent b8ab0415c5
commit 46654dd1b5
14 changed files with 298 additions and 35 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/news-feed-1.7.1-SNAPSHOT/WEB-INF/classes" path="src/main/java">
<classpathentry kind="src" output="target/news-feed-1.8.0-SNAPSHOT/WEB-INF/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
@ -31,5 +31,5 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/news-feed-1.7.1-SNAPSHOT/WEB-INF/classes"/>
<classpathentry kind="output" path="target/news-feed-1.8.0-SNAPSHOT/WEB-INF/classes"/>
</classpath>

View File

@ -1,5 +1,5 @@
eclipse.preferences.version=1
jarsExcludedFromWebInfLib=
lastWarOutDir=/Users/massi/Documents/workspace/news-feed/target/news-feed-1.7.1-SNAPSHOT
lastWarOutDir=/Users/massi/Documents/workspace/news-feed/target/news-feed-1.8.0-SNAPSHOT
warSrcDir=src/main/webapp
warSrcDirIsOutput=false

View File

@ -4,7 +4,7 @@
<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"/>
<dependent-module archiveName="session-checker-0.2.5-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/session-checker/session-checker">
<dependent-module archiveName="workspace-light-tree-2.13.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/workspace-light-tree/workspace-light-tree">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="wsmail-widget-1.7.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/wsmail-widget/wsmail-widget">

View File

@ -13,7 +13,7 @@
<groupId>org.gcube.portlets.user</groupId>
<artifactId>news-feed</artifactId>
<packaging>war</packaging>
<version>1.7.1-SNAPSHOT</version>
<version>1.8.0-SNAPSHOT</version>
<name>gCube News Feed Portlet</name>
<description>

View File

@ -25,6 +25,8 @@ public interface NewsService extends RemoteService {
ArrayList<EnhancedFeed> getOnlyLikedFeeds();
ArrayList<EnhancedFeed> getFeedsByHashtag(String hashtag);
MoreFeedsBean getMoreFeeds(int from, int quantity);
boolean like(String feedid, String feedText, String feedOwnerId);

View File

@ -58,5 +58,8 @@ public interface NewsServiceAsync {
void getOrganizationUsers(String currentScope,
AsyncCallback<ArrayList<PickingUser>> callback);
void getFeedsByHashtag(String hashtag,
AsyncCallback<ArrayList<EnhancedFeed>> callback);
}

View File

@ -39,6 +39,7 @@ import org.gcube.portlets.user.newsfeed.client.event.UnLikeEvent;
import org.gcube.portlets.user.newsfeed.client.event.UnLikeEventHandler;
import org.gcube.portlets.user.newsfeed.client.ui.FilterPanel;
import org.gcube.portlets.user.newsfeed.client.ui.NewFeedsAvailable;
import org.gcube.portlets.user.newsfeed.client.ui.ResultsFor;
import org.gcube.portlets.user.newsfeed.client.ui.ShowMoreFeeds;
import org.gcube.portlets.user.newsfeed.client.ui.SingleComment;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
@ -55,7 +56,9 @@ import org.gcube.portlets.widgets.userselection.shared.ItemSelectableBean;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import java.util.HashMap;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.shared.HandlerManager;
@ -111,7 +114,7 @@ public class NewsFeedPanel extends Composite {
public static final String MESSAGE_LABEL = "Message";
private String vreLabel;
private boolean showFeedTimelineSource = false;
private boolean isInfrastructure = false;
@ -159,7 +162,7 @@ public class NewsFeedPanel extends Composite {
doAddLike( event.getOwner(), event.getFeedId());
}
});
eventBus.addHandler(UnLikeEvent.TYPE, new UnLikeEventHandler() {
@Override
public void onUnLike(UnLikeEvent event) {
@ -251,7 +254,7 @@ public class NewsFeedPanel extends Composite {
newsPanel.add(loadingImage);
CheckSession.getInstance().startPolling();
newsService.getUserSettings(new AsyncCallback<UserSettings>() {
@Override
public void onFailure(Throwable caught) {
@ -268,11 +271,19 @@ public class NewsFeedPanel extends Composite {
doShowSessionExpired();
}
else {
GWT.log("checking params ");
if (getFeedToShowId() != null) {
String feedKey = getFeedToShowId();
showSingleFeed(feedKey);
filterPanel.removeFilterSelected();
} else {
}
else if (getHashtagParam() != null) {
String hashtag = Encoder.decode(getHashtagParam());
GWT.log("Found hashtag " + hashtag);
showFeedsByHashtag(hashtag);
filterPanel.removeFilterSelected();
}
else {
showAllUpdatesFeeds();
}
currentFilter = FilterType.ALL_UPDATES;
@ -340,6 +351,13 @@ public class NewsFeedPanel extends Composite {
private String getFeedToShowId() {
return Window.Location.getParameter(GET_OID_PARAMETER);
}
/**
* check if it has to show the feeds given an hashtag
* @return
*/
private String getHashtagParam() {
return Window.Location.getParameter(Encoder.encode(GCubeSocialNetworking.HASHTAG_OID));
}
/**
* used from notification referrals (see this Post)
* @param feedKey
@ -350,7 +368,7 @@ public class NewsFeedPanel extends Composite {
@Override
public void onSuccess(EnhancedFeed result) {
if (result.getFeed().getType() == FeedType.DISABLED) {
String usrLink = "<a class=\"link\" href=\""+GCubeSocialNetworking.USER_PROFILE_LINK+"?"+
Encoder.encode(GCubeSocialNetworking.USER_PROFILE_OID)+"="+
Encoder.encode(result.getFeed().getEntityId())+"\">"+result.getFeed().getFullName()+
@ -437,7 +455,67 @@ public class NewsFeedPanel extends Composite {
}
});
}
/**
* get the hashtagged feeds
* @param hashtag to look for
*/
private void showFeedsByHashtag(final String hashtag) {
showLoader();
newsService.getUserSettings(new AsyncCallback<UserSettings>() {
@Override
public void onFailure(Throwable caught) {
doStopFeedsTimer();
}
@Override
public void onSuccess(UserSettings result) {
if (result.getUserInfo().getUsername().equals("test.user")) {
doStopFeedsTimer();
doShowSessionExpired();
} else {
/**
* this check avoids the 2 tabs open in 2 different scope, if the previous tab was open at VRE Level and then antoher
* is open at infra level the first tab stops checking for updates
*/
if (result.getCurrentScope().compareTo(currentScope) == 0) {
newsService.getFeedsByHashtag(hashtag, new AsyncCallback<ArrayList<EnhancedFeed>>() {
@Override
public void onSuccess(ArrayList<EnhancedFeed> feeds) {
filterPanelWrapper.setVisible(false);
newsPanel.clear();
if (feeds != null) {
if (feeds.size() == 0) {
newsPanel.add(new ResultsFor(hashtag));
newsPanel.add(new HTML("<div class=\"nofeed-message\" style=\"height: 200px;\">" +
"Sorry, looks like we found no updates with topic: " + hashtag +"</div>"));
isFirstTweet = true;
}
else {
newsPanel.setHeight("");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
newsPanel.add(new ResultsFor(hashtag));
for (EnhancedFeed feed : feeds) {
newsPanel.add(new TweetTemplate(false, showFeedTimelineSource, myUserInfo, feed, eventBus)); //in the view
}
if (feeds.size() < 5) {
newsPanel.add(new Image(spacer));
}
isFirstTweet = false;
}
} else {
showProblems();
}
}
@Override
public void onFailure(Throwable caught) {
showProblems();
}
});
}
}
}
});
}
/**
* called when a user click on the are new updates
@ -775,7 +853,7 @@ public class NewsFeedPanel extends Composite {
}
});
}
protected void doUnLike(TweetTemplate owner, String feedId) {
newsService.unlike(feedId, owner.getMyFeedText(), owner.getMyFeedUserId(), new AsyncCallback<Boolean>() {
@Override
@ -787,7 +865,7 @@ public class NewsFeedPanel extends Composite {
}
}
});
}
private void doShowSessionExpired() {
@ -801,7 +879,7 @@ public class NewsFeedPanel extends Composite {
}
});
}
private void doShowLikes(final String feedId) {
GWT.runAsync(UserSelectionDialog.class, new RunAsyncCallback() {
@Override

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 hashtag) {
initWidget(uiBinder.createAndBindUi(this));
allUpdatesLink.setHTML("<a>All Updates</a>");
allUpdatesLink.getElement().getStyle().setCursor(Cursor.POINTER);
resultForDiv.setHTML("results for <a>" + hashtag+"</a>");
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

@ -82,8 +82,6 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
*/
private DatabookStore store;
private boolean withinPortal = false;
private final static int MAX_FEEDS_NO = 45;
public void init() {
@ -104,11 +102,8 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
if (user == null) {
_log.warn("USER IS NULL setting testing user and Running OUTSIDE PORTAL");
user = getDevelopmentUser();
SessionManager.getInstance().getASLSession(sessionID, user).setScope("/gcube/devNext/NextNext");
}
else {
withinPortal = true;
}
SessionManager.getInstance().getASLSession(sessionID, user).setScope("/gcube/devsec/USTORE_VRE");
}
return SessionManager.getInstance().getASLSession(sessionID, user);
}
/**
@ -117,9 +112,23 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
*/
public String getDevelopmentUser() {
String user = TEST_USER;
// user = "massimiliano.assante";
//user = "massimiliano.assante";
return user;
}
/**
*
* @return true if you're running into the portal, false if in development
*/
private boolean isWithinPortal() {
try {
UserLocalServiceUtil.getService();
return true;
}
catch (com.liferay.portal.kernel.bean.BeanLocatorException ex) {
_log.trace("Development Mode ON");
return false;
}
}
/**
* this is the first method called by the web app
*/
@ -199,7 +208,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
ArrayList<Feed> toMerge = new ArrayList<Feed>();
HashMap<String, Feed> feedsMap = new HashMap<String, Feed>();
try {
if (!withinPortal) {
if (!isWithinPortal()) {
return getEclipseResult(userName, feedsNoPerCategory, false);
}
else {
@ -276,6 +285,85 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
return null;
}
/**
* return the feeds having the hashtag passed as param the user has access on
* @param hashtag the hashtag to look for including '#'
*/
@Override
public ArrayList<EnhancedFeed> getFeedsByHashtag(String hashtag) {
ASLSession session = getASLSession();
String userName = session.getUsername();
ArrayList<Feed> toMerge = new ArrayList<Feed>();
HashMap<String, Feed> feedsMap = new HashMap<String, Feed>();
try {
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
//this check just return nothing if that happens
if (userName.compareTo("test.user") == 0) {
_log.debug("Found " + userName + " returning nothing");
return null;
}
_log.info("****** retrieving feeds for user: " + userName);
/**
* this handles the case where the portlet is deployed outside of VREs (regular)
*/
if (isInfrastructureScope()) {
User currUser = OrganizationsUtil.validateUser(userName);
//VRE Feeds
for (Organization org : currUser.getOrganizations()) {
GroupManager gm = new LiferayGroupManager();
if (gm.isVRE(org.getOrganizationId()+"")) {
String vreid = gm.getScope(""+org.getOrganizationId()); //get the scope
_log.debug("Reading hastagged feeds for VRE: " + vreid + " hashtag=" + hashtag);
ArrayList<Feed> OrganizationFeeds = (ArrayList<Feed>) store.getVREFeedsByHashtag(vreid, hashtag);
for (Feed feed : OrganizationFeeds) {
feedsMap.put(feed.getKey(), feed);
}
}
}
}
//else must be in a VRE scope
else {
String vreid = session.getScopeName();
_log.trace("News Feed in VRE, Reading feeds for VRE: " + vreid);
ArrayList<Feed> OrganizationFeeds = (ArrayList<Feed>) store.getVREFeedsByHashtag(vreid, hashtag);
for (Feed feed : OrganizationFeeds) {
feedsMap.put(feed.getKey(), feed);
}
}
for (String key: feedsMap.keySet()) {
toMerge.add(feedsMap.get(key));
}
//sort the feeds in reverse chronological order
Collections.sort(toMerge, Collections.reverseOrder());
ArrayList<Feed> toReturn = new ArrayList<Feed>();
//return only <MAX_FEEDS_NO> feeds
if (toMerge.size() > MAX_FEEDS_NO)
for (int i = 0; i < MAX_FEEDS_NO; i++)
toReturn.add(toMerge.get(i));
else {
return enhanceFeeds(toMerge, 2);
}
return enhanceFeeds(toReturn, 2);
} catch (PrivacyLevelTypeNotFoundException e) {
_log.error("Privacy Level not Found " + e.getMessage());
e.printStackTrace();
} catch (FeedTypeNotFoundException e) {
_log.error("Feed Type not Found " + e.getMessage());
e.printStackTrace();
} catch (ColumnNameNotFoundException e) {
_log.error("Column name not Found " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* return only the user connection feeds
*/
@ -285,7 +373,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
HashMap<String, Feed> feedsMap = new HashMap<String, Feed>();
String userName = getASLSession().getUsername();
try {
if (! withinPortal) {
if (! isWithinPortal()) {
return getEclipseResult(userName, NewsConstants.FEEDS_NO_PER_CATEGORY, true);
}
else {
@ -459,11 +547,11 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
public boolean like(String feedid, String feedText, String feedOwnerId) {
boolean likeCommitResult = false;
UserInfo user = getUserSettings().getUserInfo();
if (user.getUsername().compareTo(TEST_USER) == 0) {
return false;
}
Like toLike = new Like(UUID.randomUUID().toString(), user.getUsername(),
new Date(), feedid, user.getFullName(), user.getAvatarId());
try {
@ -534,7 +622,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
return null;
}
//if the comment was correctly delivered && is not an app feed notify users involved
if (commentCommitResult && withinPortal) {
if (commentCommitResult && isWithinPortal()) {
//if the user who commented this post is not the user who posted it notify the poster user (Feed owner)
NotificationsManager nm = new ApplicationNotificationsManager(getASLSession());
if (! user.getUsername().equals(feedOwnerId) && (!isAppFeed)) {
@ -585,7 +673,8 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
*/
private ArrayList<EnhancedFeed> enhanceFeeds(ArrayList<Feed> toEnhance, int commentsNumberPerFeed) {
ArrayList<EnhancedFeed> toReturn = new ArrayList<EnhancedFeed>();
String username = getASLSession().getUsername();
ASLSession session = getASLSession();
String username = session.getUsername();
ArrayList<String> likedFeeds = (ArrayList<String>) store.getAllLikedFeedIdsByUser(getASLSession().getUsername());
boolean skip = false;
@ -652,7 +741,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
* @return the url of the image portrait for this portal instance
*/
private String getUserImagePortraitUrlLocal(String screenName) {
if (! withinPortal) {
if (! isWithinPortal()) {
return "";
}
StringBuilder thumbnailURL = new StringBuilder("/image/user_male_portrait?img_id=");
@ -709,9 +798,18 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
}
@Override
public boolean deleteFeed(String feedid) {
_log.trace("Attempting to delete feed " + feedid);
_log.trace("Called delete feed " + feedid);
try {
Feed toDelete = store.readFeed(feedid);
List<String> hashtags = Utils.getHashTags(toDelete.getDescription());
if (hashtags != null && !hashtags.isEmpty()) {
_log.trace("The feed has hashtags, attempting to delete them ... " + hashtags.toString());
boolean deletedHashtag = store.deleteHashTags(feedid, toDelete.getVreid(), hashtags);
_log.trace("deletedHashtag? " + deletedHashtag);
}
_log.trace("Attempting to delete feed " + feedid);
return store.deleteFeed(feedid);
} catch (Exception e) {
e.printStackTrace();
return false;
@ -719,7 +817,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
}
@Override
public ArrayList<PickingUser> getOrganizationUsers(String currentScope) {
ArrayList<PickingUser> toReturn = Utils.getOrganizationUsers(currentScope, getASLSession().getUsername(), withinPortal);
ArrayList<PickingUser> toReturn = Utils.getOrganizationUsers(currentScope, getASLSession().getUsername(), isWithinPortal());
_log.trace("Returning " + toReturn.size() + " users for scope " + currentScope);
return toReturn;
}
@ -784,7 +882,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
if (fullNames == null)
return new ArrayList<PickingUser>();
else {
ArrayList<PickingUser> allUsers = Utils.getOrganizationUsers("/"+OrganizationsUtil.getRootOrganizationName(), getASLSession().getUsername(), withinPortal);
ArrayList<PickingUser> allUsers = Utils.getOrganizationUsers("/"+OrganizationsUtil.getRootOrganizationName(), getASLSession().getUsername(), isWithinPortal());
ArrayList<PickingUser> toReturn = new ArrayList<PickingUser>();
for (String fullName : fullNames)
for (PickingUser puser : allUsers) {
@ -804,7 +902,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
* @throws PortalException
*/
private boolean isAdmin() throws PortalException, SystemException {
if (! withinPortal)
if (! isWithinPortal())
return false;
try {
@ -926,4 +1024,6 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
}

View File

@ -4,6 +4,8 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.codec.binary.Base64;
import org.gcube.common.scope.impl.ScopeBean;
@ -76,6 +78,20 @@ public class Utils {
}
return portalUsers;
}
/**
* utility method that extract the hashtags from a text
* @param postText
* @return the list of hashtags present in the text
*/
protected static List<String> getHashTags(String postText) {
List<String> hashtags = new ArrayList<>();
Pattern MY_PATTERN = Pattern.compile("#(\\w+)");
Matcher matcher = MY_PATTERN.matcher(postText);
while (matcher.find()) {
hashtags.add("#"+matcher.group(1));
}
return hashtags;
}
/**
* Escape an html string. Escaping data received from the client helps to
* prevent cross-site script vulnerabilities.

View File

@ -4,7 +4,7 @@
<inherits name='com.google.gwt.user.User' />
<!-- To Comment out -->
<!-- <set-property name="user.agent" value="safari,gecko1_8,ie9" /> -->
<set-property name="user.agent" value="safari,gecko1_8" />
<!-- Other module inherits -->
<inherits name="net.eliasbalasis.tibcopagebus4gwt.tibcopagebus4gwt" />

View File

@ -5,7 +5,10 @@ table {
border-spacing: 0;
}
.result-hashtag {
color: #555;
font-size: 20px;
}
/* Superpose TextArea and Highlight DIV trick starts here */
#comment-supercontainer {
position: relative;
@ -180,6 +183,11 @@ table {
background-image: none;
}
.feed-filters li.feed-breadcrumb {
background-image: url("images/arrow-right.png");
}
.filter-selected a {
color: #336699 !important;
font-weight: bold;

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B