Added Support for user subscribe/favorite via mail to post notifications

Revised the way we shorten posts' text when this is very long, better heuristic used
Revised the way we format mail notification messages, user text is now more clear and visible
Revised the way we provide back links for posts, removed assumption that News Feed is always present the default community page

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/news-feed@117269 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Massimiliano Assante 2015-07-15 16:47:28 +00:00
parent ea4b4cf7b8
commit c22c4f5ce6
9 changed files with 69 additions and 32 deletions

View File

@ -4,6 +4,18 @@
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/> <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
<dependent-module archiveName="session-checker-0.3.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/session-checker/session-checker">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="pickitem-widget-1.1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/pickitem-widget/pickitem-widget">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="notifications-common-library-1.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/notifications-common-library/notifications-common-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="workspace-light-tree-2.14.0-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="gcube-widgets-1.9.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/gcube-widgets/gcube-widgets"> <dependent-module archiveName="gcube-widgets-1.9.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/gcube-widgets/gcube-widgets">
<dependency-type>uses</dependency-type> <dependency-type>uses</dependency-type>
</dependent-module> </dependent-module>

View File

@ -1,4 +1,11 @@
<ReleaseNotes> <ReleaseNotes>
<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" <Changeset component="org.gcube.portlets-user.newsfeed.1-9-0"
date="2015-04-27"> date="2015-04-27">
<Change>Integrated gwt-bootstrap and revised css</Change> <Change>Integrated gwt-bootstrap and revised css</Change>

View File

