feeds) {
+ filterPanelWrapper.setVisible(false);
+ newsPanel.clear();
+ if (feeds != null) {
+ if (feeds.size() == 0) {
+ newsPanel.add(new ResultsFor(hashtag));
+ newsPanel.add(new HTML("" +
+ "Sorry, looks like we found no updates with topic: " + hashtag +"
"));
+ 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() {
@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
diff --git a/src/main/java/org/gcube/portlets/user/newsfeed/client/ui/ResultsFor.java b/src/main/java/org/gcube/portlets/user/newsfeed/client/ui/ResultsFor.java
new file mode 100644
index 0000000..f4ba205
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/user/newsfeed/client/ui/ResultsFor.java
@@ -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 {
+ }
+
+ @UiField HTML allUpdatesLink;
+ @UiField HTML resultForDiv;
+ public ResultsFor(String hashtag) {
+ initWidget(uiBinder.createAndBindUi(this));
+ allUpdatesLink.setHTML("All Updates");
+ allUpdatesLink.getElement().getStyle().setCursor(Cursor.POINTER);
+ resultForDiv.setHTML("results for " + hashtag+"");
+ 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);
+ }
+
+}
diff --git a/src/main/java/org/gcube/portlets/user/newsfeed/client/ui/ResultsFor.ui.xml b/src/main/java/org/gcube/portlets/user/newsfeed/client/ui/ResultsFor.ui.xml
new file mode 100644
index 0000000..36a403e
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/user/newsfeed/client/ui/ResultsFor.ui.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/gcube/portlets/user/newsfeed/server/NewsServiceImpl.java b/src/main/java/org/gcube/portlets/user/newsfeed/server/NewsServiceImpl.java
index cc761ec..54ba0e9 100644
--- a/src/main/java/org/gcube/portlets/user/newsfeed/server/NewsServiceImpl.java
+++ b/src/main/java/org/gcube/portlets/user/newsfeed/server/NewsServiceImpl.java
@@ -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 toMerge = new ArrayList();
HashMap feedsMap = new HashMap();
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 getFeedsByHashtag(String hashtag) {
+ ASLSession session = getASLSession();
+ String userName = session.getUsername();
+ ArrayList toMerge = new ArrayList();
+ HashMap feedsMap = new HashMap();
+ 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 OrganizationFeeds = (ArrayList) 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 OrganizationFeeds = (ArrayList) 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 toReturn = new ArrayList();
+ //return only 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 feedsMap = new HashMap();
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 enhanceFeeds(ArrayList toEnhance, int commentsNumberPerFeed) {
ArrayList toReturn = new ArrayList();
- String username = getASLSession().getUsername();
+ ASLSession session = getASLSession();
+ String username = session.getUsername();
ArrayList likedFeeds = (ArrayList) 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 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 getOrganizationUsers(String currentScope) {
- ArrayList toReturn = Utils.getOrganizationUsers(currentScope, getASLSession().getUsername(), withinPortal);
+ ArrayList 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();
else {
- ArrayList allUsers = Utils.getOrganizationUsers("/"+OrganizationsUtil.getRootOrganizationName(), getASLSession().getUsername(), withinPortal);
+ ArrayList allUsers = Utils.getOrganizationUsers("/"+OrganizationsUtil.getRootOrganizationName(), getASLSession().getUsername(), isWithinPortal());
ArrayList toReturn = new ArrayList();
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
+
+
}
diff --git a/src/main/java/org/gcube/portlets/user/newsfeed/server/Utils.java b/src/main/java/org/gcube/portlets/user/newsfeed/server/Utils.java
index 0612613..b7c6b1d 100644
--- a/src/main/java/org/gcube/portlets/user/newsfeed/server/Utils.java
+++ b/src/main/java/org/gcube/portlets/user/newsfeed/server/Utils.java
@@ -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 getHashTags(String postText) {
+ List 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.
diff --git a/src/main/resources/org/gcube/portlets/user/newsfeed/NewsFeed.gwt.xml b/src/main/resources/org/gcube/portlets/user/newsfeed/NewsFeed.gwt.xml
index 61246ea..6db3cdf 100644
--- a/src/main/resources/org/gcube/portlets/user/newsfeed/NewsFeed.gwt.xml
+++ b/src/main/resources/org/gcube/portlets/user/newsfeed/NewsFeed.gwt.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/src/main/webapp/NewsFeed.css b/src/main/webapp/NewsFeed.css
index 9f5e2b5..f7affaa 100644
--- a/src/main/webapp/NewsFeed.css
+++ b/src/main/webapp/NewsFeed.css
@@ -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;
diff --git a/src/main/webapp/images/arrow-right.png b/src/main/webapp/images/arrow-right.png
new file mode 100644
index 0000000..b278de8
Binary files /dev/null and b/src/main/webapp/images/arrow-right.png differ