smart refresh partially implemented

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/news-feed@72970 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Massimiliano Assante 2013-04-05 14:16:07 +00:00
parent ae51ecbc94
commit b496c36a5a
5 changed files with 213 additions and 66 deletions

View File

@ -1,6 +1,7 @@
package org.gcube.portlets.user.newsfeed.client.panels; package org.gcube.portlets.user.newsfeed.client.panels;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import org.gcube.portal.databook.shared.ClientFeed; import org.gcube.portal.databook.shared.ClientFeed;
import org.gcube.portal.databook.shared.Comment; import org.gcube.portal.databook.shared.Comment;
@ -30,6 +31,7 @@ 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.event.StopTimerEventHandler;
import org.gcube.portlets.user.newsfeed.client.panels.dialog.LikesDialog; 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.FilterPanel;
import org.gcube.portlets.user.newsfeed.client.templates.NewFeedsAvailable;
import org.gcube.portlets.user.newsfeed.client.templates.SingleComment; import org.gcube.portlets.user.newsfeed.client.templates.SingleComment;
import org.gcube.portlets.user.newsfeed.client.templates.TweetTemplate; import org.gcube.portlets.user.newsfeed.client.templates.TweetTemplate;
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed; import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
@ -47,6 +49,7 @@ import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.VerticalPanel;
/** /**
* *
@ -63,6 +66,7 @@ public class NewsFeedPanel extends Composite {
private VerticalPanel mainPanel = new VerticalPanel(); private VerticalPanel mainPanel = new VerticalPanel();
private HorizontalPanel filterPanel = new HorizontalPanel(); private HorizontalPanel filterPanel = new HorizontalPanel();
private SimplePanel newUpdatesPanel = new SimplePanel();
private VerticalPanel newsPanel = new VerticalPanel(); private VerticalPanel newsPanel = new VerticalPanel();
private static final String warning = GWT.getModuleBaseURL() + "../images/warning_blue.png"; private static final String warning = GWT.getModuleBaseURL() + "../images/warning_blue.png";
@ -74,7 +78,9 @@ public class NewsFeedPanel extends Composite {
public static final String COMMENT_LABEL = "Reply"; public static final String COMMENT_LABEL = "Reply";
public static final String MESSAGE_LABEL = "Message"; public static final String MESSAGE_LABEL = "Message";
private int delayMillis = 300000; //5 minutes by default private int delayMillis = 300000; //5 minutes by default (is read from a configuration file in the first async callback)
private int currNewUpdatesNo = 0;
private boolean isFirstTweet = false; private boolean isFirstTweet = false;
@ -82,6 +88,11 @@ public class NewsFeedPanel extends Composite {
private UserInfo myUserInfo; private UserInfo myUserInfo;
private FilterType currentFilter; private FilterType currentFilter;
private Timer feedsTimer; private Timer feedsTimer;
private ArrayList<EnhancedFeed> allUpdates = new ArrayList<EnhancedFeed>();
private ArrayList<EnhancedFeed> tempCacheNewUpdates = new ArrayList<EnhancedFeed>();
/** /**
* events binder * events binder
*/ */
@ -164,6 +175,7 @@ public class NewsFeedPanel extends Composite {
public NewsFeedPanel() { public NewsFeedPanel() {
bind(); bind();
mainPanel.add(filterPanel); mainPanel.add(filterPanel);
mainPanel.add(newUpdatesPanel);
mainPanel.add(newsPanel); mainPanel.add(newsPanel);
filterPanel.add(new FilterPanel(this, newsService)); filterPanel.add(new FilterPanel(this, newsService));
@ -198,7 +210,7 @@ public class NewsFeedPanel extends Composite {
feedsTimer = new Timer() { feedsTimer = new Timer() {
@Override @Override
public void run() { public void run() {
refreshFeeds(); checkForNewUpdates();
} }
}; };
feedsTimer.scheduleRepeating(delayMillis); feedsTimer.scheduleRepeating(delayMillis);
@ -214,10 +226,10 @@ public class NewsFeedPanel extends Composite {
/** /**
* *
*/ */
private void refreshFeeds() { private void checkForNewUpdates() {
switch (currentFilter) { switch (currentFilter) {
case ALL_UPDATES: case ALL_UPDATES:
showAllUpdatesFeeds(); checkAllUpdatesFeeds();
break; break;
case CONNECTIONS: case CONNECTIONS:
showOnlyConnectionsFeeds(); showOnlyConnectionsFeeds();
@ -227,6 +239,43 @@ public class NewsFeedPanel extends Composite {
break; break;
} }
} }
//TODO: finish this
private void checkAllUpdatesFeeds() {
newsService.getAllUpdateUserFeeds(new AsyncCallback<ArrayList<EnhancedFeed>>() {
@Override
public void onSuccess(ArrayList<EnhancedFeed> feeds) {
if (feeds != null && allUpdates.size() > 0) {
Date myLastUpdateTime = allUpdates.get(0).getFeed().getTime(); //this is the last update in the View
tempCacheNewUpdates = new ArrayList<EnhancedFeed>(); //need to reset it everytime i check (in case someone deleted the updated in the meanwhile)
//check if there are new updates (enter the while) and put them in a temporary cache for displaying on user click
int i = 0;
while (i < feeds.size() && feeds.get(i).getFeed().getTime().after(myLastUpdateTime)) {
tempCacheNewUpdates.add(feeds.get(i));
i++;
}
/* currNewUpdatesNo keeps the number of updates to be added on user clicks,
* i keeps the total number as it arrives,
* if they differ you got to refresh the updates to show the new number
*/
if (currNewUpdatesNo < i) {
newUpdatesPanel.clear(); //remove the current show update button if present
newUpdatesPanel.add(new NewFeedsAvailable(i));
currNewUpdatesNo = i;
}
}
}
@Override
public void onFailure(Throwable caught) {}
});
}
/** /**
* All Updates * All Updates
*/ */
@ -249,8 +298,10 @@ public class NewsFeedPanel extends Composite {
newsPanel.setHeight(""); newsPanel.setHeight("");
newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT); newsPanel.setHorizontalAlignment(HasAlignment.ALIGN_LEFT);
newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP); newsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
for (EnhancedFeed feed : feeds) for (EnhancedFeed feed : feeds) {
newsPanel.add(new TweetTemplate(myUserInfo, feed, eventBus)); newsPanel.add(new TweetTemplate(myUserInfo, feed, eventBus));
allUpdates.add(feed);
}
if (feeds.size() < 5) { if (feeds.size() < 5) {
newsPanel.add(new Image(spacer)); newsPanel.add(new Image(spacer));
} }

View File

@ -0,0 +1,36 @@
package org.gcube.portlets.user.newsfeed.client.templates;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Timer;
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 NewFeedsAvailable extends Composite {
private static NewFeedsAvailableUiBinder uiBinder = GWT
.create(NewFeedsAvailableUiBinder.class);
interface NewFeedsAvailableUiBinder extends
UiBinder<Widget, NewFeedsAvailable> {
}
@UiField HTML caption;
public NewFeedsAvailable(int newUpdatesNo) {
initWidget(uiBinder.createAndBindUi(this));
if (newUpdatesNo > 0) {
caption.setHTML(newUpdatesNo > 1 ? "See " + newUpdatesNo + " new Updates" : "See 1 new Update");
//create the fade transition effect
Timer t = new Timer() {
@Override
public void run() {
caption.addStyleName("new-feeds-show");
}
};
t.schedule(100);
}
else throw new IllegalArgumentException("newUpdatesNo must be greater than 0");
}
}

View File

@ -0,0 +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">
<g:HTMLPanel styleName="new-feeds-container">
<g:HTML ui:field="caption" styleName="new-feeds-available" />
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -62,6 +62,11 @@ 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 DatabookStore store; private DatabookStore store;
private boolean withinPortal = false; private boolean withinPortal = false;
@ -238,28 +243,28 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
ArrayList<Feed> toMerge = new ArrayList<Feed>(); ArrayList<Feed> toMerge = new ArrayList<Feed>();
HashMap<String, Feed> feedsMap = new HashMap<String, Feed>(); HashMap<String, Feed> feedsMap = new HashMap<String, Feed>();
ArrayList<Feed> OrganizationFeeds = (ArrayList<Feed>) store.getRecentFeedsByVRE("/gcube/devsec/devVRE", 10); ArrayList<Feed> OrganizationFeeds = (ArrayList<Feed>) store.getRecentFeedsByVRE("/gcube/devsec/devVRE", 5);
for (Feed feed : OrganizationFeeds) { for (Feed feed : OrganizationFeeds) {
feedsMap.put(feed.getKey(), feed); feedsMap.put(feed.getKey(), feed);
} }
if (! onlyConnections) { // if (! onlyConnections) {
//User Own Feeds // //User Own Feeds
ArrayList<Feed> userFeeds = (ArrayList<Feed>) store.getRecentFeedsByUser(userName, 10); // ArrayList<Feed> userFeeds = (ArrayList<Feed>) store.getRecentFeedsByUser(userName, 10);
for (Feed feed : userFeeds) // for (Feed feed : userFeeds)
feedsMap.put(feed.getKey(), feed); // feedsMap.put(feed.getKey(), feed);
// //Portal Feeds // // //Portal Feeds
ArrayList<Feed> portalFeeds = (ArrayList<Feed>) store.getAllPortalPrivacyLevelFeeds(); // ArrayList<Feed> portalFeeds = (ArrayList<Feed>) store.getAllPortalPrivacyLevelFeeds();
for (Feed feed : portalFeeds) // for (Feed feed : portalFeeds)
feedsMap.put(feed.getKey(), feed); // feedsMap.put(feed.getKey(), feed);
} // }
//UserFriends Feeds // //UserFriends Feeds
ArrayList<String> userFriendsIds = (ArrayList<String>)store.getFriends(userName); // ArrayList<String> userFriendsIds = (ArrayList<String>)store.getFriends(userName);
for (String userid : userFriendsIds) { // for (String userid : userFriendsIds) {
for (Feed feed : store.getRecentFeedsByUser(userid, 10)) { // for (Feed feed : store.getRecentFeedsByUser(userid, 10)) {
feedsMap.put(feed.getKey(), feed); // feedsMap.put(feed.getKey(), feed);
} // }
} // }
for (String key: feedsMap.keySet()) { for (String key: feedsMap.keySet()) {
toMerge.add(feedsMap.get(key)); toMerge.add(feedsMap.get(key));
} }
@ -451,8 +456,8 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
@Override @Override
public UserSettings getUserSettings() { public UserSettings getUserSettings() {
if (getUserFromSession() != null) if (getUserSettingsFromSession() != null)
return getUserFromSession(); return getUserSettingsFromSession();
try { try {
String username = getASLSession().getUsername(); String username = getASLSession().getUsername();
String email = username+"@isti.cnr.it"; String email = username+"@isti.cnr.it";
@ -469,7 +474,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
UserInfo userInfo = new UserInfo(username, fullName, thumbnailURL, user.getEmailAddress(), accountURL, true, false, null); UserInfo userInfo = new UserInfo(username, fullName, thumbnailURL, user.getEmailAddress(), accountURL, true, false, null);
UserSettings toReturn = new UserSettings(userInfo, getFeedsRefreshTimeInMillis()); UserSettings toReturn = new UserSettings(userInfo, getFeedsRefreshTimeInMillis());
setUserInSession(toReturn); setUserSettingsInSession(toReturn);
return toReturn; return toReturn;
} }
else { else {
@ -525,12 +530,12 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
} }
} }
private UserSettings getUserFromSession() { private UserSettings getUserSettingsFromSession() {
return (UserSettings) getASLSession().getAttribute(UserInfo.USER_INFO_ATTR); return (UserSettings) getASLSession().getAttribute(USER_SETTINGS_ATTR);
} }
private void setUserInSession(UserSettings user) { private void setUserSettingsInSession(UserSettings user) {
getASLSession().setAttribute(UserInfo.USER_INFO_ATTR, user); getASLSession().setAttribute(USER_SETTINGS_ATTR, user);
} }
/** /**
* tell if a feed is belonging to the current user or not * tell if a feed is belonging to the current user or not
@ -631,31 +636,34 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
* @return the refreshingTime in milliseconds * @return the refreshingTime in milliseconds
*/ */
private int getFeedsRefreshTimeInMillis() { private int getFeedsRefreshTimeInMillis() {
Properties props = new Properties(); return 15000;
int toReturn = 0; //TODO:
int minutes = 0; // Properties props = new Properties();
try { // int toReturn = 0;
String propertyfile = this.getThreadLocalRequest().getServletPath()+"conf/settings.properties"; // int minutes = 0;
File propsFile = new File(propertyfile); // String propertyfile = "";
FileInputStream fis = new FileInputStream(propsFile); // try {
props.load( fis); // propertyfile = this.getThreadLocalRequest().getContextPath()+"conf/settings.properties";
// File propsFile = new File(propertyfile);
minutes = Integer.parseInt(props.getProperty("REFRESH_TIME")); // FileInputStream fis = new FileInputStream(propsFile);
toReturn = minutes*60*1000; // props.load( fis);
} //
//catch exception in case properties file does not exist // minutes = Integer.parseInt(props.getProperty("REFRESH_TIME"));
catch(IOException e) { // toReturn = minutes*60*1000;
toReturn = 300000; //5 minutes // }
_log.error("settings.properties file not found under conf dir, returning 5 minutes"); // //catch exception in case properties file does not exist
return toReturn; // catch(IOException e) {
} // toReturn = 300000; //5 minutes
//catch exception in case the property value isNot a Number // _log.error("settings.properties file not found under " + propertyfile +", returning 5 minutes");
catch (ClassCastException ex) { // return toReturn;
toReturn = 300000; //5 minutes // }
_log.error("REFRESH_TIME must be a number (in minutes) returning 5 minutes"); // //catch exception in case the property value isNot a Number
return toReturn; // catch (ClassCastException ex) {
} // toReturn = 300000; //5 minutes
_log.debug("Returning REFRESH_TIME in millis: " + toReturn + " minutes: " + minutes); // _log.error("REFRESH_TIME must be a number (in minutes) returning 5 minutes");
return toReturn; // return toReturn;
// }
// _log.debug("Returning REFRESH_TIME in millis: " + toReturn + ", (" + minutes + " minutes)");
// return toReturn;
} }
} }

View File

@ -1,11 +1,56 @@
@import url(http://fonts.googleapis.com/css?family=Architects+Daughter); @import url(http://fonts.googleapis.com/css?family=Architects+Daughter);
/* FILTER Widget*/
table { table {
border-collapse: separate !important; border-collapse: separate !important;
border-spacing: 0; border-spacing: 0;
} }
.new-feeds-container {
position: relative;
}
.new-feeds-available {
color: #444;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
text-align: center;
font-size: 13px;
width: 576px;
margin: 0px 25px 0px 8px;
padding: 3px;
border: 1px solid #75AAD0;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
height: 0px;
opacity: 0;
transition-property: opacity, height;
transition-duration: .40s;
transition-timing-function: ease-out;
-moz-transition-property: opacity, height;
-moz-transition-duration: .40s;
-moz-transition-timing-function: ease-out;
-webkit-transition-property: opacity, height;
-webkit-transition-duration: .40s;
-webkit-transition-timing-function: ease-out;
-ms-transition-property: opacity, height;
-ms-transition-duration: .40s;
-ms-transition-timing-function: ease-out;
}
.new-feeds-show {
opacity: 1;
background: #D6E2FC;
height: 18px;
}
.new-feeds-available:hover {
background: #EDEFF4;
cursor: pointer;
cursor: hand;
text-decoration: underline;
}
.nofeed-message { .nofeed-message {
line-height: 40px; line-height: 40px;
font-family: 'Architects Daughter', arial, sans-serif; font-family: 'Architects Daughter', arial, sans-serif;