@ -1,6 +1,7 @@
package org.gcube.portlets.user.newsfeed.client; package org.gcube.portlets.user.newsfeed.client;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import org.gcube.portal.databook.shared.Comment; import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Like; import org.gcube.portal.databook.shared.Like;
@ -38,7 +39,9 @@ public interface NewsService extends RemoteService {
boolean deleteFeed(String feedid); boolean deleteFeed(String feedid);
OperationResult comment(String feedid, String text, ArrayList<String> mentionedUsers, String feedOwnerId, boolean isAppFeed); OperationResult comment(String feedid, String text,
HashSet<String> mentionedUsers, String feedOwnerId,
boolean isAppFeed);
OperationResult editComment(Comment toEdit); OperationResult editComment(Comment toEdit);

View File

@ -1,6 +1,7 @@
package org.gcube.portlets.user.newsfeed.client; package org.gcube.portlets.user.newsfeed.client;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import org.gcube.portal.databook.shared.Comment; import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Like; import org.gcube.portal.databook.shared.Like;
@ -33,7 +34,7 @@ public interface NewsServiceAsync {
void getUserSettings(AsyncCallback<UserSettings> callback); void getUserSettings(AsyncCallback<UserSettings> callback);
void comment(String feedid, String text, ArrayList<String> mentionedUsers, void comment(String feedid, String text, HashSet<String> mentionedUsers,
String feedOwnerId, boolean isAppFeed, String feedOwnerId, boolean isAppFeed,
AsyncCallback<OperationResult> callback); AsyncCallback<OperationResult> callback);

View File

@ -1,6 +1,6 @@
package org.gcube.portlets.user.newsfeed.client.event; package org.gcube.portlets.user.newsfeed.client.event;
import java.util.ArrayList; import java.util.HashSet;
import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate; import org.gcube.portlets.user.newsfeed.client.ui.TweetTemplate;
@ -13,9 +13,9 @@ public class AddCommentEvent extends GwtEvent<AddCommentEventHandler> {
private TweetTemplate owner; private TweetTemplate owner;
private String text; private String text;
private ArrayList<String> mentionedUsers; private HashSet<String> mentionedUsers;
public AddCommentEvent(TweetTemplate owner, String text, ArrayList<String> mentionedUsers) { public AddCommentEvent(TweetTemplate owner, String text, HashSet<String> mentionedUsers) {
this.owner = owner; this.owner = owner;
this.text = text; this.text = text;
this.mentionedUsers = mentionedUsers; this.mentionedUsers = mentionedUsers;
@ -29,7 +29,7 @@ public class AddCommentEvent extends GwtEvent<AddCommentEventHandler> {
return text; return text;
} }
public ArrayList<String> getMentionedUsers() { public HashSet<String> getMentionedUsers() {
return mentionedUsers; return mentionedUsers;
} }

View File

@ -2,6 +2,7 @@ package org.gcube.portlets.user.newsfeed.client.panels;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import org.gcube.portal.databook.client.GCubeSocialNetworking; import org.gcube.portal.databook.client.GCubeSocialNetworking;
import org.gcube.portal.databook.client.util.Encoder; import org.gcube.portal.databook.client.util.Encoder;
@ -839,7 +840,7 @@ public class NewsFeedPanel extends Composite {
newsPanel.setHeight("300px"); newsPanel.setHeight("300px");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_CENTER); newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_CENTER);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
newsPanel.add(loadingIcon); newsPanel.add(new Image(loading));
} }
private void showProblems() { private void showProblems() {
@ -919,7 +920,7 @@ public class NewsFeedPanel extends Composite {
} }
private void doAddComment(final TweetTemplate owner, String text, ArrayList<String> mentionedUsers) { private void doAddComment(final TweetTemplate owner, String text, HashSet<String> mentionedUsers) {
newsService.comment(owner.getFeedKey(), text, mentionedUsers, owner.getMyFeedUserId(), owner.isAppFeed(), new AsyncCallback<OperationResult>() { newsService.comment(owner.getFeedKey(), text, mentionedUsers, owner.getMyFeedUserId(), owner.isAppFeed(), new AsyncCallback<OperationResult>() {
@Override @Override
public void onFailure(Throwable caught) { public void onFailure(Throwable caught) {

View File

@ -4,6 +4,8 @@
package org.gcube.portlets.user.newsfeed.client.ui; package org.gcube.portlets.user.newsfeed.client.ui;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.gcube.portlets.user.gcubewidgets.client.elements.Div; import org.gcube.portlets.user.gcubewidgets.client.elements.Div;
import org.gcube.portlets.user.newsfeed.client.NewsService; import org.gcube.portlets.user.newsfeed.client.NewsService;
@ -40,7 +42,7 @@ public class SuperPosedTextArea extends TextArea {
public final static int ARROW_UP = 38; public final static int ARROW_UP = 38;
public final static int ARROW_DOWN = 40; public final static int ARROW_DOWN = 40;
private ArrayList<String> mentionedUsers = new ArrayList<String>(); private HashSet<String> mentionedUsers = new HashSet<String>();
private String areaId; private String areaId;
@ -49,9 +51,10 @@ public class SuperPosedTextArea extends TextArea {
*/ */
public SuperPosedTextArea(Div highlighterDIV) { public SuperPosedTextArea(Div highlighterDIV) {
sinkEvents(Event.ONPASTE); sinkEvents(Event.ONPASTE);
sinkEvents(Event.ONKEYUP); sinkEvents(Event.ONKEYPRESS);
sinkEvents(Event.ONCONTEXTMENU); sinkEvents(Event.ONCONTEXTMENU);
sinkEvents(Event.ONKEYDOWN); sinkEvents(Event.ONKEYDOWN);
sinkEvents(Event.ONKEYUP);
setText(AddCommentTemplate.COMMENT_TEXT); setText(AddCommentTemplate.COMMENT_TEXT);
this.highlighterDIV = highlighterDIV; this.highlighterDIV = highlighterDIV;
//needed to give unique identifiers to the Area (for the jQuery plugin) //needed to give unique identifiers to the Area (for the jQuery plugin)
@ -68,7 +71,7 @@ public class SuperPosedTextArea extends TextArea {
public void onFailure(Throwable caught) { public void onFailure(Throwable caught) {
} }
}); });
DOM.setElementAttribute(getElement(), "id", areaId); getElement().setAttribute("id", areaId);
bind(); bind();
Timer t = new Timer() { Timer t = new Timer() {
@Override @Override
@ -108,9 +111,13 @@ public class SuperPosedTextArea extends TextArea {
} }
break; break;
} }
case Event.ONKEYPRESS: {
pickUserDlg.onKeyPress(this.getCursorPos(), event.getKeyCode(), this.getAbsoluteLeft(), this.getAbsoluteTop()+this.getOffsetHeight(), getText());
break;
}
case Event.ONKEYUP: { case Event.ONKEYUP: {
injectInDiv(getText()); injectInDiv(getText());
pickUserDlg.onKeyUp(event.getKeyCode(), this.getAbsoluteLeft(), this.getAbsoluteTop()+this.getOffsetHeight(), getText()); pickUserDlg.onKeyUp(event.getKeyCode());
break; break;
} }
case Event.ONCONTEXTMENU: { case Event.ONCONTEXTMENU: {
@ -122,7 +129,7 @@ public class SuperPosedTextArea extends TextArea {
//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 //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) { if (event.getKeyCode() == ARROW_UP || event.getKeyCode() == KeyCodes.KEY_TAB || event.getKeyCode() == KeyCodes.KEY_ENTER) {
DOM.eventCancelBubble(event, true); DOM.eventCancelBubble(event, true);
DOM.eventPreventDefault(event); event.preventDefault();
return; return;
} }
} }
@ -171,21 +178,17 @@ public class SuperPosedTextArea extends TextArea {
String toAdd = event.getSelectedItem().getAlternativeName(); String toAdd = event.getSelectedItem().getAlternativeName();
mentionedUsers.add(toAdd); mentionedUsers.add(toAdd);
String[] toSplit = getText().split("@"); //get the preceeding part String preceedingPart = getText().substring(0, event.getItemCursorIndexStart());
String afterPart = getText().substring(event.getItemCursorIndexEnd()+1);
setText(toSplit[0]+toAdd);
//Element highDiv = DOM.getElementById("comment-highlighter"); setText(preceedingPart + toAdd + " " + afterPart);
Element highDiv = highlighterDIV.getElement(); injectInDiv(getText());
String[] htmlToSplit = highDiv.getInnerHTML().split("@"); //get the preceeding part
String highLightedUser = "<span class=\"highlightedUser\">"+toAdd+"</span>";
highDiv.setInnerHTML(htmlToSplit[0]+highLightedUser);
} }
}); });
} }
public ArrayList<String> getMentionedUsers() { public HashSet<String> getMentionedUsers() {
ArrayList<String> toReturn = new ArrayList<String>(); HashSet<String> toReturn = new HashSet<String>();
for (String mentionedUser : mentionedUsers) { for (String mentionedUser : mentionedUsers) {
if (getText().contains(mentionedUser)) if (getText().contains(mentionedUser))
toReturn.add(mentionedUser); toReturn.add(mentionedUser);

View File

@ -147,8 +147,10 @@ public class TweetTemplate extends Composite {
String feedText = feed.getDescription(); String feedText = feed.getDescription();
String descWithoutHTML = new HTML(feedText).getText(); String descWithoutHTML = new HTML(feedText).getText();
if ( (! feedText.startsWith("<span")) && descWithoutHTML.length() > MAX_SHOWTEXT_LENGTH && !displaySingle) { if ( (! feedText.startsWith("<span")) && descWithoutHTML.length() > MAX_SHOWTEXT_LENGTH && !displaySingle) {
feedText = feedText.substring(0, MAX_SHOWTEXT_LENGTH) + "..."; final int TEXT_TO_SHOW_LENGHT = (descWithoutHTML.length() < 500) ? (feedText.length() - (feedText.length() / 3)) : 500;
feedText = feedText.substring(0, TEXT_TO_SHOW_LENGHT) + "...";
seeMore.setHTML("<a class=\"seemore\"> See More </a>"); seeMore.setHTML("<a class=\"seemore\"> See More </a>");
} }

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
@ -81,8 +82,10 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
private static final String SESSION_ADMIN_ATTR = "SESSION_ADMIN_ATTR"; private static final String SESSION_ADMIN_ATTR = "SESSION_ADMIN_ATTR";
private static final String USER_SETTINGS_ATTR = "USER_SETTINGS_ATTR"; private static final String USER_SETTINGS_ATTR = "USER_SETTINGS_ATTR";
public static final String TEST_USER = "test.user"; public static final String TEST_USER = "test.user";
public static final String TEST_SCOPE = "/gcube/devsec/devVRE"; public static final String TEST_SCOPE = "/gcube/devsec/USTORE_VRE";
private String APP_ID;
/** /**
* *
@ -92,7 +95,8 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
private final static int MAX_FEEDS_NO = 45; private final static int MAX_FEEDS_NO = 45;
public void init() { public void init() {
store = new DBCassandraAstyanaxImpl(); store = new DBCassandraAstyanaxImpl();
APP_ID = this.getClass().getName();
} }
public void destroy() { public void destroy() {
@ -570,7 +574,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
if (likeCommitResult) { if (likeCommitResult) {
//if the user who liked this post is not the user who posted it notify the poster user (Feed owner) //if the user who liked this post is not the user who posted it notify the poster user (Feed owner)
if (! user.getUsername().equals(feedOwnerId)) { if (! user.getUsername().equals(feedOwnerId)) {
NotificationsManager nm = new ApplicationNotificationsManager(getASLSession()); NotificationsManager nm = new ApplicationNotificationsManager(getASLSession(), APP_ID);
boolean nResult = nm.notifyLikedFeed(feedOwnerId, feedid, escapeHtml(feedText)); boolean nResult = nm.notifyLikedFeed(feedOwnerId, feedid, escapeHtml(feedText));
_log.trace("Like Notification added? " + nResult); _log.trace("Like Notification added? " + nResult);
} }
@ -602,7 +606,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
* @param feedOwnerId the username of the user who created the post that was commented * @param feedOwnerId the username of the user who created the post that was commented
*/ */
@Override @Override
public OperationResult comment(String feedid, String commentText, ArrayList<String> mentionedUserFullNames, String feedOwnerId, boolean isAppFeed) { public OperationResult comment(String feedid, String commentText, HashSet<String> mentionedUserFullNames, String feedOwnerId, boolean isAppFeed) {
boolean commentCommitResult = false; boolean commentCommitResult = false;
_log.trace("Trying to add this comment " + commentText); _log.trace("Trying to add this comment " + commentText);
UserInfo user = getUserSettings().getUserInfo(); UserInfo user = getUserSettings().getUserInfo();
@ -613,9 +617,13 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
String escapedCommentText = Utils.escapeHtmlAndTransformUrl(commentText); String escapedCommentText = Utils.escapeHtmlAndTransformUrl(commentText);
//copy the set into a list
ArrayList<String> mentionedUserFullNamesList = new ArrayList<String>();
mentionedUserFullNamesList.addAll(mentionedUserFullNames);
ArrayList<ItemBean> mentionedUsers = null; ArrayList<ItemBean> mentionedUsers = null;
if (mentionedUserFullNames != null && ! mentionedUserFullNames.isEmpty()) { if (mentionedUserFullNames != null && ! mentionedUserFullNames.isEmpty()) {
mentionedUsers = getSelectedUserIds(mentionedUserFullNames); mentionedUsers = getSelectedUserIds(mentionedUserFullNamesList);
escapedCommentText = Utils.convertMentionPeopleAnchorHTML(escapedCommentText, mentionedUsers); escapedCommentText = Utils.convertMentionPeopleAnchorHTML(escapedCommentText, mentionedUsers);
} }
@ -632,7 +640,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
//if the comment was correctly delivered && is not an app feed notify users involved //if the comment was correctly delivered && is not an app feed notify users involved
if (commentCommitResult && isWithinPortal()) { if (commentCommitResult && isWithinPortal()) {
//if the user who commented this post is not the user who posted it notify the poster user (Feed owner) //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()); NotificationsManager nm = new ApplicationNotificationsManager(getASLSession(), APP_ID);
if (! user.getUsername().equals(feedOwnerId) && (!isAppFeed)) { if (! user.getUsername().equals(feedOwnerId) && (!isAppFeed)) {
boolean result = nm.notifyOwnCommentReply(feedOwnerId, feedid, escapeHtml(commentText)); boolean result = nm.notifyOwnCommentReply(feedOwnerId, feedid, escapeHtml(commentText));
_log.trace("Comment Notification to post owner added? " + result); _log.trace("Comment Notification to post owner added? " + result);