user mentions in comments implemented and ready for testing, preserve new lines in comments implemented

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/news-feed@94731 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Massimiliano Assante 2014-04-10 15:45:50 +00:00
parent 1728e6dfc3
commit 1e6587f314
14 changed files with 353 additions and 152 deletions

View File

@ -4,7 +4,6 @@ import java.util.ArrayList;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
@ -36,7 +35,7 @@ public interface NewsService extends RemoteService {
boolean deleteFeed(String feedid);
Comment comment(String feedid, String text, String feedOwnerId, boolean isAppFeed);
Comment comment(String feedid, String text, ArrayList<String> mentionedUsers, String feedOwnerId, boolean isAppFeed);
Comment editComment(Comment toEdit);

View File

@ -32,8 +32,9 @@ public interface NewsServiceAsync {
void getUserSettings(AsyncCallback<UserSettings> callback);
void comment(String feedid, String text, String feedOwnerId,
boolean isAppFeed, AsyncCallback<Comment> callback);
void comment(String feedid, String text, ArrayList<String> mentionedUsers,
String feedOwnerId, boolean isAppFeed,
AsyncCallback<Comment> callback);
void getAllCommentsByFeed(String feedid,
AsyncCallback<ArrayList<Comment>> callback);

View File

@ -1,5 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.event;
import java.util.ArrayList;
import org.gcube.portlets.user.newsfeed.client.templates.TweetTemplate;
import com.google.gwt.event.shared.GwtEvent;
@ -11,16 +13,24 @@ public class AddCommentEvent extends GwtEvent<AddCommentEventHandler> {
private TweetTemplate owner;
private String text;
private ArrayList<String> mentionedUsers;
public AddCommentEvent(TweetTemplate owner, String text, ArrayList<String> mentionedUsers) {
this.owner = owner;
this.text = text;
this.mentionedUsers = mentionedUsers;
}
public TweetTemplate getOwner() {
return owner;
}
public String getText() {
return text;
}
public AddCommentEvent(TweetTemplate owner, String text) {
this.owner = owner;
this.text = text;
public ArrayList<String> getMentionedUsers() {
return mentionedUsers;
}
@Override

View File

@ -169,7 +169,7 @@ public class NewsFeedPanel extends Composite {
eventBus.addHandler(AddCommentEvent.TYPE, new AddCommentEventHandler() {
@Override
public void onAddComment(AddCommentEvent event) {
doAddComment(event.getOwner(), event.getText());
doAddComment(event.getOwner(), event.getText(), event.getMentionedUsers());
}
});
@ -822,8 +822,8 @@ public class NewsFeedPanel extends Composite {
}
private void doAddComment(final TweetTemplate owner, String text) {
newsService.comment(owner.getFeedKey(), text, owner.getMyFeedUserId(), owner.isAppFeed(), new AsyncCallback<Comment>() {
private void doAddComment(final TweetTemplate owner, String text, ArrayList<String> mentionedUsers) {
newsService.comment(owner.getFeedKey(), text, mentionedUsers, owner.getMyFeedUserId(), owner.isAppFeed(), new AsyncCallback<Comment>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Could not deliver this comment: " + caught.getMessage());

View File

@ -1,35 +1,25 @@
package org.gcube.portlets.user.newsfeed.client.templates;
import java.util.ArrayList;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.newsfeed.client.NewsService;
import org.gcube.portlets.user.newsfeed.client.NewsServiceAsync;
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 org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
import org.gcube.portlets.widgets.pickuser.client.dialog.PickUsersDialog;
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
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.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.shared.HandlerManager;
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.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
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.TextArea;
import com.google.gwt.user.client.ui.Widget;
public class AddCommentTemplate extends Composite {
@ -40,13 +30,10 @@ public class AddCommentTemplate extends Composite {
private static CommentTemplateUiBinder uiBinder = GWT.create(CommentTemplateUiBinder.class);
private final static String COMMENT_TEXT = "Add a comment ... use @ to mention someone";
private final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
public final static String COMMENT_TEXT = "Add 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 final static int TEXT_AREA_WIDTH = 450;
private final static int TEXT_AREA_HEIGHT = 40;
private TweetTemplate owner;
private HandlerManager eventBus;
private boolean isEditing = false;
@ -56,6 +43,7 @@ public class AddCommentTemplate extends Composite {
@UiField HTMLPanel mainPanel;
@UiField Image avatarImage;
@UiField SuperPosedTextArea commentTextArea;
@UiField Div highlighterDIV;
@UiField Button submitButton;
@UiField Button cancelButton;
@ -72,8 +60,6 @@ public class AddCommentTemplate extends Composite {
owner = caller;
avatarImage.setPixelSize(30, 30);
avatarImage.setUrl(myUserInfo.getAvatarId());
//commentTextArea.setPixelSize(TEXT_AREA_WIDTH, TEXT_AREA_HEIGHT);
commentTextArea.setText(COMMENT_TEXT);
}
/**
* called on edit comment
@ -89,13 +75,16 @@ public class AddCommentTemplate extends Composite {
owner = caller;
avatarImage.setPixelSize(30, 30);
avatarImage.setUrl(caller.getMyUserInfo().getAvatarId());
//commentTextArea.setPixelSize(TEXT_AREA_WIDTH, TEXT_AREA_HEIGHT);
commentTextArea.setText(new HTML(toEdit.getText()).getText());
mainPanel.removeStyleName("comment-hidden");
mainPanel.setStyleName("single-comment");
commentTextArea.addStyleName("comment-dark-color");
}
/** Used by AddCommentTemplate to instantiate SuperPosedTextArea */
@UiFactory SuperPosedTextArea build() {
return new SuperPosedTextArea(highlighterDIV);
}
public void setFocus() {
commentTextArea.setFocus(true);
@ -117,8 +106,9 @@ public class AddCommentTemplate extends Composite {
toEdit.setText(escapeHtml(commentTextArea.getText()));
eventBus.fireEvent(new EditCommentEvent(owner, toEdit));
}
else
eventBus.fireEvent(new AddCommentEvent(owner, escapeHtml(commentTextArea.getText())));
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);
}

View File

@ -1,6 +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"
xmlns:w="urn:import:org.gcube.portlets.user.gcubewidgets.client.elements"
xmlns:m="urn:import:org.gcube.portlets.user.newsfeed.client.templates">
<ui:style>
.important {
@ -19,16 +20,14 @@
<td>
<div id="comment-supercontainer">
<div id="comment-highlighterContainer">
<div id="comment-highlighter">
</div>
<!-- <div id="comment-highlighter"> -->
<!-- </div> -->
<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>
<!-- <div class="commentContainer"> -->
<!-- <g:TextArea styleName="post-comment" ui:field="commentTextArea" /> -->
<!-- </div> -->
</td>
</tr>
<tr>

View File

@ -54,6 +54,11 @@ public class SingleComment extends Composite {
avatarImage.setUrl(toShow.getThumbnailURL());
String commentToShow = toShow.getText();
//replace the < & and >
commentToShow = commentToShow.replaceAll("&lt;","<").replaceAll("&gt;",">");
commentToShow = commentToShow.replaceAll("&amp;","&");
if (commentToShow.length() > MAX_SHOWTEXT_LENGTH) {
commentToShow = commentToShow.substring(0, MAX_SHOWTEXT_LENGTH) + "...";
seeMore.setHTML("<a class=\"seemore\"> See More </a>");
@ -114,4 +119,6 @@ public class SingleComment extends Composite {
editImage.removeStyleName("uiEditButton");
}
}
}

View File

@ -5,6 +5,7 @@ package org.gcube.portlets.user.newsfeed.client.templates;
import java.util.ArrayList;
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.client.panels.NewsFeedPanel;
@ -19,6 +20,7 @@ import com.google.gwt.event.dom.client.KeyCodes;
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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.TextArea;
@ -32,24 +34,29 @@ public class SuperPosedTextArea extends TextArea {
private final NewsServiceAsync newsService = GWT.create(NewsService.class);
private final HandlerManager eventBus = new HandlerManager(null);
private final static String COMMENT_TEXT = "Add a comment ... use @ to mention someone";
private final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
PickUsersDialog pickUserDlg;
private PickUsersDialog pickUserDlg;
private Div highlighterDIV;
public final static int ARROW_UP = 38;
public final static int ARROW_DOWN = 40;
private ArrayList<String> mentionedUsers = new ArrayList<String>();
private String areaId;
/**
*
*/
public SuperPosedTextArea() {
public SuperPosedTextArea(Div highlighterDIV) {
sinkEvents(Event.ONPASTE);
sinkEvents(Event.ONKEYUP);
sinkEvents(Event.ONCONTEXTMENU);
sinkEvents(Event.ONKEYDOWN);
setText(AddCommentTemplate.COMMENT_TEXT);
this.highlighterDIV = highlighterDIV;
//needed to give unique identifiers to the Area (for the jQuery plugin)
areaId = "postTextArea"+Random.nextInt();
newsService.getOrganizationUsers(NewsFeedPanel.getCurrentScope(), new AsyncCallback<ArrayList<PickingUser>>() {
@Override
@ -61,19 +68,23 @@ public class SuperPosedTextArea extends TextArea {
public void onFailure(Throwable caught) {
}
});
DOM.setElementAttribute(getElement(), "id", "postTextArea");
DOM.setElementAttribute(getElement(), "id", areaId);
bind();
Timer t = new Timer() {
@Override
public void run() {
myAutoSize();
myAutoSize(areaId);
setCaretPositionToBegin(areaId);
}
};
t.schedule(1000);
t.schedule(200);
}
public static native void myAutoSize() /*-{
function autoSizeArea() {
$wnd.jQuery('#postTextArea').autosize();
/**
* 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();
}-*/;
@ -91,7 +102,7 @@ public class SuperPosedTextArea extends TextArea {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE: {
if (getText().equals(COMMENT_TEXT) || getText().equals(ERROR_UPDATE_TEXT) ) {
if (getText().equals(AddCommentTemplate.COMMENT_TEXT) || getText().equals(AddCommentTemplate.ERROR_UPDATE_TEXT) ) {
setText("");
addStyleName("dark-color");
removeStyleName("error");
@ -100,7 +111,7 @@ public class SuperPosedTextArea extends TextArea {
}
case Event.ONKEYUP: {
injectInDiv(getText());
pickUserDlg.onKeyUp(event.getKeyCode(), this.getAbsoluteLeft(), this.getAbsoluteTop()+45, getText());
pickUserDlg.onKeyUp(event.getKeyCode(), this.getAbsoluteLeft(), this.getAbsoluteTop()+this.getOffsetHeight(), getText());
break;
}
case Event.ONCONTEXTMENU: {
@ -121,15 +132,20 @@ public class SuperPosedTextArea extends TextArea {
}
}
protected void removeSampleText() {
if (getText().equals(COMMENT_TEXT) || getText().equals(ERROR_UPDATE_TEXT) ) {
if (getText().equals(AddCommentTemplate.COMMENT_TEXT) || getText().equals(AddCommentTemplate.ERROR_UPDATE_TEXT) ) {
setText("");
addStyleName("darker-color");
removeStyleName("error");
}
}
protected void cleanHighlighterDiv() {
DOM.getElementById("comment-highlighter").setInnerHTML("");
//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:
@ -141,7 +157,8 @@ public class SuperPosedTextArea extends TextArea {
text = text.replaceAll(mentionedUser,"<span class=\"highlightedUser\">"+mentionedUser+"</span>");
}
// re-inject the processed text into the div
DOM.getElementById("comment-highlighter").setInnerHTML(text);
//DOM.getElementById("comment-highlighter").setInnerHTML(text);
highlighterDIV.getElement().setInnerHTML(text);
}
/**
@ -158,7 +175,8 @@ public class SuperPosedTextArea extends TextArea {
String[] toSplit = getText().split("@"); //get the preceeding part
setText(toSplit[0]+toAdd);
Element highDiv = DOM.getElementById("comment-highlighter");
//Element highDiv = DOM.getElementById("comment-highlighter");
Element highDiv = highlighterDIV.getElement();
String[] htmlToSplit = highDiv.getInnerHTML().split("@"); //get the preceeding part
String highLightedUser = "<span class=\"highlightedUser\">"+toAdd+"</span>";
@ -177,20 +195,26 @@ public class SuperPosedTextArea extends TextArea {
return mentionedUsers;
}
/*
*
* <script>
$(document).ready(function(){
setTimeout(function(){
$('.postTextArea').autosize();
}, 3000);
});
</script>
*
*
/**
* this position the caret at the begin
*/
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

@ -149,7 +149,11 @@ public class TweetTemplate extends Composite {
feedText = feedText.substring(0, MAX_SHOWTEXT_LENGTH) + "...";
seeMore.setHTML("<a class=\"seemore\"> See More </a>");
}
//replace the < & and >
feedText = feedText.replaceAll("&lt;","<").replaceAll("&gt;",">");
feedText = feedText.replaceAll("&amp;","&");
if (! isAppFeed) {
messageArea.setHTML("<a>" + NewsFeedPanel.MESSAGE_LABEL + "</a>");
contentArea.setHTML("<a class=\"link\" href=\""+GCubeSocialNetworking.USER_PROFILE_LINK

View File

@ -0,0 +1,39 @@
package org.gcube.portlets.user.newsfeed.server;
import java.util.ArrayList;
import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Massimiliano Assante ISTI-CNR
*
*/
public class MentionNotificationsThread implements Runnable {
private static Logger _log = LoggerFactory.getLogger(MentionNotificationsThread.class);
private String postText;
private String postId;
private NotificationsManager nm;
private ArrayList<PickingUser> users;
public MentionNotificationsThread(String postId, String postText, NotificationsManager nm, ArrayList<PickingUser> users) {
super();
this.postId = postId;
this.postText = postText;
this.nm = nm;
this.users = users;
}
@Override
public void run() {
for (PickingUser userToNotify : users) {
boolean result = nm.notifyUserTag(userToNotify.getUsername(), postId, postText);
_log.trace("Sending Notification for post mention to: " + userToNotify.getUsername() + " result?"+ result);
}
}
}

View File

@ -491,12 +491,22 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
* @param feedOwnerId the username of the user who created the post that was commented
*/
@Override
public Comment comment(String feedid, String commentText, String feedOwnerId, boolean isAppFeed) {
public Comment comment(String feedid, String commentText, ArrayList<String> mentionedUserFullNames, String feedOwnerId, boolean isAppFeed) {
boolean commentCommitResult = false;
_log.trace("Trying to add this comment " + commentText);
UserInfo user = getUserSettings().getUserInfo();
String escapedCommentText = Utils.escapeHtmlAndTransformUrl(commentText);
ArrayList<PickingUser> mentionedUsers = null;
if (mentionedUserFullNames != null && ! mentionedUserFullNames.isEmpty()) {
mentionedUsers = getSelectedUserIds(mentionedUserFullNames);
escapedCommentText = Utils.convertMentionPeopleAnchorHTML(escapedCommentText, mentionedUsers);
}
Comment comment = new Comment(UUID.randomUUID().toString(), user.getUsername(),
new Date(), feedid, transformUrls(escapeHtml(commentText)), user.getFullName(), user.getAvatarId());
new Date(), feedid, escapedCommentText, user.getFullName(), user.getAvatarId());
try {
if (store.addComment(comment))
commentCommitResult = true;
@ -521,7 +531,13 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
//notify the other users who commented this post (excluding the ones above)
Thread commentsNotificationthread = new Thread(new CommentNotificationsThread(store, user.getUsername(), comment.getFeedid(), commentText, nm, feedOwnerId, favorites));
commentsNotificationthread.start();
commentsNotificationthread.start();
//send the notification to the mentioned users, if any
if (mentionedUsers != null && mentionedUsers.size() > 0) {
Thread thread = new Thread(new MentionNotificationsThread(comment.getFeedid(), commentText, nm, mentionedUsers));
thread.start();
}
}
return comment;
}
@ -683,7 +699,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
}
@Override
public ArrayList<PickingUser> getOrganizationUsers(String currentScope) {
ArrayList<PickingUser> toReturn = UsersUtil.getOrganizationUsers(currentScope, getASLSession().getUsername(), withinPortal);
ArrayList<PickingUser> toReturn = Utils.getOrganizationUsers(currentScope, getASLSession().getUsername(), withinPortal);
_log.trace("Returning " + toReturn.size() + " users for scope " + currentScope);
return toReturn;
}
@ -740,6 +756,26 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
}
return (Boolean) getASLSession().getAttribute(SESSION_ADMIN_ATTR);
}
/**
*
* @return the screennames of the addressee (user logins e.g. pino.pini)
*/
public ArrayList<PickingUser> getSelectedUserIds(ArrayList<String> fullNames) {
if (fullNames == null)
return new ArrayList<PickingUser>();
else {
ArrayList<PickingUser> allUsers = Utils.getOrganizationUsers("/"+OrganizationsUtil.getRootOrganizationName(), getASLSession().getUsername(), withinPortal);
ArrayList<PickingUser> toReturn = new ArrayList<PickingUser>();
for (String fullName : fullNames)
for (PickingUser puser : allUsers) {
if (puser.getFullName().compareTo(fullName) == 0) {
toReturn.add(puser);
break;
}
}
return toReturn;
}
}
/**
* tell if the user is a portal administrator or not
* @param username

View File

@ -1,75 +0,0 @@
package org.gcube.portlets.user.newsfeed.server;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.portal.custom.communitymanager.OrganizationsUtil;
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.liferay.portal.service.UserLocalServiceUtil;
public class UsersUtil {
private static final Logger _log = LoggerFactory.getLogger(UsersUtil.class);
/**
*
* @param session the Asl Session
* @param withinPortal true when is on Liferay portal
* @return the users belonging to the current organization (scope)
*/
public static ArrayList<PickingUser> getOrganizationUsers(String scope, String currUser, boolean withinPortal) {
ArrayList<PickingUser> portalUsers = new ArrayList<PickingUser>();
try {
if (withinPortal) {
UserManager um = new LiferayUserManager();
GroupManager gm = new LiferayGroupManager();
ScopeBean sb = new ScopeBean(scope);
List<UserModel> users = null;
if (sb.is(Type.INFRASTRUCTURE))
users = um.listUsersByGroup(gm.getRootVO().getGroupId());
else if (sb.is(Type.VRE)) { //must be in VRE
//get the name from the scope
String orgName = scope.substring(scope.lastIndexOf("/")+1, scope.length());
//ask the users
users = um.listUsersByGroup(gm.getGroupId(orgName));
}
else {
_log.error("Error, you must be in SCOPE VRE OR INFRASTURCTURE, you are in VO SCOPE returning no users");
return portalUsers;
}
for (UserModel user : users) {
if (user.getScreenName().compareTo("test.user") != 0 && user.getScreenName().compareTo(currUser) != 0) { //skip test.user & current user
String thumbnailURL = "";
com.liferay.portal.model.UserModel lifeUser = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), user.getScreenName());
thumbnailURL = "/image/user_male_portrait?img_id="+lifeUser.getPortraitId();
portalUsers.add(new PickingUser(user.getUserId(), user.getScreenName(), user.getFullname(), thumbnailURL));
}
}
}
else { //test users
portalUsers.add(new PickingUser("12111", "massimiliano.assante", "Test User #1", ""));
portalUsers.add(new PickingUser("14111", "massimiliano.assante", "Test Second User #2", ""));
portalUsers.add(new PickingUser("11511", "massimiliano.assante", "Test Third User", ""));
portalUsers.add(new PickingUser("11611", "massimiliano.assante", "Test Fourth User", ""));
portalUsers.add(new PickingUser("11711", "massimiliano.assante", "Test Fifth User", ""));
portalUsers.add(new PickingUser("11811", "massimiliano.assante", "Test Sixth User", ""));
portalUsers.add(new PickingUser("15811", "massimiliano.assante", "Ninth Testing User", ""));
portalUsers.add(new PickingUser("15811", "massimiliano.assante", "Eighth Testing User", ""));
portalUsers.add(new PickingUser("11211", "giogio.giorgi", "Seventh Test User", ""));
portalUsers.add(new PickingUser("2222", "pino.pinetti", "Tenth Testing User", ""));
}
} catch (Exception e) {
_log.error("Error in server get all contacts ", e);
}
return portalUsers;
}
}

View File

@ -0,0 +1,167 @@
package org.gcube.portlets.user.newsfeed.server;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.portal.custom.communitymanager.OrganizationsUtil;
import org.gcube.portal.databook.client.GCubeSocialNetworking;
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.liferay.portal.service.UserLocalServiceUtil;
public class Utils {
private static final Logger _log = LoggerFactory.getLogger(Utils.class);
/**
*
* @param session the Asl Session
* @param withinPortal true when is on Liferay portal
* @return the users belonging to the current organization (scope)
*/
public static ArrayList<PickingUser> getOrganizationUsers(String scope, String currUser, boolean withinPortal) {
ArrayList<PickingUser> portalUsers = new ArrayList<PickingUser>();
try {
if (withinPortal) {
UserManager um = new LiferayUserManager();
GroupManager gm = new LiferayGroupManager();
ScopeBean sb = new ScopeBean(scope);
List<UserModel> users = null;
if (sb.is(Type.INFRASTRUCTURE))
users = um.listUsersByGroup(gm.getRootVO().getGroupId());
else if (sb.is(Type.VRE)) { //must be in VRE
//get the name from the scope
String orgName = scope.substring(scope.lastIndexOf("/")+1, scope.length());
//ask the users
users = um.listUsersByGroup(gm.getGroupId(orgName));
}
else {
_log.error("Error, you must be in SCOPE VRE OR INFRASTURCTURE, you are in VO SCOPE returning no users");
return portalUsers;
}
for (UserModel user : users) {
if (user.getScreenName().compareTo("test.user") != 0 && user.getScreenName().compareTo(currUser) != 0) { //skip test.user & current user
String thumbnailURL = "";
com.liferay.portal.model.UserModel lifeUser = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), user.getScreenName());
thumbnailURL = "/image/user_male_portrait?img_id="+lifeUser.getPortraitId();
portalUsers.add(new PickingUser(user.getUserId(), user.getScreenName(), user.getFullname(), thumbnailURL));
}
}
}
else { //test users
portalUsers.add(new PickingUser("12111", "massimiliano.assante", "Test User #1", ""));
portalUsers.add(new PickingUser("14111", "massimiliano.assante", "Test Second User #2", ""));
portalUsers.add(new PickingUser("11511", "massimiliano.assante", "Test Third User", ""));
portalUsers.add(new PickingUser("11611", "massimiliano.assante", "Test Fourth User", ""));
portalUsers.add(new PickingUser("11711", "massimiliano.assante", "Test Fifth User", ""));
portalUsers.add(new PickingUser("11811", "massimiliano.assante", "Test Sixth User", ""));
portalUsers.add(new PickingUser("15811", "massimiliano.assante", "Ninth Testing User", ""));
portalUsers.add(new PickingUser("15811", "massimiliano.assante", "Eighth Testing User", ""));
portalUsers.add(new PickingUser("11211", "giogio.giorgi", "Seventh Test User", ""));
portalUsers.add(new PickingUser("2222", "pino.pinetti", "Tenth Testing User", ""));
}
} catch (Exception e) {
_log.error("Error in server get all contacts ", e);
}
return portalUsers;
}
/**
* 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
*/
protected static String escapeHtmlAndTransformUrl(String html) {
if (html == null) {
return null;
}
String toReturn = html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
.replaceAll(">", "&gt;");
// replace all the line breaks by <br/>
toReturn = toReturn.replaceAll("(\r\n|\n)"," <br/> ");
//transfrom the URL in a clickable URL
toReturn = transformUrls(toReturn);
// then replace all the double spaces by the html version &nbsp;
toReturn = toReturn.replaceAll("\\s\\s","&nbsp;&nbsp;");
return toReturn;
}
/**
* utility method that convert a url ina text in a clickable url by the browser
* and if the user has just pasted a link, converts the link in: shared a link
* @param feedText
* @return the text with the clickable url in it
*/
protected static String transformUrls(String feedText) {
StringBuilder sb = new StringBuilder();
// separate input by spaces ( URLs have no spaces )
String [] parts = feedText.split("\\s");
// Attempt to convert each item into an URL.
for (int i = 0; i < parts.length; i++) {
String toCheck = getHttpToken(parts[i]);
if (toCheck != null) {
try {
URL url = new URL(toCheck);
if (i == 0 && parts.length == 1) //then he shared just a link
return sb.append("<span style=\"color:gray; font-size:12px;\">shared </span><a class=\"link\" href=\"").append(url).append("\" target=\"_blank\">").append("a link.").append("</a> ").toString();
// If possible then replace with anchor...
sb.append("<a class=\"link\" href=\"").append(url).append("\" target=\"_blank\">").append(url).append("</a> ");
} catch (MalformedURLException e) {
// If there was an URL then it's not valid
_log.error("MalformedURLException returning... ");
return feedText;
}
} else {
sb.append(parts[i]);
sb.append(" ");
}
}
return sb.toString();
}
/**
* convert the mentioned people in HTML anchor and also Encode the params Base64
* @param escapedFeedText
* @param taggedPeople
* @return
*/
protected static String convertMentionPeopleAnchorHTML(String escapedFeedText, ArrayList<PickingUser> taggedPeople) {
for (PickingUser tagged : taggedPeople) {
String taggedHTML = "<a class=\"link\" href=\""+GCubeSocialNetworking.USER_PROFILE_LINK
+"?"+
new String(Base64.encodeBase64(GCubeSocialNetworking.USER_PROFILE_OID.getBytes()))+"="+
new String(Base64.encodeBase64(tagged.getUsername().getBytes()))+"\">"+tagged.getFullName()+"</a> ";
escapedFeedText = escapedFeedText.replace(tagged.getFullName(), taggedHTML);
}
return escapedFeedText;
}
/**
* check the tokens of a pasted text and see if there's any http link in it
* @param item a text token
* @return the actual http link
*/
private static String getHttpToken(String item) {
if (item.startsWith("http") || item.startsWith("www") || item.startsWith("(www") || item.startsWith("(http")) {
if (item.startsWith("("))
item = item.substring(1, item.length());
if (item.endsWith(".") || item.endsWith(")")) { //sometimes people write the url and close the phrase with a .
item = item.substring(0, item.length()-1);
}
item = item.startsWith("www") ? "http://"+item : item;
//System.out.println("getHttpToken returns -> " + item);
return item;
}
return null;
}
}

View File

@ -25,7 +25,7 @@ table {
position: relative;
}
#comment-highlighter {
.comment-highlighter {
padding: 4px 2px;
color: #ffffff;
background-color: #FFF;
@ -56,7 +56,7 @@ table {
letter-spacing: normal;
line-height: normal;
border: 1px solid #999;
border: 1px solid #C3CDE7;
width: 450px;
min-height: 40px;