diff --git a/.gitignore b/.gitignore index 6eaffa3b..674bb1d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ -#log files +#runtime files commafeed.log derby.log -data +data/ +java_pid* # Maven build directory target diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java new file mode 100644 index 00000000..18fd4c90 --- /dev/null +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java @@ -0,0 +1,10 @@ +package com.commafeed.backend.dao; + +import javax.ejb.Stateless; + +import com.commafeed.model.FeedEntryStatus; + +@Stateless +public class FeedEntryStatusService extends GenericDAO { + +} diff --git a/src/main/java/com/commafeed/frontend/CommaFeedApplication.java b/src/main/java/com/commafeed/frontend/CommaFeedApplication.java index 708c7a05..0aa1c31e 100644 --- a/src/main/java/com/commafeed/frontend/CommaFeedApplication.java +++ b/src/main/java/com/commafeed/frontend/CommaFeedApplication.java @@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory; import com.commafeed.frontend.components.auth.LoginPage; import com.commafeed.frontend.components.auth.LogoutPage; import com.commafeed.frontend.pages.home.HomePage; +import com.commafeed.frontend.rest.FeedEntriesREST; import com.commafeed.frontend.rest.FeedSubscriptionsREST; import com.commafeed.frontend.utils.exception.DisplayExceptionPage; @@ -43,8 +44,11 @@ public class CommaFeedApplication extends AuthenticatedWebApplication { mountPage("login", LoginPage.class); mountPage("logout", LogoutPage.class); mountPage("error", DisplayExceptionPage.class); - + mountPage("subscriptions", FeedSubscriptionsREST.class); + mountPage(String.format("entries/${%s}/${%s}/${%s}", + FeedEntriesREST.PARAM_TYPE, FeedEntriesREST.PARAM_ID, + FeedEntriesREST.PARAM_READTYPE), FeedEntriesREST.class); setupInjection(); diff --git a/src/main/java/com/commafeed/frontend/pages/home/HomePage.html b/src/main/java/com/commafeed/frontend/pages/home/HomePage.html index 6dc9e3ea..09c380ac 100644 --- a/src/main/java/com/commafeed/frontend/pages/home/HomePage.html +++ b/src/main/java/com/commafeed/frontend/pages/home/HomePage.html @@ -16,6 +16,7 @@ + diff --git a/src/main/java/com/commafeed/frontend/rest/FeedEntriesREST.java b/src/main/java/com/commafeed/frontend/rest/FeedEntriesREST.java new file mode 100644 index 00000000..20cac017 --- /dev/null +++ b/src/main/java/com/commafeed/frontend/rest/FeedEntriesREST.java @@ -0,0 +1,85 @@ +package com.commafeed.frontend.rest; + +import java.text.DateFormat; +import java.util.List; + +import javax.inject.Inject; + +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import com.commafeed.backend.dao.FeedEntryService; +import com.commafeed.backend.dao.FeedEntryStatusService; +import com.commafeed.backend.dao.FeedSubscriptionService; +import com.commafeed.frontend.rest.model.Entries; +import com.commafeed.frontend.rest.model.Entry; +import com.commafeed.frontend.utils.ModelFactory.MF; +import com.commafeed.model.FeedEntry; +import com.commafeed.model.FeedEntryStatus; +import com.commafeed.model.FeedSubscription; +import com.google.common.collect.Iterables; + +public class FeedEntriesREST extends JSONPage { + + public static final String PARAM_TYPE = "type"; + public static final String PARAM_ID = "id"; + public static final String PARAM_READTYPE = "readtype"; + + @Inject + FeedEntryService feedEntryService; + + @Inject + FeedEntryStatusService feedEntryStatusService; + + @Inject + FeedSubscriptionService feedSubscriptionService; + + public FeedEntriesREST(PageParameters pageParameters) { + super(pageParameters); + } + + @Override + protected Object getObject(PageParameters parameters) { + + String type = parameters.get(PARAM_TYPE).toString(); + String id = parameters.get(PARAM_ID).toString(); + + @SuppressWarnings("unused") + String readType = parameters.get(PARAM_READTYPE).toString(); + + Entries entries = new Entries(); + if ("feed".equals(type)) { + FeedSubscription subscription = feedSubscriptionService + .findById(Long.valueOf(id)); + List feedEntries = feedEntryService.getUnreadEntries( + subscription.getFeed(), getUser()); + + entries.setName(subscription.getTitle()); + for (FeedEntry feedEntry : feedEntries) { + + List feedEntryStatus = feedEntryStatusService.findByField(MF.i(MF.p(FeedEntryStatus.class).getEntry()), feedEntry); + + Entry entry = buildEntry(feedEntry); + entry.setFeedName(subscription.getTitle()); + entry.setFeedId(String.valueOf(subscription.getId())); + entry.setRead(feedEntryStatus.isEmpty() ? false : Iterables.getFirst(feedEntryStatus, null).isRead()); + entry.setStarred(feedEntryStatus.isEmpty() ? false : Iterables.getFirst(feedEntryStatus, null).isStarred()); + entries.getEntries().add(entry); + } + } + + return entries; + } + + private Entry buildEntry(FeedEntry feedEntry) { + Entry entry = new Entry(); + entry.setId(feedEntry.getGuid()); + entry.setTitle(feedEntry.getTitle()); + entry.setContent(feedEntry.getContent()); + entry.setDate(DateFormat.getDateInstance(DateFormat.SHORT, getLocale()) + .format(feedEntry.getUpdated())); + entry.setUrl(feedEntry.getUrl()); + + return entry; + } + +} diff --git a/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java b/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java index 44f3077f..c6657ad6 100644 --- a/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java +++ b/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java @@ -5,15 +5,13 @@ import java.util.List; import javax.inject.Inject; import org.apache.commons.lang.ObjectUtils; +import org.apache.wicket.request.mapper.parameter.PageParameters; import com.commafeed.backend.dao.FeedCategoryService; import com.commafeed.backend.dao.FeedEntryService; import com.commafeed.backend.dao.FeedSubscriptionService; -import com.commafeed.frontend.CommaFeedSession; -import com.commafeed.frontend.pages.JSONPage; import com.commafeed.model.FeedCategory; import com.commafeed.model.FeedSubscription; -import com.commafeed.model.User; import com.google.common.collect.Lists; @SuppressWarnings("serial") @@ -28,19 +26,23 @@ public class FeedSubscriptionsREST extends JSONPage { @Inject FeedEntryService feedEntryService; + public FeedSubscriptionsREST(PageParameters pageParameters) { + super(pageParameters); + // TODO Auto-generated constructor stub + } + @Override - protected Object getObject() { - User user = CommaFeedSession.get().getUser(); - List categories = feedCategoryService.findAll(user); + protected Object getObject(PageParameters parameters) { + List categories = feedCategoryService.findAll(getUser()); Category root = new Category(); addChildren(categories, root); for (FeedSubscription subscription : feedSubscriptionService - .findWithoutCategories(user)) { + .findWithoutCategories(getUser())) { Subscription sub = new Subscription(); sub.setId(subscription.getId()); sub.setName(subscription.getTitle()); int size = feedEntryService.getUnreadEntries( - subscription.getFeed(), user).size(); + subscription.getFeed(), getUser()).size(); sub.setUnread(size); root.getFeeds().add(sub); } @@ -62,8 +64,7 @@ public class FeedSubscriptionsREST extends JSONPage { sub.setId(subscription.getId()); sub.setName(subscription.getTitle()); int size = feedEntryService.getUnreadEntries( - subscription.getFeed(), - CommaFeedSession.get().getUser()).size(); + subscription.getFeed(), getUser()).size(); sub.setUnread(size); child.getFeeds().add(sub); } diff --git a/src/main/java/com/commafeed/frontend/pages/JSONPage.java b/src/main/java/com/commafeed/frontend/rest/JSONPage.java similarity index 59% rename from src/main/java/com/commafeed/frontend/pages/JSONPage.java rename to src/main/java/com/commafeed/frontend/rest/JSONPage.java index 4db1ca22..7a29429a 100644 --- a/src/main/java/com/commafeed/frontend/pages/JSONPage.java +++ b/src/main/java/com/commafeed/frontend/rest/JSONPage.java @@ -1,24 +1,25 @@ -package com.commafeed.frontend.pages; +package com.commafeed.frontend.rest; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.request.handler.TextRequestHandler; import org.apache.wicket.request.mapper.parameter.PageParameters; +import com.commafeed.frontend.CommaFeedSession; +import com.commafeed.model.User; import com.google.gson.Gson; @SuppressWarnings("serial") public abstract class JSONPage extends WebPage { - public JSONPage() { - this(new PageParameters()); - } - public JSONPage(PageParameters pageParameters) { getRequestCycle().scheduleRequestHandlerAfterCurrent( new TextRequestHandler("application/json", "UTF-8", new Gson() - .toJson(getObject()))); + .toJson(getObject(pageParameters)))); } - protected abstract Object getObject(); + protected abstract Object getObject(PageParameters parameters); + protected User getUser() { + return CommaFeedSession.get().getUser(); + } } diff --git a/src/main/java/com/commafeed/frontend/rest/model/Entries.java b/src/main/java/com/commafeed/frontend/rest/model/Entries.java index 1e42f519..fa951a49 100644 --- a/src/main/java/com/commafeed/frontend/rest/model/Entries.java +++ b/src/main/java/com/commafeed/frontend/rest/model/Entries.java @@ -2,9 +2,11 @@ package com.commafeed.frontend.rest.model; import java.util.List; +import com.google.common.collect.Lists; + public class Entries { private String name; - private List entries; + private List entries = Lists.newArrayList(); public String getName() { return name; diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html deleted file mode 100644 index 6dc9e3ea..00000000 --- a/src/main/webapp/index.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - -
- -
- - - - - - - - - - - - - diff --git a/src/main/webapp/js/controllers.js b/src/main/webapp/js/controllers.js index 520f1a48..93d919e5 100644 --- a/src/main/webapp/js/controllers.js +++ b/src/main/webapp/js/controllers.js @@ -6,86 +6,92 @@ module.run(function($rootScope) { }); }); -module.controller('CategoryTreeCtrl', - function($scope, $routeParams, $location, CategoryService) { - - $scope.selectedType = $routeParams._type; - $scope.selectedId = $routeParams._id; - - $scope.root = CategoryService.get(); - - var unreadCount = function(category) { - var count = 0; - if (category.children) { - for ( var i = 0; i < category.children.length; i++) { - count = count + unreadCount(category.children[i]); - } - } - if (category.feeds) { - for ( var i = 0; i < category.feeds.length; i++) { - var feed = category.feeds[i]; - count = count + feed.unread; - } - } - return count; - } - - $scope.formatCategoryName = function(category) { - var count = unreadCount(category); - var label = category.name; - if (count > 0) { - label = label + " (" + count + ")"; - } - return label; - } - - $scope.formatFeedName = function(feed) { - var label = feed.name; - if (feed.unread > 0) { - label = label + " (" + feed.unread + ")"; - } - return label; - } - - $scope.feedClicked = function(id) { - $location.path('/feeds/view/feed/' + id); - }; - - $scope.categoryClicked = function(id) { - $location.path('/feeds/view/category/' + id); - }; - - var markAsRead = function(children, entry, read) { - for ( var i = 0; i < children.length; i++) { - var child = children[i]; - if (child.children) { - markAsRead(child.children, entry, read); - } - if (child.feeds) { - for ( var j = 0; j < child.feeds.length; j++) { - var feed = child.feeds[j]; - console.log(entry.feedId) - if (feed.id == entry.feedId) { - var c = read ? -1 : 1; - console.log(c) - feed.unread = feed.unread + c; - } - } - } - } - }; - - $scope.$on('markAsRead', function(event, args) { - markAsRead($scope.root.children, args.entry, args.read) - }); - }); - -module.controller('FeedListCtrl', function($scope, $routeParams, $http) { +module.controller('CategoryTreeCtrl', function($scope, $routeParams, $location, + CategoryService) { $scope.selectedType = $routeParams._type; $scope.selectedId = $routeParams._id; - $scope.entryList = { + $scope.root = CategoryService.get(); + + var unreadCount = function(category) { + var count = 0; + if (category.children) { + for ( var i = 0; i < category.children.length; i++) { + count = count + unreadCount(category.children[i]); + } + } + if (category.feeds) { + for ( var i = 0; i < category.feeds.length; i++) { + var feed = category.feeds[i]; + count = count + feed.unread; + } + } + return count; + } + + $scope.formatCategoryName = function(category) { + var count = unreadCount(category); + var label = category.name; + if (count > 0) { + label = label + " (" + count + ")"; + } + return label; + } + + $scope.formatFeedName = function(feed) { + var label = feed.name; + if (feed.unread > 0) { + label = label + " (" + feed.unread + ")"; + } + return label; + } + + $scope.feedClicked = function(id) { + $location.path('/feeds/view/feed/' + id); + }; + + $scope.categoryClicked = function(id) { + $location.path('/feeds/view/category/' + id); + }; + + var markAsRead = function(children, entry, read) { + for ( var i = 0; i < children.length; i++) { + var child = children[i]; + if (child.children) { + markAsRead(child.children, entry, read); + } + if (child.feeds) { + for ( var j = 0; j < child.feeds.length; j++) { + var feed = child.feeds[j]; + if (feed.id == entry.feedId) { + var c = read ? -1 : 1; + feed.unread = feed.unread + c; + } + } + } + } + }; + + $scope.$on('markAsRead', function(event, args) { + console.log(args.entry) + markAsRead($scope.root.children, args.entry, args.read) + }); +}); + +module.controller('FeedListCtrl', function($scope, $routeParams, $http, + EntryService) { + + $scope.selectedType = $routeParams._type; + $scope.selectedId = $routeParams._id; + + $scope.entryList = EntryService.getUnread({ + _type : $scope.selectedType, + _id : $scope.selectedId, + _readtype : 'unread' + }) + + $scope.entryList2 = { name : 'aaa', entries : [ { id : '1', diff --git a/src/main/webapp/js/main.js b/src/main/webapp/js/main.js index 8efd8849..9d20b8d0 100644 --- a/src/main/webapp/js/main.js +++ b/src/main/webapp/js/main.js @@ -1,6 +1,6 @@ var app = angular .module('commafeed', [ 'ui', 'ui.bootstrap', 'commafeed.directives', - 'commafeed.controllers', 'commafeed.services' ]); + 'commafeed.controllers', 'commafeed.services', 'ngSanitize' ]); app.config([ '$routeProvider', function($routeProvider) { $routeProvider.when('/feeds/view/:_type/:_id', { diff --git a/src/main/webapp/js/services.js b/src/main/webapp/js/services.js index 2d315378..ace95832 100644 --- a/src/main/webapp/js/services.js +++ b/src/main/webapp/js/services.js @@ -2,7 +2,6 @@ var module = angular.module('commafeed.services', [ 'ngResource' ]); module.factory('CategoryService', [ '$resource', '$http', function($resource, $http) { - var actions = { 'get' : { method : 'GET' @@ -10,4 +9,20 @@ module.factory('CategoryService', [ '$resource', '$http', } res = $resource('subscriptions', {}, actions); return res + } ]); + +module.factory('EntryService', [ '$resource', '$http', + function($resource, $http) { + var actions = { + 'getUnread' : { + method : 'GET', + params : { + _type : 'category', + _id : '1', + _readtype : 'unread', + } + } + } + res = $resource('entries/:_type/:_id/:_readtype', {}, actions); + return res } ]); \ No newline at end of file diff --git a/src/main/webapp/templates/feeds.html b/src/main/webapp/templates/feeds.html index 9d0a73fd..55783376 100644 --- a/src/main/webapp/templates/feeds.html +++ b/src/main/webapp/templates/feeds.html @@ -23,7 +23,7 @@
-
{{entry.content}}
+
diff --git a/src/main/webapp/vendor/angular/angular-sanitize.min.js b/src/main/webapp/vendor/angular/angular-sanitize.min.js new file mode 100644 index 00000000..212a90a9 --- /dev/null +++ b/src/main/webapp/vendor/angular/angular-sanitize.min.js @@ -0,0 +1,13 @@ +/* + AngularJS v1.0.5 + (c) 2010-2012 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(I,g){'use strict';function i(a){var d={},a=a.split(","),b;for(b=0;b=0;e--)if(f[e]==b)break;if(e>=0){for(c=f.length-1;c>=e;c--)d.end&&d.end(f[c]);f.length= +e}}var c,h,f=[],j=a;for(f.last=function(){return f[f.length-1]};a;){h=!0;if(!f.last()||!q[f.last()]){if(a.indexOf("<\!--")===0)c=a.indexOf("--\>"),c>=0&&(d.comment&&d.comment(a.substring(4,c)),a=a.substring(c+3),h=!1);else if(B.test(a)){if(c=a.match(r))a=a.substring(c[0].length),c[0].replace(r,e),h=!1}else if(C.test(a)&&(c=a.match(s)))a=a.substring(c[0].length),c[0].replace(s,b),h=!1;h&&(c=a.indexOf("<"),h=c<0?a:a.substring(0,c),a=c<0?"":a.substring(c),d.chars&&d.chars(k(h)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+ +f.last()+"[^>]*>","i"),function(b,a){a=a.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(a));return""}),e("",f.last());if(a==j)throw"Parse Error: "+a;j=a}e()}function k(a){l.innerHTML=a.replace(//g,">")}function u(a){var d=!1,b=g.bind(a,a.push);return{start:function(a,c,h){a=g.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]== +!0&&(b("<"),b(a),g.forEach(c,function(a,c){var e=g.lowercase(c);if(G[e]==!0&&(w[e]!==!0||a.match(H)))b(" "),b(c),b('="'),b(t(a)),b('"')}),b(h?"/>":">"))},end:function(a){a=g.lowercase(a);!d&&v[a]==!0&&(b(""));a==d&&(d=!1)},chars:function(a){d||b(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^/g, +E=//g,H=/^((ftp|https?):\/\/|mailto:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=g.extend({},y,x),m=g.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=g.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")), +q=i("script,style"),v=g.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=g.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");g.module("ngSanitize",[]).value("$sanitize",function(a){var d=[]; +z(a,u(d));return d.join("")});g.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,b,e){b.addClass("ng-binding").data("$binding",e.ngBindHtml);d.$watch(e.ngBindHtml,function(c){c=a(c);b.html(c||"")})}}]);g.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(b){if(!b)return b;for(var e=b,c=[],h=u(c),f,g;b=e.match(a);)f=b[0],b[2]==b[3]&&(f="mailto:"+f),g=b.index, +h.chars(e.substr(0,g)),h.start("a",{href:f}),h.chars(b[0].replace(d,"")),h.end("a"),e=e.substring(g+b[0].length);h.chars(e);return c.join("")}})})(window,window.angular);