diff --git a/pom.xml b/pom.xml
index 4526eb30..2c195490 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,12 +10,14 @@
UTF-8
+ jdbc/commafeedDS
src/main/resources
+ true
src/main/java
@@ -195,11 +197,24 @@
wicket-webjars
0.2.0
+
+ org.webjars
+ angularjs
+ 1.0.5
+
+
+ com.google.code.gson
+ gson
+ 2.2.2
+
openshift
+
+ java:/jdbc/commafeedDS
+
commafeed
diff --git a/src/main/java/com/commafeed/backend/StartupBean.java b/src/main/java/com/commafeed/backend/StartupBean.java
index e17ef44b..8f1b183b 100644
--- a/src/main/java/com/commafeed/backend/StartupBean.java
+++ b/src/main/java/com/commafeed/backend/StartupBean.java
@@ -5,6 +5,9 @@ import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.commafeed.backend.dao.FeedCategoryService;
import com.commafeed.backend.dao.FeedService;
import com.commafeed.backend.dao.FeedSubscriptionService;
@@ -19,6 +22,8 @@ import com.commafeed.model.User;
@Singleton
public class StartupBean {
+ private static Logger log = LoggerFactory.getLogger(StartupBean.class);
+
@Inject
FeedService feedService;
@@ -38,6 +43,7 @@ public class StartupBean {
private void init() {
if (userService.getCount() == 0) {
+ log.info("Populating database with default values");
User user = new User();
byte[] salt = encryptionService.generateSalt();
user.setName("admin");
diff --git a/src/main/java/com/commafeed/frontend/CommaFeedApplication.java b/src/main/java/com/commafeed/frontend/CommaFeedApplication.java
index e2c17021..f6c2e551 100644
--- a/src/main/java/com/commafeed/frontend/CommaFeedApplication.java
+++ b/src/main/java/com/commafeed/frontend/CommaFeedApplication.java
@@ -28,7 +28,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.commafeed.frontend.components.auth.LoginPage;
-import com.commafeed.frontend.pages.feed.FeedViewPage;
+import com.commafeed.frontend.pages.feed.FeedSubscriptionsPage;
+import com.commafeed.frontend.pages.home.HomePage;
import com.commafeed.frontend.utils.exception.DisplayExceptionPage;
import de.agilecoders.wicket.Bootstrap;
@@ -44,7 +45,7 @@ public class CommaFeedApplication extends AuthenticatedWebApplication {
super.init();
mountPage("login", LoginPage.class);
- mountPage("feeds", FeedViewPage.class);
+ mountPage("/subscriptions/all", FeedSubscriptionsPage.class);
setupInjection();
@@ -84,7 +85,7 @@ public class CommaFeedApplication extends AuthenticatedWebApplication {
@Override
public Class extends Page> getHomePage() {
- return FeedViewPage.class;
+ return HomePage.class;
}
protected void setupInjection() {
diff --git a/src/main/java/com/commafeed/frontend/pages/JSONPage.java b/src/main/java/com/commafeed/frontend/pages/JSONPage.java
new file mode 100644
index 00000000..7cd1400c
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/pages/JSONPage.java
@@ -0,0 +1,27 @@
+package com.commafeed.frontend.pages;
+
+import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+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.components.auth.Role;
+import com.google.gson.Gson;
+
+@SuppressWarnings("serial")
+@AuthorizeInstantiation(Role.USER)
+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())));
+ }
+
+ protected abstract Object getObject();
+
+}
diff --git a/src/main/java/com/commafeed/frontend/pages/feed/FeedSubscriptionsPage.java b/src/main/java/com/commafeed/frontend/pages/feed/FeedSubscriptionsPage.java
new file mode 100644
index 00000000..b7b2914f
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/pages/feed/FeedSubscriptionsPage.java
@@ -0,0 +1,139 @@
+package com.commafeed.frontend.pages.feed;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.commons.lang.ObjectUtils;
+
+import com.commafeed.backend.dao.FeedCategoryService;
+import com.commafeed.backend.dao.FeedSubscriptionService;
+import com.commafeed.frontend.CommaFeedSession;
+import com.commafeed.frontend.pages.JSONPage;
+import com.commafeed.frontend.utils.ModelFactory.MF;
+import com.commafeed.model.FeedCategory;
+import com.commafeed.model.FeedSubscription;
+import com.commafeed.model.User;
+import com.google.common.collect.Lists;
+
+@SuppressWarnings("serial")
+public class FeedSubscriptionsPage extends JSONPage {
+
+ @Inject
+ FeedSubscriptionService feedSubscriptionService;
+
+ @Inject
+ FeedCategoryService FeedCategoryService;
+
+ @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
+ .findByField(MF.i(MF.p(FeedSubscription.class).getCategory()),
+ null)) {
+ Subscription sub = new Subscription();
+ sub.setId(subscription.getId());
+ sub.setName(subscription.getTitle());
+ sub.setUnread(77);
+ }
+ return root;
+ }
+
+ private void addChildren(List categories, Category current) {
+ for (FeedCategory category : categories) {
+ if ((category.getParent() == null && current.getId() == null)
+ || (category.getParent() != null && (ObjectUtils.equals(
+ category.getParent().getId(), current.getId())))) {
+ Category child = new Category();
+ child.setId(category.getId());
+ child.setName(category.getName());
+ addChildren(categories, child);
+ for (FeedSubscription subscription : category
+ .getSubscriptions()) {
+ Subscription sub = new Subscription();
+ sub.setId(subscription.getId());
+ sub.setName(subscription.getTitle());
+ sub.setUnread(77);
+ }
+ current.getChildren().add(child);
+ }
+ }
+ }
+
+ public static 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;
+ }
+
+ }
+
+ public static 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;
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/commafeed/frontend/pages/feed/FeedViewPage.java b/src/main/java/com/commafeed/frontend/pages/feed/FeedViewPage.java
index d09d6025..d8c4885e 100644
--- a/src/main/java/com/commafeed/frontend/pages/feed/FeedViewPage.java
+++ b/src/main/java/com/commafeed/frontend/pages/feed/FeedViewPage.java
@@ -7,8 +7,8 @@ import javax.inject.Inject;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import com.commafeed.backend.dao.FeedCategoryService;
@@ -20,6 +20,7 @@ import com.commafeed.frontend.pages.BasePage;
import com.commafeed.frontend.utils.ModelFactory.MF;
import com.commafeed.frontend.utils.stateless.StatelessAjaxLink;
import com.commafeed.model.FeedCategory;
+import com.commafeed.model.FeedEntryStatus;
import com.commafeed.model.FeedSubscription;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
@@ -36,7 +37,7 @@ public class FeedViewPage extends BasePage {
public FeedViewPage() {
add(newTree("tree"));
- add(new Label("entries", Model.of("")));
+ add(newFeedsPanel("entries"));
}
private Component newTree(String markupId) {
@@ -113,4 +114,16 @@ public class FeedViewPage extends BasePage {
}
};
}
+
+ private Component newFeedsPanel(String markupId) {
+
+ new LoadableDetachableModel>() {
+ @Override
+ protected List load() {
+
+ return null;
+ }
+ };
+ return null;
+ }
}
diff --git a/src/main/java/com/commafeed/frontend/pages/feed/components/FeedsPanel.html b/src/main/java/com/commafeed/frontend/pages/feed/components/FeedsPanel.html
new file mode 100644
index 00000000..1cdb194c
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/pages/feed/components/FeedsPanel.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
Anim pariatur cliche...
+
+
+
+
+
diff --git a/src/main/java/com/commafeed/frontend/pages/feed/components/FeedsPanel.java b/src/main/java/com/commafeed/frontend/pages/feed/components/FeedsPanel.java
new file mode 100644
index 00000000..c889b0e4
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/pages/feed/components/FeedsPanel.java
@@ -0,0 +1,54 @@
+package com.commafeed.frontend.pages.feed.components;
+
+import java.util.List;
+
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.GenericPanel;
+import org.apache.wicket.model.IModel;
+
+import com.commafeed.model.FeedEntryStatus;
+
+import de.agilecoders.wicket.markup.html.bootstrap.behavior.CssClassNameAppender;
+import de.agilecoders.wicket.util.Components;
+
+@SuppressWarnings("serial")
+public class FeedsPanel extends GenericPanel> {
+
+ private AttributeModifier dataParentModifier;
+
+ public FeedsPanel(String id, IModel> model) {
+ super(id, model);
+ add(new CssClassNameAppender("accordion"));
+
+ dataParentModifier = new AttributeModifier("data-parent", getMarkupId());
+
+ ListView listView = new ListView(
+ "entry", model) {
+ @Override
+ protected void populateItem(ListItem item) {
+ FeedEntryStatus status = item.getModelObject();
+ WebMarkupContainer link = new WebMarkupContainer("link");
+ link.add(dataParentModifier);
+
+ WebMarkupContainer body = new WebMarkupContainer("body");
+ body.add(new Label("content", status.getEntry().getContent())
+ .setEscapeModelStrings(false));
+
+ link.add(new AttributeModifier("href", "#" + body.getMarkupId()));
+ }
+ };
+ add(listView);
+
+ }
+
+ @Override
+ protected void onComponentTag(ComponentTag tag) {
+ super.onComponentTag(tag);
+ Components.assertTag(this, tag, "div");
+ }
+}
diff --git a/src/main/java/com/commafeed/frontend/pages/home/HomePage.html b/src/main/java/com/commafeed/frontend/pages/home/HomePage.html
new file mode 100644
index 00000000..14fac012
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/pages/home/HomePage.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/commafeed/frontend/pages/home/HomePage.java b/src/main/java/com/commafeed/frontend/pages/home/HomePage.java
index 35091a60..bfac9fd5 100644
--- a/src/main/java/com/commafeed/frontend/pages/home/HomePage.java
+++ b/src/main/java/com/commafeed/frontend/pages/home/HomePage.java
@@ -1,8 +1,34 @@
package com.commafeed.frontend.pages.home;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.resource.UrlResourceReference;
+
import com.commafeed.frontend.pages.BasePage;
+import com.commafeed.frontend.references.angular.AngularReference;
+import com.commafeed.frontend.references.csstree.CssTreeViewReference;
@SuppressWarnings("serial")
public class HomePage extends BasePage {
+ @Override
+ public void renderHead(IHeaderResponse response) {
+ super.renderHead(response);
+ AngularReference.render(response);
+ CssTreeViewReference.render(response);
+ response.render(CssHeaderItem.forReference(new UrlResourceReference(Url
+ .parse("css/app.css"))));
+
+ response.render(JavaScriptHeaderItem
+ .forReference(new UrlResourceReference(Url.parse("js/main.js"))));
+ response.render(JavaScriptHeaderItem
+ .forReference(new UrlResourceReference(Url
+ .parse("js/directives.js"))));
+ response.render(JavaScriptHeaderItem
+ .forReference(new UrlResourceReference(Url
+ .parse("js/controllers.js"))));
+ }
+
}
diff --git a/src/main/java/com/commafeed/frontend/references/angular/AngularReference.java b/src/main/java/com/commafeed/frontend/references/angular/AngularReference.java
new file mode 100644
index 00000000..eb090b26
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/references/angular/AngularReference.java
@@ -0,0 +1,20 @@
+package com.commafeed.frontend.references.angular;
+
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+
+import de.agilecoders.wicket.webjars.request.resource.WebjarsJavaScriptResourceReference;
+
+@SuppressWarnings("serial")
+public class AngularReference extends WebjarsJavaScriptResourceReference {
+
+ private static AngularReference instance = new AngularReference();
+
+ public AngularReference() {
+ super("angularjs/current/angular.min.js");
+ }
+
+ public static void render(IHeaderResponse response) {
+ response.render(JavaScriptHeaderItem.forReference(instance));
+ }
+}
diff --git a/src/main/java/com/commafeed/model/UserSettings.java b/src/main/java/com/commafeed/model/UserSettings.java
new file mode 100644
index 00000000..812611fc
--- /dev/null
+++ b/src/main/java/com/commafeed/model/UserSettings.java
@@ -0,0 +1,55 @@
+package com.commafeed.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "USERS")
+@SuppressWarnings("serial")
+public class UserSettings implements Serializable {
+
+ public enum ReadingMode {
+ ALL, UNREAD
+ }
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private User user;
+
+ @Enumerated(EnumType.STRING)
+ private ReadingMode readingMode;
+
+ public ReadingMode getReadingMode() {
+ return readingMode;
+ }
+
+ public void setReadingMode(ReadingMode readingMode) {
+ this.readingMode = readingMode;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+}
diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml
index 000a7083..2bccfd40 100644
--- a/src/main/resources/META-INF/persistence.xml
+++ b/src/main/resources/META-INF/persistence.xml
@@ -5,7 +5,7 @@
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
- java:/jdbc/commafeedDS
+ ${jpa.datasource.name}
diff --git a/src/main/webapp/css/app.css b/src/main/webapp/css/app.css
new file mode 100644
index 00000000..ceb3b973
--- /dev/null
+++ b/src/main/webapp/css/app.css
@@ -0,0 +1,3 @@
+.css-treeview .selected {
+ font-weight: bold;
+}
\ No newline at end of file
diff --git a/src/main/webapp/directives/category.html b/src/main/webapp/directives/category.html
new file mode 100644
index 00000000..cb7b0c67
--- /dev/null
+++ b/src/main/webapp/directives/category.html
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/js/controllers.js b/src/main/webapp/js/controllers.js
new file mode 100644
index 00000000..03475a50
--- /dev/null
+++ b/src/main/webapp/js/controllers.js
@@ -0,0 +1,56 @@
+var module = angular.module('commafeed.controllers', []);
+
+module.controller('CategoryTreeCtrl',
+ function($scope, $routeParams, $location) {
+
+ $scope.selectedType = $routeParams._type;
+ $scope.selectedId = $routeParams._id;
+
+ $scope.root = {
+ children : [ {
+ id : "1",
+ name : "News",
+ feeds : [ {
+ id : "2",
+ name : "Cyanide & Happiness"
+ } ],
+ children : [ {
+ id : "2",
+ name : "Comics",
+ feeds : [ {
+ id : "1",
+ name : "Dilbert"
+ } ]
+ } ]
+ }, {
+ id : '3',
+ name : "Blogs",
+ feeds : [ {
+ id : "3",
+ name : "Engadget"
+ } ]
+ } ]
+ };
+
+ $scope.feedClicked = function(id) {
+ $location.path('/feeds/view/feed/' + id);
+ };
+
+ $scope.categoryClicked = function(id) {
+ $location.path('/feeds/view/category/' + id);
+ };
+ });
+
+module.controller('FeedListCtrl', function($scope, $routeParams, $http) {
+
+ $scope.entries = [ {
+ id : '1',
+ title : '',
+ content : '',
+ date : '',
+ feed : '',
+ url : '',
+ read : false,
+ starred : false,
+ } ];
+});
diff --git a/src/main/webapp/js/directives.js b/src/main/webapp/js/directives.js
new file mode 100644
index 00000000..99f368e1
--- /dev/null
+++ b/src/main/webapp/js/directives.js
@@ -0,0 +1,23 @@
+var module = angular.module('commafeed.directives', []);
+
+module.directive('category', function($compile) {
+ return {
+ scope: {
+ node: '=',
+ selectedType: '=',
+ selectedId: '=',
+ feedClick: '&',
+ categoryClick: '&'
+ },
+ restrict : 'E',
+ replace: true,
+ templateUrl: 'directives/category.html',
+ link: function(scope, element) {
+ if (scope.node.children) {
+ var ul = element.find('ul');
+ ul.prepend('');
+ $compile(ul.contents())(scope);
+ }
+ }
+ };
+});
\ No newline at end of file
diff --git a/src/main/webapp/js/main.js b/src/main/webapp/js/main.js
new file mode 100644
index 00000000..3cebabd8
--- /dev/null
+++ b/src/main/webapp/js/main.js
@@ -0,0 +1,11 @@
+var app = angular.module('commafeed', [ 'commafeed.directives',
+ 'commafeed.controllers' ]);
+
+app.config([ '$routeProvider', function($routeProvider) {
+ $routeProvider.when('/feeds/view/:_type/:_id', {
+ templateUrl : 'templates/feeds.html'
+ });
+ $routeProvider.otherwise({
+ redirectTo : '/feeds/view/category/all'
+ });
+} ]);
\ No newline at end of file
diff --git a/src/main/webapp/templates/feeds.html b/src/main/webapp/templates/feeds.html
new file mode 100644
index 00000000..48673ae8
--- /dev/null
+++ b/src/main/webapp/templates/feeds.html
@@ -0,0 +1,14 @@
+
\ No newline at end of file