diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryService.java b/src/main/java/com/commafeed/backend/dao/FeedEntryService.java index cdca7254..43f12e72 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedEntryService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryService.java @@ -2,12 +2,15 @@ package com.commafeed.backend.dao; import java.util.Calendar; import java.util.Collection; +import java.util.List; import javax.ejb.Stateless; import javax.inject.Inject; +import javax.persistence.TypedQuery; import com.commafeed.model.Feed; import com.commafeed.model.FeedEntry; +import com.commafeed.model.User; @Stateless public class FeedEntryService extends GenericDAO { @@ -28,4 +31,13 @@ public class FeedEntryService extends GenericDAO { em.merge(feed); } + public List getUnreadEntries(Feed feed, User user) { + String query = "select entry from FeedEntry entry where entry.feed = :feed and not in (select status.entry from FeedEntryStatus status where status.user = :user and status.read = true)"; + TypedQuery typedQuery = em.createQuery(query, + FeedEntry.class); + typedQuery.setParameter("feed", feed); + typedQuery.setParameter("user", user); + return typedQuery.getResultList(); + } + } diff --git a/src/main/java/com/commafeed/frontend/CommaFeedApplication.java b/src/main/java/com/commafeed/frontend/CommaFeedApplication.java index eb54580c..708c7a05 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.FeedSubscriptionsREST; import com.commafeed.frontend.utils.exception.DisplayExceptionPage; public class CommaFeedApplication extends AuthenticatedWebApplication { @@ -42,6 +43,8 @@ public class CommaFeedApplication extends AuthenticatedWebApplication { mountPage("login", LoginPage.class); mountPage("logout", LogoutPage.class); mountPage("error", DisplayExceptionPage.class); + + mountPage("subscriptions", FeedSubscriptionsREST.class); setupInjection(); diff --git a/src/main/java/com/commafeed/frontend/components/auth/LogoutPage.java b/src/main/java/com/commafeed/frontend/components/auth/LogoutPage.java index 5299a6e2..bab41534 100644 --- a/src/main/java/com/commafeed/frontend/components/auth/LogoutPage.java +++ b/src/main/java/com/commafeed/frontend/components/auth/LogoutPage.java @@ -2,6 +2,7 @@ package com.commafeed.frontend.components.auth; import org.apache.wicket.markup.html.WebPage; +@SuppressWarnings("serial") public class LogoutPage extends WebPage { public LogoutPage() { getSession().invalidate(); 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 5c2e440f..6dc9e3ea 100644 --- a/src/main/java/com/commafeed/frontend/pages/home/HomePage.html +++ b/src/main/java/com/commafeed/frontend/pages/home/HomePage.html @@ -15,10 +15,12 @@ + + diff --git a/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java b/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java index 2216e79f..489ffe43 100644 --- a/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java +++ b/src/main/java/com/commafeed/frontend/rest/FeedSubscriptionsREST.java @@ -7,6 +7,7 @@ import javax.inject.Inject; import org.apache.commons.lang.ObjectUtils; 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; @@ -25,12 +26,14 @@ public class FeedSubscriptionsREST extends JSONPage { @Inject FeedCategoryService FeedCategoryService; + @Inject + FeedEntryService feedEntryService; + + User user = CommaFeedSession.get().getUser(); + @Override protected Object getObject() { - - User user = CommaFeedSession.get().getUser(); List categories = FeedCategoryService.findAll(user); - Category root = new Category(); addChildren(categories, root); for (FeedSubscription subscription : feedSubscriptionService @@ -39,7 +42,10 @@ public class FeedSubscriptionsREST extends JSONPage { Subscription sub = new Subscription(); sub.setId(subscription.getId()); sub.setName(subscription.getTitle()); - sub.setUnread(77); + int size = feedEntryService.getUnreadEntries( + subscription.getFeed(), user).size(); + sub.setUnread(size); + root.getFeeds().add(sub); } return root; } @@ -58,7 +64,10 @@ public class FeedSubscriptionsREST extends JSONPage { Subscription sub = new Subscription(); sub.setId(subscription.getId()); sub.setName(subscription.getTitle()); - sub.setUnread(77); + int size = feedEntryService.getUnreadEntries( + subscription.getFeed(), user).size(); + sub.setUnread(size); + child.getFeeds().add(sub); } current.getChildren().add(child); } diff --git a/src/main/java/com/commafeed/frontend/rest/model/Category.java b/src/main/java/com/commafeed/frontend/rest/model/Category.java new file mode 100644 index 00000000..e7016c27 --- /dev/null +++ b/src/main/java/com/commafeed/frontend/rest/model/Category.java @@ -0,0 +1,46 @@ +package com.commafeed.frontend.rest.model; + +import java.util.List; + +import com.commafeed.frontend.rest.FeedSubscriptionsREST.Subscription; +import com.google.common.collect.Lists; + +public class Category { + private Long id; + private String name; + private List children = Lists.newArrayList(); + private List feeds = Lists.newArrayList(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public List getFeeds() { + return feeds; + } + + public void setFeeds(List feeds) { + this.feeds = feeds; + } + +} \ No newline at end of file diff --git a/src/main/java/com/commafeed/frontend/rest/model/Entries.java b/src/main/java/com/commafeed/frontend/rest/model/Entries.java new file mode 100644 index 00000000..1e42f519 --- /dev/null +++ b/src/main/java/com/commafeed/frontend/rest/model/Entries.java @@ -0,0 +1,25 @@ +package com.commafeed.frontend.rest.model; + +import java.util.List; + +public class Entries { + private String name; + private List entries; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getEntries() { + return entries; + } + + public void setEntries(List entries) { + this.entries = entries; + } + +} diff --git a/src/main/java/com/commafeed/frontend/rest/model/Entry.java b/src/main/java/com/commafeed/frontend/rest/model/Entry.java new file mode 100644 index 00000000..338cfd01 --- /dev/null +++ b/src/main/java/com/commafeed/frontend/rest/model/Entry.java @@ -0,0 +1,86 @@ +package com.commafeed.frontend.rest.model; + +public class Entry { + private String id; + private String title; + private String content; + private String date; + private String feedId; + private String feedName; + private String url; + private boolean read; + private boolean starred; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getFeedName() { + return feedName; + } + + public void setFeedName(String feedName) { + this.feedName = feedName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public boolean isRead() { + return read; + } + + public void setRead(boolean read) { + this.read = read; + } + + public boolean isStarred() { + return starred; + } + + public void setStarred(boolean starred) { + this.starred = starred; + } + +} diff --git a/src/main/java/com/commafeed/frontend/rest/model/Subscription.java b/src/main/java/com/commafeed/frontend/rest/model/Subscription.java new file mode 100644 index 00000000..bf97b6fc --- /dev/null +++ b/src/main/java/com/commafeed/frontend/rest/model/Subscription.java @@ -0,0 +1,32 @@ +package com.commafeed.frontend.rest.model; + +public class Subscription { + private Long id; + private String name; + private int unread; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getUnread() { + return unread; + } + + public void setUnread(int unread) { + this.unread = unread; + } + +} \ No newline at end of file diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 2bccfd40..5ee4bd37 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -10,7 +10,6 @@ - diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index 5c2e440f..6dc9e3ea 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -15,10 +15,12 @@ + + diff --git a/src/main/webapp/js/controllers.js b/src/main/webapp/js/controllers.js index ac68afc8..f1fcf39e 100644 --- a/src/main/webapp/js/controllers.js +++ b/src/main/webapp/js/controllers.js @@ -1,10 +1,18 @@ var module = angular.module('commafeed.controllers', []); +module.run(function($rootScope) { + $rootScope.$on('emitMarkAsRead', function(event, args) { + $rootScope.$broadcast('markAsRead', args); + }); +}); + module.controller('CategoryTreeCtrl', - function($scope, $routeParams, $location) { + function($scope, $routeParams, $location, CategoryService) { $scope.selectedType = $routeParams._type; $scope.selectedId = $routeParams._id; + + $scope.root2 = CategoryService.get(); $scope.root = { children : [ { @@ -75,31 +83,70 @@ module.controller('CategoryTreeCtrl', $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) { - $scope.entries = [ { - id : '1', - title : 'my title', - content : 'my content', - date : 'my date', - feed : 'my feed', - url : 'my url', - read : false, - starred : false, - }, { - id : '1', - title : 'my title', - content : 'my content', - date : 'my date', - feed : 'my feed', - url : 'my url', - read : false, - starred : false, - } ]; + $scope.selectedType = $routeParams._type; + $scope.selectedId = $routeParams._id; + + $scope.entryList = { + name : 'aaa', + entries : [ { + id : '1', + title : 'my title', + content : 'my content', + date : 'my date', + feedId : '1', + feedName : 'my feed', + url : 'my url', + read : false, + starred : false, + }, { + id : '2', + title : 'my other title', + content : 'my other content', + date : 'my other date', + feedId : '2', + feedName : 'my other feed', + url : 'my other url', + read : false, + starred : false, + } ] + }; $scope.markAsRead = function(entry) { + var read = entry.read; entry.read = true; + if (entry.read != read) { + $scope.$emit('emitMarkAsRead', { + entry : entry, + read : true + }); + } }; }); diff --git a/src/main/webapp/js/main.js b/src/main/webapp/js/main.js index 72ac241d..8efd8849 100644 --- a/src/main/webapp/js/main.js +++ b/src/main/webapp/js/main.js @@ -1,4 +1,6 @@ -var app = angular.module('commafeed', [ 'ui', 'ui.bootstrap', 'commafeed.directives', 'commafeed.controllers' ]); +var app = angular + .module('commafeed', [ 'ui', 'ui.bootstrap', 'commafeed.directives', + 'commafeed.controllers', 'commafeed.services' ]); 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 new file mode 100644 index 00000000..2d315378 --- /dev/null +++ b/src/main/webapp/js/services.js @@ -0,0 +1,13 @@ +var module = angular.module('commafeed.services', [ 'ngResource' ]); + +module.factory('CategoryService', [ '$resource', '$http', + function($resource, $http) { + + var actions = { + 'get' : { + method : 'GET' + } + } + res = $resource('subscriptions', {}, 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 c9186dff..9d0a73fd 100644 --- a/src/main/webapp/templates/feeds.html +++ b/src/main/webapp/templates/feeds.html @@ -13,12 +13,13 @@
+ {{entryList.name}}»
-
+
diff --git a/src/main/webapp/vendor/angular/angular-resource.min.js b/src/main/webapp/vendor/angular/angular-resource.min.js new file mode 100644 index 00000000..f37559c7 --- /dev/null +++ b/src/main/webapp/vendor/angular/angular-resource.min.js @@ -0,0 +1,10 @@ +/* + AngularJS v1.0.5 + (c) 2010-2012 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(C,d,w){'use strict';d.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function s(b,e){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(e?null:/%20/g,"+")}function t(b,e){this.template=b+="#";this.defaults=e||{};var a=this.urlParams={};h(b.split(/\W/),function(f){f&&RegExp("(^|[^\\\\]):"+f+"\\W").test(b)&&(a[f]=!0)});this.template=b.replace(/\\:/g,":")}function u(b,e,a){function f(m,a){var b= +{},a=o({},e,a);h(a,function(a,z){var c;a.charAt&&a.charAt(0)=="@"?(c=a.substr(1),c=y(c)(m)):c=a;b[z]=c});return b}function g(a){v(a||{},this)}var k=new t(b),a=o({},A,a);h(a,function(a,b){a.method=d.uppercase(a.method);var e=a.method=="POST"||a.method=="PUT"||a.method=="PATCH";g[b]=function(b,c,d,B){var j={},i,l=p,q=null;switch(arguments.length){case 4:q=B,l=d;case 3:case 2:if(r(c)){if(r(b)){l=b;q=c;break}l=c;q=d}else{j=b;i=c;l=d;break}case 1:r(b)?l=b:e?i=b:j=b;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+ +arguments.length+" arguments.";}var n=this instanceof g?this:a.isArray?[]:new g(i);x({method:a.method,url:k.url(o({},f(i,a.params||{}),j)),data:i}).then(function(b){var c=b.data;if(c)a.isArray?(n.length=0,h(c,function(a){n.push(new g(a))})):v(c,n);(l||p)(n,b.headers)},q);return n};g.prototype["$"+b]=function(a,d,h){var m=f(this),j=p,i;switch(arguments.length){case 3:m=a;j=d;i=h;break;case 2:case 1:r(a)?(j=a,i=d):(m=a,j=d||p);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+ +arguments.length+" arguments.";}g[b].call(this,m,e?this:w,j,i)}});g.bind=function(d){return u(b,o({},e,d),a)};return g}var A={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},p=d.noop,h=d.forEach,o=d.extend,v=d.copy,r=d.isFunction;t.prototype={url:function(b){var e=this,a=this.template,f,g,b=b||{};h(this.urlParams,function(h,c){f=b.hasOwnProperty(c)?b[c]:e.defaults[c];d.isDefined(f)&&f!==null?(g=s(f,!0).replace(/%26/gi,"&").replace(/%3D/gi, +"=").replace(/%2B/gi,"+"),a=a.replace(RegExp(":"+c+"(\\W)","g"),g+"$1")):a=a.replace(RegExp("(/?):"+c+"(\\W)","g"),function(a,b,c){return c.charAt(0)=="/"?c:b+c})});var a=a.replace(/\/?#$/,""),k=[];h(b,function(a,b){e.urlParams[b]||k.push(s(b)+"="+s(a))});k.sort();a=a.replace(/\/*$/,"");return a+(k.length?"?"+k.join("&"):"")}};return u}])})(window,window.angular);