From f0c4733b768d36fa7a4184c98b0901abfb1012e7 Mon Sep 17 00:00:00 2001 From: Jeremie Panzer Date: Mon, 25 Mar 2013 12:24:00 +0100 Subject: [PATCH] import OPML --- pom.xml | 12 ++- .../backend/dao/FeedCategoryService.java | 30 +++++++ .../backend/dao/FeedEntryService.java | 4 +- .../backend/dao/FeedEntryStatusService.java | 1 + .../commafeed/backend/dao/FeedService.java | 1 + .../backend/dao/FeedSubscriptionService.java | 17 ++++ .../com/commafeed/backend/dao/GenericDAO.java | 4 + .../commafeed/backend/dao/UserService.java | 1 + .../backend/dao/UserSettingsService.java | 1 + .../commafeed/backend/feeds/FeedFetcher.java | 2 +- .../commafeed/backend/feeds/FeedParser.java | 5 +- .../commafeed/backend/feeds/FeedTimer.java | 37 +++++--- .../commafeed/backend/feeds/OPMLImporter.java | 85 +++++++++++++++++++ .../com/commafeed/backend/model/Feed.java | 11 +++ .../commafeed/backend/model/FeedEntry.java | 2 +- .../commafeed/frontend/model/Category.java | 1 + .../com/commafeed/frontend/model/Entries.java | 1 + .../com/commafeed/frontend/model/Entry.java | 1 + .../commafeed/frontend/model/Settings.java | 1 + .../frontend/model/Subscription.java | 10 +++ .../frontend/model/SubscriptionRequest.java | 1 + .../commafeed/frontend/pages/HomePage.html | 1 + .../frontend/rest/resources/AbstractREST.java | 4 + .../frontend/rest/resources/EntriesREST.java | 6 +- .../rest/resources/SubscriptionsREST.java | 30 +++++++ src/main/webapp/directives/subscribe.html | 36 +++++++- src/main/webapp/js/controllers.js | 3 + src/main/webapp/js/directives.js | 16 +++- src/main/webapp/js/main.js | 6 +- .../vendor/angular-upload/ng-upload.min.js | 1 + 30 files changed, 307 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/commafeed/backend/feeds/OPMLImporter.java create mode 100644 src/main/webapp/vendor/angular-upload/ng-upload.min.js diff --git a/pom.xml b/pom.xml index bd32080a..62896c49 100644 --- a/pom.xml +++ b/pom.xml @@ -118,6 +118,11 @@ commons-lang 2.6 + + commons-fileupload + commons-fileupload + 1.2.2 + com.googlecode.lambdaj lambdaj @@ -134,6 +139,12 @@ rome 1.0.0 + + org.rometools + rome-opml + 1.0 + + org.apache.httpcomponents httpclient @@ -171,7 +182,6 @@ wicket-cdi 6.6.0 - diff --git a/src/main/java/com/commafeed/backend/dao/FeedCategoryService.java b/src/main/java/com/commafeed/backend/dao/FeedCategoryService.java index 91d56adc..9b256b37 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedCategoryService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedCategoryService.java @@ -3,15 +3,45 @@ package com.commafeed.backend.dao; import java.util.List; import javax.ejb.Stateless; +import javax.persistence.NoResultException; import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.User; import com.commafeed.frontend.utils.ModelFactory.MF; +import com.google.common.collect.Iterables; +import com.uaihebert.model.EasyCriteria; @Stateless +@SuppressWarnings("serial") public class FeedCategoryService extends GenericDAO { public List findAll(User user) { return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user); } + + public FeedCategory findById(User user, Long id) { + EasyCriteria criteria = createCriteria(); + criteria.andEquals(MF.i(proxy().getUser()), user); + criteria.andEquals(MF.i(proxy().getId()), id); + return Iterables.getFirst(criteria.getResultList(), null); + } + + public FeedCategory findByName(User user, String name, FeedCategory parent) { + EasyCriteria criteria = createCriteria(); + criteria.andEquals(MF.i(proxy().getUser()), user); + criteria.andEquals(MF.i(proxy().getName()), name); + if (parent == null) { + criteria.andIsNull(MF.i(proxy().getParent())); + } else { + criteria.andEquals(MF.i(proxy().getParent()), parent); + } + + FeedCategory category = null; + try { + category = criteria.getSingleResult(); + } catch (NoResultException e) { + category = null; + } + return category; + } } diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryService.java b/src/main/java/com/commafeed/backend/dao/FeedEntryService.java index 3560cd2c..0945c2c7 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedEntryService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryService.java @@ -15,6 +15,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF; import com.google.common.collect.Iterables; @Stateless +@SuppressWarnings("serial") public class FeedEntryService extends GenericDAO { @Inject @@ -34,6 +35,7 @@ public class FeedEntryService extends GenericDAO { } } feed.setLastUpdated(Calendar.getInstance().getTime()); + feed.setMessage(null); em.merge(feed); } @@ -45,7 +47,7 @@ public class FeedEntryService extends GenericDAO { typedQuery.setParameter("user", user); return typedQuery.getResultList(); } - + public List getAllEntries(Feed feed) { String query = "select e from FeedEntry e where e.feed=:feed"; TypedQuery typedQuery = em.createQuery(query, diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java index 6d08040c..31c73c9f 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusService.java @@ -11,6 +11,7 @@ import com.uaihebert.factory.EasyCriteriaFactory; import com.uaihebert.model.EasyCriteria; @Stateless +@SuppressWarnings("serial") public class FeedEntryStatusService extends GenericDAO { public FeedEntryStatus getStatus(User user, FeedEntry entry) { diff --git a/src/main/java/com/commafeed/backend/dao/FeedService.java b/src/main/java/com/commafeed/backend/dao/FeedService.java index 877a5aa8..74926731 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedService.java @@ -9,6 +9,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF; import com.google.common.collect.Iterables; @Stateless +@SuppressWarnings("serial") public class FeedService extends GenericDAO { public Feed findByUrl(String url) { diff --git a/src/main/java/com/commafeed/backend/dao/FeedSubscriptionService.java b/src/main/java/com/commafeed/backend/dao/FeedSubscriptionService.java index 402e9eea..4c30433b 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedSubscriptionService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedSubscriptionService.java @@ -8,20 +8,37 @@ import javax.persistence.TypedQuery; import org.apache.commons.lang.ObjectUtils; +import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedSubscription; import com.commafeed.backend.model.User; import com.commafeed.frontend.utils.ModelFactory.MF; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.uaihebert.factory.EasyCriteriaFactory; import com.uaihebert.model.EasyCriteria; @Stateless +@SuppressWarnings("serial") public class FeedSubscriptionService extends GenericDAO { @Inject FeedCategoryService feedCategoryService; + public FeedSubscription findById(User user, Long id) { + EasyCriteria criteria = createCriteria(); + criteria.andEquals(MF.i(proxy().getUser()), user); + criteria.andEquals(MF.i(proxy().getId()), id); + return Iterables.getFirst(criteria.getResultList(), null); + } + + public FeedSubscription findByFeed(User user, Feed feed) { + EasyCriteria criteria = createCriteria(); + criteria.andEquals(MF.i(proxy().getUser()), user); + criteria.andEquals(MF.i(proxy().getFeed()), feed); + return Iterables.getFirst(criteria.getResultList(), null); + } + public List findAll(User user) { return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user); } diff --git a/src/main/java/com/commafeed/backend/dao/GenericDAO.java b/src/main/java/com/commafeed/backend/dao/GenericDAO.java index 138bbbff..3ac37547 100644 --- a/src/main/java/com/commafeed/backend/dao/GenericDAO.java +++ b/src/main/java/com/commafeed/backend/dao/GenericDAO.java @@ -98,6 +98,10 @@ public abstract class GenericDAO implements protected Class getType() { return (Class) type.getRawType(); } + + public EasyCriteria createCriteria(){ + return EasyCriteriaFactory.createQueryCriteria(em, getType()); + } protected T proxy() { return MF.p(getType()); diff --git a/src/main/java/com/commafeed/backend/dao/UserService.java b/src/main/java/com/commafeed/backend/dao/UserService.java index 12630e2e..1e14eafb 100644 --- a/src/main/java/com/commafeed/backend/dao/UserService.java +++ b/src/main/java/com/commafeed/backend/dao/UserService.java @@ -11,6 +11,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF; import com.google.common.collect.Iterables; @Stateless +@SuppressWarnings("serial") public class UserService extends GenericDAO { @Inject diff --git a/src/main/java/com/commafeed/backend/dao/UserSettingsService.java b/src/main/java/com/commafeed/backend/dao/UserSettingsService.java index 6cca0a77..8a70064f 100644 --- a/src/main/java/com/commafeed/backend/dao/UserSettingsService.java +++ b/src/main/java/com/commafeed/backend/dao/UserSettingsService.java @@ -10,6 +10,7 @@ import com.uaihebert.factory.EasyCriteriaFactory; import com.uaihebert.model.EasyCriteria; @Stateless +@SuppressWarnings("serial") public class UserSettingsService extends GenericDAO { public UserSettings findByUser(User user) { diff --git a/src/main/java/com/commafeed/backend/feeds/FeedFetcher.java b/src/main/java/com/commafeed/backend/feeds/FeedFetcher.java index 5ab4d7ab..6dd55fbd 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedFetcher.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedFetcher.java @@ -48,7 +48,7 @@ public class FeedFetcher { String content = EntityUtils.toString(entity, "UTF-8"); feed = parser.parse(feedUrl, content); } catch (Exception e) { - e.printStackTrace(); + throw new RuntimeException(e); } finally { httpclient.getConnectionManager().shutdown(); } diff --git a/src/main/java/com/commafeed/backend/feeds/FeedParser.java b/src/main/java/com/commafeed/backend/feeds/FeedParser.java index d9377026..e1b67d99 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedParser.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedParser.java @@ -47,8 +47,9 @@ public class FeedParser { feed.getEntries().add(entry); } } catch (Exception e) { - throw new FeedException("Could not parse feed : " + e.getMessage(), - e); + throw new FeedException(String.format( + "Could not parse feed from %s : %s", feedUrl, + e.getMessage()), e); } return feed; } diff --git a/src/main/java/com/commafeed/backend/feeds/FeedTimer.java b/src/main/java/com/commafeed/backend/feeds/FeedTimer.java index c6d30e9a..4fd80281 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedTimer.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedTimer.java @@ -1,20 +1,26 @@ package com.commafeed.backend.feeds; -import java.util.List; +import java.util.Calendar; +import java.util.Map; import java.util.concurrent.Future; import javax.ejb.Schedule; import javax.ejb.Singleton; import javax.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.commafeed.backend.dao.FeedEntryService; import com.commafeed.backend.dao.FeedService; import com.commafeed.backend.model.Feed; -import com.google.common.collect.Lists; +import com.google.common.collect.Maps; @Singleton public class FeedTimer { + private static Logger log = LoggerFactory.getLogger(FeedTimer.class); + @Inject FeedService feedService; @@ -26,21 +32,32 @@ public class FeedTimer { @Schedule(hour = "*", minute = "*", persistent = false) private void timeout() { - List feeds = feedService.findAll(); - - List> futures = Lists.newArrayList(); - for (Feed feed : feeds) { - Future future = fetcher.fetch(feed.getUrl()); - futures.add(future); + Map feeds = Maps.newHashMap(); + for (Feed feed : feedService.findAll()) { + feeds.put(feed.getUrl(), feed); } - for (Future future : futures) { + Map> futures = Maps.newHashMap(); + for (Feed feed : feeds.values()) { + Future future = fetcher.fetch(feed.getUrl()); + futures.put(feed.getUrl(), future); + } + + for (String key : futures.keySet()) { + Future future = futures.get(key); try { Feed feed = future.get(); feedEntryService .updateEntries(feed.getUrl(), feed.getEntries()); } catch (Exception e) { - e.printStackTrace(); + log.info( + "Unable to refresh feed " + key + " : " + + e.getMessage(), e); + + Feed feed = feeds.get(key); + feed.setLastUpdated(Calendar.getInstance().getTime()); + feed.setMessage("Unable to refresh feed: " + e.getMessage()); + feedService.update(feed); } } } diff --git a/src/main/java/com/commafeed/backend/feeds/OPMLImporter.java b/src/main/java/com/commafeed/backend/feeds/OPMLImporter.java new file mode 100644 index 00000000..2489f332 --- /dev/null +++ b/src/main/java/com/commafeed/backend/feeds/OPMLImporter.java @@ -0,0 +1,85 @@ +package com.commafeed.backend.feeds; + +import java.io.StringReader; +import java.util.List; + +import javax.ejb.Singleton; +import javax.inject.Inject; + +import org.apache.commons.lang.StringUtils; + +import com.commafeed.backend.dao.FeedCategoryService; +import com.commafeed.backend.dao.FeedService; +import com.commafeed.backend.dao.FeedSubscriptionService; +import com.commafeed.backend.model.Feed; +import com.commafeed.backend.model.FeedCategory; +import com.commafeed.backend.model.FeedSubscription; +import com.commafeed.backend.model.User; +import com.sun.syndication.feed.opml.Opml; +import com.sun.syndication.feed.opml.Outline; +import com.sun.syndication.io.FeedException; +import com.sun.syndication.io.WireFeedInput; + +@Singleton +public class OPMLImporter { + + @Inject + FeedService feedService; + + @Inject + FeedSubscriptionService feedSubscriptionService; + + @Inject + FeedCategoryService feedCategoryService; + + @SuppressWarnings("unchecked") + public void importOpml(User user, String xml) throws FeedException { + + WireFeedInput input = new WireFeedInput(); + Opml feed = (Opml) input.build(new StringReader(xml)); + List outlines = (List) feed.getOutlines(); + for (Outline outline : outlines) { + handleOutline(user, outline, null); + } + } + + @SuppressWarnings("unchecked") + private void handleOutline(User user, Outline outline, FeedCategory parent) { + + if (StringUtils.isEmpty(outline.getType())) { + FeedCategory category = feedCategoryService.findByName(user, + outline.getText(), parent); + if (category == null) { + category = new FeedCategory(); + category.setName(outline.getText()); + category.setParent(parent); + category.setUser(user); + feedCategoryService.save(category); + } + + List children = outline.getChildren(); + for (Outline child : children) { + handleOutline(user, child, category); + } + } else { + Feed feed = feedService.findByUrl(outline.getXmlUrl()); + if (feed == null) { + feed = new Feed(); + feed.setUrl(outline.getXmlUrl()); + feedService.save(feed); + } + + FeedSubscription sub = feedSubscriptionService.findByFeed(user, + feed); + if (sub == null) { + sub = new FeedSubscription(); + sub.setFeed(feed); + sub.setUser(user); + feedSubscriptionService.save(sub); + } + sub.setCategory(parent); + sub.setTitle(outline.getText()); + feedSubscriptionService.update(sub); + } + } +} diff --git a/src/main/java/com/commafeed/backend/model/Feed.java b/src/main/java/com/commafeed/backend/model/Feed.java index a348b5f8..fd51b0c7 100644 --- a/src/main/java/com/commafeed/backend/model/Feed.java +++ b/src/main/java/com/commafeed/backend/model/Feed.java @@ -24,6 +24,9 @@ public class Feed extends AbstractModel { @Temporal(TemporalType.TIMESTAMP) private Date lastUpdated; + @Column(length = 1024) + private String message; + @OneToMany(mappedBy = "feed", fetch = FetchType.EAGER) private Set entries = Sets.newHashSet(); @@ -59,4 +62,12 @@ public class Feed extends AbstractModel { this.entries = entries; } + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } diff --git a/src/main/java/com/commafeed/backend/model/FeedEntry.java b/src/main/java/com/commafeed/backend/model/FeedEntry.java index e5246945..b074283d 100644 --- a/src/main/java/com/commafeed/backend/model/FeedEntry.java +++ b/src/main/java/com/commafeed/backend/model/FeedEntry.java @@ -21,7 +21,7 @@ public class FeedEntry extends AbstractModel { @ManyToOne private Feed feed; - @Column(length = 256) + @Column(length = 2048) private String title; @Lob diff --git a/src/main/java/com/commafeed/frontend/model/Category.java b/src/main/java/com/commafeed/frontend/model/Category.java index f4ccacb4..99d180ec 100644 --- a/src/main/java/com/commafeed/frontend/model/Category.java +++ b/src/main/java/com/commafeed/frontend/model/Category.java @@ -5,6 +5,7 @@ import java.util.List; import com.google.common.collect.Lists; +@SuppressWarnings("serial") public class Category implements Serializable { private String id; diff --git a/src/main/java/com/commafeed/frontend/model/Entries.java b/src/main/java/com/commafeed/frontend/model/Entries.java index a3bf23ad..10cd7358 100644 --- a/src/main/java/com/commafeed/frontend/model/Entries.java +++ b/src/main/java/com/commafeed/frontend/model/Entries.java @@ -5,6 +5,7 @@ import java.util.List; import com.google.common.collect.Lists; +@SuppressWarnings("serial") public class Entries implements Serializable { private String name; private List entries = Lists.newArrayList(); diff --git a/src/main/java/com/commafeed/frontend/model/Entry.java b/src/main/java/com/commafeed/frontend/model/Entry.java index dc14a973..f8b1ae57 100644 --- a/src/main/java/com/commafeed/frontend/model/Entry.java +++ b/src/main/java/com/commafeed/frontend/model/Entry.java @@ -3,6 +3,7 @@ package com.commafeed.frontend.model; import java.io.Serializable; import java.util.Date; +@SuppressWarnings("serial") public class Entry implements Serializable { private String id; diff --git a/src/main/java/com/commafeed/frontend/model/Settings.java b/src/main/java/com/commafeed/frontend/model/Settings.java index b83a0604..967ab276 100644 --- a/src/main/java/com/commafeed/frontend/model/Settings.java +++ b/src/main/java/com/commafeed/frontend/model/Settings.java @@ -2,6 +2,7 @@ package com.commafeed.frontend.model; import java.io.Serializable; +@SuppressWarnings("serial") public class Settings implements Serializable { private String readingMode; diff --git a/src/main/java/com/commafeed/frontend/model/Subscription.java b/src/main/java/com/commafeed/frontend/model/Subscription.java index 036138d3..89d1c752 100644 --- a/src/main/java/com/commafeed/frontend/model/Subscription.java +++ b/src/main/java/com/commafeed/frontend/model/Subscription.java @@ -2,10 +2,12 @@ package com.commafeed.frontend.model; import java.io.Serializable; +@SuppressWarnings("serial") public class Subscription implements Serializable { private Long id; private String name; + private String message; private int unread; public Long getId() { @@ -32,4 +34,12 @@ public class Subscription implements Serializable { this.unread = unread; } + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } \ No newline at end of file diff --git a/src/main/java/com/commafeed/frontend/model/SubscriptionRequest.java b/src/main/java/com/commafeed/frontend/model/SubscriptionRequest.java index ff178f5c..71348c1c 100644 --- a/src/main/java/com/commafeed/frontend/model/SubscriptionRequest.java +++ b/src/main/java/com/commafeed/frontend/model/SubscriptionRequest.java @@ -2,6 +2,7 @@ package com.commafeed.frontend.model; import java.io.Serializable; +@SuppressWarnings("serial") public class SubscriptionRequest implements Serializable { private String url; diff --git a/src/main/java/com/commafeed/frontend/pages/HomePage.html b/src/main/java/com/commafeed/frontend/pages/HomePage.html index 12c46a6f..660cfdd8 100644 --- a/src/main/java/com/commafeed/frontend/pages/HomePage.html +++ b/src/main/java/com/commafeed/frontend/pages/HomePage.html @@ -38,6 +38,7 @@ + diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java index 68c4ab28..37a6b745 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java @@ -24,6 +24,7 @@ import com.commafeed.backend.dao.FeedService; import com.commafeed.backend.dao.FeedSubscriptionService; import com.commafeed.backend.dao.UserService; import com.commafeed.backend.dao.UserSettingsService; +import com.commafeed.backend.feeds.OPMLImporter; import com.commafeed.backend.model.User; import com.commafeed.frontend.CommaFeedApplication; import com.commafeed.frontend.CommaFeedSession; @@ -59,6 +60,9 @@ public abstract class AbstractREST { @Inject UserSettingsService userSettingsService; + @Inject + OPMLImporter opmlImporter; + @PostConstruct public void init() { CommaFeedApplication app = CommaFeedApplication.get(); diff --git a/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java b/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java index efb4db23..eed7f775 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java @@ -33,14 +33,14 @@ public class EntriesREST extends AbstractREST { boolean unreadOnly = "unread".equals(readType); if ("feed".equals(type)) { - FeedSubscription subscription = feedSubscriptionService - .findById(Long.valueOf(id)); + FeedSubscription subscription = feedSubscriptionService.findById( + getUser(), Long.valueOf(id)); entries.setName(subscription.getTitle()); entries.getEntries().addAll(buildEntries(subscription, unreadOnly)); } else { FeedCategory feedCategory = "all".equals(id) ? null - : feedCategoryService.findById(Long.valueOf(id)); + : feedCategoryService.findById(getUser(), Long.valueOf(id)); Collection subscriptions = "all".equals(id) ? feedSubscriptionService .findAll(getUser()) : feedSubscriptionService .findWithCategory(getUser(), feedCategory); diff --git a/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java b/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java index 3fd0fd6f..325877d8 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java @@ -2,11 +2,18 @@ package com.commafeed.frontend.rest.resources; import java.util.List; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ObjectUtils; import com.commafeed.backend.model.Feed; @@ -50,6 +57,27 @@ public class SubscriptionsREST extends AbstractREST { feedSubscriptionService.deleteById(subscriptionId); } + @POST + @Path("import") + @Consumes(MediaType.MULTIPART_FORM_DATA) + @SuppressWarnings("unchecked") + public void importOpml() { + try { + FileItemFactory factory = new DiskFileItemFactory(1000000, null); + ServletFileUpload upload = new ServletFileUpload(factory); + List items = upload.parseRequest(request); + for (FileItem item : items) { + if ("file".equals(item.getFieldName())) { + opmlImporter.importOpml(getUser(), + IOUtils.toString(item.getInputStream(), "UTF-8")); + break; + } + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + @GET public Category getSubscriptions() { Category root = new Category(); @@ -65,6 +93,7 @@ public class SubscriptionsREST extends AbstractREST { Subscription sub = new Subscription(); sub.setId(subscription.getId()); sub.setName(subscription.getTitle()); + sub.setMessage(subscription.getFeed().getMessage()); int size = feedEntryService.getUnreadEntries( subscription.getFeed(), getUser()).size(); sub.setUnread(size); @@ -88,6 +117,7 @@ public class SubscriptionsREST extends AbstractREST { Subscription sub = new Subscription(); sub.setId(subscription.getId()); sub.setName(subscription.getTitle()); + sub.setMessage(subscription.getFeed().getMessage()); int size = feedEntryService.getUnreadEntries( subscription.getFeed(), getUser()).size(); sub.setUnread(size); diff --git a/src/main/webapp/directives/subscribe.html b/src/main/webapp/directives/subscribe.html index 9445ecda..333bf01b 100644 --- a/src/main/webapp/directives/subscribe.html +++ b/src/main/webapp/directives/subscribe.html @@ -1,5 +1,16 @@
- +
+ + + +
+
+ +
+ + +
+
\ No newline at end of file diff --git a/src/main/webapp/js/controllers.js b/src/main/webapp/js/controllers.js index 64873756..4b8e5bd8 100644 --- a/src/main/webapp/js/controllers.js +++ b/src/main/webapp/js/controllers.js @@ -44,6 +44,9 @@ module.controller('CategoryTreeCtrl', function($scope, $routeParams, $location, $scope.formatFeedName = function(feed) { var label = feed.name; + if (feed.message) { + label = "!!! " + label; + } if (feed.unread > 0) { label = label + " (" + feed.unread + ")"; } diff --git a/src/main/webapp/js/directives.js b/src/main/webapp/js/directives.js index ba67f9c6..68863502 100644 --- a/src/main/webapp/js/directives.js +++ b/src/main/webapp/js/directives.js @@ -1,6 +1,6 @@ var module = angular.module('commafeed.directives', []); -module.directive('subscribe', function() { +module.directive('subscribe', function(SubscriptionService) { return { scope : {}, restrict : 'E', @@ -13,6 +13,7 @@ module.directive('subscribe', function() { }; $scope.isOpen = false; + $scope.isOpenImport = false; $scope.sub = {}; $scope.SubscriptionService = SubscriptionService; @@ -31,6 +32,19 @@ module.directive('subscribe', function() { $scope.close(); }); }; + + $scope.openImport = function() { + $scope.isOpenImport = true; + }; + + $scope.closeImport = function() { + $scope.isOpenImport = false; + }; + + $scope.uploadComplete = function(contents, completed) { + SubscriptionService.init(); + $scope.closeImport(); + }; } }; }); diff --git a/src/main/webapp/js/main.js b/src/main/webapp/js/main.js index 9d20b8d0..fde46d90 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', 'ngSanitize' ]); +var app = angular.module('commafeed', [ 'ui', 'ui.bootstrap', + 'commafeed.directives', 'commafeed.controllers', 'commafeed.services', + 'ngSanitize', 'ngUpload' ]); app.config([ '$routeProvider', function($routeProvider) { $routeProvider.when('/feeds/view/:_type/:_id', { diff --git a/src/main/webapp/vendor/angular-upload/ng-upload.min.js b/src/main/webapp/vendor/angular-upload/ng-upload.min.js new file mode 100644 index 00000000..f7c868e2 --- /dev/null +++ b/src/main/webapp/vendor/angular-upload/ng-upload.min.js @@ -0,0 +1 @@ +angular.module("ngUpload",[]).directive("uploadSubmit",["$parse",function(t){return{restrict:"AC",link:function(a,e,n){var o={};o.enableControls=n.uploadOptionsEnableControls;var i=e.parents("form[ng-upload]")||e.parents("form.ng-upload"),r=t(n.uploadSubmit);if(!angular.isFunction(r)){var l="The expression on the ngUpload directive does not point to a valid function.";throw l+"\n"}e.bind("click",function(t){t.preventDefault=!0;var n=angular.element("