news-feed/src/main/java/org/gcube/portlets/user/newsfeed/client/panels/NewsFeedPanel.java

593 lines
18 KiB
Java

package org.gcube.portlets.user.newsfeed.client.panels;
import java.util.ArrayList;
import org.gcube.portal.databook.shared.ClientFeed;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.newsfeed.client.FilterType;
import org.gcube.portlets.user.newsfeed.client.NewsService;
import org.gcube.portlets.user.newsfeed.client.NewsServiceAsync;
import org.gcube.portlets.user.newsfeed.client.event.AddCommentEvent;
import org.gcube.portlets.user.newsfeed.client.event.AddCommentEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.AddLikeEvent;
import org.gcube.portlets.user.newsfeed.client.event.AddLikeEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.DeleteCommentEvent;
import org.gcube.portlets.user.newsfeed.client.event.DeleteCommentEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.DeleteFeedEvent;
import org.gcube.portlets.user.newsfeed.client.event.DeleteFeedEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.EditCommentEvent;
import org.gcube.portlets.user.newsfeed.client.event.EditCommentEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.SeeCommentsEvent;
import org.gcube.portlets.user.newsfeed.client.event.SeeCommentsEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.SeeLikesEvent;
import org.gcube.portlets.user.newsfeed.client.event.SeeLikesEventHandler;
import org.gcube.portlets.user.newsfeed.client.event.StopTimerEvent;
import org.gcube.portlets.user.newsfeed.client.event.StopTimerEventHandler;
import org.gcube.portlets.user.newsfeed.client.panels.dialog.LikesDialog;
import org.gcube.portlets.user.newsfeed.client.templates.FilterPanel;
import org.gcube.portlets.user.newsfeed.client.templates.SingleComment;
import org.gcube.portlets.user.newsfeed.client.templates.TweetTemplate;
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Timer;
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.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
*
* @author Massimiliano Assante, ISTI-CNR
*
*/
public class NewsFeedPanel extends Composite {
/**
* Create a remote service proxy to talk to the server-side News service.
*/
private final NewsServiceAsync newsService = GWT.create(NewsService.class);
private final HandlerManager eventBus = new HandlerManager(null);
private VerticalPanel mainPanel = new VerticalPanel();
private HorizontalPanel filterPanel = new HorizontalPanel();
private VerticalPanel newsPanel = new VerticalPanel();
private static final String warning = GWT.getModuleBaseURL() + "../images/warning_blue.png";
private static final String spacer = GWT.getModuleBaseURL() + "../images/feeds-spacer.gif";
public static final String loading = GWT.getModuleBaseURL() + "../images/feeds-loader.gif";
public static final String LIKE_LABEL = "Favorite";
public static final String LIKED_LABEL = "Favorited";
public static final String COMMENT_LABEL = "Reply";
public static final String MESSAGE_LABEL = "Message";
public static final int delayMillis = 300000; //5 minutes
private boolean isFirstTweet = false;
private Image loadingImage;
private UserInfo myUserInfo;
private FilterType currentFilter;
private Timer feedsTimer;
/**
* events binder
*/
private void bind() {
eventBus.addHandler(StopTimerEvent.TYPE, new StopTimerEventHandler() {
@Override
public void onStopTimer(StopTimerEvent event) {
GWT.log("Stop timer");
if (event.isRestart())
resetTimer();
else
stopTimer();
}
});
eventBus.addHandler(AddLikeEvent.TYPE, new AddLikeEventHandler() {
@Override
public void onAddLike(AddLikeEvent event) {
resetTimer();
doAddLike( event.getOwner(), event.getFeedId());
}
});
eventBus.addHandler(AddCommentEvent.TYPE, new AddCommentEventHandler() {
@Override
public void onAddComment(AddCommentEvent event) {
resetTimer();
doAddComment(event.getOwner(), event.getText());
}
});
eventBus.addHandler(EditCommentEvent.TYPE, new EditCommentEventHandler() {
@Override
public void onEditComment(EditCommentEvent event) {
resetTimer();
doEditComment(event.getOwner(), event.getCommentInstance());
}
});
eventBus.addHandler(SeeLikesEvent.TYPE, new SeeLikesEventHandler() {
@Override
public void onSeeLikes(SeeLikesEvent event) {
resetTimer();
doShowLikes(event.getFeedId());
}
});
eventBus.addHandler(SeeCommentsEvent.TYPE, new SeeCommentsEventHandler() {
@Override
public void onSeeComments(SeeCommentsEvent event) {
resetTimer();
doShowComments(event.getOwner(), event.isCommentForm2Add());
}
});
eventBus.addHandler(DeleteCommentEvent.TYPE, new DeleteCommentEventHandler() {
@Override
public void onDeleteComment(DeleteCommentEvent event) {
resetTimer();
doDeleteComment(event.getOwner(), event.getCommentId());
}
});
eventBus.addHandler(DeleteFeedEvent.TYPE, new DeleteFeedEventHandler() {
@Override
public void onDeleteFeed(DeleteFeedEvent event) {
resetTimer();
doDeleteFeed(event.getToDelete());
}
});
}
/**
*
*/
public NewsFeedPanel() {
bind();
mainPanel.add(filterPanel);
mainPanel.add(newsPanel);
filterPanel.add(new FilterPanel(this, newsService));
initWidget(mainPanel);
newsPanel.clear();
newsPanel.setWidth("100%");
newsPanel.setHeight("300px");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_CENTER);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
loadingImage = new Image(loading);
newsPanel.add(loadingImage);
newsService.getUserInfo(new AsyncCallback<UserInfo>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(UserInfo result) {
myUserInfo = result;
if (result.getUsername().equals("test.user")) {
Window.alert("Your session has expired, please log out and login again");
}
else {
showAllUpdatesFeeds();
currentFilter = FilterType.ALL_UPDATES;
}
}
});
feedsTimer = new Timer() {
@Override
public void run() {
refreshFeeds();
}
};
feedsTimer.scheduleRepeating(delayMillis);
}
private void resetTimer() {
feedsTimer.cancel();
feedsTimer.scheduleRepeating(delayMillis);
}
private void stopTimer() {
feedsTimer.cancel();
}
/**
*
*/
private void refreshFeeds() {
switch (currentFilter) {
case ALL_UPDATES:
showAllUpdatesFeeds();
break;
case CONNECTIONS:
showOnlyConnectionsFeeds();
break;
case MINE:
showOnlyMyFeeds();
break;
}
}
/**
* All Updates
*/
public void showAllUpdatesFeeds() {
showLoader();
resetTimer();
newsService.getAllUpdateUserFeeds(new AsyncCallback<ArrayList<EnhancedFeed>>() {
@Override
public void onSuccess(ArrayList<EnhancedFeed> feeds) {
newsPanel.clear();
if (feeds != null) {
if (feeds.size() == 0) {
newsPanel.add(new HTML("<div class=\"nofeed-message\">" +
"Looks like we've got nothing for you at the moment. <br> " +
"You may begin by <a class=\"vrelink\" href=\"/group/data-e-infrastructure-gateway/join-new/\"><span class=\"important\">joining</span></a> some of the available " +
"<br>Virtual Research Environments.</div>"));
isFirstTweet = true;
}
else {
newsPanel.setHeight("");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
for (EnhancedFeed feed : feeds)
newsPanel.add(new TweetTemplate(myUserInfo, feed, eventBus));
if (feeds.size() < 5) {
newsPanel.add(new Image(spacer));
}
isFirstTweet = false;
}
} else {
showProblems();
}
}
@Override
public void onFailure(Throwable caught) {
newsPanel.clear();
newsPanel.add(new HTML("<div class=\"nofeed-message\">" +
"Ops! There were problems while retrieving your feeds!. <br> " +
"Please try again in a short while.</div>"));
}
});
}
/**
* Only User Connections
*/
public void showOnlyConnectionsFeeds() {
showLoader();
resetTimer();
newsService.getOnlyConnectionsUserFeeds(new AsyncCallback<ArrayList<EnhancedFeed>>() {
@Override
public void onSuccess(ArrayList<EnhancedFeed> feeds) {
if (feeds != null) {
newsPanel.clear();
if (feeds.size() == 0) {
//TODO: provide actual link for Making some friends
newsPanel.add(new HTML("<div class=\"nofeed-message\">" +
"Looks like we've got nothing for you at the moment. <br> " +
"You may begin by <strong>adding</strong> some friend!</div>"));
isFirstTweet = true;
}
else {
newsPanel.setHeight("");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
for (EnhancedFeed feed : feeds)
newsPanel.add(new TweetTemplate(myUserInfo, feed, eventBus));
if (feeds.size() < 5) {
newsPanel.add(new Image(spacer));
}
isFirstTweet = false;
}
} else
showProblems();
}
@Override
public void onFailure(Throwable caught) {
loadingImage.setUrl(warning);
newsPanel.add(new HTML("Ops! There were problems while retrieving your feeds! Please try again in a short while"));
}
});
}
/**
* Only User Feeds
*/
public void showOnlyMyFeeds() {
showLoader();
resetTimer();
newsService.getOnlyMyUserFeeds(new AsyncCallback<ArrayList<EnhancedFeed>>() {
@Override
public void onSuccess(ArrayList<EnhancedFeed> feeds) {
if (feeds != null) {
newsPanel.clear();
if (feeds.size() == 0) {
newsPanel.add(new HTML("<div class=\"nofeed-message\">" +
"Looks like we've got nothing for you at the moment. <br> " +
"You may begin by <strong>sharing</strong> an update!</div>"));
isFirstTweet = true;
}
else {
newsPanel.setHeight("");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
for (EnhancedFeed feed : feeds)
newsPanel.add(new TweetTemplate(myUserInfo, feed, eventBus));
if (feeds.size() < 5) {
newsPanel.add(new Image(spacer));
}
isFirstTweet = false;
}
} else
showProblems();
}
@Override
public void onFailure(Throwable caught) {
loadingImage.setUrl(warning);
newsPanel.add(new HTML("Ops! There were problems while retrieving your feeds! Please try again in a short while"));
}
});
}
/**
* Only User Liked Feeds
*/
public void showOnlyLikedFeeds() {
showLoader();
resetTimer();
newsService.getOnlyLikedFeeds(new AsyncCallback<ArrayList<EnhancedFeed>>() {
@Override
public void onSuccess(ArrayList<EnhancedFeed> feeds) {
if (feeds != null) {
newsPanel.clear();
if (feeds.size() == 0) {
newsPanel.add(new HTML("<div class=\"nofeed-message\">" +
"Looks like we've got nothing for you at the moment. <br> " +
"Set an update as your <strong>favorite</strong> to see it here</div>"));
isFirstTweet = true;
}
else {
newsPanel.setHeight("");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
for (EnhancedFeed feed : feeds)
newsPanel.add(new TweetTemplate(myUserInfo, feed, eventBus));
if (feeds.size() < 5) {
newsPanel.add(new Image(spacer));
}
isFirstTweet = false;
}
} else
showProblems();
}
@Override
public void onFailure(Throwable caught) {
loadingImage.setUrl(warning);
newsPanel.add(new HTML("Ops! There were problems while retrieving your feeds! Please try again in a short while"));
}
});
}
/**
* used when addin directly a feed from the UI (IPC)
* @param userid
* @param fullName
* @param thumbURL
* @param description
*/
public void addJustAddedFeed(ClientFeed cFeed) {
Feed feed = new Feed(cFeed.getKey(), FeedType.SHARE, cFeed.getUserid(), null, "", cFeed.getUri(), cFeed.getLinkUrlThumbnail(),
cFeed.getDescription(), PrivacyLevel.CONNECTION, cFeed.getFullName(),
cFeed.getEmail(), cFeed.getThumbnailURL(), cFeed.getLinkTitle(), cFeed.getLinkDescription(), cFeed.getLinkHost());
EnhancedFeed toAdd = new EnhancedFeed(feed, false, true); //false cuz he could not have liked this yet and true because is the current user's
final TweetTemplate tt = new TweetTemplate(myUserInfo, toAdd, eventBus, true);
if (isFirstTweet) {
newsPanel.clear();
newsPanel.add(new Image(spacer));
isFirstTweet = false;
}
newsPanel.insert(tt, 0);
Timer t = new Timer() {
@Override
public void run() {
tt.setcontentAreaStyle("visible");
}
};
t.schedule(500);
}
private void showLoader() {
newsPanel.clear();
newsPanel.setWidth("100%");
newsPanel.setHeight("300px");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_CENTER);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
newsPanel.add(loadingImage);
}
private void showProblems() {
newsPanel.clear();
newsPanel.add(new HTML("<div class=\"nofeed-message\">" +
"Ops! There were problems while retrieving your feeds!. <br> " +
"Looks like we are not able to communicate with the infrastructure, <br> please try again in a short while.</div>"));
}
private void doAddLike(final TweetTemplate owner, final String feedId) {
newsService.like(feedId, owner.getMyFeedText(), owner.getMyFeedUserId(), new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {}
@Override
public void onSuccess(Boolean result) { }
});
}
private void doShowLikes(final String feedId) {
GWT.runAsync(new RunAsyncCallback() {
@Override
public void onSuccess() {
final LikesDialog dlg = new LikesDialog();
dlg.center();
dlg.show();
newsService.getAllLikesByFeed(feedId, new AsyncCallback<ArrayList<Like>>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("People who liked this could not be retrieved: " + caught.getMessage());
}
@Override
public void onSuccess(ArrayList<Like> result) {
dlg.showLikes(result);
}
});
}
public void onFailure(Throwable reason) {
Window.alert("Could not load this component: " + reason.getMessage());
}
});
}
private void doAddComment(final TweetTemplate owner, String text) {
newsService.comment(owner.getFeedKey(), text, owner.getMyFeedUserId(), new AsyncCallback<Comment>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Could not deliver this comment: " + caught.getMessage());
}
@Override
public void onSuccess(Comment result) {
if (result != null) {
owner.addComment(new SingleComment(result, owner, (result.getUserid().equals(myUserInfo.getUsername())) ));
owner.setCommentingDisabled(false);
owner.updateCommentsNumberCount();
}
else {
Window.alert("Could not deliver this comment. Please try again in a short while.");
}
}
});
}
private void doEditComment(final TweetTemplate owner, Comment edited) {
newsService.editComment(edited, new AsyncCallback<Comment>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Could not edit this comment: " + caught.getMessage());
}
@Override
public void onSuccess(Comment result) {
if (result != null) {
owner.addComment(new SingleComment(result, owner, (result.getUserid().equals(myUserInfo.getUsername())) ));
owner.setCommentingDisabled(false);
}
else {
Window.alert("Could not deliver this comment. Please try again in a short while.");
}
}
});
}
private void doShowComments(final TweetTemplate owner, final boolean commentForm2Add) {
owner.showLoadingComments();
newsService.getAllCommentsByFeed(owner.getFeedKey(), new AsyncCallback<ArrayList<Comment>>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Comments could not be retrieved: " + caught.getMessage());
}
@Override
public void onSuccess(ArrayList<Comment> comments) {
owner.clearComments();
for (Comment comment :comments)
owner.addComment(new SingleComment(comment, owner,(comment.getUserid().equals(myUserInfo.getUsername())) ));
owner.setCommentsFetched(true);
if (commentForm2Add)
owner.showAddCommentForm();
owner.updateCommentsNumberCount();
}
});
}
protected void doDeleteComment(final TweetTemplate owner, String commentId) {
newsService.deleteComment(commentId, owner.getFeedKey(), new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Comment could not be deleted: " + caught.getMessage());
}
@Override
public void onSuccess(Boolean result) {
if (result) {
doShowComments(owner, false);
owner.updateCommentsNumberCount();
} else
Window.alert("Comment could not be deleted, please try again in a short while.");
}
});
}
private void doDeleteFeed(final TweetTemplate toDelete) {
if (Window.confirm("Are you sure you want to delete this feed?")) {
newsService.deleteFeed(toDelete.getFeedKey(), new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Feed could not be deleted: " + caught.getMessage());
}
@Override
public void onSuccess(Boolean result) {
if (result) {
toDelete.removeFromParent();
} else
Window.alert("Feed could not be deleted, please try again in a short while.");
}
});
}
}
/**
* set the filter type status for automatic reloading of tweets
* @param currentFilter
*/
public void setCurrentFilter(FilterType currentFilter) {
this.currentFilter = currentFilter;
}
}