mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
tagging support (#96)
This commit is contained in:
@@ -31,6 +31,8 @@ import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryContent_;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
import com.commafeed.backend.model.FeedEntryStatus_;
|
||||
import com.commafeed.backend.model.FeedEntryTag;
|
||||
import com.commafeed.backend.model.FeedEntryTag_;
|
||||
import com.commafeed.backend.model.FeedEntry_;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.Models;
|
||||
@@ -47,6 +49,10 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
private static final String ALIAS_STATUS = "status";
|
||||
private static final String ALIAS_ENTRY = "entry";
|
||||
private static final String ALIAS_TAG = "tag";
|
||||
|
||||
@Inject
|
||||
FeedEntryTagDAO feedEntryTagDAO;
|
||||
|
||||
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_DESC = new Comparator<FeedEntryStatus>() {
|
||||
@Override
|
||||
@@ -63,7 +69,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
public FeedEntryStatus getStatus(FeedSubscription sub, FeedEntry entry) {
|
||||
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
|
||||
|
||||
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
|
||||
Root<FeedEntryStatus> root = query.from(getType());
|
||||
@@ -76,14 +82,14 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
List<FeedEntryStatus> statuses = em.createQuery(query).getResultList();
|
||||
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
||||
|
||||
return handleStatus(status, sub, entry);
|
||||
return handleStatus(user, status, sub, entry);
|
||||
}
|
||||
|
||||
private FeedEntryStatus handleStatus(FeedEntryStatus status, FeedSubscription sub, FeedEntry entry) {
|
||||
private FeedEntryStatus handleStatus(User user, FeedEntryStatus status, FeedSubscription sub, FeedEntry entry) {
|
||||
if (status == null) {
|
||||
Date unreadThreshold = applicationSettingsService.getUnreadThreshold();
|
||||
boolean read = unreadThreshold == null ? false : entry.getUpdated().before(unreadThreshold);
|
||||
status = new FeedEntryStatus(sub.getUser(), sub, entry);
|
||||
status = new FeedEntryStatus(user, sub, entry);
|
||||
status.setRead(read);
|
||||
status.setMarkable(!read);
|
||||
} else {
|
||||
@@ -92,6 +98,12 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return status;
|
||||
}
|
||||
|
||||
private FeedEntryStatus fetchTags(User user, FeedEntryStatus status) {
|
||||
List<FeedEntryTag> tags = feedEntryTagDAO.findByEntry(user, status.getEntry());
|
||||
status.setTags(tags);
|
||||
return status;
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||
|
||||
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
|
||||
@@ -114,13 +126,14 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
setTimeout(q);
|
||||
List<FeedEntryStatus> statuses = q.getResultList();
|
||||
for (FeedEntryStatus status : statuses) {
|
||||
status = handleStatus(status, status.getSubscription(), status.getEntry());
|
||||
status = handleStatus(user, status, status.getSubscription(), status.getEntry());
|
||||
status = fetchTags(user, status);
|
||||
}
|
||||
return lazyLoadContent(includeContent, statuses);
|
||||
}
|
||||
|
||||
private Criteria buildSearchCriteria(FeedSubscription sub, boolean unreadOnly, String keywords, Date newerThan, int offset, int limit,
|
||||
ReadingOrder order, Date last) {
|
||||
ReadingOrder order, Date last, String tag) {
|
||||
Criteria criteria = getSession().createCriteria(FeedEntry.class, ALIAS_ENTRY);
|
||||
|
||||
criteria.add(Restrictions.eq(FeedEntry_.feed.getName(), sub.getFeed()));
|
||||
@@ -138,7 +151,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
Criteria statusJoin = criteria.createCriteria(FeedEntry_.statuses.getName(), ALIAS_STATUS, JoinType.LEFT_OUTER_JOIN,
|
||||
Restrictions.eq(FeedEntryStatus_.subscription.getName(), sub));
|
||||
|
||||
if (unreadOnly) {
|
||||
if (unreadOnly && tag == null) {
|
||||
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
or.add(Restrictions.isNull(FeedEntryStatus_.read.getName()));
|
||||
@@ -151,6 +164,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
}
|
||||
|
||||
if (tag != null) {
|
||||
criteria.createCriteria(FeedEntry_.tags.getName(), ALIAS_TAG, JoinType.INNER_JOIN,
|
||||
Restrictions.eq(FeedEntryTag_.name.getName(), tag));
|
||||
}
|
||||
|
||||
if (newerThan != null) {
|
||||
criteria.add(Restrictions.ge(FeedEntry_.inserted.getName(), newerThan));
|
||||
}
|
||||
@@ -185,14 +203,14 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<FeedEntryStatus> findBySubscriptions(List<FeedSubscription> subs, boolean unreadOnly, String keywords, Date newerThan,
|
||||
int offset, int limit, ReadingOrder order, boolean includeContent, boolean onlyIds) {
|
||||
public List<FeedEntryStatus> findBySubscriptions(User user, List<FeedSubscription> subs, boolean unreadOnly, String keywords,
|
||||
Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent, boolean onlyIds, String tag) {
|
||||
int capacity = offset + limit;
|
||||
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC : STATUS_COMPARATOR_ASC;
|
||||
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
|
||||
for (FeedSubscription sub : subs) {
|
||||
Date last = (order != null && set.isFull()) ? set.last().getEntryUpdated() : null;
|
||||
Criteria criteria = buildSearchCriteria(sub, unreadOnly, keywords, newerThan, -1, capacity, order, last);
|
||||
Criteria criteria = buildSearchCriteria(sub, unreadOnly, keywords, newerThan, -1, capacity, order, last, tag);
|
||||
ProjectionList projection = Projections.projectionList();
|
||||
projection.add(Projections.property("id"), "id");
|
||||
projection.add(Projections.property("updated"), "updated");
|
||||
@@ -234,7 +252,10 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
for (FeedEntryStatus placeholder : placeholders) {
|
||||
Long statusId = placeholder.getId();
|
||||
FeedEntry entry = em.find(FeedEntry.class, placeholder.getEntry().getId());
|
||||
statuses.add(handleStatus(statusId == null ? null : findById(statusId), placeholder.getSubscription(), entry));
|
||||
FeedEntryStatus status = handleStatus(user, statusId == null ? null : findById(statusId), placeholder.getSubscription(),
|
||||
entry);
|
||||
status = fetchTags(user, status);
|
||||
statuses.add(status);
|
||||
}
|
||||
statuses = lazyLoadContent(includeContent, statuses);
|
||||
}
|
||||
@@ -244,7 +265,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
@SuppressWarnings("unchecked")
|
||||
public UnreadCount getUnreadCount(FeedSubscription subscription) {
|
||||
UnreadCount uc = null;
|
||||
Criteria criteria = buildSearchCriteria(subscription, true, null, null, -1, -1, null, null);
|
||||
Criteria criteria = buildSearchCriteria(subscription, true, null, null, -1, -1, null, null, null);
|
||||
ProjectionList projection = Projections.projectionList();
|
||||
projection.add(Projections.rowCount(), "count");
|
||||
projection.add(Projections.max(FeedEntry_.updated.getName()), "updated");
|
||||
|
||||
43
src/main/java/com/commafeed/backend/dao/FeedEntryTagDAO.java
Normal file
43
src/main/java/com/commafeed/backend/dao/FeedEntryTagDAO.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryTag;
|
||||
import com.commafeed.backend.model.FeedEntryTag_;
|
||||
import com.commafeed.backend.model.FeedEntry_;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.User_;
|
||||
|
||||
@Stateless
|
||||
public class FeedEntryTagDAO extends GenericDAO<FeedEntryTag> {
|
||||
|
||||
public List<String> findByUser(User user) {
|
||||
CriteriaQuery<String> query = builder.createQuery(String.class);
|
||||
Root<FeedEntryTag> root = query.from(getType());
|
||||
query.select(root.get(FeedEntryTag_.name));
|
||||
query.distinct(true);
|
||||
|
||||
Predicate p1 = builder.equal(root.get(FeedEntryTag_.user).get(User_.id), user.getId());
|
||||
query.where(p1);
|
||||
|
||||
return cache(em.createQuery(query)).getResultList();
|
||||
}
|
||||
|
||||
public List<FeedEntryTag> findByEntry(User user, FeedEntry entry) {
|
||||
CriteriaQuery<FeedEntryTag> query = builder.createQuery(getType());
|
||||
Root<FeedEntryTag> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(root.get(FeedEntryTag_.user).get(User_.id), user.getId());
|
||||
Predicate p2 = builder.equal(root.get(FeedEntryTag_.entry).get(FeedEntry_.id), entry.getId());
|
||||
|
||||
query.where(p1, p2);
|
||||
|
||||
return cache(em.createQuery(query)).getResultList();
|
||||
}
|
||||
}
|
||||
@@ -55,5 +55,8 @@ public class FeedEntry extends AbstractModel {
|
||||
|
||||
@OneToMany(mappedBy = "entry", cascade = CascadeType.REMOVE)
|
||||
private Set<FeedEntryStatus> statuses;
|
||||
|
||||
@OneToMany(mappedBy = "entry", cascade = CascadeType.REMOVE)
|
||||
private Set<FeedEntryTag> tags;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.commafeed.backend.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
@@ -42,6 +43,9 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
|
||||
@Transient
|
||||
private boolean markable;
|
||||
|
||||
@Transient
|
||||
private List<FeedEntryTag> tags;
|
||||
|
||||
/**
|
||||
* Denormalization starts here
|
||||
|
||||
46
src/main/java/com/commafeed/backend/model/FeedEntryTag.java
Normal file
46
src/main/java/com/commafeed/backend/model/FeedEntryTag.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.commafeed.backend.model;
|
||||
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
@Entity
|
||||
@Table(name = "FEEDENTRYTAGS")
|
||||
@SuppressWarnings("serial")
|
||||
@Cacheable
|
||||
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||
@Getter
|
||||
@Setter
|
||||
public class FeedEntryTag extends AbstractModel {
|
||||
|
||||
@JoinColumn(name = "user_id")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private User user;
|
||||
|
||||
@JoinColumn(name = "entry_id")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private FeedEntry entry;
|
||||
|
||||
@Column(name = "name", length = 40)
|
||||
private String name;
|
||||
|
||||
public FeedEntryTag() {
|
||||
}
|
||||
|
||||
public FeedEntryTag(User user, FeedEntry entry, String name) {
|
||||
this.name = name;
|
||||
this.entry = entry;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class FeedEntryService {
|
||||
return;
|
||||
}
|
||||
|
||||
FeedEntryStatus status = feedEntryStatusDAO.getStatus(sub, entry);
|
||||
FeedEntryStatus status = feedEntryStatusDAO.getStatus(user, sub, entry);
|
||||
if (status.isMarkable()) {
|
||||
status.setRead(read);
|
||||
feedEntryStatusDAO.saveOrUpdate(status);
|
||||
@@ -64,14 +64,14 @@ public class FeedEntryService {
|
||||
return;
|
||||
}
|
||||
|
||||
FeedEntryStatus status = feedEntryStatusDAO.getStatus(sub, entry);
|
||||
FeedEntryStatus status = feedEntryStatusDAO.getStatus(user, sub, entry);
|
||||
status.setStarred(starred);
|
||||
feedEntryStatusDAO.saveOrUpdate(status);
|
||||
}
|
||||
|
||||
public void markSubscriptionEntries(User user, List<FeedSubscription> subscriptions, Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO
|
||||
.findBySubscriptions(subscriptions, true, null, null, -1, -1, null, false, false);
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO.findBySubscriptions(user, subscriptions, true, null, null, -1, -1, null, false,
|
||||
false, null);
|
||||
markList(statuses, olderThan);
|
||||
cache.invalidateUnreadCount(subscriptions.toArray(new FeedSubscription[0]));
|
||||
cache.invalidateUserRootCategory(user);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.commafeed.backend.services;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.commafeed.backend.dao.FeedEntryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryTagDAO;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryTag;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@Stateless
|
||||
public class FeedEntryTagService {
|
||||
|
||||
@Inject
|
||||
FeedEntryDAO feedEntryDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryTagDAO feedEntryTagDAO;
|
||||
|
||||
public void updateTags(User user, Long entryId, List<String> tagNames) {
|
||||
FeedEntry entry = feedEntryDAO.findById(entryId);
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<FeedEntryTag> tags = feedEntryTagDAO.findByEntry(user, entry);
|
||||
Map<String, FeedEntryTag> tagMap = Maps.uniqueIndex(tags, new Function<FeedEntryTag, String>() {
|
||||
@Override
|
||||
public String apply(FeedEntryTag input) {
|
||||
return input.getName();
|
||||
}
|
||||
});
|
||||
|
||||
List<FeedEntryTag> addList = Lists.newArrayList();
|
||||
List<FeedEntryTag> removeList = Lists.newArrayList();
|
||||
|
||||
for (String tagName : tagNames) {
|
||||
FeedEntryTag tag = tagMap.get(tagName);
|
||||
if (tag == null) {
|
||||
addList.add(new FeedEntryTag(user, entry, tagName));
|
||||
}
|
||||
}
|
||||
|
||||
for (FeedEntryTag tag : tags) {
|
||||
if (!tagNames.contains(tag.getName())) {
|
||||
removeList.add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
feedEntryTagDAO.saveOrUpdate(addList);
|
||||
feedEntryTagDAO.delete(removeList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.commafeed.frontend.model;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,7 +11,9 @@ import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
import com.commafeed.backend.model.FeedEntryTag;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sun.syndication.feed.synd.SyndContentImpl;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
import com.sun.syndication.feed.synd.SyndEntryImpl;
|
||||
@@ -43,6 +46,12 @@ public class Entry implements Serializable {
|
||||
entry.setFeedLink(sub.getFeed().getLink());
|
||||
entry.setIconUrl(FeedUtils.getFaviconUrl(sub, publicUrl));
|
||||
|
||||
List<String> tags = Lists.newArrayList();
|
||||
for (FeedEntryTag tag : status.getTags()) {
|
||||
tags.add(tag.getName());
|
||||
}
|
||||
entry.setTags(tags);
|
||||
|
||||
if (content != null) {
|
||||
entry.setRtl(FeedUtils.isRTL(feedEntry));
|
||||
entry.setTitle(content.getTitle());
|
||||
@@ -125,4 +134,7 @@ public class Entry implements Serializable {
|
||||
|
||||
@ApiProperty("wether the entry is still markable (old entry statuses are discarded)")
|
||||
private boolean markable;
|
||||
|
||||
@ApiProperty("tags")
|
||||
private List<String> tags;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.commafeed.frontend.model.request;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Tag Request")
|
||||
@Data
|
||||
public class TagRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "entry id", required = true)
|
||||
private Long entryId;
|
||||
|
||||
@ApiProperty(value = "tags")
|
||||
private List<String> tags;
|
||||
|
||||
}
|
||||
@@ -54,13 +54,13 @@ public class NextUnreadRedirectPage extends WebPage {
|
||||
List<FeedEntryStatus> statuses = null;
|
||||
if (StringUtils.isBlank(categoryId) || CategoryREST.ALL.equals(categoryId)) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(user);
|
||||
statuses = feedEntryStatusDAO.findBySubscriptions(subs, true, null, null, 0, 1, order, true, false);
|
||||
statuses = feedEntryStatusDAO.findBySubscriptions(user, subs, true, null, null, 0, 1, order, true, false, null);
|
||||
} else {
|
||||
FeedCategory category = feedCategoryDAO.findById(user, Long.valueOf(categoryId));
|
||||
if (category != null) {
|
||||
List<FeedCategory> children = feedCategoryDAO.findAllChildrenCategories(user, category);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findByCategories(user, children);
|
||||
statuses = feedEntryStatusDAO.findBySubscriptions(subscriptions, true, null, null, 0, 1, order, true, false);
|
||||
statuses = feedEntryStatusDAO.findBySubscriptions(user, subscriptions, true, null, null, 0, 1, order, true, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@ public class CategoryREST extends AbstractREST {
|
||||
@ApiParam(
|
||||
value = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
|
||||
@ApiParam(value = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds,
|
||||
@ApiParam(value = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds) {
|
||||
@ApiParam(value = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds,
|
||||
@ApiParam(value = "keep only entries tagged with this tag") @QueryParam("tag") String tag) {
|
||||
|
||||
Preconditions.checkNotNull(readType);
|
||||
|
||||
@@ -138,8 +139,8 @@ public class CategoryREST extends AbstractREST {
|
||||
entries.setName("All");
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(getUser());
|
||||
removeExcludedSubscriptions(subs, excludedIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(subs, unreadOnly, keywords, newerThanDate, offset,
|
||||
limit + 1, order, true, onlyIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(getUser(), subs, unreadOnly, keywords, newerThanDate,
|
||||
offset, limit + 1, order, true, onlyIds, tag);
|
||||
|
||||
for (FeedEntryStatus status : list) {
|
||||
entries.getEntries().add(
|
||||
@@ -161,8 +162,8 @@ public class CategoryREST extends AbstractREST {
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(getUser(), parent);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategories(getUser(), categories);
|
||||
removeExcludedSubscriptions(subs, excludedIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(subs, unreadOnly, keywords, newerThanDate, offset,
|
||||
limit + 1, order, true, onlyIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(getUser(), subs, unreadOnly, keywords, newerThanDate,
|
||||
offset, limit + 1, order, true, onlyIds, tag);
|
||||
|
||||
for (FeedEntryStatus status : list) {
|
||||
entries.getEntries().add(
|
||||
@@ -192,7 +193,9 @@ public class CategoryREST extends AbstractREST {
|
||||
@Produces(MediaType.APPLICATION_XML)
|
||||
@SecurityCheck(value = Role.USER, apiKeyAllowed = true)
|
||||
public Response getCategoryEntriesAsFeed(
|
||||
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id) {
|
||||
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id, @ApiParam(
|
||||
value = "tag",
|
||||
required = true) @QueryParam("tag") String tag) {
|
||||
|
||||
Preconditions.checkNotNull(id);
|
||||
|
||||
@@ -201,7 +204,7 @@ public class CategoryREST extends AbstractREST {
|
||||
int offset = 0;
|
||||
int limit = 20;
|
||||
|
||||
Response response = getCategoryEntries(id, readType, null, offset, limit, order, null, false, null);
|
||||
Response response = getCategoryEntries(id, readType, null, offset, limit, order, null, false, null, tag);
|
||||
if (response.getStatus() != Status.OK.getStatusCode()) {
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryTagDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.FeedEntryService;
|
||||
import com.commafeed.backend.services.FeedEntryTagService;
|
||||
import com.commafeed.frontend.model.request.MarkRequest;
|
||||
import com.commafeed.frontend.model.request.MultipleMarkRequest;
|
||||
import com.commafeed.frontend.model.request.StarRequest;
|
||||
import com.commafeed.frontend.model.request.TagRequest;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.annotations.ApiOperation;
|
||||
@@ -30,6 +36,12 @@ public class EntryREST extends AbstractREST {
|
||||
@Inject
|
||||
FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryTagDAO feedEntryTagDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryTagService feedEntryTagService;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
@@ -71,4 +83,24 @@ public class EntryREST extends AbstractREST {
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/tags")
|
||||
@GET
|
||||
@ApiOperation(value = "Get list of tags for the user", notes = "Get list of tags for the user")
|
||||
public Response getTags() {
|
||||
List<String> tags = feedEntryTagDAO.findByUser(getUser());
|
||||
return Response.ok(tags).build();
|
||||
}
|
||||
|
||||
@Path("/tag")
|
||||
@POST
|
||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||
public Response tagFeedEntry(@ApiParam(value = "Tag Request", required = true) TagRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getEntryId());
|
||||
|
||||
feedEntryTagService.updateTags(getUser(), req.getEntryId(), req.getTags());
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -167,8 +167,8 @@ public class FeedREST extends AbstractREST {
|
||||
entries.setErrorCount(subscription.getFeed().getErrorCount());
|
||||
entries.setFeedLink(subscription.getFeed().getLink());
|
||||
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(Arrays.asList(subscription), unreadOnly, keywords,
|
||||
newerThanDate, offset, limit + 1, order, true, onlyIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(getUser(), Arrays.asList(subscription), unreadOnly,
|
||||
keywords, newerThanDate, offset, limit + 1, order, true, onlyIds, null);
|
||||
|
||||
for (FeedEntryStatus status : list) {
|
||||
entries.getEntries().add(
|
||||
|
||||
@@ -9,8 +9,39 @@
|
||||
</changeSet>
|
||||
<changeSet author="athou" id="set-default-scroll-speed">
|
||||
<update tableName="USERSETTINGS">
|
||||
<column name="scroll_speed" valueNumeric="400" />
|
||||
<column name="scroll_speed" valueNumeric="400" />
|
||||
</update>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="athou" id="create-tags-table">
|
||||
<createTable tableName="FEEDENTRYTAGS">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" />
|
||||
</column>
|
||||
<column name="entry_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="user_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(40)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<addForeignKeyConstraint constraintName="fk_entry_id" baseTableName="FEEDENTRYTAGS" baseColumnNames="entry_id"
|
||||
referencedTableName="FEEDENTRIES" referencedColumnNames="id" />
|
||||
<addForeignKeyConstraint constraintName="fk_user_id" baseTableName="FEEDENTRYTAGS" baseColumnNames="user_id"
|
||||
referencedTableName="USERS" referencedColumnNames="id" />
|
||||
|
||||
<createIndex tableName="FEEDENTRYTAGS" indexName="user_entry_index">
|
||||
<column name="user_id" />
|
||||
<column name="entry_id" />
|
||||
</createIndex>
|
||||
<createIndex tableName="FEEDENTRYTAGS" indexName="user_name_index">
|
||||
<column name="user_id" />
|
||||
<column name="name" />
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=تحميل
|
||||
global.link=رابط
|
||||
global.bookmark=مرجعية
|
||||
global.close=أغلق
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=اشترك
|
||||
tree.import=استورد
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Show feeds and categories with no unread entries
|
||||
settings.general.social_buttons=Show social sharing buttons
|
||||
settings.general.scroll_marks=In expanded view, scrolling through entries mark them as read
|
||||
settings.appearance=Appearance
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Theme
|
||||
settings.submit_your_theme=Submit your theme
|
||||
settings.custom_css=Custom CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Feed URL
|
||||
details.generate_api_key_first=Generate an API key in your profile first.
|
||||
details.unsubscribe=Unsubscribe
|
||||
details.category_details=Category details
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Parent category
|
||||
|
||||
profile.user_name=User name
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download = Stáhnout
|
||||
global.link = Odkaz
|
||||
global.bookmark = Záložky
|
||||
global.close = Zavřít
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe = Nový odběr
|
||||
tree.import = Importovat
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread = Zobrazit položky a kategorie z přečtenými pol
|
||||
settings.general.social_buttons = Zobrazit možnosti sdílení
|
||||
settings.general.scroll_marks = Skrolování v rozšířeném náhledu označí položky jako přečtené
|
||||
settings.appearance = Vzhled
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme = Motiv
|
||||
settings.submit_your_theme = Nahrát vlastní motiv
|
||||
settings.custom_css = Vlastní motiv (CSS)
|
||||
@@ -85,6 +88,7 @@ details.feed_url = URL RSS zdroje
|
||||
details.generate_api_key_first = Vygenerujte si API klíč na stránce vašeho profilu.
|
||||
details.unsubscribe = Odhlásit odběr.
|
||||
details.category_details = Detail kategorie
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category = Hlavní kategorie
|
||||
|
||||
profile.user_name = Uživatelské jméno
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Lawrlwytho
|
||||
global.link=Dolen
|
||||
global.bookmark=Nod tudalen
|
||||
global.close=Cau
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Tanysgrifio
|
||||
tree.import=Mewnforio
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Dangos ffrydiau a chategoriau gyda dim eitemau heb
|
||||
settings.general.social_buttons=Dangos botymau rhannu
|
||||
settings.general.scroll_marks=Marcio eitemau fel wedi eu darllen wrth sgrolio drwyddynt yn y golwg estynedig ###### Defnyddio gystrawen debyg i'r ddau uwch.
|
||||
settings.appearance=Golwg
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Thema
|
||||
settings.submit_your_theme=Cyflwyna dy thema
|
||||
settings.custom_css=CSS wedi'i addasu
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL Ffrwd
|
||||
details.generate_api_key_first=Rhaid creu allwedd API yn dy broffil yn gyntaf.
|
||||
details.unsubscribe=Dad-danysgrifio
|
||||
details.category_details=Manylion categori
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Categori rhiant
|
||||
|
||||
profile.user_name=Enw defnyddiwr
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Hent
|
||||
global.link=Link
|
||||
global.bookmark=Bogmærke
|
||||
global.close=Luk
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Abonner
|
||||
tree.import=Importer
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Vis abonnomenter og kategorier med læste artikler
|
||||
settings.general.social_buttons=Vis delingsknapper
|
||||
settings.general.scroll_marks=I udvidet visning, marker artikler som læste når der rulles forbi dem
|
||||
settings.appearance=Udseende
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Indsend dit tema
|
||||
settings.custom_css=Brugerdefineret CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL for abonnement
|
||||
details.generate_api_key_first=Generer en API nøgle i din profil først.
|
||||
details.unsubscribe=Afmeld abonnement
|
||||
details.category_details=Kategori detaljer
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Overordnet kategori
|
||||
|
||||
profile.user_name=Brugernavn
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Herunterladen
|
||||
global.link=Link
|
||||
global.bookmark=Lesezeichen
|
||||
global.close=Schließen
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Abonnieren
|
||||
tree.import=Importieren
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Zeige Feeds und Kategorien mit ungelesenen Einträg
|
||||
settings.general.social_buttons=Zeige Buttons zum Teilen von Inhalten über soziale Netzwerke
|
||||
settings.general.scroll_marks=In der ausgedehnten Ansicht werden Artikel beim Scrollen als gelesen markiert
|
||||
settings.appearance=Aussehen
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Theme
|
||||
settings.submit_your_theme=Füg dein Theme hinzu
|
||||
settings.custom_css=Eigenes CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Feed Adresse
|
||||
details.generate_api_key_first=Generiere zuerst einen API Schlüssel in deinem Profil.
|
||||
details.unsubscribe=Kündigen
|
||||
details.category_details=Kategoriedetails
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Übergeordnete Kategorie
|
||||
|
||||
profile.user_name=Benutzername
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Download
|
||||
global.link=Link
|
||||
global.bookmark=Bookmark
|
||||
global.close=Close
|
||||
global.tags=Tags
|
||||
|
||||
tree.subscribe=Subscribe
|
||||
tree.import=Import
|
||||
@@ -87,6 +88,7 @@ details.feed_url=Feed URL
|
||||
details.generate_api_key_first=Generate an API key in your profile first.
|
||||
details.unsubscribe=Unsubscribe
|
||||
details.category_details=Category details
|
||||
details.tag_details=Tag details
|
||||
details.parent_category=Parent category
|
||||
|
||||
profile.user_name=User name
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Descargar
|
||||
global.link=Enlace
|
||||
global.bookmark=Marcador
|
||||
global.close=Close ####### Needs translation
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Subscribir
|
||||
tree.import=Importar
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Mostrar canales y categorías sin entradas no leíd
|
||||
settings.general.social_buttons=Mostrar botones de compartir de redes sociales.
|
||||
settings.general.scroll_marks=En vista expandida, el desplazamiento por las entradas las marca como leídas
|
||||
settings.appearance=Appearance ####### Needs translation
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Theme ####### Needs translation
|
||||
settings.submit_your_theme=Submit your theme ####### Needs translation
|
||||
settings.custom_css=CSS Personalizado
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL del Canal
|
||||
details.generate_api_key_first=Genera una llave API en tu perfil primero.
|
||||
details.unsubscribe=Terminar subscripción
|
||||
details.category_details=Detalles de la categoría
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Categoría principal
|
||||
|
||||
profile.user_name=Nombre de usuario
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=بارگیری
|
||||
global.link=پیوند
|
||||
global.bookmark=بوکمارک
|
||||
global.close=بستن
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=مشترک شوید
|
||||
tree.import=درونریزی
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=تنها خوراکها و دستههای ر
|
||||
settings.general.social_buttons=نشاندادن دکمههای اشتراکگذاری در شبکههای اجتماعی
|
||||
settings.general.scroll_marks=در نمای گسترشیافته، لغزیدن بر روی مطالب بهعنوان نشانهگذاری بهعنوان خواندهشده در نظر گرفتهشوند.
|
||||
settings.appearance=ظاهر
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=پوسته
|
||||
settings.submit_your_theme=پوستهٔ خود را ارسالکنید
|
||||
settings.custom_css=سیاساس شخصیسازیشده
|
||||
@@ -85,6 +88,7 @@ details.feed_url=نشانی خوراک
|
||||
details.generate_api_key_first=ابتدا یک کلید API در نمایهٔ خود ایجاد کنید.
|
||||
details.unsubscribe=لغو اشتراک
|
||||
details.category_details=جزئیات دسته
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=ردهٔ پدر
|
||||
|
||||
profile.user_name=نام کاربری
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Lataa
|
||||
global.link=Linkki
|
||||
global.bookmark=Kirjanmerkki
|
||||
global.close=Sulje
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Tilaa syöte
|
||||
tree.import=Tuo
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Näytä syötteet ja kansiot, joissa ei ole lukemat
|
||||
settings.general.social_buttons=Näytä jakonapit
|
||||
settings.general.scroll_marks=Laajennetussa näkymässä otsikoiden selaaminen merkitsee ne luetuiksi
|
||||
settings.appearance=Ulkonäkö
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Teema
|
||||
settings.submit_your_theme=Lähetä oma teemasi
|
||||
settings.custom_css=Oma CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Syötteen osoite
|
||||
details.generate_api_key_first=Luo API-avain profiilissasi.
|
||||
details.unsubscribe=Peruuta tilaus
|
||||
details.category_details=Kansion tiedot
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Yläkansio
|
||||
|
||||
profile.user_name=Käyttäjänimi
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Télécharger
|
||||
global.link=Lien
|
||||
global.bookmark=Favoris
|
||||
global.close=Fermer
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=S'abonner
|
||||
tree.import=Importer
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Afficher les flux et les catégories pour lesquels
|
||||
settings.general.social_buttons=Afficher les boutons de partage sur réseaux sociaux
|
||||
settings.general.scroll_marks=En mode de lecture étendu, marquer comme lu les éléments lorsque la fenêtre descend.
|
||||
settings.appearance=Apparence
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Thème
|
||||
settings.submit_your_theme=Soumettez votre thème.
|
||||
settings.custom_css=CSS personnelle
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL du flux
|
||||
details.generate_api_key_first=Générez une clé API dans votre profil d'abord.
|
||||
details.unsubscribe=Se désabonner
|
||||
details.category_details=Détails de la catégorie
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Catégorie parente
|
||||
|
||||
profile.user_name=Nom
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Descargar
|
||||
global.link=Ligazón
|
||||
global.bookmark=Marcador
|
||||
global.close=Pechar
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Subscribir
|
||||
tree.import=Importar
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Mostrar fontes e categorías sen entradas non lidas
|
||||
settings.general.social_buttons=Mostrar botóns de compartir en redes sociais.
|
||||
settings.general.scroll_marks=En vista expandida, o desplazamento polas entradas márcaas como lidas.
|
||||
settings.appearance=Aspecto
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Decorado
|
||||
settings.submit_your_theme=Envíe o seu decorado
|
||||
settings.custom_css=CSS Personalizado
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL da fonte
|
||||
details.generate_api_key_first=Antes debes xerar unha chave API no teu perfil.
|
||||
details.unsubscribe=Rematar suscripción
|
||||
details.category_details=Detalles da categoría
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Categoría principal
|
||||
|
||||
profile.user_name=Nome de usuario
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=جیرأکش
|
||||
global.link=خال
|
||||
global.bookmark=بوکمارک
|
||||
global.close=دَوَستن
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=مشترک ببید
|
||||
tree.import=درینأدأن
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=تنها خوراکها و دستههای ر
|
||||
settings.general.social_buttons=نشاندادن دکمههای اشتراکگذاری در شبکههای اجتماعی
|
||||
settings.general.scroll_marks=در نمای گسترشیافته، لغزیدن بر روی مطالب بهعنوان نشانهگذاری بهعنوان خواندهشده در نظر گرفتهشوند.
|
||||
settings.appearance=ظاهر
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=پوسته
|
||||
settings.submit_your_theme=شیمه پوستهٰ اوسه کونید
|
||||
settings.custom_css=سیاساس شخصیسازیشده
|
||||
@@ -85,6 +88,7 @@ details.feed_url=نشانی خوراک
|
||||
details.generate_api_key_first=ابتدا یک کلید API در نمایهٔ خود ایجاد کنید.
|
||||
details.unsubscribe=لغو اشتراک
|
||||
details.category_details=جرگه جزئیات
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=پئرˇ جرگه
|
||||
|
||||
profile.user_name=کاربری نام
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Letöltés
|
||||
global.link=Link
|
||||
global.bookmark=Könyvjelző
|
||||
global.close=Bezár
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Feliratkozás
|
||||
tree.import=Importálás
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Mutassa azokat a hírcsatornákat és kategóriáka
|
||||
settings.general.social_buttons=Mutassa a közösségi oldalak megosztás gombjait
|
||||
settings.general.scroll_marks=Kiterjesztett nézetben, görgetéssel olvasottként jelöli meg a bejegyzést
|
||||
settings.appearance=Megjelenés
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Téma
|
||||
settings.submit_your_theme=Küldje el a témáját
|
||||
settings.custom_css=Saját CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Hírcsatorna URL
|
||||
details.generate_api_key_first=A profiljában először egy API kulcsot kell generálnia.
|
||||
details.unsubscribe=Leiratkozás
|
||||
details.category_details=Kategória részletei
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Szülő kategória
|
||||
|
||||
profile.user_name=Felhasználói név
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Download
|
||||
global.link=Link
|
||||
global.bookmark=Segnalibro
|
||||
global.close=Chiudi
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Iscriviti
|
||||
tree.import=Importa
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Show feeds and categories with no unread entries
|
||||
settings.general.social_buttons=Visualizza i social button
|
||||
settings.general.scroll_marks=Marca come letto quando scorri
|
||||
settings.appearance=Appearance ####### Needs translation
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Sottoponi il tuo tema
|
||||
settings.custom_css=Css modificato
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Feed URL
|
||||
details.generate_api_key_first=Generate an API key in your profile first.
|
||||
details.unsubscribe=Annulla l"'"iscrizione
|
||||
details.category_details=Dettagli categoria
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Parent category
|
||||
|
||||
profile.user_name=User name
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Download ####### Needs translation
|
||||
global.link=Link ####### Needs translation
|
||||
global.bookmark=Bookmark ####### Needs translation
|
||||
global.close=Close ####### Needs translation
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=구독
|
||||
tree.import=임포트
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=안읽은 항목들이 있는 피드와 카테고
|
||||
settings.general.social_buttons=소셜미디아 버튼들 보여주기
|
||||
settings.general.scroll_marks=Expanded View에서 스크롤하면 항목들을 읽음으로 저장하기
|
||||
settings.appearance=Appearance ####### Needs translation
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Theme ####### Needs translation
|
||||
settings.submit_your_theme=Submit your theme ####### Needs translation
|
||||
settings.custom_css=커스톰 CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=피드 유알엘
|
||||
details.generate_api_key_first=당신의 프로필을 위해 API Key를 먼저 생성하세요.
|
||||
details.unsubscribe=주소 삭제
|
||||
details.category_details=카테고리 세부
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=부모 카테고리
|
||||
|
||||
profile.user_name=사용자 이름
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Muat turun
|
||||
global.link=Pautan
|
||||
global.bookmark=Bookmark
|
||||
global.close=Tutup
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Langgan
|
||||
tree.import=Import
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Tunjuk semua feed dan kategori yang telah dibaca
|
||||
settings.general.social_buttons=Tunjuk social sharing
|
||||
settings.general.scroll_marks=Dalam wide view, tanda item dibaca ketika scrolling
|
||||
settings.appearance=Rupa
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Muat naik tema anda
|
||||
settings.custom_css=Custom CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL Feed
|
||||
details.generate_api_key_first=Janakan API key dalam profil anda dahulu.
|
||||
details.unsubscribe=Hentikan langganan
|
||||
details.category_details=Butir-butir kategori
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Kategori induk
|
||||
|
||||
profile.user_name=User name
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Last ned
|
||||
global.link=Lenke
|
||||
global.bookmark=Bokmerke
|
||||
global.close=Lukk
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Abonner
|
||||
tree.import=Importer
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Vis abonnementer og kategorier uten nye artikler
|
||||
settings.general.social_buttons=Vis delingsknapper
|
||||
settings.general.scroll_marks=I utvidet visning, merk artikler som leste når du blar deg forbi dem.
|
||||
settings.appearance=Utseende
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Drakt
|
||||
settings.submit_your_theme=Legg til egen drakt
|
||||
settings.custom_css=Egendefinert CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL for abonnement
|
||||
details.generate_api_key_first=Generer en API-nøkkel under profilinnstillinger først.
|
||||
details.unsubscribe=Avslutt abonnement
|
||||
details.category_details=Kategoridetaljer
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Overordnet kategori
|
||||
|
||||
profile.user_name=Brukernavn
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Download
|
||||
global.link=Link
|
||||
global.bookmark=Bookmark
|
||||
global.close=Sluiten
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Abonneer
|
||||
tree.import=Importeer
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Laat feeds en categorieën zonder ongelezen artikel
|
||||
settings.general.social_buttons=Laat Social Media knoppen zien
|
||||
settings.general.scroll_marks=Markeer artikelen als gelezen, wanneer je er doorheen scrollt
|
||||
settings.appearance=Uiterlijk
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Thema
|
||||
settings.submit_your_theme=Stuur thema in
|
||||
settings.custom_css=Custom CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Feed URL
|
||||
details.generate_api_key_first=Genereer eerst een API sleutel in je profiel.
|
||||
details.unsubscribe=Abonnement opzeggen
|
||||
details.category_details=Categorie details
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Bovenliggende categorie
|
||||
|
||||
profile.user_name=Gebruikersnaam
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Last ned
|
||||
global.link=Lenkje
|
||||
global.bookmark=Bokmerke
|
||||
global.close=Lukk
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Abonner
|
||||
tree.import=Importer
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Vis abonnement og kategoriar utan nye artiklar
|
||||
settings.general.social_buttons=Vis delingsknappar
|
||||
settings.general.scroll_marks=I utvida visning, merk artiklar som lesne når du blar deg forbi dei.
|
||||
settings.appearance=Utsjånad
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Drakt
|
||||
settings.submit_your_theme=Legg til eiga drakt
|
||||
settings.custom_css=Skreddarsydd CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL for abonnement
|
||||
details.generate_api_key_first=Generer ein API-nykel under profilinnstillingar fyrst.
|
||||
details.unsubscribe=Avslutt abonnement
|
||||
details.category_details=Kategoridetaljar
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Overordna kategori
|
||||
|
||||
profile.user_name=Brukarnamn
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Pobierz
|
||||
global.link=Odnośnik
|
||||
global.bookmark=Zakładka
|
||||
global.close=Zamknij
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Subskrybuj
|
||||
tree.import=Importuj
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Pokaż kanały i kategorie bez nieprzeczytanych ele
|
||||
settings.general.social_buttons=Pokaż przyciski udostępniania
|
||||
settings.general.scroll_marks=W widoku rozwiniętym przewijanie oznacza elementy jako przeczytane
|
||||
settings.appearance=Wygląd
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Motyw
|
||||
settings.submit_your_theme=Wyślij swój motyw
|
||||
settings.custom_css=Własny styl CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL kanału
|
||||
details.generate_api_key_first=Najpierw wygeneruj klucz API w swoim profilu.
|
||||
details.unsubscribe=Cofnij subskrypcje
|
||||
details.category_details=Szczegóły kategorii
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Kategoria nadrzędna
|
||||
|
||||
profile.user_name=Nazwa użytkownika
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Download
|
||||
global.link=Link
|
||||
global.bookmark=Favorito
|
||||
global.close=Fechar
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Inscrever-se
|
||||
tree.import=Importar
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Mostrar feeds e categorias sem itens não lidos
|
||||
settings.general.social_buttons=Mostrar botões de mídias sociais
|
||||
settings.general.scroll_marks=No modo expandido, percorrer os itens marca-os como lidos
|
||||
settings.appearance=Aparência
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Envie seu tema
|
||||
settings.custom_css=CSS personalizado
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL do feed
|
||||
details.generate_api_key_first=Gerar uma chave de API em seu perfil primeiro.
|
||||
details.unsubscribe=Cancelar inscrição
|
||||
details.category_details=Detalhes da categoria
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Categoria pai
|
||||
|
||||
profile.user_name=Nome de usuário
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Скачать
|
||||
global.link=Ссылка
|
||||
global.bookmark=Закладка
|
||||
global.close=Закрыть
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Подписаться
|
||||
tree.import=Импорт
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Показывать прочтённые лент
|
||||
settings.general.social_buttons=Показывать социальные кнопки
|
||||
settings.general.scroll_marks=В развёрнутом виде помечать записи как прочитанные по мере прокрутки
|
||||
settings.appearance=Вид
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Тема
|
||||
settings.submit_your_theme=Добавьте свою тему
|
||||
settings.custom_css=Собственная CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Адрес ленты
|
||||
details.generate_api_key_first=Сначала сгенерируйте API-ключ в вашем профиле.
|
||||
details.unsubscribe=Отписаться
|
||||
details.category_details=Информация о категории
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Родительская категория
|
||||
|
||||
profile.user_name=Имя пользователя
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=Stiahnuť
|
||||
global.link=Link
|
||||
global.bookmark=Záložky
|
||||
global.close=Zavrieť
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Odoberať
|
||||
tree.import=Importovať
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Zobraziť príspevky a kategórie bez neprečítan
|
||||
settings.general.social_buttons=Zobraziť možnosti zdieľania
|
||||
settings.general.scroll_marks=Scrollovanie v rozšírenom náhľade označí položky ako prečítané
|
||||
settings.appearance=Vzhľad
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Motív
|
||||
settings.submit_your_theme=Nahrať vlastný motív vzhľadu
|
||||
settings.custom_css=Vlastný motív vzhľadu (CSS)
|
||||
@@ -85,6 +88,7 @@ details.feed_url=URL RSS zdroja
|
||||
details.generate_api_key_first=Vygenerujte si API kľúč vo vašom profile.
|
||||
details.unsubscribe=Zrušiť odoberanie.
|
||||
details.category_details=Detaily kategórie
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Hlavná kategória
|
||||
|
||||
profile.user_name=Uživateľské meno
|
||||
|
||||
@@ -1,150 +1,154 @@
|
||||
global.save=Spara
|
||||
global.cancel=Avbryt
|
||||
global.delete=Radera
|
||||
global.required=Obligatorisk
|
||||
global.download=Ladda ned
|
||||
global.link=Länka
|
||||
global.bookmark=Bokmärk
|
||||
global.close=Stäng
|
||||
|
||||
tree.subscribe=Prenumerera
|
||||
tree.import=Importera
|
||||
tree.new_category=Ny kategori
|
||||
tree.all=Alla
|
||||
tree.starred=Stjärnmärkt
|
||||
|
||||
subscribe.feed_url=Prenumerationens URL
|
||||
subscribe.feed_name=Prenumerationens namn
|
||||
subscribe.category=Kategori
|
||||
|
||||
import.google_reader_prefix=Låt mig importera dina prenumerationer från ditt
|
||||
import.google_reader_suffix=-konto.
|
||||
import.google_download=Alternativt, ladda upp din subscriptions.xml-fil.
|
||||
import.google_download_link=Ladda ned den här.
|
||||
import.xml_file=OPML-fil
|
||||
|
||||
new_category.name=Namn
|
||||
new_category.parent=Överordnad
|
||||
|
||||
toolbar.unread=Oläst
|
||||
toolbar.all=Alla
|
||||
toolbar.previous_entry=Föregående post
|
||||
toolbar.next_entry=Nästa post
|
||||
toolbar.refresh=Uppdatera
|
||||
toolbar.refresh_all=Tvinga uppdatering av alla prenumerationer
|
||||
toolbar.sort_by_asc_desc=Sortera efter datum stigande/fallande
|
||||
toolbar.titles_only=Endast titlar
|
||||
toolbar.expanded_view=Expanderad vy
|
||||
toolbar.mark_all_as_read=Markera alla som lästa
|
||||
toolbar.mark_all_older_12_hours=Poster äldre än 12 timmar
|
||||
toolbar.mark_all_older_day=Poster äldre än en dag
|
||||
toolbar.mark_all_older_week=Poster äldre än en vecka
|
||||
toolbar.mark_all_older_two_weeks=Poster äldre än två veckor
|
||||
toolbar.settings=Inställningar
|
||||
toolbar.profile=Profil
|
||||
toolbar.admin=Administratör
|
||||
toolbar.about=Om
|
||||
toolbar.logout=Logga ut
|
||||
toolbar.donate=Donera
|
||||
|
||||
view.entry_source=från
|
||||
view.entry_author=av
|
||||
view.error_while_loading_feed=Fel under laddning av denna prenumeration
|
||||
view.keep_unread=Håll oläst
|
||||
view.no_unread_items=har inga olästa poster.
|
||||
view.mark_up_to_here=Markera som läst upp till denna post
|
||||
view.search_for=söker efter:
|
||||
view.no_search_results=Inga resultat för valda nyckelord
|
||||
|
||||
feedsearch.hint=Skriv in en prenumeration...
|
||||
feedsearch.help=Använd retur-tangenten för att välja och piltangenterna för att navigera.
|
||||
feedsearch.result_prefix=Dina prenumerationer:
|
||||
|
||||
settings.general=Allmänt
|
||||
settings.general.language=Språk
|
||||
settings.general.language.contribute=Bidra med översättningar
|
||||
settings.general.show_unread=Visa prenumerationer och kategorier utan olästa poster
|
||||
settings.general.social_buttons=Visa delningsknappar
|
||||
settings.general.scroll_marks=I expanderad vy, markera poster som lästa genom att scrolla förbi dem
|
||||
settings.appearance=Utseende
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Skicka in ditt tema
|
||||
settings.custom_css=Anpassad CSS
|
||||
|
||||
details.feed_details=Prenumerationsdetaljer
|
||||
details.url=URL
|
||||
details.website=Webbsida
|
||||
details.name=Namn
|
||||
details.category=Kategori
|
||||
details.position=Position
|
||||
details.last_refresh=Senaste uppdatering
|
||||
details.message=Senaste uppdateringsmeddelande
|
||||
details.next_refresh=Nästa uppdatering
|
||||
details.queued_for_refresh=I kö för uppdatering
|
||||
details.feed_url=Prenumerationens URL
|
||||
details.generate_api_key_first=Skapa en API-nyckel på din profil först.
|
||||
details.unsubscribe=Avprenumerera
|
||||
details.category_details=Kategoridetaljer
|
||||
details.parent_category=Överordnad kategori
|
||||
|
||||
profile.user_name=Användarnamn
|
||||
profile.email=E-mail
|
||||
profile.change_password=Ändra lösenord
|
||||
profile.confirm_password=Bekräfta lösenord
|
||||
profile.minimum_6_chars=Minst 6 bokstäver
|
||||
profile.passwords_do_not_match=Lösenorden matchar inte
|
||||
profile.api_key=API-nyckel
|
||||
profile.api_key_not_generated=Inte skapad än
|
||||
profile.generate_new_api_key=Skapa ny API-nyckel
|
||||
profile.generate_new_api_key_info=Lösenordsbyte skapar ny API-nyckel
|
||||
profile.opml_export=OPML-export
|
||||
profile.delete_account=Radera konto
|
||||
|
||||
about.rest_api=REST-API
|
||||
about.keyboard_shortcuts=Tangentbordsgenvägar
|
||||
about.version=CommaFeed-version
|
||||
about.line1_prefix=CommaFeed är ett open-source-projekt. Källan är tillgänglig på
|
||||
about.line1_suffix=.
|
||||
about.line2_prefix=Om du träffar på ett problem, meddela det på "Issues"-sidan för
|
||||
about.line2_suffix=-projektet.
|
||||
about.line3=Om du gillar detta projekt, avväg gärna en donation för att stötta utvecklaren och bidra till kostnaderna för att hålla denna site online.
|
||||
about.line4=För er som föredrar Bitcoin, här är adressen
|
||||
about.goodies=Godsaker
|
||||
about.goodies.android_app=Android-app
|
||||
about.goodies.subscribe_url=Prenumerations-URL
|
||||
about.goodies.chrome_extension=Chrome-tillägg
|
||||
about.goodies.firefox_extension=Firefox-tillägg
|
||||
about.goodies.opera_extension=Opera-tillägg
|
||||
about.goodies.subscribe_bookmarklet=Bokmärke för tillägg av prenumeration (klicka)
|
||||
about.goodies.subscribe_bookmarklet_asc=äldst först
|
||||
about.goodies.subscribe_bookmarklet_desc=nyast först
|
||||
about.goodies.next_unread_bookmarklet=Bokmärke för nästa olästa post (dra till bokmärkesfält)
|
||||
about.translation=Översättning
|
||||
about.translation.message=Vi behöver din hjälp med att översätta CommaFeed.
|
||||
about.translation.link=Se hur du kan bidra med översättningar.
|
||||
about.announcements=Notiser
|
||||
about.rest_api.line1=CommaFeed är byggt på JAX-RS och AngularJS. Tack vare detta är en REST-API tillgänglig.
|
||||
about.rest_api.link_to_documentation=Länk till dokumentation.
|
||||
|
||||
about.shortcuts.mouse_middleclick=mitten-musknapp
|
||||
about.shortcuts.open_next_entry=öppna nästa post
|
||||
about.shortcuts.open_previous_entry=öppna föregående post
|
||||
about.shortcuts.spacebar=mellanslag/shift+mellanslag
|
||||
about.shortcuts.move_page_down_up=flyttar sidan ned/upp
|
||||
about.shortcuts.focus_next_entry=sätt fokus på nästa post utan att öppna
|
||||
about.shortcuts.focus_previous_entry=sätt fokus på föregående post utan att öppna
|
||||
about.shortcuts.open_next_feed=öppna nästa prenumeration eller kategori
|
||||
about.shortcuts.open_previous_feed=öppna föregående prenumeration eller kategori
|
||||
about.shortcuts.open_close_current_entry=öppna/stäng nuvarande post
|
||||
about.shortcuts.open_current_entry_in_new_window=öppna nuvarande post i nytt fönster
|
||||
about.shortcuts.open_current_entry_in_new_window_background=öppna nuvarande post i nytt bakgrundsfönster
|
||||
about.shortcuts.star_unstar=stjärnmärk/ostjärnmärk nuvarande post
|
||||
about.shortcuts.mark_current_entry=markera nuvarande post läst/oläst
|
||||
about.shortcuts.mark_all_as_read=markera alla som lästa
|
||||
about.shortcuts.open_in_new_tab_mark_as_read=öppna nuvarande post i ny flik och markera som läst
|
||||
about.shortcuts.fullscreen=växla till/från fullskärmsläge
|
||||
about.shortcuts.font_size=öka/minska teckenstorlek av nuvarande post
|
||||
about.shortcuts.go_to_all=se alla poster
|
||||
about.shortcuts.go_to_starred=se stjärnmärkta poster
|
||||
about.shortcuts.feed_search=navigera till en prenumeration via prenumerationsnamn
|
||||
|
||||
global.save=Spara
|
||||
global.cancel=Avbryt
|
||||
global.delete=Radera
|
||||
global.required=Obligatorisk
|
||||
global.download=Ladda ned
|
||||
global.link=Länka
|
||||
global.bookmark=Bokmärk
|
||||
global.close=Stäng
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Prenumerera
|
||||
tree.import=Importera
|
||||
tree.new_category=Ny kategori
|
||||
tree.all=Alla
|
||||
tree.starred=Stjärnmärkt
|
||||
|
||||
subscribe.feed_url=Prenumerationens URL
|
||||
subscribe.feed_name=Prenumerationens namn
|
||||
subscribe.category=Kategori
|
||||
|
||||
import.google_reader_prefix=Låt mig importera dina prenumerationer från ditt
|
||||
import.google_reader_suffix=-konto.
|
||||
import.google_download=Alternativt, ladda upp din subscriptions.xml-fil.
|
||||
import.google_download_link=Ladda ned den här.
|
||||
import.xml_file=OPML-fil
|
||||
|
||||
new_category.name=Namn
|
||||
new_category.parent=Överordnad
|
||||
|
||||
toolbar.unread=Oläst
|
||||
toolbar.all=Alla
|
||||
toolbar.previous_entry=Föregående post
|
||||
toolbar.next_entry=Nästa post
|
||||
toolbar.refresh=Uppdatera
|
||||
toolbar.refresh_all=Tvinga uppdatering av alla prenumerationer
|
||||
toolbar.sort_by_asc_desc=Sortera efter datum stigande/fallande
|
||||
toolbar.titles_only=Endast titlar
|
||||
toolbar.expanded_view=Expanderad vy
|
||||
toolbar.mark_all_as_read=Markera alla som lästa
|
||||
toolbar.mark_all_older_12_hours=Poster äldre än 12 timmar
|
||||
toolbar.mark_all_older_day=Poster äldre än en dag
|
||||
toolbar.mark_all_older_week=Poster äldre än en vecka
|
||||
toolbar.mark_all_older_two_weeks=Poster äldre än två veckor
|
||||
toolbar.settings=Inställningar
|
||||
toolbar.profile=Profil
|
||||
toolbar.admin=Administratör
|
||||
toolbar.about=Om
|
||||
toolbar.logout=Logga ut
|
||||
toolbar.donate=Donera
|
||||
|
||||
view.entry_source=från
|
||||
view.entry_author=av
|
||||
view.error_while_loading_feed=Fel under laddning av denna prenumeration
|
||||
view.keep_unread=Håll oläst
|
||||
view.no_unread_items=har inga olästa poster.
|
||||
view.mark_up_to_here=Markera som läst upp till denna post
|
||||
view.search_for=söker efter:
|
||||
view.no_search_results=Inga resultat för valda nyckelord
|
||||
|
||||
feedsearch.hint=Skriv in en prenumeration...
|
||||
feedsearch.help=Använd retur-tangenten för att välja och piltangenterna för att navigera.
|
||||
feedsearch.result_prefix=Dina prenumerationer:
|
||||
|
||||
settings.general=Allmänt
|
||||
settings.general.language=Språk
|
||||
settings.general.language.contribute=Bidra med översättningar
|
||||
settings.general.show_unread=Visa prenumerationer och kategorier utan olästa poster
|
||||
settings.general.social_buttons=Visa delningsknappar
|
||||
settings.general.scroll_marks=I expanderad vy, markera poster som lästa genom att scrolla förbi dem
|
||||
settings.appearance=Utseende
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Skicka in ditt tema
|
||||
settings.custom_css=Anpassad CSS
|
||||
|
||||
details.feed_details=Prenumerationsdetaljer
|
||||
details.url=URL
|
||||
details.website=Webbsida
|
||||
details.name=Namn
|
||||
details.category=Kategori
|
||||
details.position=Position
|
||||
details.last_refresh=Senaste uppdatering
|
||||
details.message=Senaste uppdateringsmeddelande
|
||||
details.next_refresh=Nästa uppdatering
|
||||
details.queued_for_refresh=I kö för uppdatering
|
||||
details.feed_url=Prenumerationens URL
|
||||
details.generate_api_key_first=Skapa en API-nyckel på din profil först.
|
||||
details.unsubscribe=Avprenumerera
|
||||
details.category_details=Kategoridetaljer
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Överordnad kategori
|
||||
|
||||
profile.user_name=Användarnamn
|
||||
profile.email=E-mail
|
||||
profile.change_password=Ändra lösenord
|
||||
profile.confirm_password=Bekräfta lösenord
|
||||
profile.minimum_6_chars=Minst 6 bokstäver
|
||||
profile.passwords_do_not_match=Lösenorden matchar inte
|
||||
profile.api_key=API-nyckel
|
||||
profile.api_key_not_generated=Inte skapad än
|
||||
profile.generate_new_api_key=Skapa ny API-nyckel
|
||||
profile.generate_new_api_key_info=Lösenordsbyte skapar ny API-nyckel
|
||||
profile.opml_export=OPML-export
|
||||
profile.delete_account=Radera konto
|
||||
|
||||
about.rest_api=REST-API
|
||||
about.keyboard_shortcuts=Tangentbordsgenvägar
|
||||
about.version=CommaFeed-version
|
||||
about.line1_prefix=CommaFeed är ett open-source-projekt. Källan är tillgänglig på
|
||||
about.line1_suffix=.
|
||||
about.line2_prefix=Om du träffar på ett problem, meddela det på "Issues"-sidan för
|
||||
about.line2_suffix=-projektet.
|
||||
about.line3=Om du gillar detta projekt, avväg gärna en donation för att stötta utvecklaren och bidra till kostnaderna för att hålla denna site online.
|
||||
about.line4=För er som föredrar Bitcoin, här är adressen
|
||||
about.goodies=Godsaker
|
||||
about.goodies.android_app=Android-app
|
||||
about.goodies.subscribe_url=Prenumerations-URL
|
||||
about.goodies.chrome_extension=Chrome-tillägg
|
||||
about.goodies.firefox_extension=Firefox-tillägg
|
||||
about.goodies.opera_extension=Opera-tillägg
|
||||
about.goodies.subscribe_bookmarklet=Bokmärke för tillägg av prenumeration (klicka)
|
||||
about.goodies.subscribe_bookmarklet_asc=äldst först
|
||||
about.goodies.subscribe_bookmarklet_desc=nyast först
|
||||
about.goodies.next_unread_bookmarklet=Bokmärke för nästa olästa post (dra till bokmärkesfält)
|
||||
about.translation=Översättning
|
||||
about.translation.message=Vi behöver din hjälp med att översätta CommaFeed.
|
||||
about.translation.link=Se hur du kan bidra med översättningar.
|
||||
about.announcements=Notiser
|
||||
about.rest_api.line1=CommaFeed är byggt på JAX-RS och AngularJS. Tack vare detta är en REST-API tillgänglig.
|
||||
about.rest_api.link_to_documentation=Länk till dokumentation.
|
||||
|
||||
about.shortcuts.mouse_middleclick=mitten-musknapp
|
||||
about.shortcuts.open_next_entry=öppna nästa post
|
||||
about.shortcuts.open_previous_entry=öppna föregående post
|
||||
about.shortcuts.spacebar=mellanslag/shift+mellanslag
|
||||
about.shortcuts.move_page_down_up=flyttar sidan ned/upp
|
||||
about.shortcuts.focus_next_entry=sätt fokus på nästa post utan att öppna
|
||||
about.shortcuts.focus_previous_entry=sätt fokus på föregående post utan att öppna
|
||||
about.shortcuts.open_next_feed=öppna nästa prenumeration eller kategori
|
||||
about.shortcuts.open_previous_feed=öppna föregående prenumeration eller kategori
|
||||
about.shortcuts.open_close_current_entry=öppna/stäng nuvarande post
|
||||
about.shortcuts.open_current_entry_in_new_window=öppna nuvarande post i nytt fönster
|
||||
about.shortcuts.open_current_entry_in_new_window_background=öppna nuvarande post i nytt bakgrundsfönster
|
||||
about.shortcuts.star_unstar=stjärnmärk/ostjärnmärk nuvarande post
|
||||
about.shortcuts.mark_current_entry=markera nuvarande post läst/oläst
|
||||
about.shortcuts.mark_all_as_read=markera alla som lästa
|
||||
about.shortcuts.open_in_new_tab_mark_as_read=öppna nuvarande post i ny flik och markera som läst
|
||||
about.shortcuts.fullscreen=växla till/från fullskärmsläge
|
||||
about.shortcuts.font_size=öka/minska teckenstorlek av nuvarande post
|
||||
about.shortcuts.go_to_all=se alla poster
|
||||
about.shortcuts.go_to_starred=se stjärnmärkta poster
|
||||
about.shortcuts.feed_search=navigera till en prenumeration via prenumerationsnamn
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=İndir
|
||||
global.link=Bağlantı
|
||||
global.bookmark=Yer imi
|
||||
global.close=Kapat
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=Abone ol
|
||||
tree.import=İçe aktar
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=Okunmamış öğesi bulunan yayın ve kategorileri
|
||||
settings.general.social_buttons=Sosyal paylaşım butonlarını göster
|
||||
settings.general.scroll_marks=Genişletilmiş görünümde götüntülenen iletileri okunmuş işaretle
|
||||
settings.appearance=Görünüm
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=Tema
|
||||
settings.submit_your_theme=Tema gönder
|
||||
settings.custom_css=Kişiselleştirilmiş CSS
|
||||
@@ -85,6 +88,7 @@ details.feed_url=Yayın URL'si
|
||||
details.generate_api_key_first=Öncelikle profilinizden bir API anahtarı oluşturun.
|
||||
details.unsubscribe=Aboneliği iptal et
|
||||
details.category_details=Kategori detayları
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=Üst kategori
|
||||
|
||||
profile.user_name=Kullanıcı adı
|
||||
|
||||
@@ -6,6 +6,7 @@ global.download=下载
|
||||
global.link=链接
|
||||
global.bookmark=书签
|
||||
global.close=关闭
|
||||
global.tags=Tags ####### Needs translation
|
||||
|
||||
tree.subscribe=订阅
|
||||
tree.import=导入
|
||||
@@ -67,6 +68,8 @@ settings.general.show_unread=显示未读的订阅和目录条目
|
||||
settings.general.social_buttons=显示分享按钮
|
||||
settings.general.scroll_marks=在扩展视图中,可滚动条目将其标记为已读
|
||||
settings.appearance=外观
|
||||
settings.scroll_speed=Scrolling speed when navigating between entries (in milliseconds) ####### Needs translation
|
||||
settings.scroll_speed.help=set to 0 to disable ####### Needs translation
|
||||
settings.theme=主题
|
||||
settings.submit_your_theme=提交你的主题
|
||||
settings.custom_css=自定义 CSS 样式
|
||||
@@ -85,6 +88,7 @@ details.feed_url=订阅地址
|
||||
details.generate_api_key_first=在您的配置文件中首先生成一个 API 密钥。
|
||||
details.unsubscribe=取消订阅
|
||||
details.category_details=目录详情
|
||||
details.tag_details=Tag details ####### Needs translation
|
||||
details.parent_category=上一层目录
|
||||
|
||||
profile.user_name=用户名
|
||||
|
||||
@@ -125,17 +125,40 @@ module.controller('SubscribeCtrl', ['$scope', 'FeedService', 'CategoryService',
|
||||
}]);
|
||||
|
||||
module.controller('CategoryTreeCtrl', ['$scope', '$timeout', '$stateParams', '$window', '$location', '$state', '$route', 'CategoryService',
|
||||
'AnalyticsService',
|
||||
function($scope, $timeout, $stateParams, $window, $location, $state, $route, CategoryService, AnalyticsService) {
|
||||
'AnalyticsService', 'EntryService',
|
||||
function($scope, $timeout, $stateParams, $window, $location, $state, $route, CategoryService, AnalyticsService, EntryService) {
|
||||
|
||||
$scope.selectedType = $stateParams._type;
|
||||
$scope.selectedId = $stateParams._id;
|
||||
|
||||
$scope.EntryService = EntryService;
|
||||
|
||||
$scope.starred = {
|
||||
id : 'starred',
|
||||
name : 'Starred'
|
||||
};
|
||||
|
||||
$scope.tags = [];
|
||||
$scope.$watch('EntryService.tags', function(newValue, oldValue) {
|
||||
if (newValue) {
|
||||
$scope.tags = [];
|
||||
_.each(newValue, function(e) {
|
||||
$scope.tags.push({
|
||||
id : e,
|
||||
name : e,
|
||||
isTag : true
|
||||
});
|
||||
});
|
||||
}
|
||||
}, true);
|
||||
|
||||
$scope.toTag = function(tag) {
|
||||
$state.transitionTo('feeds.view', {
|
||||
_type : 'tag',
|
||||
_id : tag
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on('$stateChangeSuccess', function() {
|
||||
$scope.selectedType = $stateParams._type;
|
||||
$scope.selectedId = $stateParams._id;
|
||||
@@ -201,7 +224,7 @@ module.controller('CategoryTreeCtrl', ['$scope', '$timeout', '$stateParams', '$w
|
||||
|
||||
var getCurrentIndex = function(id, type, flat) {
|
||||
var index = -1;
|
||||
for ( var i = 0; i < flat.length; i++) {
|
||||
for (var i = 0; i < flat.length; i++) {
|
||||
var node = flat[i];
|
||||
if (node[0] == id && node[1] == type) {
|
||||
index = i;
|
||||
@@ -355,7 +378,7 @@ module.controller('CategoryDetailsCtrl', ['$scope', '$state', '$stateParams', 'F
|
||||
};
|
||||
return;
|
||||
}
|
||||
for ( var i = 0; i < CategoryService.flatCategories.length; i++) {
|
||||
for (var i = 0; i < CategoryService.flatCategories.length; i++) {
|
||||
var cat = CategoryService.flatCategories[i];
|
||||
if (cat.id == $stateParams._id) {
|
||||
$scope.category = {
|
||||
@@ -423,6 +446,65 @@ module.controller('CategoryDetailsCtrl', ['$scope', '$state', '$stateParams', 'F
|
||||
};
|
||||
}]);
|
||||
|
||||
module.controller('TagDetailsCtrl', ['$scope', '$state', '$stateParams', 'FeedService', 'CategoryService', 'ProfileService', '$dialog',
|
||||
function($scope, $state, $stateParams, FeedService, CategoryService, ProfileService, $dialog) {
|
||||
$scope.CategoryService = CategoryService;
|
||||
$scope.user = ProfileService.get();
|
||||
|
||||
$scope.tag = $stateParams._id;
|
||||
|
||||
$scope.back = function() {
|
||||
$state.transitionTo('feeds.view', {
|
||||
_id : $scope.tag,
|
||||
_type : 'tag'
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteTag = function() {
|
||||
var category = $scope.category;
|
||||
var title = 'Delete tag';
|
||||
var msg = 'Delete tag ' + tag + ' ?';
|
||||
var btns = [{
|
||||
result : 'cancel',
|
||||
label : 'Cancel'
|
||||
}, {
|
||||
result : 'ok',
|
||||
label : 'OK',
|
||||
cssClass : 'btn-primary'
|
||||
}];
|
||||
|
||||
$dialog.messageBox(title, msg, btns).open().then(function(result) {
|
||||
if (result == 'ok') {
|
||||
CategoryService.remove({
|
||||
id : category.id
|
||||
}, function() {
|
||||
CategoryService.init();
|
||||
});
|
||||
$state.transitionTo('feeds.view', {
|
||||
_id : 'all',
|
||||
_type : 'category'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.save = function() {
|
||||
var cat = $scope.category;
|
||||
CategoryService.modify({
|
||||
id : cat.id,
|
||||
name : cat.name,
|
||||
position : cat.position,
|
||||
parentId : cat.parentId
|
||||
}, function() {
|
||||
CategoryService.init();
|
||||
$state.transitionTo('feeds.view', {
|
||||
_id : 'all',
|
||||
_type : 'category'
|
||||
});
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
||||
module.controller('ToolbarCtrl', [
|
||||
'$scope',
|
||||
'$http',
|
||||
@@ -501,7 +583,7 @@ module.controller('ToolbarCtrl', [
|
||||
$scope.markAllAsRead = function() {
|
||||
markAll();
|
||||
};
|
||||
|
||||
|
||||
$scope.markAll12Hours = function() {
|
||||
markAll(new Date().getTime() - 43200000);
|
||||
};
|
||||
@@ -574,7 +656,7 @@ module.controller('FeedSearchCtrl', ['$scope', '$state', '$filter', '$timeout',
|
||||
}
|
||||
|
||||
var filtered = $scope.filtered;
|
||||
for ( var i = 0; i < filtered.length; i++) {
|
||||
for (var i = 0; i < filtered.length; i++) {
|
||||
if ($scope.focus.id == filtered[i].id) {
|
||||
index = i;
|
||||
break;
|
||||
@@ -706,6 +788,12 @@ module.controller('FeedListCtrl', [
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('settingsService.settings.readingOrder', function(newValue, oldValue) {
|
||||
if (newValue && oldValue && newValue != oldValue) {
|
||||
$scope.$emit('emitReload');
|
||||
}
|
||||
});
|
||||
|
||||
$scope.limit = SettingsService.settings.viewMode == 'title' ? 10 : 5;
|
||||
$scope.busy = false;
|
||||
$scope.hasMore = true;
|
||||
@@ -733,7 +821,7 @@ module.controller('FeedListCtrl', [
|
||||
}
|
||||
|
||||
var callback = function(data) {
|
||||
for ( var i = 0; i < data.entries.length; i++) {
|
||||
for (var i = 0; i < data.entries.length; i++) {
|
||||
var entry = data.entries[i];
|
||||
if (!_.some($scope.entries, {
|
||||
id : entry.id
|
||||
@@ -750,15 +838,23 @@ module.controller('FeedListCtrl', [
|
||||
$scope.feedLink = data.feedLink;
|
||||
};
|
||||
|
||||
var service = $scope.selectedType == 'feed' ? FeedService : CategoryService;
|
||||
service.entries({
|
||||
var data = {
|
||||
id : $scope.selectedId,
|
||||
readType : $scope.keywords ? 'all' : $scope.settingsService.settings.readingMode,
|
||||
order : $scope.settingsService.settings.readingOrder,
|
||||
offset : offset,
|
||||
limit : limit,
|
||||
keywords : $scope.keywords
|
||||
}, callback);
|
||||
};
|
||||
if ($scope.selectedType == 'feed') {
|
||||
FeedService.entries(data, callback);
|
||||
} else if ($scope.selectedType == 'category') {
|
||||
CategoryService.entries(data, callback);
|
||||
} else if ($scope.selectedType == 'tag') {
|
||||
data.tag = data.id;
|
||||
data.id = 'all';
|
||||
CategoryService.entries(data, callback);
|
||||
}
|
||||
};
|
||||
|
||||
var watch_scrolling = true;
|
||||
@@ -808,7 +904,7 @@ module.controller('FeedListCtrl', [
|
||||
var docTop = w.scrollTop();
|
||||
|
||||
var current = null;
|
||||
for ( var i = 0; i < $scope.entries.length; i++) {
|
||||
for (var i = 0; i < $scope.entries.length; i++) {
|
||||
var entry = $scope.entries[i];
|
||||
var e = $('#entry_' + entry.id);
|
||||
if (e.offset().top + e.height() > docTop + $('#toolbar').outerHeight()) {
|
||||
@@ -871,7 +967,7 @@ module.controller('FeedListCtrl', [
|
||||
|
||||
$scope.markUpTo = function(entry) {
|
||||
var entries = [];
|
||||
for ( var i = 0; i < $scope.entries.length; i++) {
|
||||
for (var i = 0; i < $scope.entries.length; i++) {
|
||||
var e = $scope.entries[i];
|
||||
if (!e.read) {
|
||||
entries.push({
|
||||
@@ -910,7 +1006,7 @@ module.controller('FeedListCtrl', [
|
||||
var getCurrentIndex = function() {
|
||||
var index = -1;
|
||||
if ($scope.current) {
|
||||
for ( var i = 0; i < $scope.entries.length; i++) {
|
||||
for (var i = 0; i < $scope.entries.length; i++) {
|
||||
if ($scope.current == $scope.entries[i]) {
|
||||
index = i;
|
||||
break;
|
||||
@@ -1351,7 +1447,7 @@ module.controller('ManageDuplicateFeedsCtrl', ['$scope', 'AdminCleanupService',
|
||||
var callback = function() {
|
||||
alert('done!');
|
||||
};
|
||||
for ( var i = 0; i < $scope.counts.length; i++) {
|
||||
for (var i = 0; i < $scope.counts.length; i++) {
|
||||
var count = $scope.counts[i];
|
||||
if (count.autoMerge) {
|
||||
AdminCleanupService.mergeFeeds({
|
||||
|
||||
@@ -30,6 +30,38 @@ module.directive('popup', function() {
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* entry tag handling
|
||||
*/
|
||||
module.directive('tags', function() {
|
||||
return {
|
||||
restrict : 'E',
|
||||
scope : {
|
||||
entry : '='
|
||||
},
|
||||
replace : true,
|
||||
templateUrl : 'templates/_tags.html',
|
||||
controller : ['$scope', 'EntryService', function($scope, EntryService) {
|
||||
$scope.select2Options = {
|
||||
'multiple' : true,
|
||||
'simple_tags' : true,
|
||||
'maximumInputLength' : 40,
|
||||
tags : EntryService.tags
|
||||
};
|
||||
|
||||
$scope.$watch('entry.tags', function(newValue, oldValue) {
|
||||
if (newValue && oldValue && newValue != oldValue) {
|
||||
var data = {
|
||||
entryId : $scope.entry.id,
|
||||
tags : newValue
|
||||
};
|
||||
EntryService.tag(data);
|
||||
}
|
||||
}, true);
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Reusable favicon component
|
||||
*/
|
||||
@@ -116,7 +148,8 @@ module.directive('category', [function() {
|
||||
selectedId : '=',
|
||||
showLabel : '=',
|
||||
showChildren : '=',
|
||||
unreadCount : '&'
|
||||
unreadCount : '&',
|
||||
tag : '='
|
||||
},
|
||||
restrict : 'E',
|
||||
replace : true,
|
||||
@@ -174,13 +207,14 @@ module.directive('category', [function() {
|
||||
}
|
||||
};
|
||||
|
||||
$scope.categoryClicked = function(id) {
|
||||
$scope.categoryClicked = function(id, isTag) {
|
||||
MobileService.toggleLeftMenu();
|
||||
if ($scope.selectedType == 'category' && id == $scope.selectedId) {
|
||||
var type = isTag ? 'tag' : 'category';
|
||||
if ($scope.selectedType == type && id == $scope.selectedId) {
|
||||
$scope.$emit('emitReload');
|
||||
} else {
|
||||
$state.transitionTo('feeds.view', {
|
||||
_type : 'category',
|
||||
_type : type,
|
||||
_id : id
|
||||
});
|
||||
}
|
||||
@@ -192,10 +226,16 @@ module.directive('category', [function() {
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showCategoryDetails = function(category) {
|
||||
$state.transitionTo('feeds.category_details', {
|
||||
_id : category.id
|
||||
});
|
||||
$scope.showCategoryDetails = function(id, isTag) {
|
||||
if (isTag) {
|
||||
$state.transitionTo('feeds.tag_details', {
|
||||
_id : id
|
||||
});
|
||||
} else {
|
||||
$state.transitionTo('feeds.category_details', {
|
||||
_id : id
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.toggleCategory = function(category, event) {
|
||||
|
||||
@@ -54,6 +54,11 @@ app.config(['$routeProvider', '$stateProvider', '$urlRouterProvider', '$httpProv
|
||||
templateUrl : 'templates/feeds.category_details.html',
|
||||
controller : 'CategoryDetailsCtrl'
|
||||
});
|
||||
$stateProvider.state('feeds.tag_details', {
|
||||
url : '/details/tag/:_id',
|
||||
templateUrl : 'templates/feeds.tag_details.html',
|
||||
controller : 'TagDetailsCtrl'
|
||||
});
|
||||
$stateProvider.state('feeds.help', {
|
||||
url : '/help',
|
||||
templateUrl : 'templates/feeds.help.html',
|
||||
@@ -105,7 +110,7 @@ app.config(['$routeProvider', '$stateProvider', '$urlRouterProvider', '$httpProv
|
||||
templateUrl : 'templates/admin.metrics.html',
|
||||
controller : 'MetricsCtrl'
|
||||
});
|
||||
|
||||
|
||||
$urlRouterProvider.when('/', '/feeds/view/category/all');
|
||||
$urlRouterProvider.when('/admin', '/admin/settings');
|
||||
$urlRouterProvider.otherwise('/');
|
||||
|
||||
@@ -126,7 +126,7 @@ module.factory('CategoryService', ['$resource', '$http', function($resource, $ht
|
||||
callback(category, parentName);
|
||||
var children = category.children;
|
||||
if (children) {
|
||||
for ( var c = 0; c < children.length; c++) {
|
||||
for (var c = 0; c < children.length; c++) {
|
||||
traverse(callback, children[c], category.name);
|
||||
}
|
||||
}
|
||||
@@ -271,9 +271,29 @@ module.factory('EntryService', ['$resource', '$http', function($resource, $http)
|
||||
params : {
|
||||
_method : 'star'
|
||||
}
|
||||
},
|
||||
tag : {
|
||||
method : 'POST',
|
||||
params : {
|
||||
_method : 'tag'
|
||||
}
|
||||
}
|
||||
};
|
||||
var res = $resource('rest/entry/:_method', {}, actions);
|
||||
res.tags = [];
|
||||
var initTags = function() {
|
||||
$http.get('rest/entry/tags').success(function(data) {
|
||||
res.tags = [];
|
||||
res.tags.push.apply(res.tags, data);
|
||||
});
|
||||
};
|
||||
var oldTag = res.tag;
|
||||
res.tag = function(data) {
|
||||
oldTag(data, function() {
|
||||
initTags();
|
||||
});
|
||||
};
|
||||
initTags();
|
||||
return res;
|
||||
}]);
|
||||
|
||||
@@ -296,7 +316,6 @@ module.factory('AdminMetricsService', ['$resource', function($resource) {
|
||||
return res;
|
||||
}]);
|
||||
|
||||
|
||||
module.factory('AdminCleanupService', ['$resource', function($resource) {
|
||||
var actions = {
|
||||
findDuplicateFeeds : {
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
}
|
||||
|
||||
.full-screen #feed-accordion .entry-body-content {
|
||||
max-width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#feed-accordion .entry-enclosure {
|
||||
@@ -172,6 +172,24 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#feed-accordion .tags-panel {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
#feed-accordion .tags-panel .label{
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices .select2-search-field input {
|
||||
padding: 2px
|
||||
}
|
||||
|
||||
#feed-accordion .tag-input {
|
||||
margin: 0 0 0 5px;
|
||||
padding: 0;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#feed-accordion .entry-buttons label {
|
||||
margin-bottom: 0px;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
}
|
||||
|
||||
.sidebar-nav-fixed:hover {
|
||||
overflow-y: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.full-screen .left-menu {
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
.css-treeview {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 30px;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nolink {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.nolink:hover {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
right: 35px;
|
||||
margin-top: 22px;
|
||||
}
|
||||
#feed-accordion .tags-panel {
|
||||
display: block;
|
||||
}
|
||||
body.left-menu-active .left-menu {
|
||||
display: block !important;
|
||||
width: 100%;
|
||||
@@ -61,4 +64,4 @@
|
||||
#uvTab {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
<li>
|
||||
<div class="pointer tree-item" ng-if="showLabel" ng-class="getClass(level - 1)" droppable="node">
|
||||
<div class="dropdown pull-right">
|
||||
<div class="pull-right" ng-click="showCategoryDetails(node)">
|
||||
<div class="pull-right" ng-click="showCategoryDetails(node.id, node.isTag)">
|
||||
<i class="icon-wrench config pointer"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-click="categoryClicked(node.id)" ng-dblclick="showCategoryDetails(node)">
|
||||
<div ng-click="categoryClicked(node.id, node.isTag)" ng-dblclick="showCategoryDetails(node.id, node.isTag)">
|
||||
<span class="fldr">
|
||||
<i ng-class="{'icon-caret-right': !node.expanded, 'icon-caret-down': node.expanded}" ng-click="toggleCategory(node, $event)" ng-show="showChildren"></i>
|
||||
<i ng-class="{'icon-star' : node.id == 'starred', 'icon-inbox': node.id == 'all'}" ng-show="!showChildren"></i>
|
||||
<i ng-class="{'icon-star' : node.id == 'starred', 'icon-inbox': node.id == 'all', 'icon-tag' : node.isTag}" ng-show="!showChildren"></i>
|
||||
</span>
|
||||
<span ng-class="{selected: (node.id == selectedId && selectedType == 'category')}">
|
||||
<span ng-class="{unread: unreadCount({category:node})}" class="bidi-embed">
|
||||
|
||||
12
src/main/webapp/templates/_tags.html
Normal file
12
src/main/webapp/templates/_tags.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<span>
|
||||
<a ng-click="edit_mode=!edit_mode" class="nolink pointer">
|
||||
<i class="icon-tags"></i>
|
||||
${global.tags}
|
||||
</a>
|
||||
<span ng-if="!edit_mode">
|
||||
<span class="label label-info" ng-repeat="tag in entry.tags">{{tag}}</span>
|
||||
</span>
|
||||
<span ng-if="edit_mode">
|
||||
<input type="text" ui-select2="select2Options" ng-model="entry.tags" class="tag-input" />
|
||||
</span>
|
||||
</span>
|
||||
@@ -1,13 +1,15 @@
|
||||
<div class="css-treeview" ng-controller="CategoryTreeCtrl">
|
||||
<ul>
|
||||
<category node="CategoryService.subscriptions" show-label="'${tree.all}'" show-children="false"
|
||||
level="0" selected-type="selectedType" selected-id="selectedId"
|
||||
unread-count="unreadCount(category)"> </category>
|
||||
<category node="starred" show-label="'${tree.starred}'" show-children="false"
|
||||
level="0" selected-type="selectedType" selected-id="selectedId"
|
||||
unread-count="unreadCount(category)"> </category>
|
||||
<category node="CategoryService.subscriptions" show-label="false" show-children="true"
|
||||
level="0" selected-type="selectedType" selected-id="selectedId"
|
||||
unread-count="unreadCount(category)"> </category>
|
||||
<category node="CategoryService.subscriptions" show-label="'${tree.all}'" show-children="false" level="0" selected-type="selectedType"
|
||||
selected-id="selectedId" unread-count="unreadCount(category)"> </category>
|
||||
<category node="starred" show-label="'${tree.starred}'" show-children="false" level="0" selected-type="selectedType"
|
||||
selected-id="selectedId" unread-count="unreadCount(category)"> </category>
|
||||
<category node="CategoryService.subscriptions" show-label="false" show-children="true" level="0" selected-type="selectedType"
|
||||
selected-id="selectedId" unread-count="unreadCount(category)"> </category>
|
||||
|
||||
<li ng-repeat="tag in tags | orderBy: 'name'">
|
||||
<category node="tag" show-label="tag.name" show-children="false" level="0" selected-type="selectedType" selected-id="selectedId"
|
||||
unread-count="unreadCount(category)"> </category>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
19
src/main/webapp/templates/feeds.tag_details.html
Normal file
19
src/main/webapp/templates/feeds.tag_details.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<div>
|
||||
<div class="page-header">
|
||||
<h3>${details.tag_details}</h3>
|
||||
</div>
|
||||
<form name="form" class="form-horizontal" ng-submit="save()">
|
||||
<div class="control-group">
|
||||
<label class="control-label">${details.feed_url}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<a ng-show="user.apiKey" href="{{'rest/category/entriesAsFeed?id=all&tag=' + tag + '&apiKey=' + user.apiKey}}" target="_blank">${global.link}</a>
|
||||
<span ng-show="!user.apiKey">${details.generate_api_key_first}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn" ng-click="back()">${global.cancel}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@@ -13,9 +13,9 @@
|
||||
<span ng-show="keywords">${view.search_for} '{{keywords}}'</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode" infinite-scroll-distance="1" id="feed-accordion"
|
||||
ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
|
||||
|
||||
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode"
|
||||
infinite-scroll-distance="1" id="feed-accordion" ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
|
||||
<div ng-show="message && errorCount > 10">${view.error_while_loading_feed} : {{message}}</div>
|
||||
<div ng-repeat="entry in entries" class="entry entry-font-size-{{font_size}}" id="entry_{{entry.id}}"
|
||||
ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen }">
|
||||
@@ -23,8 +23,7 @@
|
||||
<a href="{{entry.url}}" target="_blank" class="entry-heading-link" ng-click="noop($event)" ng-mouseup="entryClicked(entry, $event)">
|
||||
<span class="feed-name">
|
||||
<span class="star" ng-mouseup="star(entry, !entry.starred, $event)">
|
||||
<i ng-class="{'icon-star icon-star-yellow': entry.starred, 'icon-star-empty': !entry.starred}"
|
||||
class="pointer"></i>
|
||||
<i ng-class="{'icon-star icon-star-yellow': entry.starred, 'icon-star-empty': !entry.starred}" class="pointer"></i>
|
||||
</span>
|
||||
<favicon url="entry.iconUrl" />
|
||||
{{entry.feedName}}
|
||||
@@ -36,15 +35,17 @@
|
||||
<i class="icon-external-link"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="entry-body" ng-if="settingsService.settings.viewMode == 'expanded' || (isOpen && current == entry)" ng-mouseup="bodyClicked(entry, $event)"
|
||||
ng-class="{rtl: entry.rtl}">
|
||||
<div class="entry-body" ng-if="settingsService.settings.viewMode == 'expanded' || (isOpen && current == entry)"
|
||||
ng-mouseup="bodyClicked(entry, $event)" ng-class="{rtl: entry.rtl}">
|
||||
<div class="entry-header">
|
||||
<div class="entry-title">
|
||||
<a href="{{entry.url}}" target="_blank" ng-bind-html-unsafe="entry.title | highlight:keywords"></a>
|
||||
<div class="entry-subtitle">
|
||||
<span class="entry-source" ng-if="selectedType == 'category'">
|
||||
<span class="entry-source-prefix">${view.entry_source}</span>
|
||||
<a ng-click="goToFeed(entry.feedId)" class="pointer bidi-embed"><span>{{entry.feedName}}</span></a>
|
||||
<a ng-click="goToFeed(entry.feedId)" class="pointer bidi-embed">
|
||||
<span>{{entry.feedName}}</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="entry-author" ng-if="entry.author">
|
||||
<span class="entry-author-prefix">${view.entry_author}</span>
|
||||
@@ -66,16 +67,13 @@
|
||||
<div ng-if="entry.enclosureType && entry.enclosureType.indexOf('image') == 0">
|
||||
<img ng-src="{{entry.enclosureUrl}}" />
|
||||
</div>
|
||||
<a href="{{entry.enclosureUrl}}" target="_blank" ng-if="entry.enclosureType" download>
|
||||
${global.download}
|
||||
</a>
|
||||
<a href="{{entry.enclosureUrl}}" target="_blank" ng-if="entry.enclosureType" download> ${global.download} </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="entry-buttons form-horizontal">
|
||||
|
||||
|
||||
<span class="star" ng-mouseup="star(entry, !entry.starred, $event)">
|
||||
<i ng-class="{'icon-star icon-star-yellow': entry.starred, 'icon-star-empty': !entry.starred}"
|
||||
class="pointer"></i>
|
||||
<i ng-class="{'icon-star icon-star-yellow': entry.starred, 'icon-star-empty': !entry.starred}" class="pointer"></i>
|
||||
</span>
|
||||
<label class="checkbox inline" ng-if="entry.markable">
|
||||
<input type="checkbox" ng-checked="!entry.read" ng-click="mark(entry, !entry.read)" class="mousetrap"></input>
|
||||
@@ -86,7 +84,8 @@
|
||||
<a href="mailto:?subject={{entry.title|escape}}&body={{entry.url|escape}}" title="E-mail" popup>
|
||||
<i class="icon-envelope"></i>
|
||||
</a>
|
||||
<a href="https://mail.google.com/mail/?view=cm&fs=1&tf=1&source=mailto&su={{entry.title|escape}}&body={{entry.url|escape}}" title="Gmail" popup>
|
||||
<a href="https://mail.google.com/mail/?view=cm&fs=1&tf=1&source=mailto&su={{entry.title|escape}}&body={{entry.url|escape}}"
|
||||
title="Gmail" popup>
|
||||
<i class="icon-gmail"></i>
|
||||
</a>
|
||||
<a href="http://www.facebook.com/sharer.php?u=={{entry.url|escape}}" title="Facebook" popup>
|
||||
@@ -108,7 +107,10 @@
|
||||
<i class="icon-buffer"></i>
|
||||
</a>
|
||||
</span>
|
||||
|
||||
|
||||
<span class="tags-panel">
|
||||
<tags entry="entry"></tags>
|
||||
</span>
|
||||
<a ng-click="markUpTo(entry)" class="mark-up-to" title="${view.mark_up_to_here}">
|
||||
<i class="icon-step-forward icon-rotate-90"></i>
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user