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 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