mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1dac2e064 | ||
|
|
f707993188 | ||
|
|
ea612d9d53 | ||
|
|
b44e737448 | ||
|
|
bb429afd95 | ||
|
|
475a8f8a28 | ||
|
|
c7ba5ca894 | ||
|
|
3023f0a7cc | ||
|
|
ddaefbc952 | ||
|
|
0b3a0fb3ed | ||
|
|
7f40a430fd | ||
|
|
05f5d3b25c | ||
|
|
c3ca0b18b3 | ||
|
|
696e0b1fa7 | ||
|
|
201f7dbd3e | ||
|
|
0bfd3e906c | ||
|
|
71ac2bfc45 | ||
|
|
5370db7c5e | ||
|
|
bcc30e40ba | ||
|
|
2f70f654f7 | ||
|
|
b64115dcbd | ||
|
|
c9c71d8582 | ||
|
|
689bc19296 | ||
|
|
27498ab649 | ||
|
|
678a11f998 | ||
|
|
e9ef98716f | ||
|
|
b3ce43eaf7 | ||
|
|
72083b7e87 | ||
|
|
0cc94c2033 | ||
|
|
1d6296b400 | ||
|
|
7ad5da2a9e | ||
|
|
a7665a9994 | ||
|
|
a4cd3f26e8 | ||
|
|
fcdb33b64b | ||
|
|
7fd6119bcf | ||
|
|
b4d4b2473c | ||
|
|
91f715c3c3 | ||
|
|
ea5fccfe5f | ||
|
|
86835eec73 | ||
|
|
2bccee2333 | ||
|
|
2d01b0d714 | ||
|
|
44bf37b05a | ||
|
|
cf617f0a64 | ||
|
|
eeeaffd883 | ||
|
|
d178302d34 | ||
|
|
83a5364903 | ||
|
|
aef76db664 | ||
|
|
c3b3240191 | ||
|
|
f381974955 | ||
|
|
bd16dd98c4 | ||
|
|
2fca6132a0 | ||
|
|
137eba33c9 | ||
|
|
143699c0a4 | ||
|
|
0485403fff | ||
|
|
489fcb9666 | ||
|
|
7cc3b84ebc | ||
|
|
cb254f87d4 | ||
|
|
d4db98fd64 | ||
|
|
d14a6d8311 | ||
|
|
286c115167 | ||
|
|
6038b9e052 | ||
|
|
552082a36a | ||
|
|
5cea92d96d | ||
|
|
02b7b89b94 | ||
|
|
93697cf1f5 | ||
|
|
8daaee28c3 | ||
|
|
c32f608ec5 | ||
|
|
7b09029c5b | ||
|
|
6e1c414c84 | ||
|
|
e57976be99 | ||
|
|
a37e6a3f4c | ||
|
|
2dbe4064b2 | ||
|
|
2b0c0d467a | ||
|
|
40fa4516df | ||
|
|
5201c0cd14 | ||
|
|
61039dcd7e | ||
|
|
039ff4ee41 | ||
|
|
b40349805f | ||
|
|
d709d119ac | ||
|
|
8d2b6bdc12 | ||
|
|
ff78af2d56 | ||
|
|
ada53dba3b | ||
|
|
ba2f6c0f66 | ||
|
|
268869345c | ||
|
|
4b556bd3a9 | ||
|
|
6f10d35a4c | ||
|
|
33167fcdce | ||
|
|
e9c85b0e77 | ||
|
|
e521254600 | ||
|
|
a773d98400 | ||
|
|
ae066d3cd9 | ||
|
|
b5726fc0f3 | ||
|
|
4a056a0d27 | ||
|
|
7817431bce | ||
|
|
c02d2745c3 | ||
|
|
ee610ec800 | ||
|
|
6c0d585fef | ||
|
|
29417005b0 | ||
|
|
cf87fd8340 | ||
|
|
f1b85b0dde | ||
|
|
abef73d384 | ||
|
|
83f26cde53 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@ config.yml
|
|||||||
|
|
||||||
# build directory
|
# build directory
|
||||||
target
|
target
|
||||||
|
target-ide
|
||||||
|
|
||||||
# log files
|
# log files
|
||||||
log
|
log
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
language: java
|
language: java
|
||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- openjdk8
|
||||||
|
|||||||
17
CHANGELOG
17
CHANGELOG
@@ -1,3 +1,18 @@
|
|||||||
|
v 2.5.0
|
||||||
|
- unread count is now displayed in a favicon badge when supported
|
||||||
|
- the user agent string for the bot fetching feeds is now configurable
|
||||||
|
- feed parsing performance improvements
|
||||||
|
- support for java9+ runtime
|
||||||
|
- can now properly start from an empty postgresql database
|
||||||
|
v 2.4.0
|
||||||
|
- users were not able to change password or delete account
|
||||||
|
- fix api key generation
|
||||||
|
- feed entries can now be sorted alphabetically
|
||||||
|
- fix facebook sharing
|
||||||
|
- fix layout on iOS
|
||||||
|
- postgresql driver update (fix for postgres 9.6)
|
||||||
|
- various internationalization fixes
|
||||||
|
- security fixes
|
||||||
v 2.3.0
|
v 2.3.0
|
||||||
- dropwizard upgrade 0.9.1
|
- dropwizard upgrade 0.9.1
|
||||||
- feed enclosures are hidden if they already displayed in the content
|
- feed enclosures are hidden if they already displayed in the content
|
||||||
@@ -42,4 +57,4 @@ v2.0.0
|
|||||||
- The backend has been completely rewritten using Dropwizard instead of TomEE, resulting in a lot less memory consumption and better overall performances.
|
- The backend has been completely rewritten using Dropwizard instead of TomEE, resulting in a lot less memory consumption and better overall performances.
|
||||||
See the README on how to build CommaFeed from now on.
|
See the README on how to build CommaFeed from now on.
|
||||||
- CommaFeed should no longer fetch the same feed multiple times in a row
|
- CommaFeed should no longer fetch the same feed multiple times in a row
|
||||||
- Users can use their username or email to log in
|
- Users can use their username or email to log in
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -3,6 +3,7 @@
|
|||||||
Sources for [CommaFeed.com](http://www.commafeed.com/).
|
Sources for [CommaFeed.com](http://www.commafeed.com/).
|
||||||
|
|
||||||
Google Reader inspired self-hosted RSS reader, based on Dropwizard and AngularJS.
|
Google Reader inspired self-hosted RSS reader, based on Dropwizard and AngularJS.
|
||||||
|
CommaFeed is now considered feature-complete and is in maintenance mode.
|
||||||
|
|
||||||
## Related open-source projects
|
## Related open-source projects
|
||||||
|
|
||||||
@@ -16,8 +17,8 @@ Browser extensions: [Chrome](https://github.com/Athou/commafeed-chrome) - [Firef
|
|||||||
### The very short version (download precompiled package)
|
### The very short version (download precompiled package)
|
||||||
|
|
||||||
mkdir commafeed && cd commafeed
|
mkdir commafeed && cd commafeed
|
||||||
wget https://github.com/Athou/commafeed/releases/download/2.2.0/commafeed.jar
|
wget https://github.com/Athou/commafeed/releases/download/2.4.0/commafeed.jar
|
||||||
wget https://raw.githubusercontent.com/Athou/commafeed/2.2.0/config.yml.example -O config.yml
|
wget https://raw.githubusercontent.com/Athou/commafeed/2.4.0/config.yml.example -O config.yml
|
||||||
vi config.yml
|
vi config.yml
|
||||||
java -Djava.net.preferIPv4Stack=true -jar commafeed.jar server config.yml
|
java -Djava.net.preferIPv4Stack=true -jar commafeed.jar server config.yml
|
||||||
|
|
||||||
@@ -66,20 +67,6 @@ Issue the following command to run the app, the server will listen by default on
|
|||||||
|
|
||||||
You can use a proxy http server such as nginx or apache.
|
You can use a proxy http server such as nginx or apache.
|
||||||
|
|
||||||
## Deployment on OpenShift
|
|
||||||
|
|
||||||
[OpenShift](https://openshift.redhat.com) is Red Hat's Platform-as-a-Service (PaaS) that allows developers to quickly develop, host, and scale applications in a cloud environment. CommaFeed runs perfectly on OpenShift and can even be used in the free tier. Follow the [Getting Started](https://developers.openshift.com/en/getting-started-overview.html) guide and after you sign up and install the Command Line Tools (RHC), do:
|
|
||||||
|
|
||||||
rhc create-app commafeed diy-0.1 mysql-5.5
|
|
||||||
cd commafeed
|
|
||||||
git remote add upstream -m master https://github.com/Athou/commafeed.git
|
|
||||||
git pull -s recursive -X theirs upstream master
|
|
||||||
git push
|
|
||||||
|
|
||||||
# To upgrade an existing openshift installation
|
|
||||||
git pull upstream master
|
|
||||||
git push
|
|
||||||
|
|
||||||
## Translate CommaFeed into your language
|
## Translate CommaFeed into your language
|
||||||
|
|
||||||
Files for internationalization are located [here](https://github.com/Athou/commafeed/tree/master/src/main/app/i18n).
|
Files for internationalization are located [here](https://github.com/Athou/commafeed/tree/master/src/main/app/i18n).
|
||||||
@@ -123,7 +110,7 @@ Steps to configuring a development environment for CommaFeed may include, but ma
|
|||||||
|
|
||||||
## Copyright and license
|
## Copyright and license
|
||||||
|
|
||||||
Copyright 2013-2015 CommaFeed.
|
Copyright 2013-2016 CommaFeed.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this work except in compliance with the License.
|
you may not use this work except in compliance with the License.
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
"devicejs": "0.2.4",
|
"devicejs": "0.2.4",
|
||||||
"readabilicons": "arc90/readability-readabilicons#34c55561c5b8ec6e90714b50237c06b13cb9d59c",
|
"readabilicons": "arc90/readability-readabilicons#34c55561c5b8ec6e90714b50237c06b13cb9d59c",
|
||||||
"zocial-less": "1.0.0",
|
"zocial-less": "1.0.0",
|
||||||
"swagger-ui": "2.1.0"
|
"swagger-ui": "2.1.0",
|
||||||
|
"tinycon": "0.6.5"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"angular": "1.3.14",
|
"angular": "1.3.14",
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ app:
|
|||||||
smtpTls: false
|
smtpTls: false
|
||||||
smtpUserName: user
|
smtpUserName: user
|
||||||
smtpPassword: pass
|
smtpPassword: pass
|
||||||
|
|
||||||
|
# Graphite Metric settings
|
||||||
|
# Allows those who use Graphite to have CommaFeed send metrics for graphing (time in seconds)
|
||||||
|
graphiteEnabled: false
|
||||||
|
graphitePrefix: "test.commafeed"
|
||||||
|
graphiteHost: "localhost"
|
||||||
|
graphitePort: 2003
|
||||||
|
graphiteInterval: 60
|
||||||
|
|
||||||
# wether this commafeed instance has a lot of feeds to refresh
|
# wether this commafeed instance has a lot of feeds to refresh
|
||||||
# leave this to false in almost all cases
|
# leave this to false in almost all cases
|
||||||
@@ -59,6 +67,9 @@ app:
|
|||||||
# announcement string displayed on the main page
|
# announcement string displayed on the main page
|
||||||
announcement:
|
announcement:
|
||||||
|
|
||||||
|
# user-agent string that will be used by the http client, leave empty for the default one
|
||||||
|
userAgent:
|
||||||
|
|
||||||
# Database connection
|
# Database connection
|
||||||
# -------------------
|
# -------------------
|
||||||
# for MySQL
|
# for MySQL
|
||||||
@@ -75,7 +86,7 @@ app:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
driverClass: org.h2.Driver
|
driverClass: org.h2.Driver
|
||||||
url: jdbc:h2:./target/example;mv_store=false
|
url: jdbc:h2:./target/example
|
||||||
user: sa
|
user: sa
|
||||||
password: sa
|
password: sa
|
||||||
properties:
|
properties:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ app:
|
|||||||
# url used to access commafeed
|
# url used to access commafeed
|
||||||
publicUrl: http://localhost:8082/
|
publicUrl: http://localhost:8082/
|
||||||
|
|
||||||
# wether to allow user registrations
|
# whether to allow user registrations
|
||||||
allowRegistrations: false
|
allowRegistrations: false
|
||||||
|
|
||||||
# create a demo account the first time the app starts
|
# create a demo account the first time the app starts
|
||||||
@@ -29,6 +29,14 @@ app:
|
|||||||
smtpUserName:
|
smtpUserName:
|
||||||
smtpPassword:
|
smtpPassword:
|
||||||
smtpFromAddress:
|
smtpFromAddress:
|
||||||
|
|
||||||
|
# Graphite Metric settings
|
||||||
|
# Allows those who use Graphite to have CommaFeed send metrics for graphing (time in seconds)
|
||||||
|
graphiteEnabled: false
|
||||||
|
graphitePrefix: "test.commafeed"
|
||||||
|
graphiteHost: "localhost"
|
||||||
|
graphitePort: 2003
|
||||||
|
graphiteInterval: 60
|
||||||
|
|
||||||
# wether this commafeed instance has a lot of feeds to refresh
|
# wether this commafeed instance has a lot of feeds to refresh
|
||||||
# leave this to false in almost all cases
|
# leave this to false in almost all cases
|
||||||
@@ -60,6 +68,9 @@ app:
|
|||||||
# announcement string displayed on the main page
|
# announcement string displayed on the main page
|
||||||
announcement:
|
announcement:
|
||||||
|
|
||||||
|
# user-agent string that will be used by the http client, leave empty for the default one
|
||||||
|
userAgent:
|
||||||
|
|
||||||
# Database connection
|
# Database connection
|
||||||
# -------------------
|
# -------------------
|
||||||
# for MySQL
|
# for MySQL
|
||||||
@@ -100,6 +111,7 @@ logging:
|
|||||||
com.commafeed: INFO
|
com.commafeed: INFO
|
||||||
liquibase: INFO
|
liquibase: INFO
|
||||||
io.dropwizard.server.ServerFactory: INFO
|
io.dropwizard.server.ServerFactory: INFO
|
||||||
|
org.hibernate.orm.deprecation: "OFF"
|
||||||
appenders:
|
appenders:
|
||||||
- type: console
|
- type: console
|
||||||
- type: file
|
- type: file
|
||||||
@@ -120,4 +132,4 @@ redis:
|
|||||||
timeout: 2000
|
timeout: 2000
|
||||||
database: 0
|
database: 0
|
||||||
maxTotal: 500
|
maxTotal: 500
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#Maven download properties
|
#Maven download properties
|
||||||
#Sat Jul 04 09:06:32 CEST 2015
|
#Sat Jul 04 09:06:32 CEST 2015
|
||||||
distributionUrl=https\://repository.apache.org/content/repositories/releases/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
|
distributionUrl=https\://repository.apache.org/content/repositories/releases/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bower": "1.4.1",
|
"bower": "1.8.8",
|
||||||
"gulp": "3.8.11",
|
"gulp": "3.8.11",
|
||||||
"gulp-rev": "4.0.0",
|
"gulp-rev": "4.0.0",
|
||||||
"gulp-rev-replace": "0.4.1",
|
"gulp-rev-replace": "0.4.1",
|
||||||
|
|||||||
160
pom.xml
160
pom.xml
@@ -4,20 +4,16 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.commafeed</groupId>
|
<groupId>com.commafeed</groupId>
|
||||||
<artifactId>commafeed</artifactId>
|
<artifactId>commafeed</artifactId>
|
||||||
<version>2.3.0</version>
|
<version>2.5.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>CommaFeed</name>
|
<name>CommaFeed</name>
|
||||||
|
|
||||||
<prerequisites>
|
|
||||||
<maven>3.1.0</maven>
|
|
||||||
</prerequisites>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<dropwizard.version>0.9.1</dropwizard.version>
|
<dropwizard.version>1.3.20</dropwizard.version>
|
||||||
<guice.version>4.0</guice.version>
|
<guice.version>4.2.2</guice.version>
|
||||||
<querydsl.version>4.0.2</querydsl.version>
|
<querydsl.version>4.2.1</querydsl.version>
|
||||||
<rome.version>1.5.0</rome.version>
|
<rome.version>1.5.0</rome.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -36,43 +32,11 @@
|
|||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.eclipse.m2e</groupId>
|
|
||||||
<artifactId>lifecycle-mapping</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<configuration>
|
|
||||||
<lifecycleMappingMetadata>
|
|
||||||
<pluginExecutions>
|
|
||||||
<pluginExecution>
|
|
||||||
<pluginExecutionFilter>
|
|
||||||
<groupId>com.github.eirslett</groupId>
|
|
||||||
<artifactId>frontend-maven-plugin</artifactId>
|
|
||||||
<versionRange>[0.0.22,)</versionRange>
|
|
||||||
<goals>
|
|
||||||
<goal>npm</goal>
|
|
||||||
<goal>gulp</goal>
|
|
||||||
<goal>bower</goal>
|
|
||||||
</goals>
|
|
||||||
</pluginExecutionFilter>
|
|
||||||
<action>
|
|
||||||
<execute>
|
|
||||||
<runOnIncremental>false</runOnIncremental>
|
|
||||||
</execute>
|
|
||||||
</action>
|
|
||||||
</pluginExecution>
|
|
||||||
</pluginExecutions>
|
|
||||||
</lifecycleMappingMetadata>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.8.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${java.version}</source>
|
<source>${java.version}</source>
|
||||||
<target>${java.version}</target>
|
<target>${java.version}</target>
|
||||||
@@ -132,11 +96,15 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.github.kongchen</groupId>
|
<groupId>com.github.kongchen</groupId>
|
||||||
<artifactId>swagger-maven-plugin</artifactId>
|
<artifactId>swagger-maven-plugin</artifactId>
|
||||||
<version>3.1.1</version>
|
<version>3.1.7</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apiSources>
|
<apiSources>
|
||||||
<apiSource>
|
<apiSource>
|
||||||
<locations>com.commafeed.frontend.resource;com.commafeed.frontend.model;com.commafeed.frontend.model.request</locations>
|
<locations>
|
||||||
|
<location>com.commafeed.frontend.resource</location>
|
||||||
|
<location>com.commafeed.frontend.model</location>
|
||||||
|
<location>com.commafeed.frontend.model.request</location>
|
||||||
|
</locations>
|
||||||
<swaggerDirectory>target/swagger</swaggerDirectory>
|
<swaggerDirectory>target/swagger</swaggerDirectory>
|
||||||
<basePath>/rest</basePath>
|
<basePath>/rest</basePath>
|
||||||
<info>
|
<info>
|
||||||
@@ -161,7 +129,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.github.eirslett</groupId>
|
<groupId>com.github.eirslett</groupId>
|
||||||
<artifactId>frontend-maven-plugin</artifactId>
|
<artifactId>frontend-maven-plugin</artifactId>
|
||||||
<version>0.0.25</version>
|
<version>1.6</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>install node and npm</id>
|
<id>install node and npm</id>
|
||||||
@@ -170,8 +138,8 @@
|
|||||||
</goals>
|
</goals>
|
||||||
<phase>compile</phase>
|
<phase>compile</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<nodeVersion>v0.10.39</nodeVersion>
|
<nodeVersion>v6.11.4</nodeVersion>
|
||||||
<npmVersion>2.12.1</npmVersion>
|
<npmVersion>3.10.6</npmVersion>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -181,7 +149,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
<phase>compile</phase>
|
<phase>compile</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<arguments>install --loglevel info</arguments>
|
<arguments>install</arguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -206,7 +174,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>2.6</version>
|
<version>3.1.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
@@ -218,11 +186,70 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>only-eclipse</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>m2e.version</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<directory>target-ide</directory>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.eclipse.m2e</groupId>
|
||||||
|
<artifactId>lifecycle-mapping</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<configuration>
|
||||||
|
<lifecycleMappingMetadata>
|
||||||
|
<pluginExecutions>
|
||||||
|
<pluginExecution>
|
||||||
|
<pluginExecutionFilter>
|
||||||
|
<groupId>com.github.eirslett</groupId>
|
||||||
|
<artifactId>frontend-maven-plugin</artifactId>
|
||||||
|
<versionRange>[0.0.22,)</versionRange>
|
||||||
|
<goals>
|
||||||
|
<goal>npm</goal>
|
||||||
|
<goal>gulp</goal>
|
||||||
|
<goal>bower</goal>
|
||||||
|
</goals>
|
||||||
|
</pluginExecutionFilter>
|
||||||
|
<action>
|
||||||
|
<execute>
|
||||||
|
<runOnIncremental>false</runOnIncremental>
|
||||||
|
</execute>
|
||||||
|
</action>
|
||||||
|
</pluginExecution>
|
||||||
|
<pluginExecution>
|
||||||
|
<pluginExecutionFilter>
|
||||||
|
<groupId>com.github.kongchen</groupId>
|
||||||
|
<artifactId>swagger-maven-plugin</artifactId>
|
||||||
|
<versionRange>[3.1.7,)</versionRange>
|
||||||
|
<goals>
|
||||||
|
<goal>generate</goal>
|
||||||
|
</goals>
|
||||||
|
</pluginExecutionFilter>
|
||||||
|
<action>
|
||||||
|
<ignore></ignore>
|
||||||
|
</action>
|
||||||
|
</pluginExecution>
|
||||||
|
</pluginExecutions>
|
||||||
|
</lifecycleMappingMetadata>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.16.4</version>
|
<version>1.18.6</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -283,11 +310,21 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.dropwizard.metrics</groupId>
|
||||||
|
<artifactId>metrics-graphite</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
<version>4.5</version>
|
<version>4.5.2</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
@@ -299,7 +336,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.swagger</groupId>
|
<groupId>io.swagger</groupId>
|
||||||
<artifactId>swagger-annotations</artifactId>
|
<artifactId>swagger-annotations</artifactId>
|
||||||
<version>1.5.0</version>
|
<version>1.5.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -315,11 +352,6 @@
|
|||||||
<version>${querydsl.version}</version>
|
<version>${querydsl.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<version>18.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
@@ -328,7 +360,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-collections4</artifactId>
|
<artifactId>commons-collections4</artifactId>
|
||||||
<version>4.0</version>
|
<version>4.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
@@ -385,11 +417,15 @@
|
|||||||
<artifactId>jdom2</artifactId>
|
<artifactId>jdom2</artifactId>
|
||||||
<version>2.0.6</version>
|
<version>2.0.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.ahocorasick</groupId>
|
||||||
|
<artifactId>ahocorasick</artifactId>
|
||||||
|
<version>0.4.0</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
<artifactId>jsoup</artifactId>
|
<artifactId>jsoup</artifactId>
|
||||||
<version>1.8.2</version>
|
<version>1.8.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ibm.icu</groupId>
|
<groupId>com.ibm.icu</groupId>
|
||||||
@@ -417,17 +453,17 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>1.4.190</version>
|
<version>1.4.197</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>5.1.37</version>
|
<version>5.1.42</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.postgresql</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<version>9.4-1205-jdbc42</version>
|
<version>9.4.1212</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sourceforge.jtds</groupId>
|
<groupId>net.sourceforge.jtds</groupId>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "إعادة انعاش",
|
"refresh" : "إعادة انعاش",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "الترتيب حسب التاريخ تصاعدي / تنازلي",
|
"sort_by_asc_desc" : "الترتيب حسب التاريخ تصاعدي / تنازلي",
|
||||||
|
"sort_by_abc_zyx" : "Sort alphabetically",
|
||||||
"titles_only" : "العناوين فقط",
|
"titles_only" : "العناوين فقط",
|
||||||
"expanded_view" : "عرض موسع",
|
"expanded_view" : "عرض موسع",
|
||||||
"mark_all_as_read" : "اعتبر الكل مقروء",
|
"mark_all_as_read" : "اعتبر الكل مقروء",
|
||||||
@@ -174,7 +175,8 @@
|
|||||||
"font_size" : "increase/decrease font size of the current entry ",
|
"font_size" : "increase/decrease font size of the current entry ",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "go to the All view ",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "go to the Starred view ",
|
||||||
"feed_search" : "navigate to a subscription by entering the subscription name"
|
"feed_search" : "navigate to a subscription by entering the subscription name",
|
||||||
|
"refresh": "refresh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Actualitzar",
|
"refresh" : "Actualitzar",
|
||||||
"refresh_all" : "Força l'actualització de tots els canals",
|
"refresh_all" : "Força l'actualització de tots els canals",
|
||||||
"sort_by_asc_desc" : "Ordenar per data asc/desc",
|
"sort_by_asc_desc" : "Ordenar per data asc/desc",
|
||||||
|
"sort_by_abc_zyx" : "Sort alphabetically",
|
||||||
"titles_only" : "Només títols",
|
"titles_only" : "Només títols",
|
||||||
"expanded_view" : "Vista ampliada",
|
"expanded_view" : "Vista ampliada",
|
||||||
"mark_all_as_read" : "Marcar tots llegits",
|
"mark_all_as_read" : "Marcar tots llegits",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh " : " Obnovit",
|
"refresh " : " Obnovit",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc " : " Seřadit podle nejnovějšího/nejstaršího",
|
"sort_by_asc_desc " : " Seřadit podle nejnovějšího/nejstaršího",
|
||||||
|
"sort_by_abc_zyx" : "Sort alphabetically",
|
||||||
"titles_only " : " Zobrazit jenom titulky",
|
"titles_only " : " Zobrazit jenom titulky",
|
||||||
"expanded_view " : " Rozšířený náhled",
|
"expanded_view " : " Rozšířený náhled",
|
||||||
"mark_all_as_read " : " Označit vše jako přečtené",
|
"mark_all_as_read " : " Označit vše jako přečtené",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Adnewyddu",
|
"refresh" : "Adnewyddu",
|
||||||
"refresh_all" : "Gorfodi ail-lwytho pob ffrwd",
|
"refresh_all" : "Gorfodi ail-lwytho pob ffrwd",
|
||||||
"sort_by_asc_desc" : "Trefnu yn ôl dyddiad",
|
"sort_by_asc_desc" : "Trefnu yn ôl dyddiad",
|
||||||
|
"sort_by_abc_zyx" : "Sort alphabetically",
|
||||||
"titles_only" : "Teitlau yn unig",
|
"titles_only" : "Teitlau yn unig",
|
||||||
"expanded_view" : "Golwg estynedig",
|
"expanded_view" : "Golwg estynedig",
|
||||||
"mark_all_as_read" : "Nodi'r cyfan fel wedi ei ddarllen",
|
"mark_all_as_read" : "Nodi'r cyfan fel wedi ei ddarllen",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Opdater",
|
"refresh" : "Opdater",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "Sorter efter dato ny/gammel",
|
"sort_by_asc_desc" : "Sorter efter dato ny/gammel",
|
||||||
|
"sort_by_abc_zyx" : "Sort alphabetically",
|
||||||
"titles_only" : "Kun titler",
|
"titles_only" : "Kun titler",
|
||||||
"expanded_view" : "Udvidet visning",
|
"expanded_view" : "Udvidet visning",
|
||||||
"mark_all_as_read" : "Marker alle som læst",
|
"mark_all_as_read" : "Marker alle som læst",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Aktualisieren",
|
"refresh" : "Aktualisieren",
|
||||||
"refresh_all" : "Erzwinge Aktualisierung aller Feeds",
|
"refresh_all" : "Erzwinge Aktualisierung aller Feeds",
|
||||||
"sort_by_asc_desc" : "Nach Datum sortieren (auf-/absteigend)",
|
"sort_by_asc_desc" : "Nach Datum sortieren (auf-/absteigend)",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Nur Überschriften",
|
"titles_only" : "Nur Überschriften",
|
||||||
"expanded_view" : "Ausgedehnte Ansicht",
|
"expanded_view" : "Ausgedehnte Ansicht",
|
||||||
"mark_all_as_read" : "Alle Artikel als gelesen markieren",
|
"mark_all_as_read" : "Alle Artikel als gelesen markieren",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Refresh",
|
"refresh" : "Refresh",
|
||||||
"refresh_all" : "Force refresh all my feeds",
|
"refresh_all" : "Force refresh all my feeds",
|
||||||
"sort_by_asc_desc" : "Sort by date asc/desc",
|
"sort_by_asc_desc" : "Sort by date asc/desc",
|
||||||
|
"sort_by_abc_zyx" : "Sort alphabetically",
|
||||||
"titles_only" : "Titles only",
|
"titles_only" : "Titles only",
|
||||||
"expanded_view" : "Expanded view",
|
"expanded_view" : "Expanded view",
|
||||||
"mark_all_as_read" : "Mark all as read",
|
"mark_all_as_read" : "Mark all as read",
|
||||||
@@ -176,7 +177,8 @@
|
|||||||
"font_size" : "increase/decrease font size of the current entry",
|
"font_size" : "increase/decrease font size of the current entry",
|
||||||
"go_to_all" : "go to the All view",
|
"go_to_all" : "go to the All view",
|
||||||
"go_to_starred" : "go to the Starred view",
|
"go_to_starred" : "go to the Starred view",
|
||||||
"feed_search" : "navigate to a subscription by entering the subscription name"
|
"feed_search" : "navigate to a subscription by entering the subscription name",
|
||||||
|
"refresh": "refresh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,10 @@
|
|||||||
"all" : "Todos",
|
"all" : "Todos",
|
||||||
"previous_entry" : "Entrada anterior",
|
"previous_entry" : "Entrada anterior",
|
||||||
"next_entry" : "Entrada siguiente",
|
"next_entry" : "Entrada siguiente",
|
||||||
"refresh" : "Atualizar",
|
"refresh" : "Actualizar",
|
||||||
"refresh_all" : "Forzar la actualización de todos mis canales.",
|
"refresh_all" : "Forzar la actualización de todos mis canales.",
|
||||||
"sort_by_asc_desc" : "Ordenar por fecha asc/desc.",
|
"sort_by_asc_desc" : "Ordenar por fecha asc/desc.",
|
||||||
|
"sort_by_abc_zyx" : "Ordenar alfabéticamente",
|
||||||
"titles_only" : "Sólo títulos",
|
"titles_only" : "Sólo títulos",
|
||||||
"expanded_view" : "Vista expandida",
|
"expanded_view" : "Vista expandida",
|
||||||
"mark_all_as_read" : "Marcar todos como leído",
|
"mark_all_as_read" : "Marcar todos como leído",
|
||||||
@@ -94,7 +95,7 @@
|
|||||||
"website" : "Sitio web",
|
"website" : "Sitio web",
|
||||||
"name" : "Nombre",
|
"name" : "Nombre",
|
||||||
"category" : "Categoría",
|
"category" : "Categoría",
|
||||||
"position" : "Posicióon",
|
"position" : "Posición",
|
||||||
"last_refresh" : "Última actualización",
|
"last_refresh" : "Última actualización",
|
||||||
"message" : "Último mensaje de actualización",
|
"message" : "Último mensaje de actualización",
|
||||||
"next_refresh" : "Próxima actualización",
|
"next_refresh" : "Próxima actualización",
|
||||||
@@ -105,7 +106,7 @@
|
|||||||
"unsubscribe_confirmation" : "¿Estás seguro de querer terminar tu suscripción a este canal?",
|
"unsubscribe_confirmation" : "¿Estás seguro de querer terminar tu suscripción a este canal?",
|
||||||
"delete_category_confirmation" : "¿Estás seguro de querer eliminar esta categoría?",
|
"delete_category_confirmation" : "¿Estás seguro de querer eliminar esta categoría?",
|
||||||
"category_details" : "Detalles de la categoría",
|
"category_details" : "Detalles de la categoría",
|
||||||
"tag_details" : "Detalles de las etiuqetas ",
|
"tag_details" : "Detalles de las etiquetas ",
|
||||||
"parent_category" : "Categoría principal"
|
"parent_category" : "Categoría principal"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "تازهسازی",
|
"refresh" : "تازهسازی",
|
||||||
"refresh_all" : "مجبورکردن تازهسازی همهٔ خوراکها",
|
"refresh_all" : "مجبورکردن تازهسازی همهٔ خوراکها",
|
||||||
"sort_by_asc_desc" : "مرتبکردن بر اساس تاریخ بهصورت صعودی/نزولی",
|
"sort_by_asc_desc" : "مرتبکردن بر اساس تاریخ بهصورت صعودی/نزولی",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "فقط عنوانها",
|
"titles_only" : "فقط عنوانها",
|
||||||
"expanded_view" : "نمای گسترشیافته",
|
"expanded_view" : "نمای گسترشیافته",
|
||||||
"mark_all_as_read" : "علامتگذاری تمامی مطالب بهعنوان خواندهشده",
|
"mark_all_as_read" : "علامتگذاری تمامی مطالب بهعنوان خواندهشده",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Päivitä",
|
"refresh" : "Päivitä",
|
||||||
"refresh_all" : "Pakota kaikkien syötteiden päivitys",
|
"refresh_all" : "Pakota kaikkien syötteiden päivitys",
|
||||||
"sort_by_asc_desc" : "Järjestä päivämäärän mukaan nousevasti/laskevasti",
|
"sort_by_asc_desc" : "Järjestä päivämäärän mukaan nousevasti/laskevasti",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Näytä vain otsikot",
|
"titles_only" : "Näytä vain otsikot",
|
||||||
"expanded_view" : "Laajennettu näkymä",
|
"expanded_view" : "Laajennettu näkymä",
|
||||||
"mark_all_as_read" : "Merkitse kaikki luetuiksi",
|
"mark_all_as_read" : "Merkitse kaikki luetuiksi",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Rafraîchir",
|
"refresh" : "Rafraîchir",
|
||||||
"refresh_all" : "Rafraîchir tous les flux",
|
"refresh_all" : "Rafraîchir tous les flux",
|
||||||
"sort_by_asc_desc" : "Trier par date croissante/décroissante",
|
"sort_by_asc_desc" : "Trier par date croissante/décroissante",
|
||||||
|
"sort_by_abc_zyx" : "Trier par ordre alphabétique",
|
||||||
"titles_only" : "Titres uniquement",
|
"titles_only" : "Titres uniquement",
|
||||||
"expanded_view" : "Vue étendue",
|
"expanded_view" : "Vue étendue",
|
||||||
"mark_all_as_read" : "Tout marquer comme lu",
|
"mark_all_as_read" : "Tout marquer comme lu",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Actualizar",
|
"refresh" : "Actualizar",
|
||||||
"refresh_all" : "Forzar a actualización de todas as fontes ",
|
"refresh_all" : "Forzar a actualización de todas as fontes ",
|
||||||
"sort_by_asc_desc" : "Ordenar por data asc/desc",
|
"sort_by_asc_desc" : "Ordenar por data asc/desc",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Só títulos",
|
"titles_only" : "Só títulos",
|
||||||
"expanded_view" : "Vista expandida",
|
"expanded_view" : "Vista expandida",
|
||||||
"mark_all_as_read" : "Marcar todos como lidos",
|
"mark_all_as_read" : "Marcar todos como lidos",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "واجأری",
|
"refresh" : "واجأری",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "تاریخˇ سر دچئن",
|
"sort_by_asc_desc" : "تاریخˇ سر دچئن",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "خالی تیتران",
|
"titles_only" : "خالی تیتران",
|
||||||
"expanded_view" : "واشاده نما",
|
"expanded_view" : "واشاده نما",
|
||||||
"mark_all_as_read" : "همهته مطالبه چاکون بخانده",
|
"mark_all_as_read" : "همهته مطالبه چاکون بخانده",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Frissítés",
|
"refresh" : "Frissítés",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "Rendezés időrend szerint",
|
"sort_by_asc_desc" : "Rendezés időrend szerint",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Csak cím",
|
"titles_only" : "Csak cím",
|
||||||
"expanded_view" : "Részletes nézet",
|
"expanded_view" : "Részletes nézet",
|
||||||
"mark_all_as_read" : "Az összes megjelölése olvasottként",
|
"mark_all_as_read" : "Az összes megjelölése olvasottként",
|
||||||
|
|||||||
183
src/main/app/i18n/id.js
Normal file
183
src/main/app/i18n/id.js
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
{
|
||||||
|
"global" : {
|
||||||
|
"save" : "Simpan",
|
||||||
|
"cancel" : "Batal",
|
||||||
|
"delete" : "Hapus",
|
||||||
|
"required" : "Diminta",
|
||||||
|
"download" : "Unduh",
|
||||||
|
"link" : "Tautan",
|
||||||
|
"bookmark" : "Penanda halaman buku",
|
||||||
|
"close" : "Tutup",
|
||||||
|
"tags" : "Penanda"
|
||||||
|
},
|
||||||
|
"tree" : {
|
||||||
|
"subscribe" : "Berlangganan",
|
||||||
|
"import" : "Impor",
|
||||||
|
"new_category" : "Kategori Baru",
|
||||||
|
"all" : "Semua",
|
||||||
|
"starred" : "Diutamakan"
|
||||||
|
},
|
||||||
|
"subscribe" : {
|
||||||
|
"feed_url" : "Umpan URL",
|
||||||
|
"feed_name" : "Nama Umpan",
|
||||||
|
"category" : "Kategori"
|
||||||
|
},
|
||||||
|
"import" : {
|
||||||
|
"google_reader_prefix" : "Izinkan saya mengimpor umpan Anda dari kepunyaan Anda ",
|
||||||
|
"google_reader_suffix" : " akun.",
|
||||||
|
"google_download" : "Atau, unggah berkas subscriptions.xml Anda.",
|
||||||
|
"google_download_link" : "Unggah dari sini.",
|
||||||
|
"xml_file" : "Berkas OPML"
|
||||||
|
},
|
||||||
|
"new_category" : {
|
||||||
|
"name" : "Nama",
|
||||||
|
"parent" : "Induk"
|
||||||
|
},
|
||||||
|
"toolbar" : {
|
||||||
|
"unread" : "Belum dibaca",
|
||||||
|
"all" : "Semua",
|
||||||
|
"previous_entry" : "Catatan sebelumnya",
|
||||||
|
"next_entry" : "Catatan selanjutnya",
|
||||||
|
"refresh" : "Segarkan",
|
||||||
|
"refresh_all" : "Memaksa menyegarkan semua umpan saya",
|
||||||
|
"sort_by_asc_desc" : "Urutkan menurut tanggal asc/desc",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
|
"titles_only" : "Hanya Judul",
|
||||||
|
"expanded_view" : "Penglihatan diperluas",
|
||||||
|
"mark_all_as_read" : "Tandai semua sebagai telah dibaca",
|
||||||
|
"mark_all_older_12_hours" : "Butir lebih lama 12 jam",
|
||||||
|
"mark_all_older_day" : "Butir lebih lama sehari",
|
||||||
|
"mark_all_older_week" : "Butir lebih lama seminggu",
|
||||||
|
"mark_all_older_two_weeks" : "Butir lebih lama dua minggu",
|
||||||
|
"settings" : "Pengaturan",
|
||||||
|
"profile" : "Profil",
|
||||||
|
"admin" : "Admin",
|
||||||
|
"about" : "Tentang",
|
||||||
|
"logout" : "Keluar",
|
||||||
|
"donate" : "Donasi"
|
||||||
|
},
|
||||||
|
"view" : {
|
||||||
|
"entry_source" : "dari ",
|
||||||
|
"entry_author" : "oleh ",
|
||||||
|
"error_while_loading_feed" : "Galat saat memuat umpan ini",
|
||||||
|
"keep_unread" : "Tetapkan belum dibaca",
|
||||||
|
"no_unread_items" : "Tidak ada yang butir yang belum dibaca.",
|
||||||
|
"mark_up_to_here" : "Tandai sebagai dibaca di sini",
|
||||||
|
"search_for" : "mencari: ",
|
||||||
|
"no_search_results" : "Tidak ditemukan kata kunci yang sesuai dengan permintaan"
|
||||||
|
},
|
||||||
|
"feedsearch" : {
|
||||||
|
"hint" : "Ketik sebuah langganan...",
|
||||||
|
"help" : "Gunakan tombol enter untuk memilih dan tombol panah untuk navigasi.",
|
||||||
|
"result_prefix" : "Langganan Anda:"
|
||||||
|
},
|
||||||
|
"settings" : {
|
||||||
|
"general" : {
|
||||||
|
"value" : "Umum",
|
||||||
|
"language" : "Bahasa",
|
||||||
|
"language_contribute" : "Kontribusi dengan terjemahan",
|
||||||
|
"show_unread" : "Menampilkan umpan dan kategori tanpa catatan belum dibaca",
|
||||||
|
"social_buttons" : "Menampilkan tombol sosial berbagi",
|
||||||
|
"scroll_marks" : "Di penglihatan luas, menggulir melalui catatan menandakan sebagai telah dibaca"
|
||||||
|
},
|
||||||
|
"appearance" : "Penampilan",
|
||||||
|
"scroll_speed" : "Kecepatan menggulir ketika menavigasi antar catatan (dalam milidetik)",
|
||||||
|
"scroll_speed_help" : "setel ke 0 untuk menonaktifkan",
|
||||||
|
"theme" : "Tema",
|
||||||
|
"submit_your_theme" : "Mengajukan tema Anda",
|
||||||
|
"custom_css" : "Ubah CSS"
|
||||||
|
},
|
||||||
|
"details" : {
|
||||||
|
"feed_details" : "Rincian Umpan",
|
||||||
|
"url" : "URL",
|
||||||
|
"website" : "Situs",
|
||||||
|
"name" : "Nama",
|
||||||
|
"category" : "Kategori",
|
||||||
|
"position" : "Posisi",
|
||||||
|
"last_refresh" : "Penyegaran terakhir",
|
||||||
|
"message" : "Menyegarkan pesan terakhir",
|
||||||
|
"next_refresh" : "Penyegaran selanjutnya",
|
||||||
|
"queued_for_refresh" : "Antri untuk penyegaran",
|
||||||
|
"feed_url" : "Umpan URL",
|
||||||
|
"filtering_expression" : "Penyaring ekspresi",
|
||||||
|
"filtering_expression_help" : "Jika tidak kosong, sebuah ekspresi mengevaluasi ke 'benar' atau 'salah'. Jika salah, catatan baru untuk umpan ini akan ditandai sebagai telah dibaca secara otomatis. \nVariabel yang tersedia adalah 'judul', 'konten', 'url' 'penulis' dan 'kategori' dan konten mereka dikonversi dari huruf kecil ke perbandingan string yang mudah. \nContoh: url.contains('youtube') or (author eq 'athou' and title.contains('github'). \nSintaksis lengkap tersedia di <a href='http://commons.apache.org/proper/commons-jexl/reference/syntax.html' target='_blank'>here</a>.",
|
||||||
|
"generate_api_key_first" : "Menghasilkan sebuah kunci API di profil Anda terlebih dahulu.",
|
||||||
|
"unsubscribe" : "Berhenti berlangganan",
|
||||||
|
"unsubscribe_confirmation" : "Apakah Anda yakin ingin berhenti berlangganan dari umpan ini?",
|
||||||
|
"delete_category_confirmation" : "Apakah Anda yakin ingin menghapus dari kategori ini?",
|
||||||
|
"category_details" : "rincian Kategori",
|
||||||
|
"tag_details" : "rincian Penanda",
|
||||||
|
"parent_category" : "kategori Induk"
|
||||||
|
},
|
||||||
|
"profile" : {
|
||||||
|
"user_name" : "nama Pengguna",
|
||||||
|
"email" : "Surel",
|
||||||
|
"change_password" : "Ganti kata sandi",
|
||||||
|
"confirm_password" : "Konfirmasi kata sandi",
|
||||||
|
"minimum_6_chars" : "Minimal 6 karakter",
|
||||||
|
"passwords_do_not_match" : "Kata sandi tidak sesuai",
|
||||||
|
"api_key" : "kunci API",
|
||||||
|
"api_key_not_generated" : "Belum menghasilkan",
|
||||||
|
"generate_new_api_key" : "Hasilkan kunci API baru",
|
||||||
|
"generate_new_api_key_info" : "Mengganti kata sandi akan menghasilkan sebuah kunci API baru",
|
||||||
|
"opml_export" : "ekspor OPML",
|
||||||
|
"delete_account" : "Hapus akun",
|
||||||
|
"delete_account_confirmation" : "Hapus akun Anda? Hal ini tidak dapat dikembalikan!"
|
||||||
|
},
|
||||||
|
"about" : {
|
||||||
|
"rest_api" : {
|
||||||
|
"value" : "REST API",
|
||||||
|
"line1" : "CommaFeed dibangun di atas JAX-RS dan AngularJS. Dengan demikian, tersedia sebuah REST API.",
|
||||||
|
"link_to_documentation" : "Tautan menuju dokumentasi."
|
||||||
|
},
|
||||||
|
"keyboard_shortcuts" : "pintasan Papanketik",
|
||||||
|
"version" : "versi CommaFeed",
|
||||||
|
"line1_prefix" : "CommaFeed adalah suatu proyek open-source. Sumber di ",
|
||||||
|
"line1_suffix" : ".",
|
||||||
|
"line2_prefix" : "Jika Anda mengalami sebuah isu, silahkan laporkan pada halaman isu ",
|
||||||
|
"line2_suffix" : " proyek.",
|
||||||
|
"line3" : "Jika Anda menyukai proyek ini, silahkan mempertimbangkan suatu donasi untuk mendukung pengembang dan membantu menutupi biaya online situs ini.",
|
||||||
|
"line4" : "Untuk Anda yang lebih suka bitcoin, alamatnya di sini",
|
||||||
|
"goodies" : {
|
||||||
|
"value" : "Bingkisan",
|
||||||
|
"android_app" : "Android app",
|
||||||
|
"subscribe_url" : "URL Langganan",
|
||||||
|
"chrome_extension" : "ekstensi Chrome",
|
||||||
|
"firefox_extension" : "ekstensi Firefox",
|
||||||
|
"opera_extension" : "ekstensi Opera",
|
||||||
|
"subscribe_bookmarklet" : "Tambahkan bookmarklet langganan(klik)",
|
||||||
|
"subscribe_bookmarklet_asc" : "Terlama dahulu",
|
||||||
|
"subscribe_bookmarklet_desc" : "Terbaru dahulu",
|
||||||
|
"next_unread_bookmarklet" : "Butir bookmarklet selanjutnya yang belum dibaca (seret ke batang penanda halaman buku)"
|
||||||
|
},
|
||||||
|
"translation" : {
|
||||||
|
"value" : "Terjemahan",
|
||||||
|
"message" : "Kami membutuhkan bantuan Anda untuk menterjemahkan CommaFeed.",
|
||||||
|
"link" : "Lihat bagaimana berkontribusi dengan terjemahan."
|
||||||
|
},
|
||||||
|
"announcements" : "Pengumuman",
|
||||||
|
"shortcuts" : {
|
||||||
|
"mouse_middleclick" : "klik tengah tetikus",
|
||||||
|
"open_next_entry" : "buka catatan selanjutnya",
|
||||||
|
"open_previous_entry" : "buka catatan sebelumnya",
|
||||||
|
"spacebar" : "spasi/shift+spasi",
|
||||||
|
"move_page_down_up" : "pindah halaman bawah/atas",
|
||||||
|
"focus_next_entry" : "setel fokus pada catatan selanjutnya tanpa membukanya",
|
||||||
|
"focus_previous_entry" : "setel fokus pada catatan sebelumnya tanpa membukanya",
|
||||||
|
"open_next_feed" : "buka umpan atau kategori selanjutnya",
|
||||||
|
"open_previous_feed" : "buka umpan atau kategori sebelumnya",
|
||||||
|
"open_close_current_entry" : "buka/tutup catatan saat ini",
|
||||||
|
"open_current_entry_in_new_window" : "buka catatan saat ini di sebuah jendela baru",
|
||||||
|
"open_current_entry_in_new_window_background" : "buka catatan saat ini di sebuah jendela baru pada latar",
|
||||||
|
"star_unstar" : "tanda bintang/tidak catatan saat ini",
|
||||||
|
"mark_current_entry" : "tandai sebagai telah dibaca/belum catatan saat ini",
|
||||||
|
"mark_all_as_read" : "tandai semua catatan sebagai telah dibaca",
|
||||||
|
"open_in_new_tab_mark_as_read" : "buka catatan di tab baru dan tandai sebagai telah dibaca",
|
||||||
|
"fullscreen" : "beralih modus layar penuh",
|
||||||
|
"font_size" : "tingkatkan/turunkan ukuran huruf dari catatan saat ini",
|
||||||
|
"go_to_all" : "menuju ke lihat Semua",
|
||||||
|
"go_to_starred" : "menuju ke lihat Tanda Bintang",
|
||||||
|
"feed_search" : "navigasi ke langganan dengan memasukkan nama langganan"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Aggiorna",
|
"refresh" : "Aggiorna",
|
||||||
"refresh_all" : "Forza l'aggiornamento di tutti i feed",
|
"refresh_all" : "Forza l'aggiornamento di tutti i feed",
|
||||||
"sort_by_asc_desc" : "Ordina per data crescente/decrescente",
|
"sort_by_asc_desc" : "Ordina per data crescente/decrescente",
|
||||||
|
"sort_by_abc_zyx" : "Ordina alfabeticamente",
|
||||||
"titles_only" : "Solo i titoli",
|
"titles_only" : "Solo i titoli",
|
||||||
"expanded_view" : "Espandi",
|
"expanded_view" : "Espandi",
|
||||||
"mark_all_as_read" : "Segna tutti come già letti",
|
"mark_all_as_read" : "Segna tutti come già letti",
|
||||||
@@ -56,8 +57,8 @@
|
|||||||
"donate" : "Dona"
|
"donate" : "Dona"
|
||||||
},
|
},
|
||||||
"view" : {
|
"view" : {
|
||||||
"entry_source" : "da",
|
"entry_source" : "da ",
|
||||||
"entry_author" : "di",
|
"entry_author" : "di ",
|
||||||
"error_while_loading_feed" : "Si è verificato un errore durante il caricamento del feed",
|
"error_while_loading_feed" : "Si è verificato un errore durante il caricamento del feed",
|
||||||
"keep_unread" : "Mantieni come da leggere",
|
"keep_unread" : "Mantieni come da leggere",
|
||||||
"no_unread_items" : "non contiene elementi da leggere",
|
"no_unread_items" : "non contiene elementi da leggere",
|
||||||
@@ -81,9 +82,9 @@
|
|||||||
},
|
},
|
||||||
"appearance" : "Aspetto",
|
"appearance" : "Aspetto",
|
||||||
"scroll_speed" : "Velocità di scorrimento quando navighi tra i feed (in millisecondi)",
|
"scroll_speed" : "Velocità di scorrimento quando navighi tra i feed (in millisecondi)",
|
||||||
"scroll_speed_help" : "Imposta su 0 per disabilitare",
|
"scroll_speed_help" : "imposta su 0 per disabilitare",
|
||||||
"theme" : "Tema",
|
"theme" : "Tema",
|
||||||
"submit_your_theme" : "Sottoponi il tuo tema",
|
"submit_your_theme" : "Inserisci il tuo tema",
|
||||||
"custom_css" : "CSS personalizzato"
|
"custom_css" : "CSS personalizzato"
|
||||||
},
|
},
|
||||||
"details" : {
|
"details" : {
|
||||||
@@ -129,7 +130,7 @@
|
|||||||
"line1" : "CommaFeed è basato su JAX-RS e AngularJS. Pertanto è disponibile una REST API.",
|
"line1" : "CommaFeed è basato su JAX-RS e AngularJS. Pertanto è disponibile una REST API.",
|
||||||
"link_to_documentation" : "Link alla documentazione."
|
"link_to_documentation" : "Link alla documentazione."
|
||||||
},
|
},
|
||||||
"keyboard_shortcuts" : "Scorciatoie da tastiera",
|
"keyboard_shortcuts" : "Scorciatoie da tastiera",
|
||||||
"version" : "Versione di CommaFeed",
|
"version" : "Versione di CommaFeed",
|
||||||
"line1_prefix" : "CommaFeed è un progetto open source. Trovi i sorgenti su ",
|
"line1_prefix" : "CommaFeed è un progetto open source. Trovi i sorgenti su ",
|
||||||
"line1_suffix" : ".",
|
"line1_suffix" : ".",
|
||||||
@@ -147,12 +148,12 @@
|
|||||||
"subscribe_bookmarklet" : "Aggiungi la sottoscrizione ai segnalibri (clicca)",
|
"subscribe_bookmarklet" : "Aggiungi la sottoscrizione ai segnalibri (clicca)",
|
||||||
"subscribe_bookmarklet_asc" : "Prima i vecchi",
|
"subscribe_bookmarklet_asc" : "Prima i vecchi",
|
||||||
"subscribe_bookmarklet_desc" : "Prima i recenti",
|
"subscribe_bookmarklet_desc" : "Prima i recenti",
|
||||||
"next_unread_bookmarklet" : "Bookmarklet al prossimo elemento da leggere (trascinalo nella barra dei segnalibri)"
|
"next_unread_bookmarklet" : "Segnalibro al prossimo elemento da leggere (trascinalo nella barra dei segnalibri)"
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "Traduzioni",
|
"value" : "Traduzioni",
|
||||||
"message" : "Abbiamo bisogno del tuo aiuto per tradurre CommaFeed.",
|
"message" : "Abbiamo bisogno del tuo aiuto per tradurre CommaFeed.",
|
||||||
"link" : "Scopri come aiutarci nella traduzioni."
|
"link" : "Scopri come aiutarci nelle traduzioni."
|
||||||
},
|
},
|
||||||
"announcements" : "Annunci",
|
"announcements" : "Annunci",
|
||||||
"shortcuts" : {
|
"shortcuts" : {
|
||||||
@@ -176,7 +177,8 @@
|
|||||||
"font_size" : "aumenta/decrementa la dimensione del font per la voce corrente",
|
"font_size" : "aumenta/decrementa la dimensione del font per la voce corrente",
|
||||||
"go_to_all" : "vai alla vista Tutti",
|
"go_to_all" : "vai alla vista Tutti",
|
||||||
"go_to_starred" : "vai alla vista Preferiti",
|
"go_to_starred" : "vai alla vista Preferiti",
|
||||||
"feed_search" : "raggiungi una sottoscrizione scrivendo il suo nome"
|
"feed_search" : "raggiungi una sottoscrizione scrivendo il suo nome",
|
||||||
|
"refresh" : "aggiorna"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"save" : "保存",
|
"save" : "保存",
|
||||||
"cancel" : "取り消し",
|
"cancel" : "取り消し",
|
||||||
"delete" : "削除",
|
"delete" : "削除",
|
||||||
"required" : "Required",
|
"required" : "必須",
|
||||||
"download" : "ダウンロード",
|
"download" : "ダウンロード",
|
||||||
"link" : "リンク",
|
"link" : "リンク",
|
||||||
"bookmark" : "ブックマーク",
|
"bookmark" : "ブックマーク",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"import" : "インポート",
|
"import" : "インポート",
|
||||||
"new_category" : "新しいカテゴリー",
|
"new_category" : "新しいカテゴリー",
|
||||||
"all" : "全て",
|
"all" : "全て",
|
||||||
"starred" : "スター付"
|
"starred" : "スター付き"
|
||||||
},
|
},
|
||||||
"subscribe" : {
|
"subscribe" : {
|
||||||
"feed_url" : "フィードURL",
|
"feed_url" : "フィードURL",
|
||||||
@@ -40,7 +40,8 @@
|
|||||||
"next_entry" : "次のエントリー",
|
"next_entry" : "次のエントリー",
|
||||||
"refresh" : "更新",
|
"refresh" : "更新",
|
||||||
"refresh_all" : "全てのフィードを更新",
|
"refresh_all" : "全てのフィードを更新",
|
||||||
"sort_by_asc_desc" : "昇順/降順にソート",
|
"sort_by_asc_desc" : "日時でソート",
|
||||||
|
"sort_by_abc_zyx" : "名前でソート",
|
||||||
"titles_only" : "タイトルのみ",
|
"titles_only" : "タイトルのみ",
|
||||||
"expanded_view" : "拡張ビュー",
|
"expanded_view" : "拡張ビュー",
|
||||||
"mark_all_as_read" : "全て既読にする",
|
"mark_all_as_read" : "全て既読にする",
|
||||||
@@ -100,8 +101,8 @@
|
|||||||
"feed_url" : "フィードURL",
|
"feed_url" : "フィードURL",
|
||||||
"generate_api_key_first" : "最初にあなたのAPIキーを生成して下さい。",
|
"generate_api_key_first" : "最初にあなたのAPIキーを生成して下さい。",
|
||||||
"unsubscribe" : "購読解除",
|
"unsubscribe" : "購読解除",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "フィードの購読を解除してよろしいですか?",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "カテゴリーを削除してよろしいですか?",
|
||||||
"category_details" : "カテゴリー詳細",
|
"category_details" : "カテゴリー詳細",
|
||||||
"tag_details" : "タグ詳細",
|
"tag_details" : "タグ詳細",
|
||||||
"parent_category" : "親カテゴリー"
|
"parent_category" : "親カテゴリー"
|
||||||
@@ -116,10 +117,10 @@
|
|||||||
"api_key" : "APIキー",
|
"api_key" : "APIキー",
|
||||||
"api_key_not_generated" : "APIキーが生成されていません",
|
"api_key_not_generated" : "APIキーが生成されていません",
|
||||||
"generate_new_api_key" : "新しいAPIキーを生成",
|
"generate_new_api_key" : "新しいAPIキーを生成",
|
||||||
"generate_new_api_key_info" : "パスワードの変更は新しいAPIキーが生成されます",
|
"generate_new_api_key_info" : "パスワードを変更すると新しいAPIキーが生成されます",
|
||||||
"opml_export" : "OPMLエクスポート",
|
"opml_export" : "OPMLエクスポート",
|
||||||
"delete_account" : "アカウント削除",
|
"delete_account" : "アカウント削除",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "アカウントを削除してよろしいですか? 削除すると戻すことはできません!"
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
@@ -149,10 +150,10 @@
|
|||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "翻訳",
|
"value" : "翻訳",
|
||||||
"message" : "CommaFeedの翻訳に助けが必要です!",
|
"message" : "CommaFeedの翻訳にご協力ください!",
|
||||||
"link" : "どうやって翻訳に貢献できるか見て下さい。"
|
"link" : "翻訳にあたっての案内はこちら"
|
||||||
},
|
},
|
||||||
"announcements" : "Announcements",
|
"announcements" : "お知らせ",
|
||||||
"shortcuts" : {
|
"shortcuts" : {
|
||||||
"mouse_middleclick" : "中クリック",
|
"mouse_middleclick" : "中クリック",
|
||||||
"open_next_entry" : "次のエントリーを開く",
|
"open_next_entry" : "次のエントリーを開く",
|
||||||
@@ -170,7 +171,7 @@
|
|||||||
"mark_current_entry" : "現在のエントリーを既読/未読にする",
|
"mark_current_entry" : "現在のエントリーを既読/未読にする",
|
||||||
"mark_all_as_read" : "全エントリーを既読にする",
|
"mark_all_as_read" : "全エントリーを既読にする",
|
||||||
"open_in_new_tab_mark_as_read" : "エントリーを既読にして新しいタブで開く",
|
"open_in_new_tab_mark_as_read" : "エントリーを既読にして新しいタブで開く",
|
||||||
"fullscreen" : "フルスクリーントグル",
|
"fullscreen" : "フルスクリーン切り替え",
|
||||||
"font_size" : "現在のエントリーのフォントサイズを大きく/小さくする",
|
"font_size" : "現在のエントリーのフォントサイズを大きく/小さくする",
|
||||||
"go_to_all" : "All viewに変更する",
|
"go_to_all" : "All viewに変更する",
|
||||||
"go_to_starred" : "スター付きviewに変更する",
|
"go_to_starred" : "スター付きviewに変更する",
|
||||||
|
|||||||
@@ -4,23 +4,23 @@
|
|||||||
"cancel" : "취소",
|
"cancel" : "취소",
|
||||||
"delete" : "삭제",
|
"delete" : "삭제",
|
||||||
"required" : "필수",
|
"required" : "필수",
|
||||||
"download" : "Download ",
|
"download" : "다운로드",
|
||||||
"link" : "Link ",
|
"link" : "링크",
|
||||||
"bookmark" : "Bookmark ",
|
"bookmark" : "북마크",
|
||||||
"close" : "Close ",
|
"close" : "닫기 ",
|
||||||
"tags" : "Tags "
|
"tags" : "태그 "
|
||||||
},
|
},
|
||||||
"tree" : {
|
"tree" : {
|
||||||
"subscribe" : "구독",
|
"subscribe" : "구독",
|
||||||
"import" : "임포트",
|
"import" : "가져오기",
|
||||||
"new_category" : "새로운 카테고리",
|
"new_category" : "새로운 카테고리",
|
||||||
"all" : "전체",
|
"all" : "전체",
|
||||||
"starred" : "스타"
|
"starred" : "중요 표시됨"
|
||||||
},
|
},
|
||||||
"subscribe" : {
|
"subscribe" : {
|
||||||
"feed_url" : "피드 URL",
|
"feed_url" : "피드 URL",
|
||||||
"feed_name" : "피드 이름",
|
"feed_name" : "피드 이름",
|
||||||
"category" : "카테로기"
|
"category" : "카테고리"
|
||||||
},
|
},
|
||||||
"import" : {
|
"import" : {
|
||||||
"google_reader_prefix" : "당신의 Google Reader",
|
"google_reader_prefix" : "당신의 Google Reader",
|
||||||
@@ -31,23 +31,24 @@
|
|||||||
},
|
},
|
||||||
"new_category" : {
|
"new_category" : {
|
||||||
"name" : "이름",
|
"name" : "이름",
|
||||||
"parent" : "카테고리 주소로 가기"
|
"parent" : "부모 카테고리"
|
||||||
},
|
},
|
||||||
"toolbar" : {
|
"toolbar" : {
|
||||||
"unread" : "안읽음",
|
"unread" : "읽지 않음",
|
||||||
"all" : "전체",
|
"all" : "전체",
|
||||||
"previous_entry" : "Previous entry ",
|
"previous_entry" : "이전 항목",
|
||||||
"next_entry" : "Next entry ",
|
"next_entry" : "다음 항목",
|
||||||
"refresh" : "리프래쉬",
|
"refresh" : "새로고침",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "모든 피드를 강제로 새로고침",
|
||||||
"sort_by_asc_desc" : "Sort by date asc/desc ",
|
"sort_by_asc_desc" : "날짜별 오름차/내림차순 정렬",
|
||||||
"titles_only" : "Titles only ",
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"expanded_view" : "Expanded view ",
|
"titles_only" : "제목만 표시하기",
|
||||||
"mark_all_as_read" : "읽음표시",
|
"expanded_view" : "Expanded View",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_as_read" : "읽음으로 표시",
|
||||||
"mark_all_older_day" : "Items older than a day ",
|
"mark_all_older_12_hours" : "12시간보다 오래된 항목",
|
||||||
"mark_all_older_week" : "Items older than a week ",
|
"mark_all_older_day" : "1일보다 오래된 항목",
|
||||||
"mark_all_older_two_weeks" : "Items older than two weeks ",
|
"mark_all_older_week" : "1주일보다 오래된 항목",
|
||||||
|
"mark_all_older_two_weeks" : "2주일보다 오래된 항목",
|
||||||
"settings" : "설정",
|
"settings" : "설정",
|
||||||
"profile" : "프로필",
|
"profile" : "프로필",
|
||||||
"admin" : "괸리자",
|
"admin" : "괸리자",
|
||||||
@@ -57,124 +58,124 @@
|
|||||||
},
|
},
|
||||||
"view" : {
|
"view" : {
|
||||||
"entry_source" : "from ",
|
"entry_source" : "from ",
|
||||||
"entry_author" : "by ",
|
"entry_author" : "by ",
|
||||||
"error_while_loading_feed" : "피드로딩중 에러",
|
"error_while_loading_feed" : "피드 로딩중 에러",
|
||||||
"keep_unread" : "안읽은것 저장",
|
"keep_unread" : "항상 읽지 않음으로 표시",
|
||||||
"no_unread_items" : " 읽지않은 항목이 없읍니다.",
|
"no_unread_items" : " 읽지 않은 항목이 없습니다.",
|
||||||
"mark_up_to_here" : "Mark as read up to here ",
|
"mark_up_to_here" : "이 위로 읽음으로 표시",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "검색: ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "검색 결과 없음"
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Type in a subscription... ",
|
"hint" : "구독 이름을 입력하세요",
|
||||||
"help" : "Use the return key to select and arrow keys to navigate. ",
|
"help" : "화살표 키로 이동하고 엔터 키로 선택하세요.",
|
||||||
"result_prefix" : "Your subscriptions: "
|
"result_prefix" : "검색 결과:"
|
||||||
},
|
},
|
||||||
"settings" : {
|
"settings" : {
|
||||||
"general" : {
|
"general" : {
|
||||||
"value" : "일반",
|
"value" : "일반",
|
||||||
"language" : "일반 언어",
|
"language" : "언어",
|
||||||
"language_contribute" : "번역 도움하기",
|
"language_contribute" : "번역에 기여하기",
|
||||||
"show_unread" : "안읽은 항목들이 있는 피드와 카테고리 보여주기",
|
"show_unread" : "안 읽은 항목들이 있는 피드와 카테고리 보여주기",
|
||||||
"social_buttons" : "소셜미디아 버튼들 보여주기",
|
"social_buttons" : "공유 버튼 표시하기",
|
||||||
"scroll_marks" : "Expanded View에서 스크롤하면 항목들을 읽음으로 저장하기"
|
"scroll_marks" : "Expanded View에서 스크롤하면 항목들을 읽음으로 표시하기"
|
||||||
},
|
},
|
||||||
"appearance" : "Appearance ",
|
"appearance" : "외관",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "항목 사이를 이동할 때 스크롤 속도 (밀리초로 설정)",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "비활성화하려면 0으로 설정하세요",
|
||||||
"theme" : "Theme ",
|
"theme" : "테마",
|
||||||
"submit_your_theme" : "Submit your theme ",
|
"submit_your_theme" : "새 테마 업로드",
|
||||||
"custom_css" : "커스톰 CSS"
|
"custom_css" : "커스텀 CSS"
|
||||||
},
|
},
|
||||||
"details" : {
|
"details" : {
|
||||||
"feed_details" : "피드 세부",
|
"feed_details" : "피드 상세",
|
||||||
"url" : "유알엘",
|
"url" : "URL",
|
||||||
"website" : "Website ",
|
"website" : "웹사이트",
|
||||||
"name" : "이름",
|
"name" : "이름",
|
||||||
"category" : "카테고리",
|
"category" : "카테고리",
|
||||||
"position" : "Position ",
|
"position" : "위치",
|
||||||
"last_refresh" : "마지막 리프래쉬",
|
"last_refresh" : "마지막 새로고침",
|
||||||
"message" : "Last refresh message ",
|
"message" : "마지막 새로고침 메시지",
|
||||||
"next_refresh" : "Next refresh ",
|
"next_refresh" : "다음 새로고침",
|
||||||
"queued_for_refresh" : "Queued for refresh ",
|
"queued_for_refresh" : "새로고침 대기중",
|
||||||
"feed_url" : "피드 유알엘",
|
"feed_url" : "피드 URL",
|
||||||
"generate_api_key_first" : "당신의 프로필을 위해 API Key를 먼저 생성하세요.",
|
"generate_api_key_first" : "당신의 프로필을 위해 API Key를 먼저 생성하세요.",
|
||||||
"unsubscribe" : "주소 삭제",
|
"unsubscribe" : "구독 해제",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "정말 이 피드를 구독 해제하시겠습니까?",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "정말 이 카테고리를 삭제하시겠습니까?",
|
||||||
"category_details" : "카테고리 세부",
|
"category_details" : "카테고리 상세",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "태그 상세",
|
||||||
"parent_category" : "부모 카테고리"
|
"parent_category" : "부모 카테고리"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
"user_name" : "사용자 이름",
|
"user_name" : "사용자 이름",
|
||||||
"email" : "이메일",
|
"email" : "이메일",
|
||||||
"change_password" : "비밀번호변경",
|
"change_password" : "비밀번호 변경",
|
||||||
"confirm_password" : "비밀번호확인",
|
"confirm_password" : "비밀번호 확인",
|
||||||
"minimum_6_chars" : "최소로 6자문자가 필요합니다.",
|
"minimum_6_chars" : "최소 6개의 문자가 필요합니다.",
|
||||||
"passwords_do_not_match" : "비밀번호가 일치하지 않습니다.",
|
"passwords_do_not_match" : "비밀번호가 일치하지 않습니다.",
|
||||||
"api_key" : "API key",
|
"api_key" : "API key",
|
||||||
"api_key_not_generated" : "아직 API Key가 생성되지 않았습니다.",
|
"api_key_not_generated" : "아직 API Key가 생성되지 않았습니다.",
|
||||||
"generate_new_api_key" : "API Key 생성하기",
|
"generate_new_api_key" : "API Key 생성하기",
|
||||||
"generate_new_api_key_info" : "비밀번호를 변경하면 새로운 API Key가 생성됩니다.",
|
"generate_new_api_key_info" : "비밀번호를 변경하면 새로운 API Key가 생성됩니다.",
|
||||||
"opml_export" : "OPML export ",
|
"opml_export" : "OPML 내보내기",
|
||||||
"delete_account" : "프로필삭제",
|
"delete_account" : "계정 삭제하기",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "계정을 삭제하시겠습니까? 되돌릴 수 없어요!"
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
"value" : "REST API",
|
"value" : "REST API",
|
||||||
"line1" : "CommaFeed는 JAX-RS하고 AngularJS를 이용해서 만들었습니다. 그렇기 때문에 REST API를 사용할수있습니다.",
|
"line1" : "CommaFeed는 JAX-RS와 AngularJS를 이용해 만들었습니다. 그렇기 때문에 REST API를 사용할수있습니다.",
|
||||||
"link_to_documentation" : "문서 링크."
|
"link_to_documentation" : "문서 링크."
|
||||||
},
|
},
|
||||||
"keyboard_shortcuts" : "단축기",
|
"keyboard_shortcuts" : "단축키",
|
||||||
"version" : "CommaFeed version ",
|
"version" : "CommaFeed 버전",
|
||||||
"line1_prefix" : "CommaFeed는 오픈 소스프로젝트입니다. 소스는",
|
"line1_prefix" : "CommaFeed는 오픈 소스 프로젝트입니다. 소스는",
|
||||||
"line1_suffix" : "에 있습니다.",
|
"line1_suffix" : "에 있습니다.",
|
||||||
"line2_prefix" : "문제가 발생하는 경우",
|
"line2_prefix" : "문제가 발생하는 경우",
|
||||||
"line2_suffix" : " 프로젝트 문제페이지에 보고하십시요.",
|
"line2_suffix" : " 프로젝트 문제 페이지에 보고하십시오.",
|
||||||
"line3" : "이 프로젝트를 좋아하시면 개발자를 지원하고 웹사이트 유지용비를 충당하는 데 도움이되는 기부금을 고려하시기 바랍니다.",
|
"line3" : "이 프로젝트를 좋아하시면 개발자를 지원하고 웹사이트 유지비용을 충당하는 데 도움이 되는 기부금을 고려하시기 바랍니다.",
|
||||||
"line4" : "For those of you who prefer bitcoin, here is the address ",
|
"line4" : "비트코인으로 기부하기",
|
||||||
"goodies" : {
|
"goodies" : {
|
||||||
"value" : "Goodies",
|
"value" : "Goodies",
|
||||||
"android_app" : "Android app ",
|
"android_app" : "안드로이드 앱",
|
||||||
"subscribe_url" : "Subscribe URL ",
|
"subscribe_url" : "구독 URL",
|
||||||
"chrome_extension" : "Chrome extension ",
|
"chrome_extension" : "Chrome 확장 프로그램",
|
||||||
"firefox_extension" : "Firefox extension ",
|
"firefox_extension" : "Firefox 확장 기능",
|
||||||
"opera_extension" : "Opera extension ",
|
"opera_extension" : "Opera 확장 기능",
|
||||||
"subscribe_bookmarklet" : "Add subscription bookmarklet (click) ",
|
"subscribe_bookmarklet" : "구독 북마크 추가 (클릭)",
|
||||||
"subscribe_bookmarklet_asc" : "Oldest first ",
|
"subscribe_bookmarklet_asc" : "오래된 것 먼저",
|
||||||
"subscribe_bookmarklet_desc" : "Newest first ",
|
"subscribe_bookmarklet_desc" : "새로운 것 먼저",
|
||||||
"next_unread_bookmarklet" : "Next unread item bookmarklet (drag to bookmark bar) "
|
"next_unread_bookmarklet" : "안 읽은 항목 북마크 (북마크바에 끌기) "
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "번역",
|
"value" : "번역",
|
||||||
"message" : "CommaFeed를 번역할려면 당신의 도움이 필요합니다.",
|
"message" : "CommaFeed를 번역하는데 당신의 도움이 필요합니다.",
|
||||||
"link" : "번역에 기여하기"
|
"link" : "번역에 기여하기"
|
||||||
},
|
},
|
||||||
"announcements" : "공지",
|
"announcements" : "공지",
|
||||||
"shortcuts" : {
|
"shortcuts" : {
|
||||||
"mouse_middleclick" : "마우시 미들클릭",
|
"mouse_middleclick" : "마우스 미들클릭",
|
||||||
"open_next_entry" : "다음 항목 열기",
|
"open_next_entry" : "다음 항목 열기",
|
||||||
"open_previous_entry" : "이전 항목 열기",
|
"open_previous_entry" : "이전 항목 열기",
|
||||||
"spacebar" : "space/shift+space ",
|
"spacebar" : "space/shift+space ",
|
||||||
"move_page_down_up" : "moves the page down/up ",
|
"move_page_down_up" : "페이지 아래/위로 이동 ",
|
||||||
"focus_next_entry" : "set focus on next entry without opening it ",
|
"focus_next_entry" : "열지 않고 다음 항목 보기",
|
||||||
"focus_previous_entry" : "set focus on previous entry without opening it ",
|
"focus_previous_entry" : "열지 않고 이전 항목 보기",
|
||||||
"open_next_feed" : "open next feed or category ",
|
"open_next_feed" : "다음 피드나 카테고리 열기",
|
||||||
"open_previous_feed" : "open previous feed or category ",
|
"open_previous_feed" : "이전 피드나 카테고리 열기",
|
||||||
"open_close_current_entry" : "현재 항목 열기/닫기",
|
"open_close_current_entry" : "현재 항목 열기/닫기",
|
||||||
"open_current_entry_in_new_window" : "새 창에서 현재 항목열기",
|
"open_current_entry_in_new_window" : "새 창으로 현재 항목 열기",
|
||||||
"open_current_entry_in_new_window_background" : "open current entry in a new window in the background ",
|
"open_current_entry_in_new_window_background" : "백그라운드에 새 창으로 현재 항목 열기",
|
||||||
"star_unstar" : "현재 항목 스타/스타제거",
|
"star_unstar" : "현재 항목 중요 표시/중요 표시 제거",
|
||||||
"mark_current_entry" : "현재 항목 읽음/안읽음 표시",
|
"mark_current_entry" : "현재 항목 읽음/안읽음 표시",
|
||||||
"mark_all_as_read" : "모든 항목 읽음으로 표시",
|
"mark_all_as_read" : "모든 항목 읽음으로 표시",
|
||||||
"open_in_new_tab_mark_as_read" : "읽음으로 표시하고 새로운 탭에서 열기",
|
"open_in_new_tab_mark_as_read" : "읽음으로 표시하고 새로운 탭에서 열기",
|
||||||
"fullscreen" : "toggle full screen mode ",
|
"fullscreen" : "전체화면 켜기/끄기",
|
||||||
"font_size" : "increase/decrease font size of the current entry ",
|
"font_size" : "현재 항목의 글꼴 크기를 크게/작게",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "모든 항목 보기",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "중요 표시한 항목 보기",
|
||||||
"feed_search" : "navigate to a subscription by entering the subscription name "
|
"feed_search" : "구독 이름으로 구독 찾기"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Refresh",
|
"refresh" : "Refresh",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "Aturkan mengikut tarikh (baru/lama)",
|
"sort_by_asc_desc" : "Aturkan mengikut tarikh (baru/lama)",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Tajuk sahaja",
|
"titles_only" : "Tajuk sahaja",
|
||||||
"expanded_view" : "Wide view",
|
"expanded_view" : "Wide view",
|
||||||
"mark_all_as_read" : "Tanda kesemuanya telah dibaca",
|
"mark_all_as_read" : "Tanda kesemuanya telah dibaca",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Oppdater",
|
"refresh" : "Oppdater",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "Sorter etter dato ny/gammel",
|
"sort_by_asc_desc" : "Sorter etter dato ny/gammel",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Kun titler",
|
"titles_only" : "Kun titler",
|
||||||
"expanded_view" : "Utvidet visning",
|
"expanded_view" : "Utvidet visning",
|
||||||
"mark_all_as_read" : "Merk alle som lest",
|
"mark_all_as_read" : "Merk alle som lest",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Vernieuwen",
|
"refresh" : "Vernieuwen",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "Sorteer op datum opl/afl",
|
"sort_by_asc_desc" : "Sorteer op datum opl/afl",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Alleen titels",
|
"titles_only" : "Alleen titels",
|
||||||
"expanded_view" : "Uitgebreide weergave",
|
"expanded_view" : "Uitgebreide weergave",
|
||||||
"mark_all_as_read" : "Markeer alles als gelezen",
|
"mark_all_as_read" : "Markeer alles als gelezen",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Oppdater",
|
"refresh" : "Oppdater",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Force refresh all my feeds ",
|
||||||
"sort_by_asc_desc" : "Sorter etter dato ny/gamal",
|
"sort_by_asc_desc" : "Sorter etter dato ny/gamal",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Berre titlar",
|
"titles_only" : "Berre titlar",
|
||||||
"expanded_view" : "Utvida visning",
|
"expanded_view" : "Utvida visning",
|
||||||
"mark_all_as_read" : "Merk alle som lesne",
|
"mark_all_as_read" : "Merk alle som lesne",
|
||||||
|
|||||||
@@ -39,12 +39,13 @@
|
|||||||
"previous_entry" : "Poprzedni element",
|
"previous_entry" : "Poprzedni element",
|
||||||
"next_entry" : "Następny element",
|
"next_entry" : "Następny element",
|
||||||
"refresh" : "Odswież",
|
"refresh" : "Odswież",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Odśwież teraz wszystkie kanały ",
|
||||||
"sort_by_asc_desc" : "Sortuj od najnowszego/najstarszego",
|
"sort_by_asc_desc" : "Sortuj od najnowszego/najstarszego",
|
||||||
|
"sort_by_abc_zyx" : "Sortuj alfabetycznie",
|
||||||
"titles_only" : "Widok listy",
|
"titles_only" : "Widok listy",
|
||||||
"expanded_view" : "Widok rozwinięty",
|
"expanded_view" : "Widok rozwinięty",
|
||||||
"mark_all_as_read" : "Oznacz wszystko jako przeczytane",
|
"mark_all_as_read" : "Oznacz wszystko jako przeczytane",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_older_12_hours" : "Elementy starsze niż 12 godzin ",
|
||||||
"mark_all_older_day" : "Elementy starsze niż dzień",
|
"mark_all_older_day" : "Elementy starsze niż dzień",
|
||||||
"mark_all_older_week" : "Elementy starsze niż tydzień",
|
"mark_all_older_week" : "Elementy starsze niż tydzień",
|
||||||
"mark_all_older_two_weeks" : "Elementy starsze niż dwa tygodnie",
|
"mark_all_older_two_weeks" : "Elementy starsze niż dwa tygodnie",
|
||||||
@@ -61,9 +62,9 @@
|
|||||||
"error_while_loading_feed" : "Wystąpił błąd podczas ładowania tego kanału.",
|
"error_while_loading_feed" : "Wystąpił błąd podczas ładowania tego kanału.",
|
||||||
"keep_unread" : "Pozostaw nieprzeczytane",
|
"keep_unread" : "Pozostaw nieprzeczytane",
|
||||||
"no_unread_items" : " nie ma nieprzeczytanych elementów.",
|
"no_unread_items" : " nie ma nieprzeczytanych elementów.",
|
||||||
"mark_up_to_here" : "Mark as read up to here ",
|
"mark_up_to_here" : "Oznacz jako przeczytane do tego elementu ",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "wyszukiwanie dla: ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "Nie znaleziono wyników dla wyszukiwanej frazy "
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Wpisz subskrybcję...",
|
"hint" : "Wpisz subskrybcję...",
|
||||||
@@ -80,8 +81,8 @@
|
|||||||
"scroll_marks" : "W widoku rozwiniętym przewijanie oznacza elementy jako przeczytane"
|
"scroll_marks" : "W widoku rozwiniętym przewijanie oznacza elementy jako przeczytane"
|
||||||
},
|
},
|
||||||
"appearance" : "Wygląd",
|
"appearance" : "Wygląd",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "Prędkość przewijania podczas nawigowania pomiędzy wpisami (w milisekundach) ",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "ustaw na 0 by wyłączyć ",
|
||||||
"theme" : "Motyw",
|
"theme" : "Motyw",
|
||||||
"submit_your_theme" : "Wyślij swój motyw",
|
"submit_your_theme" : "Wyślij swój motyw",
|
||||||
"custom_css" : "Własny styl CSS"
|
"custom_css" : "Własny styl CSS"
|
||||||
@@ -89,21 +90,23 @@
|
|||||||
"details" : {
|
"details" : {
|
||||||
"feed_details" : "Szczegóły kanału",
|
"feed_details" : "Szczegóły kanału",
|
||||||
"url" : "URL",
|
"url" : "URL",
|
||||||
"website" : "Website ",
|
"website" : "Strona internetowa",
|
||||||
"name" : "Nazwa",
|
"name" : "Nazwa",
|
||||||
"category" : "Kategoria",
|
"category" : "Kategoria",
|
||||||
"position" : "Pozycja",
|
"position" : "Pozycja",
|
||||||
"last_refresh" : "Ostatnio odświeżony",
|
"last_refresh" : "Ostatnio odświeżony",
|
||||||
"message" : "Last refresh message ",
|
"message" : "Ostatnia odpowiedź odświeżenia",
|
||||||
"next_refresh" : "Następne odświeżenie",
|
"next_refresh" : "Następne odświeżenie",
|
||||||
"queued_for_refresh" : "W kolejce do odświeżenia",
|
"queued_for_refresh" : "W kolejce do odświeżenia",
|
||||||
"feed_url" : "URL kanału",
|
"feed_url" : "URL kanału",
|
||||||
|
"filtering_expression" : "Wyrażenie filtrujące",
|
||||||
|
"filtering_expression_help" : "Ustaw puste, by wyłączyć. W przeciwnym razie wyrażenie zwracające 'true' lub 'false'. Dla 'false' nowe elementy w kanale będą autmatycznie \noznaczane jako przeczytane. Dostępne zmienne to: 'title', 'content', 'url' 'author' and 'categories'. Ich zawartość jest konwertowana na małe litery \npodczas porówynywania tekstu. Przykład: url.contains('youtube') albo (author eq 'athou' and title.contains('github') \nPełna dostępna składnia jest dostępna pod <a href='http://commons.apache.org/proper/commons-jexl/reference/syntax.html' target='_blank'>tym</a> adresem.",
|
||||||
"generate_api_key_first" : "Najpierw wygeneruj klucz API w swoim profilu.",
|
"generate_api_key_first" : "Najpierw wygeneruj klucz API w swoim profilu.",
|
||||||
"unsubscribe" : "Cofnij subskrypcje",
|
"unsubscribe" : "Cofnij subskrypcje",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "Czy na pewno chcesz cofnąć sybskrypcję tego kanału? ",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "Czy na pewno chcesz usunąć tą kategorię? ",
|
||||||
"category_details" : "Szczegóły kategorii",
|
"category_details" : "Szczegóły kategorii",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "Szczegóły tagu ",
|
||||||
"parent_category" : "Kategoria nadrzędna"
|
"parent_category" : "Kategoria nadrzędna"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
@@ -119,7 +122,7 @@
|
|||||||
"generate_new_api_key_info" : "Zmiana hasła spowoduje wygenerowanie nowego klucza API",
|
"generate_new_api_key_info" : "Zmiana hasła spowoduje wygenerowanie nowego klucza API",
|
||||||
"opml_export" : "Eksportuj do pliku OPML",
|
"opml_export" : "Eksportuj do pliku OPML",
|
||||||
"delete_account" : "Usuń konto",
|
"delete_account" : "Usuń konto",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "Na pewno usunąć to konto? Nie można tego cofnąć! "
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
@@ -143,8 +146,8 @@
|
|||||||
"firefox_extension" : "Dodatek do Firefoxa",
|
"firefox_extension" : "Dodatek do Firefoxa",
|
||||||
"opera_extension" : "Dodatek do Opery",
|
"opera_extension" : "Dodatek do Opery",
|
||||||
"subscribe_bookmarklet" : "Dodaj subskrybcje jako skryptozakładkę (kliknij)",
|
"subscribe_bookmarklet" : "Dodaj subskrybcje jako skryptozakładkę (kliknij)",
|
||||||
"subscribe_bookmarklet_asc" : "Oldest first ",
|
"subscribe_bookmarklet_asc" : "Najpierw najstarsze ",
|
||||||
"subscribe_bookmarklet_desc" : "Newest first ",
|
"subscribe_bookmarklet_desc" : "Najpierw najnowsze ",
|
||||||
"next_unread_bookmarklet" : "Następny nieprzeczytany element jako skryptozakładka (przeciągnij na pasek zakładek)"
|
"next_unread_bookmarklet" : "Następny nieprzeczytany element jako skryptozakładka (przeciągnij na pasek zakładek)"
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
@@ -172,9 +175,9 @@
|
|||||||
"open_in_new_tab_mark_as_read" : "otwórz w nowej zakładce i oznacz jako przeczytane",
|
"open_in_new_tab_mark_as_read" : "otwórz w nowej zakładce i oznacz jako przeczytane",
|
||||||
"fullscreen" : "przełącz tryb pełnoekranowy",
|
"fullscreen" : "przełącz tryb pełnoekranowy",
|
||||||
"font_size" : "zmień wielkość czcionki",
|
"font_size" : "zmień wielkość czcionki",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "przejdź do widoku Wszystkich elementów ",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "przejdź do Elementów oznaczonych gwiazdką ",
|
||||||
"feed_search" : "przejdź do subskrybcji wpisując jej nazwę"
|
"feed_search" : "przejdź do subskrybcji wpisując jej nazwę"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Atualizar",
|
"refresh" : "Atualizar",
|
||||||
"refresh_all" : "Forçar atualização de todos os meus feeds",
|
"refresh_all" : "Forçar atualização de todos os meus feeds",
|
||||||
"sort_by_asc_desc" : "Ordenar por data cresc/decres",
|
"sort_by_asc_desc" : "Ordenar por data cresc/decres",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Somente títulos",
|
"titles_only" : "Somente títulos",
|
||||||
"expanded_view" : "Modo Expandido",
|
"expanded_view" : "Modo Expandido",
|
||||||
"mark_all_as_read" : "Marcar tudo como lido",
|
"mark_all_as_read" : "Marcar tudo como lido",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Обновить",
|
"refresh" : "Обновить",
|
||||||
"refresh_all" : "Обновить все подписки вручную",
|
"refresh_all" : "Обновить все подписки вручную",
|
||||||
"sort_by_asc_desc" : "Сначала новые/старые",
|
"sort_by_asc_desc" : "Сначала новые/старые",
|
||||||
|
"sort_by_abc_zyx" : "По алфавиту",
|
||||||
"titles_only" : "Только заголовки",
|
"titles_only" : "Только заголовки",
|
||||||
"expanded_view" : "Развёрнутый вид",
|
"expanded_view" : "Развёрнутый вид",
|
||||||
"mark_all_as_read" : "Отметить всё как прочитанное",
|
"mark_all_as_read" : "Отметить всё как прочитанное",
|
||||||
@@ -177,4 +178,4 @@
|
|||||||
"feed_search" : "перейти к подписке по названию"
|
"feed_search" : "перейти к подписке по названию"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Obnoviť",
|
"refresh" : "Obnoviť",
|
||||||
"refresh_all" : "Vynútené obnovenie všetkých položiek",
|
"refresh_all" : "Vynútené obnovenie všetkých položiek",
|
||||||
"sort_by_asc_desc" : "Zoradiť podľa najnovšieho/najstaršieho",
|
"sort_by_asc_desc" : "Zoradiť podľa najnovšieho/najstaršieho",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Náhľad titulkov",
|
"titles_only" : "Náhľad titulkov",
|
||||||
"expanded_view" : "Rozšírený náhľad",
|
"expanded_view" : "Rozšírený náhľad",
|
||||||
"mark_all_as_read" : "Označiť všetky ako prečítané",
|
"mark_all_as_read" : "Označiť všetky ako prečítané",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Uppdatera",
|
"refresh" : "Uppdatera",
|
||||||
"refresh_all" : "Tvinga uppdatering av alla prenumerationer",
|
"refresh_all" : "Tvinga uppdatering av alla prenumerationer",
|
||||||
"sort_by_asc_desc" : "Sortera efter datum stigande/fallande",
|
"sort_by_asc_desc" : "Sortera efter datum stigande/fallande",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Endast titlar",
|
"titles_only" : "Endast titlar",
|
||||||
"expanded_view" : "Expanderad vy",
|
"expanded_view" : "Expanderad vy",
|
||||||
"mark_all_as_read" : "Markera alla som lästa",
|
"mark_all_as_read" : "Markera alla som lästa",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "Yenile",
|
"refresh" : "Yenile",
|
||||||
"refresh_all" : "Tüm yayınları yenilemek için zorla",
|
"refresh_all" : "Tüm yayınları yenilemek için zorla",
|
||||||
"sort_by_asc_desc" : "Tarihe göre sırala artan/azalan",
|
"sort_by_asc_desc" : "Tarihe göre sırala artan/azalan",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "Sadece başlıklar",
|
"titles_only" : "Sadece başlıklar",
|
||||||
"expanded_view" : "Genişletilmiş görünüm",
|
"expanded_view" : "Genişletilmiş görünüm",
|
||||||
"mark_all_as_read" : "Tümünü okundu işaretle",
|
"mark_all_as_read" : "Tümünü okundu işaretle",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"refresh" : "刷新",
|
"refresh" : "刷新",
|
||||||
"refresh_all" : "刷新所有订阅",
|
"refresh_all" : "刷新所有订阅",
|
||||||
"sort_by_asc_desc" : "按日期升序/降序排序",
|
"sort_by_asc_desc" : "按日期升序/降序排序",
|
||||||
|
"sort_by_abc_zyx" : "Sort Alphabetically",
|
||||||
"titles_only" : "仅显示标题",
|
"titles_only" : "仅显示标题",
|
||||||
"expanded_view" : "显示内容",
|
"expanded_view" : "显示内容",
|
||||||
"mark_all_as_read" : "标记所有为已读",
|
"mark_all_as_read" : "标记所有为已读",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
@@ -70,6 +70,7 @@
|
|||||||
<script type="text/javascript" src="lib/mousetrap/mousetrap.js"></script>
|
<script type="text/javascript" src="lib/mousetrap/mousetrap.js"></script>
|
||||||
<script type="text/javascript" src="lib/momentjs/min/moment-with-locales.js"></script>
|
<script type="text/javascript" src="lib/momentjs/min/moment-with-locales.js"></script>
|
||||||
<script type="text/javascript" src="lib/devicejs/lib/device.js"></script>
|
<script type="text/javascript" src="lib/devicejs/lib/device.js"></script>
|
||||||
|
<script type="text/javascript" src="lib/tinycon/tinycon.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/controllers.js"></script>
|
<script type="text/javascript" src="js/controllers.js"></script>
|
||||||
<script type="text/javascript" src="js/directives.js"></script>
|
<script type="text/javascript" src="js/directives.js"></script>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ module.controller('SubscribeCtrl', ['$scope', '$location', 'FeedService', 'Categ
|
|||||||
// 'ok', 'loading' or 'failed'
|
// 'ok', 'loading' or 'failed'
|
||||||
$scope.state = 'ok';
|
$scope.state = 'ok';
|
||||||
$scope.urlChanged = function() {
|
$scope.urlChanged = function() {
|
||||||
if ($scope.sub.url) {
|
if ($scope.sub.url && $scope.state != 'loading') {
|
||||||
$scope.state = 'loading';
|
$scope.state = 'loading';
|
||||||
$scope.sub.title = 'Loading...';
|
$scope.sub.title = 'Loading...';
|
||||||
FeedService.fetch({
|
FeedService.fetch({
|
||||||
@@ -194,11 +194,7 @@ module.controller('CategoryTreeCtrl', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.$watch(rootUnreadCount, function(value) {
|
$scope.$watch(rootUnreadCount, function(value) {
|
||||||
var label = 'CommaFeed';
|
Tinycon.setBubble(value);
|
||||||
if (value > 0) {
|
|
||||||
label = '(' + value + ') ' + label;
|
|
||||||
}
|
|
||||||
$window.document.title = label;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var mark = function(node, entry) {
|
var mark = function(node, entry) {
|
||||||
@@ -531,7 +527,11 @@ module.controller('ToolbarCtrl', [
|
|||||||
|
|
||||||
$scope.toggleOrder = function() {
|
$scope.toggleOrder = function() {
|
||||||
var settings = $scope.settingsService.settings;
|
var settings = $scope.settingsService.settings;
|
||||||
settings.readingOrder = settings.readingOrder == 'asc' ? 'desc' : 'asc';
|
settings.readingOrder = settings.readingOrder == 'desc' ? 'asc' : 'desc';
|
||||||
|
};
|
||||||
|
$scope.toggleAbcOrder = function() {
|
||||||
|
var settings = $scope.settingsService.settings;
|
||||||
|
settings.readingOrder = settings.readingOrder == 'abc' ? 'zyx' : 'abc';
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toAdmin = function() {
|
$scope.toAdmin = function() {
|
||||||
@@ -1057,6 +1057,7 @@ module.controller('FeedListCtrl', [
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// keyboard shortcuts
|
||||||
Mousetrap.bind('j', function(e) {
|
Mousetrap.bind('j', function(e) {
|
||||||
$scope.$apply(function() {
|
$scope.$apply(function() {
|
||||||
$scope.navigationMode = 'keyboard';
|
$scope.navigationMode = 'keyboard';
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ module.service('LangService', [function() {
|
|||||||
'gl': 'Galician',
|
'gl': 'Galician',
|
||||||
'glk': 'گیلکی',
|
'glk': 'گیلکی',
|
||||||
'hu': 'Magyar',
|
'hu': 'Magyar',
|
||||||
|
'id': 'Indonesian',
|
||||||
'ja': '日本語',
|
'ja': '日本語',
|
||||||
'ko': '한국어',
|
'ko': '한국어',
|
||||||
'nl': 'Nederlands',
|
'nl': 'Nederlands',
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#loading-bar .bar {
|
#loading-bar .bar {
|
||||||
background: #2c3e50;
|
background: #2c3e50;
|
||||||
|
height: 101px;
|
||||||
|
top: -100px;
|
||||||
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#loading-bar .peg {
|
#loading-bar .peg {
|
||||||
@@ -9,4 +12,4 @@
|
|||||||
#loading-bar-spinner .spinner-icon {
|
#loading-bar-spinner .spinner-icon {
|
||||||
border-top-color: #2c3e50;
|
border-top-color: #2c3e50;
|
||||||
border-left-color: #2c3e50;
|
border-left-color: #2c3e50;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
|
<dt>r</dt>
|
||||||
|
<dd>{{ 'about.shortcuts.refresh' | translate }}</dd>
|
||||||
|
|
||||||
<dt>j</dt>
|
<dt>j</dt>
|
||||||
<dd>{{ 'about.shortcuts.open_next_entry' | translate }}</dd>
|
<dd>{{ 'about.shortcuts.open_next_entry' | translate }}</dd>
|
||||||
|
|
||||||
@@ -68,4 +71,4 @@
|
|||||||
</dt>
|
</dt>
|
||||||
<dd>{{ 'about.shortcuts.feed_search' | translate }}</dd>
|
<dd>{{ 'about.shortcuts.feed_search' | translate }}</dd>
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
@@ -60,26 +60,30 @@
|
|||||||
<div class="actions btn-group" id="toolbar-read-mode">
|
<div class="actions btn-group" id="toolbar-read-mode">
|
||||||
<div ng-if="!MobileService.mobile || MobileService.rightMenu">
|
<div ng-if="!MobileService.mobile || MobileService.rightMenu">
|
||||||
<div class="btn-group read-mode">
|
<div class="btn-group read-mode">
|
||||||
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'unread'"
|
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'unread'" ng-class="{'active': settingsService.settings.readingMode == 'unread'}">{{
|
||||||
ng-class="{'active': settingsService.settings.readingMode == 'unread'}">{{ 'toolbar.unread' | translate }}</button>
|
'toolbar.unread' | translate }}</button>
|
||||||
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'all'"
|
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'all'" ng-class="{'active': settingsService.settings.readingMode == 'all'}">{{
|
||||||
ng-class="{'active': settingsService.settings.readingMode == 'all'}">{{ 'toolbar.all' | translate }}</button>
|
'toolbar.all' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group" id="toolbar-read-order">
|
<div class="btn-group" id="toolbar-read-order">
|
||||||
<a type="button" class="btn btn-default" ng-click="toggleOrder()" title="{{ 'toolbar.sort_by_asc_desc' | translate }}">
|
<a type="button" class="btn btn-default" ng-click="toggleOrder()" title="{{ 'toolbar.sort_by_asc_desc' | translate }}"
|
||||||
<i
|
ng-class="{'active' : settingsService.settings.readingOrder == 'asc' || settingsService.settings.readingOrder == 'desc'}">
|
||||||
ng-class="{'icon-arrow-up' : settingsService.settings.readingOrder == 'asc', 'icon-arrow-down': settingsService.settings.readingOrder == 'desc'}"></i>
|
<i ng-class="{'icon-arrow-up' : settingsService.settings.readingOrder == 'asc', 'icon-arrow-down': settingsService.settings.readingOrder != 'asc'}"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<button type="button" class="btn btn-default" ng-click="toggleAbcOrder()" title="{{ 'toolbar.sort_by_abc_zyx' | translate }}"
|
||||||
|
ng-class="{'active' : settingsService.settings.readingOrder == 'abc' || settingsService.settings.readingOrder == 'zyx'}">
|
||||||
|
<i ng-class="{'icon-sort-by-alphabet' : settingsService.settings.readingOrder != 'zyx', 'icon-sort-by-alphabet-alt': settingsService.settings.readingOrder == 'zyx'}"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group" id="toolbar-read-view-settings">
|
<div class="btn-group" id="toolbar-read-view-settings">
|
||||||
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'title'"
|
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'title'" ng-class="{'active': settingsService.settings.viewMode == 'title'}"
|
||||||
ng-class="{'active': settingsService.settings.viewMode == 'title'}" title="{{ 'toolbar.titles_only' | translate }}">
|
title="{{ 'toolbar.titles_only' | translate }}">
|
||||||
<i class="icon-list"></i>
|
<i class="icon-list"></i>
|
||||||
</a>
|
</a>
|
||||||
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'expanded'"
|
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'expanded'" ng-class="{'active': settingsService.settings.viewMode == 'expanded'}"
|
||||||
ng-class="{'active': settingsService.settings.viewMode == 'expanded'}" title="{{ 'toolbar.expanded_view' | translate }}">
|
title="{{ 'toolbar.expanded_view' | translate }}">
|
||||||
<i class="icon-th-list"></i>
|
<i class="icon-th-list"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<span ng-switch-when="starred">{{ 'tree.starred' | translate }}</span>
|
<span ng-switch-when="starred">{{ 'tree.starred' | translate }}</span>
|
||||||
<span ng-switch-default>
|
<span ng-switch-default>
|
||||||
<span ng-hide="feedLink">{{name}}</span>
|
<span ng-hide="feedLink">{{name}}</span>
|
||||||
<a ng-show="feedLink" href="{{feedLink}}" target="_blank">{{name}}</a>
|
<a ng-show="feedLink" href="{{feedLink}}" target="_blank" rel="noreferrer">{{name}}</a>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span ng-show="name"> »</span>
|
<span ng-show="name"> »</span>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<div ng-repeat="entry in entries" class="entry entry-font-size-{{font_size}}" id="entry_{{entry.id}}"
|
<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 }">
|
ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen }">
|
||||||
<div class="entry-heading" ng-swipe-right="mark(entry, !entry.read)">
|
<div class="entry-heading" ng-swipe-right="mark(entry, !entry.read)">
|
||||||
<a href="{{entry.url}}" target="_blank" class="entry-heading-link" ng-click="noop($event)" ng-mouseup="entryClicked(entry, $event)">
|
<a href="{{entry.url}}" target="_blank" rel="noreferrer" class="entry-heading-link" ng-click="noop($event)" ng-mouseup="entryClicked(entry, $event)">
|
||||||
<span class="feed-name">
|
<span class="feed-name">
|
||||||
<span class="star" ng-mouseup="star(entry, !entry.starred, $event)">
|
<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>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<span class="entry-date">{{entry.date | entryDate}}</span>
|
<span class="entry-date">{{entry.date | entryDate}}</span>
|
||||||
<span class="entry-name" ng-class="{shrink: true, rtl: entry.rtl}" ng-bind-html="entry.title | highlight:keywords | trustHtml"></span>
|
<span class="entry-name" ng-class="{shrink: true, rtl: entry.rtl}" ng-bind-html="entry.title | highlight:keywords | trustHtml"></span>
|
||||||
</a>
|
</a>
|
||||||
<a href="{{entry.url}}" target="_blank" class="entry-external-link" ng-click="mark(entry, true)">
|
<a href="{{entry.url}}" target="_blank" rel="noreferrer" class="entry-external-link" ng-click="mark(entry, true)">
|
||||||
<i class="icon-external-link"></i>
|
<i class="icon-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
ng-mouseup="bodyClicked(entry, $event)" ng-class="{rtl: entry.rtl}">
|
ng-mouseup="bodyClicked(entry, $event)" ng-class="{rtl: entry.rtl}">
|
||||||
<div class="entry-header">
|
<div class="entry-header">
|
||||||
<div class="entry-title">
|
<div class="entry-title">
|
||||||
<a href="{{entry.url}}" target="_blank" ng-bind-html="entry.title | highlight:keywords | trustHtml"></a>
|
<a href="{{entry.url}}" target="_blank" rel="noreferrer" ng-bind-html="entry.title | highlight:keywords | trustHtml"></a>
|
||||||
<div class="entry-subtitle">
|
<div class="entry-subtitle">
|
||||||
<span class="entry-source" ng-if="selectedType == 'category'">
|
<span class="entry-source" ng-if="selectedType == 'category'">
|
||||||
<span class="entry-source-prefix">{{ 'view.entry_source' | translate }}</span>
|
<span class="entry-source-prefix">{{ 'view.entry_source' | translate }}</span>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
title="Gmail" popup ng-if="settingsService.settings.gmail">
|
title="Gmail" popup ng-if="settingsService.settings.gmail">
|
||||||
<i class="icon-gmail"></i>
|
<i class="icon-gmail"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="http://www.facebook.com/sharer.php?u=={{entry.url|escape}}" title="Facebook" popup ng-if="settingsService.settings.facebook">
|
<a href="http://www.facebook.com/sharer.php?u={{entry.url|escape}}" title="Facebook" popup ng-if="settingsService.settings.facebook">
|
||||||
<i class="icon-facebook"></i>
|
<i class="icon-facebook"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="http://twitter.com/share?text={{entry.title|escape}}&url={{entry.url|escape}}" title="Twitter" popup
|
<a href="http://twitter.com/share?text={{entry.title|escape}}&url={{entry.url|escape}}" title="Twitter" popup
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import javax.servlet.ServletRequest;
|
|||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import com.commafeed.backend.feed.FeedRefreshTaskGiver;
|
import com.commafeed.backend.feed.FeedRefreshTaskGiver;
|
||||||
@@ -111,7 +110,7 @@ public class CommaFeedApplication extends Application<CommaFeedConfiguration> {
|
|||||||
Injector injector = Guice.createInjector(new CommaFeedModule(hibernateBundle.getSessionFactory(), config, environment.metrics()));
|
Injector injector = Guice.createInjector(new CommaFeedModule(hibernateBundle.getSessionFactory(), config, environment.metrics()));
|
||||||
|
|
||||||
// session management
|
// session management
|
||||||
environment.servlets().setSessionHandler(new SessionHandler(config.getSessionManagerFactory().build()));
|
environment.servlets().setSessionHandler(config.getSessionHandlerFactory().build());
|
||||||
|
|
||||||
// support for "@SecurityCheck User user" injection
|
// support for "@SecurityCheck User user" injection
|
||||||
environment.jersey().register(new SecurityCheckFactoryProvider.Binder(injector.getInstance(UserService.class)));
|
environment.jersey().register(new SecurityCheckFactoryProvider.Binder(injector.getInstance(UserService.class)));
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package com.commafeed;
|
package com.commafeed;
|
||||||
|
|
||||||
import io.dropwizard.Configuration;
|
|
||||||
import io.dropwizard.db.DataSourceFactory;
|
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
@@ -10,15 +7,17 @@ import javax.validation.Valid;
|
|||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
|
|
||||||
import com.commafeed.backend.cache.RedisPoolFactory;
|
import com.commafeed.backend.cache.RedisPoolFactory;
|
||||||
import com.commafeed.frontend.session.SessionManagerFactory;
|
import com.commafeed.frontend.session.SessionHandlerFactory;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import io.dropwizard.Configuration;
|
||||||
|
import io.dropwizard.db.DataSourceFactory;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class CommaFeedConfiguration extends Configuration {
|
public class CommaFeedConfiguration extends Configuration {
|
||||||
|
|
||||||
@@ -45,7 +44,7 @@ public class CommaFeedConfiguration extends Configuration {
|
|||||||
@Valid
|
@Valid
|
||||||
@NotNull
|
@NotNull
|
||||||
@JsonProperty("session")
|
@JsonProperty("session")
|
||||||
private SessionManagerFactory sessionManagerFactory = new SessionManagerFactory();
|
private SessionHandlerFactory SessionHandlerFactory = new SessionHandlerFactory();
|
||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -96,6 +95,12 @@ public class CommaFeedConfiguration extends Configuration {
|
|||||||
private String smtpPassword;
|
private String smtpPassword;
|
||||||
private String smtpFromAddress;
|
private String smtpFromAddress;
|
||||||
|
|
||||||
|
private boolean graphiteEnabled;
|
||||||
|
private String graphitePrefix;
|
||||||
|
private String graphiteHost;
|
||||||
|
private int graphitePort;
|
||||||
|
private int graphiteInterval;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Valid
|
@Valid
|
||||||
private Boolean heavyLoad;
|
private Boolean heavyLoad;
|
||||||
@@ -132,10 +137,11 @@ public class CommaFeedConfiguration extends Configuration {
|
|||||||
@Valid
|
@Valid
|
||||||
private CacheType cache;
|
private CacheType cache;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Valid
|
@Valid
|
||||||
private String announcement;
|
private String announcement;
|
||||||
|
|
||||||
|
private String userAgent;
|
||||||
|
|
||||||
public Date getUnreadThreshold() {
|
public Date getUnreadThreshold() {
|
||||||
int keepStatusDays = getKeepStatusDays();
|
int keepStatusDays = getKeepStatusDays();
|
||||||
return keepStatusDays > 0 ? DateUtils.addDays(new Date(), -1 * keepStatusDays) : null;
|
return keepStatusDays > 0 ? DateUtils.addDays(new Date(), -1 * keepStatusDays) : null;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.commafeed;
|
package com.commafeed;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -7,6 +9,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
import com.codahale.metrics.graphite.Graphite;
|
||||||
|
import com.codahale.metrics.graphite.GraphiteReporter;
|
||||||
|
import com.codahale.metrics.MetricFilter;
|
||||||
|
import com.commafeed.CommaFeedConfiguration.ApplicationSettings;
|
||||||
import com.commafeed.CommaFeedConfiguration.CacheType;
|
import com.commafeed.CommaFeedConfiguration.CacheType;
|
||||||
import com.commafeed.backend.cache.CacheService;
|
import com.commafeed.backend.cache.CacheService;
|
||||||
import com.commafeed.backend.cache.NoopCacheService;
|
import com.commafeed.backend.cache.NoopCacheService;
|
||||||
@@ -20,6 +26,9 @@ import com.commafeed.backend.task.OldStatusesCleanupTask;
|
|||||||
import com.commafeed.backend.task.OrphanedContentsCleanupTask;
|
import com.commafeed.backend.task.OrphanedContentsCleanupTask;
|
||||||
import com.commafeed.backend.task.OrphanedFeedsCleanupTask;
|
import com.commafeed.backend.task.OrphanedFeedsCleanupTask;
|
||||||
import com.commafeed.backend.task.ScheduledTask;
|
import com.commafeed.backend.task.ScheduledTask;
|
||||||
|
import com.commafeed.backend.urlprovider.FeedURLProvider;
|
||||||
|
import com.commafeed.backend.urlprovider.InPageReferenceFeedURLProvider;
|
||||||
|
import com.commafeed.backend.urlprovider.YoutubeFeedURLProvider;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.multibindings.Multibinder;
|
import com.google.inject.multibindings.Multibinder;
|
||||||
@@ -49,10 +58,36 @@ public class CommaFeedModule extends AbstractModule {
|
|||||||
faviconMultibinder.addBinding().to(FacebookFaviconFetcher.class);
|
faviconMultibinder.addBinding().to(FacebookFaviconFetcher.class);
|
||||||
faviconMultibinder.addBinding().to(DefaultFaviconFetcher.class);
|
faviconMultibinder.addBinding().to(DefaultFaviconFetcher.class);
|
||||||
|
|
||||||
|
Multibinder<FeedURLProvider> urlProviderMultibinder = Multibinder.newSetBinder(binder(), FeedURLProvider.class);
|
||||||
|
urlProviderMultibinder.addBinding().to(InPageReferenceFeedURLProvider.class);
|
||||||
|
urlProviderMultibinder.addBinding().to(YoutubeFeedURLProvider.class);
|
||||||
|
|
||||||
Multibinder<ScheduledTask> taskMultibinder = Multibinder.newSetBinder(binder(), ScheduledTask.class);
|
Multibinder<ScheduledTask> taskMultibinder = Multibinder.newSetBinder(binder(), ScheduledTask.class);
|
||||||
taskMultibinder.addBinding().to(OldStatusesCleanupTask.class);
|
taskMultibinder.addBinding().to(OldStatusesCleanupTask.class);
|
||||||
taskMultibinder.addBinding().to(OldEntriesCleanupTask.class);
|
taskMultibinder.addBinding().to(OldEntriesCleanupTask.class);
|
||||||
taskMultibinder.addBinding().to(OrphanedFeedsCleanupTask.class);
|
taskMultibinder.addBinding().to(OrphanedFeedsCleanupTask.class);
|
||||||
taskMultibinder.addBinding().to(OrphanedContentsCleanupTask.class);
|
taskMultibinder.addBinding().to(OrphanedContentsCleanupTask.class);
|
||||||
|
|
||||||
|
ApplicationSettings settings = config.getApplicationSettings();
|
||||||
|
|
||||||
|
if (settings.isGraphiteEnabled()) {
|
||||||
|
final String graphitePrefix = settings.getGraphitePrefix();
|
||||||
|
final String graphiteHost = settings.getGraphiteHost();
|
||||||
|
final int graphitePort = settings.getGraphitePort();
|
||||||
|
final int graphiteInterval = settings.getGraphiteInterval();
|
||||||
|
|
||||||
|
log.info("Graphite Metrics will be sent to host={}, port={}, prefix={}, interval={}sec", graphiteHost, graphitePort, graphitePrefix, graphiteInterval);
|
||||||
|
|
||||||
|
final Graphite graphite = new Graphite(new InetSocketAddress(graphiteHost, graphitePort));
|
||||||
|
final GraphiteReporter reporter = GraphiteReporter.forRegistry(metrics)
|
||||||
|
.prefixedWith(graphitePrefix)
|
||||||
|
.convertRatesTo(TimeUnit.SECONDS)
|
||||||
|
.convertDurationsTo(TimeUnit.MILLISECONDS)
|
||||||
|
.filter(MetricFilter.ALL)
|
||||||
|
.build(graphite);
|
||||||
|
reporter.start(graphiteInterval, TimeUnit.SECONDS);
|
||||||
|
} else {
|
||||||
|
log.info("Graphite Metrics Disabled. Metrics will not be sent.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ public class HttpGetter {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HttpGetter(CommaFeedConfiguration config) {
|
public HttpGetter(CommaFeedConfiguration config) {
|
||||||
this.userAgent = String.format("CommaFeed/%s (https://github.com/Athou/commafeed)", config.getVersion());
|
this.userAgent = config.getApplicationSettings().getUserAgent();
|
||||||
|
if (this.userAgent == null) {
|
||||||
|
this.userAgent = String.format("CommaFeed/%s (https://github.com/Athou/commafeed)", config.getVersion());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpResult getBinary(String url, int timeout) throws ClientProtocolException, IOException, NotModifiedException {
|
public HttpResult getBinary(String url, int timeout) throws ClientProtocolException, IOException, NotModifiedException {
|
||||||
@@ -151,9 +154,13 @@ public class HttpGetter {
|
|||||||
contentType = entity.getContentType().getValue();
|
contentType = entity.getContentType().getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HttpUriRequest req = (HttpUriRequest) context.getRequest();
|
|
||||||
HttpHost host = context.getTargetHost();
|
String urlAfterRedirect = url;
|
||||||
String urlAfterRedirect = req.getURI().isAbsolute() ? req.getURI().toString() : host.toURI() + req.getURI();
|
if (context.getRequest() instanceof HttpUriRequest) {
|
||||||
|
HttpUriRequest req = (HttpUriRequest) context.getRequest();
|
||||||
|
HttpHost host = context.getTargetHost();
|
||||||
|
urlAfterRedirect = req.getURI().isAbsolute() ? req.getURI().toString() : host.toURI() + req.getURI();
|
||||||
|
}
|
||||||
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
long duration = System.currentTimeMillis() - start;
|
||||||
result = new HttpResult(content, contentType, lastModifiedHeaderValue, eTagHeaderValue, duration, urlAfterRedirect);
|
result = new HttpResult(content, contentType, lastModifiedHeaderValue, eTagHeaderValue, duration, urlAfterRedirect);
|
||||||
@@ -219,4 +226,11 @@ public class HttpGetter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
CommaFeedConfiguration config = new CommaFeedConfiguration();
|
||||||
|
HttpGetter getter = new HttpGetter(config);
|
||||||
|
HttpResult result = getter.getBinary("https://sourceforge.net/projects/mpv-player-windows/rss", 30000);
|
||||||
|
System.out.println(new String(result.content));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import com.commafeed.backend.model.QUser;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.querydsl.jpa.JPAExpressions;
|
import com.querydsl.jpa.JPAExpressions;
|
||||||
import com.querydsl.jpa.JPQLQuery;
|
import com.querydsl.jpa.JPQLQuery;
|
||||||
import com.querydsl.jpa.hibernate.HibernateQuery;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FeedDAO extends GenericDAO<Feed> {
|
public class FeedDAO extends GenericDAO<Feed> {
|
||||||
@@ -30,7 +29,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Feed> findNextUpdatable(int count, Date lastLoginThreshold) {
|
public List<Feed> findNextUpdatable(int count, Date lastLoginThreshold) {
|
||||||
HibernateQuery<Feed> query = query().selectFrom(feed);
|
JPQLQuery<Feed> query = query().selectFrom(feed);
|
||||||
query.where(feed.disabledUntil.isNull().or(feed.disabledUntil.lt(new Date())));
|
query.where(feed.disabledUntil.isNull().or(feed.disabledUntil.lt(new Date())));
|
||||||
|
|
||||||
if (lastLoginThreshold != null) {
|
if (lastLoginThreshold != null) {
|
||||||
@@ -60,7 +59,6 @@ public class FeedDAO extends GenericDAO<Feed> {
|
|||||||
|
|
||||||
public List<Feed> findWithoutSubscriptions(int max) {
|
public List<Feed> findWithoutSubscriptions(int max) {
|
||||||
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
||||||
return query().selectFrom(feed).where(JPAExpressions.selectOne().from(sub).where(sub.feed.eq(feed)).notExists()).limit(max)
|
return query().selectFrom(feed).where(JPAExpressions.selectOne().from(sub).where(sub.feed.eq(feed)).notExists()).limit(max).fetch();
|
||||||
.fetch();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.commafeed.backend.FixedSizeSortedSet;
|
|||||||
import com.commafeed.backend.feed.FeedEntryKeyword;
|
import com.commafeed.backend.feed.FeedEntryKeyword;
|
||||||
import com.commafeed.backend.feed.FeedEntryKeyword.Mode;
|
import com.commafeed.backend.feed.FeedEntryKeyword.Mode;
|
||||||
import com.commafeed.backend.model.FeedEntry;
|
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.FeedSubscription;
|
import com.commafeed.backend.model.FeedSubscription;
|
||||||
@@ -32,7 +33,7 @@ import com.google.common.collect.Iterables;
|
|||||||
import com.google.common.collect.Ordering;
|
import com.google.common.collect.Ordering;
|
||||||
import com.querydsl.core.BooleanBuilder;
|
import com.querydsl.core.BooleanBuilder;
|
||||||
import com.querydsl.core.Tuple;
|
import com.querydsl.core.Tuple;
|
||||||
import com.querydsl.jpa.hibernate.HibernateQuery;
|
import com.querydsl.jpa.impl.JPAQuery;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||||
@@ -67,6 +68,18 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
|
|
||||||
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ASC = Ordering.from(STATUS_COMPARATOR_DESC).reverse();
|
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ASC = Ordering.from(STATUS_COMPARATOR_DESC).reverse();
|
||||||
|
|
||||||
|
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ABC = new Comparator<FeedEntryStatus>() {
|
||||||
|
@Override
|
||||||
|
public int compare(FeedEntryStatus o1, FeedEntryStatus o2) {
|
||||||
|
CompareToBuilder builder = new CompareToBuilder();
|
||||||
|
builder.append(o1.getEntry().getContent().getTitle(), o2.getEntry().getContent().getTitle());
|
||||||
|
builder.append(o1.getId(), o2.getId());
|
||||||
|
return builder.toComparison();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ZYX = Ordering.from(STATUS_COMPARATOR_ABC).reverse();
|
||||||
|
|
||||||
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
|
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
|
||||||
List<FeedEntryStatus> statuses = query().selectFrom(status).where(status.entry.eq(entry), status.subscription.eq(sub)).fetch();
|
List<FeedEntryStatus> statuses = query().selectFrom(status).where(status.entry.eq(entry), status.subscription.eq(sub)).fetch();
|
||||||
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
||||||
@@ -93,22 +106,23 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||||
HibernateQuery<FeedEntryStatus> query = query().selectFrom(status).where(status.user.eq(user), status.starred.isTrue());
|
JPAQuery<FeedEntryStatus> query = query().selectFrom(status).where(status.user.eq(user), status.starred.isTrue());
|
||||||
if (newerThan != null) {
|
if (newerThan != null) {
|
||||||
query.where(status.entryInserted.gt(newerThan));
|
query.where(status.entryInserted.gt(newerThan));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order == ReadingOrder.asc) {
|
if (order == ReadingOrder.asc) {
|
||||||
query.orderBy(status.entryUpdated.asc(), status.id.asc());
|
query.orderBy(status.entryUpdated.asc(), status.id.asc());
|
||||||
} else {
|
} else if (order == ReadingOrder.desc) {
|
||||||
query.orderBy(status.entryUpdated.desc(), status.id.desc());
|
query.orderBy(status.entryUpdated.desc(), status.id.desc());
|
||||||
|
} else if (order == ReadingOrder.abc) {
|
||||||
|
query.orderBy(status.entry.content.title.asc(), status.id.desc());
|
||||||
|
} else { // order == ReadingOrder.xyz
|
||||||
|
query.orderBy(status.entry.content.title.desc(), status.id.desc());
|
||||||
}
|
}
|
||||||
|
|
||||||
query.offset(offset).limit(limit);
|
query.offset(offset).limit(limit);
|
||||||
int timeout = config.getApplicationSettings().getQueryTimeout();
|
setTimeout(query, config.getApplicationSettings().getQueryTimeout());
|
||||||
if (timeout > 0) {
|
|
||||||
query.setTimeout(timeout / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<FeedEntryStatus> statuses = query.fetch();
|
List<FeedEntryStatus> statuses = query.fetch();
|
||||||
for (FeedEntryStatus status : statuses) {
|
for (FeedEntryStatus status : statuses) {
|
||||||
@@ -118,10 +132,10 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
return lazyLoadContent(includeContent, statuses);
|
return lazyLoadContent(includeContent, statuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HibernateQuery<FeedEntry> buildQuery(User user, FeedSubscription sub, boolean unreadOnly, List<FeedEntryKeyword> keywords,
|
private JPAQuery<FeedEntry> buildQuery(User user, FeedSubscription sub, boolean unreadOnly, List<FeedEntryKeyword> keywords,
|
||||||
Date newerThan, int offset, int limit, ReadingOrder order, Date last, String tag) {
|
Date newerThan, int offset, int limit, ReadingOrder order, FeedEntryStatus last, String tag) {
|
||||||
|
|
||||||
HibernateQuery<FeedEntry> query = query().selectFrom(entry).where(entry.feed.eq(sub.getFeed()));
|
JPAQuery<FeedEntry> query = query().selectFrom(entry).where(entry.feed.eq(sub.getFeed()));
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(keywords)) {
|
if (CollectionUtils.isNotEmpty(keywords)) {
|
||||||
query.join(entry.content, content);
|
query.join(entry.content, content);
|
||||||
@@ -163,17 +177,29 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
|
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
if (order == ReadingOrder.desc) {
|
if (order == ReadingOrder.desc) {
|
||||||
query.where(entry.updated.gt(last));
|
query.where(entry.updated.gt(last.getEntryUpdated()));
|
||||||
} else {
|
} else if (order == ReadingOrder.asc) {
|
||||||
query.where(entry.updated.lt(last));
|
query.where(entry.updated.lt(last.getEntryUpdated()));
|
||||||
|
} else if (order == ReadingOrder.abc) {
|
||||||
|
query.join(entry.content, content);
|
||||||
|
query.where(content.title.lt(last.getEntry().getContent().getTitle()));
|
||||||
|
} else { // order == ReadingOrder.zyx
|
||||||
|
query.join(entry.content, content);
|
||||||
|
query.where(content.title.gt(last.getEntry().getContent().getTitle()));
|
||||||
}
|
}
|
||||||
|
} else if (order != null && (order == ReadingOrder.abc || order == ReadingOrder.zyx)) {
|
||||||
|
query.join(entry.content, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
if (order == ReadingOrder.asc) {
|
if (order == ReadingOrder.asc) {
|
||||||
query.orderBy(entry.updated.asc(), entry.id.asc());
|
query.orderBy(entry.updated.asc(), entry.id.asc());
|
||||||
} else {
|
} else if (order == ReadingOrder.desc) {
|
||||||
query.orderBy(entry.updated.desc(), entry.id.desc());
|
query.orderBy(entry.updated.desc(), entry.id.desc());
|
||||||
|
} else if (order == ReadingOrder.abc) {
|
||||||
|
query.orderBy(content.title.asc(), entry.id.asc());
|
||||||
|
} else { // order == ReadingOrder.zyx
|
||||||
|
query.orderBy(content.title.desc(), entry.id.desc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (offset > -1) {
|
if (offset > -1) {
|
||||||
@@ -182,10 +208,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
if (limit > -1) {
|
if (limit > -1) {
|
||||||
query.limit(limit);
|
query.limit(limit);
|
||||||
}
|
}
|
||||||
int timeout = config.getApplicationSettings().getQueryTimeout();
|
setTimeout(query, config.getApplicationSettings().getQueryTimeout());
|
||||||
if (timeout > 0) {
|
|
||||||
query.setTimeout(timeout / 1000);
|
|
||||||
}
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,20 +216,36 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
List<FeedEntryKeyword> keywords, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent,
|
List<FeedEntryKeyword> keywords, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent,
|
||||||
boolean onlyIds, String tag) {
|
boolean onlyIds, String tag) {
|
||||||
int capacity = offset + limit;
|
int capacity = offset + limit;
|
||||||
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC : STATUS_COMPARATOR_ASC;
|
|
||||||
|
Comparator<FeedEntryStatus> comparator;
|
||||||
|
if (order == ReadingOrder.desc) {
|
||||||
|
comparator = STATUS_COMPARATOR_DESC;
|
||||||
|
} else if (order == ReadingOrder.abc) {
|
||||||
|
comparator = STATUS_COMPARATOR_ABC;
|
||||||
|
} else if (order == ReadingOrder.zyx) {
|
||||||
|
comparator = STATUS_COMPARATOR_ZYX;
|
||||||
|
} else {
|
||||||
|
comparator = STATUS_COMPARATOR_ASC;
|
||||||
|
}
|
||||||
|
|
||||||
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
|
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
|
||||||
for (FeedSubscription sub : subs) {
|
for (FeedSubscription sub : subs) {
|
||||||
Date last = (order != null && set.isFull()) ? set.last().getEntryUpdated() : null;
|
FeedEntryStatus last = (order != null && set.isFull()) ? set.last() : null;
|
||||||
HibernateQuery<FeedEntry> query = buildQuery(user, sub, unreadOnly, keywords, newerThan, -1, capacity, order, last, tag);
|
JPAQuery<FeedEntry> query = buildQuery(user, sub, unreadOnly, keywords, newerThan, -1, capacity, order, last, tag);
|
||||||
List<Tuple> tuples = query.select(entry.id, entry.updated, status.id).fetch();
|
List<Tuple> tuples = query.select(entry.id, entry.updated, status.id, entry.content.title).fetch();
|
||||||
|
|
||||||
for (Tuple tuple : tuples) {
|
for (Tuple tuple : tuples) {
|
||||||
Long id = tuple.get(entry.id);
|
Long id = tuple.get(entry.id);
|
||||||
Date updated = tuple.get(entry.updated);
|
Date updated = tuple.get(entry.updated);
|
||||||
Long statusId = tuple.get(status.id);
|
Long statusId = tuple.get(status.id);
|
||||||
|
|
||||||
|
FeedEntryContent content = new FeedEntryContent();
|
||||||
|
content.setTitle(tuple.get(entry.content.title));
|
||||||
|
|
||||||
FeedEntry entry = new FeedEntry();
|
FeedEntry entry = new FeedEntry();
|
||||||
entry.setId(id);
|
entry.setId(id);
|
||||||
entry.setUpdated(updated);
|
entry.setUpdated(updated);
|
||||||
|
entry.setContent(content);
|
||||||
|
|
||||||
FeedEntryStatus status = new FeedEntryStatus();
|
FeedEntryStatus status = new FeedEntryStatus();
|
||||||
status.setId(statusId);
|
status.setId(statusId);
|
||||||
@@ -245,7 +284,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
|
|
||||||
public UnreadCount getUnreadCount(User user, FeedSubscription subscription) {
|
public UnreadCount getUnreadCount(User user, FeedSubscription subscription) {
|
||||||
UnreadCount uc = null;
|
UnreadCount uc = null;
|
||||||
HibernateQuery<FeedEntry> query = buildQuery(user, subscription, true, null, null, -1, -1, null, null, null);
|
JPAQuery<FeedEntry> query = buildQuery(user, subscription, true, null, null, -1, -1, null, null, null);
|
||||||
List<Tuple> tuples = query.select(entry.count(), entry.updated.max()).fetch();
|
List<Tuple> tuples = query.select(entry.count(), entry.updated.max()).fetch();
|
||||||
for (Tuple tuple : tuples) {
|
for (Tuple tuple : tuples) {
|
||||||
Long count = tuple.get(entry.count());
|
Long count = tuple.get(entry.count());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import com.commafeed.backend.model.Models;
|
|||||||
import com.commafeed.backend.model.QFeedSubscription;
|
import com.commafeed.backend.model.QFeedSubscription;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.querydsl.jpa.hibernate.HibernateQuery;
|
import com.querydsl.jpa.JPQLQuery;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||||
@@ -44,13 +44,13 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findAll(User user) {
|
public List<FeedSubscription> findAll(User user) {
|
||||||
List<FeedSubscription> subs = query().selectFrom(sub).where(sub.user.eq(user)).leftJoin(sub.feed).fetchJoin()
|
List<FeedSubscription> subs = query().selectFrom(sub).where(sub.user.eq(user)).leftJoin(sub.feed).fetchJoin().leftJoin(sub.category)
|
||||||
.leftJoin(sub.category).fetchJoin().fetch();
|
.fetchJoin().fetch();
|
||||||
return initRelations(subs);
|
return initRelations(subs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findByCategory(User user, FeedCategory category) {
|
public List<FeedSubscription> findByCategory(User user, FeedCategory category) {
|
||||||
HibernateQuery<FeedSubscription> query = query().selectFrom(sub).where(sub.user.eq(user));
|
JPQLQuery<FeedSubscription> query = query().selectFrom(sub).where(sub.user.eq(user));
|
||||||
if (category == null) {
|
if (category == null) {
|
||||||
query.where(sub.category.isNull());
|
query.where(sub.category.isNull());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,22 +3,24 @@ package com.commafeed.backend.dao;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.annotations.QueryHints;
|
||||||
|
|
||||||
import com.commafeed.backend.model.AbstractModel;
|
import com.commafeed.backend.model.AbstractModel;
|
||||||
import com.querydsl.jpa.hibernate.HibernateQueryFactory;
|
import com.querydsl.jpa.impl.JPAQuery;
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||||
|
|
||||||
import io.dropwizard.hibernate.AbstractDAO;
|
import io.dropwizard.hibernate.AbstractDAO;
|
||||||
|
|
||||||
public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T> {
|
public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T> {
|
||||||
|
|
||||||
private HibernateQueryFactory factory;
|
private JPAQueryFactory factory;
|
||||||
|
|
||||||
protected GenericDAO(SessionFactory sessionFactory) {
|
protected GenericDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
this.factory = new HibernateQueryFactory(() -> currentSession());
|
this.factory = new JPAQueryFactory(() -> currentSession());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HibernateQueryFactory query() {
|
protected JPAQueryFactory query() {
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +32,10 @@ public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T>
|
|||||||
models.forEach(m -> persist(m));
|
models.forEach(m -> persist(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void update(T model) {
|
||||||
|
currentSession().merge(model);
|
||||||
|
}
|
||||||
|
|
||||||
public T findById(Long id) {
|
public T findById(Long id) {
|
||||||
return get(id);
|
return get(id);
|
||||||
}
|
}
|
||||||
@@ -45,4 +51,10 @@ public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T>
|
|||||||
return objects.size();
|
return objects.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setTimeout(JPAQuery<?> query, int timeoutMs) {
|
||||||
|
if (timeoutMs > 0) {
|
||||||
|
query.setHint(QueryHints.TIMEOUT_JPA, timeoutMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,24 @@ package com.commafeed.backend.feed;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.StringUtils;
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.jsoup.Jsoup;
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
|
|
||||||
import com.commafeed.backend.HttpGetter;
|
import com.commafeed.backend.HttpGetter;
|
||||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||||
import com.commafeed.backend.HttpGetter.NotModifiedException;
|
import com.commafeed.backend.HttpGetter.NotModifiedException;
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
|
import com.commafeed.backend.urlprovider.FeedURLProvider;
|
||||||
import com.rometools.rome.io.FeedException;
|
import com.rometools.rome.io.FeedException;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
@@ -29,9 +27,10 @@ public class FeedFetcher {
|
|||||||
|
|
||||||
private final FeedParser parser;
|
private final FeedParser parser;
|
||||||
private final HttpGetter getter;
|
private final HttpGetter getter;
|
||||||
|
private final Set<FeedURLProvider> urlProviders;
|
||||||
|
|
||||||
public FetchedFeed fetch(String feedUrl, boolean extractFeedUrlFromHtml, String lastModified, String eTag, Date lastPublishedDate,
|
public FetchedFeed fetch(String feedUrl, boolean extractFeedUrlFromHtml, String lastModified, String eTag, Date lastPublishedDate,
|
||||||
String lastContentHash) throws FeedException, ClientProtocolException, IOException, NotModifiedException {
|
String lastContentHash) throws FeedException, IOException, NotModifiedException {
|
||||||
log.debug("Fetching feed {}", feedUrl);
|
log.debug("Fetching feed {}", feedUrl);
|
||||||
FetchedFeed fetchedFeed = null;
|
FetchedFeed fetchedFeed = null;
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ public class FeedFetcher {
|
|||||||
fetchedFeed = parser.parse(result.getUrlAfterRedirect(), content);
|
fetchedFeed = parser.parse(result.getUrlAfterRedirect(), content);
|
||||||
} catch (FeedException e) {
|
} catch (FeedException e) {
|
||||||
if (extractFeedUrlFromHtml) {
|
if (extractFeedUrlFromHtml) {
|
||||||
String extractedUrl = extractFeedUrl(StringUtils.newStringUtf8(result.getContent()), feedUrl);
|
String extractedUrl = extractFeedUrl(urlProviders, feedUrl, StringUtils.newStringUtf8(result.getContent()));
|
||||||
if (org.apache.commons.lang3.StringUtils.isNotBlank(extractedUrl)) {
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(extractedUrl)) {
|
||||||
feedUrl = extractedUrl;
|
feedUrl = extractedUrl;
|
||||||
|
|
||||||
@@ -84,20 +83,13 @@ public class FeedFetcher {
|
|||||||
return fetchedFeed;
|
return fetchedFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String extractFeedUrl(String html, String baseUri) {
|
private static String extractFeedUrl(Set<FeedURLProvider> urlProviders, String url, String urlContent) {
|
||||||
String foundUrl = null;
|
for (FeedURLProvider urlProvider : urlProviders) {
|
||||||
|
String feedUrl = urlProvider.get(url, urlContent);
|
||||||
Document doc = Jsoup.parse(html, baseUri);
|
if (feedUrl != null)
|
||||||
String root = doc.children().get(0).tagName();
|
return feedUrl;
|
||||||
if ("html".equals(root)) {
|
|
||||||
Elements atom = doc.select("link[type=application/atom+xml]");
|
|
||||||
Elements rss = doc.select("link[type=application/rss+xml]");
|
|
||||||
if (!atom.isEmpty()) {
|
|
||||||
foundUrl = atom.get(0).attr("abs:href");
|
|
||||||
} else if (!rss.isEmpty()) {
|
|
||||||
foundUrl = rss.get(0).attr("abs:href");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return foundUrl;
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import javax.inject.Inject;
|
|||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
@@ -135,9 +134,7 @@ public class FeedRefreshUpdater implements Managed {
|
|||||||
|
|
||||||
if (subscriptions == null) {
|
if (subscriptions == null) {
|
||||||
feed.setMessage("No new entries found");
|
feed.setMessage("No new entries found");
|
||||||
}
|
} else if (!subscriptions.isEmpty()) {
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(subscriptions)) {
|
|
||||||
List<User> users = subscriptions.stream().map(s -> s.getUser()).collect(Collectors.toList());
|
List<User> users = subscriptions.stream().map(s -> s.getUser()).collect(Collectors.toList());
|
||||||
cache.invalidateUnreadCount(subscriptions.toArray(new FeedSubscription[0]));
|
cache.invalidateUnreadCount(subscriptions.toArray(new FeedSubscription[0]));
|
||||||
cache.invalidateUserRootCategory(users.toArray(new User[0]));
|
cache.invalidateUserRootCategory(users.toArray(new User[0]));
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.net.URL;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -13,6 +14,9 @@ import java.util.List;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.ahocorasick.trie.Emit;
|
||||||
|
import org.ahocorasick.trie.Trie;
|
||||||
|
import org.ahocorasick.trie.Trie.TrieBuilder;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -92,6 +96,7 @@ public class FeedUtils {
|
|||||||
whitelist.addProtocols("q", "cite", "http", "https");
|
whitelist.addProtocols("q", "cite", "http", "https");
|
||||||
|
|
||||||
whitelist.addEnforcedAttribute("a", "target", "_blank");
|
whitelist.addEnforcedAttribute("a", "target", "_blank");
|
||||||
|
whitelist.addEnforcedAttribute("a", "rel", "noreferrer");
|
||||||
return whitelist;
|
return whitelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +136,32 @@ public class FeedUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String replaceHtmlEntitiesWithNumericEntities(String source) {
|
public static String replaceHtmlEntitiesWithNumericEntities(String source) {
|
||||||
return StringUtils.replaceEach(source, HtmlEntities.HTML_ENTITIES, HtmlEntities.NUMERIC_ENTITIES);
|
// Create a buffer sufficiently large that re-allocations are minimized.
|
||||||
|
StringBuilder sb = new StringBuilder(source.length() << 1);
|
||||||
|
|
||||||
|
TrieBuilder builder = Trie.builder();
|
||||||
|
builder.ignoreOverlaps();
|
||||||
|
|
||||||
|
for (String key : HtmlEntities.HTML_ENTITIES) {
|
||||||
|
builder.addKeyword(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Trie trie = builder.build();
|
||||||
|
Collection<Emit> emits = trie.parseText(source);
|
||||||
|
|
||||||
|
int prevIndex = 0;
|
||||||
|
for (Emit emit : emits) {
|
||||||
|
int matchIndex = emit.getStart();
|
||||||
|
|
||||||
|
sb.append(source.substring(prevIndex, matchIndex));
|
||||||
|
sb.append(HtmlEntities.HTML_TO_NUMERIC_MAP.get(emit.getKeyword()));
|
||||||
|
prevIndex = emit.getEnd() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the remainder of the string (contains no more matches).
|
||||||
|
sb.append(source.substring(prevIndex));
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.commafeed.backend.feed;
|
package com.commafeed.backend.feed;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class HtmlEntities {
|
public class HtmlEntities {
|
||||||
|
public static final Map<String, String> HTML_TO_NUMERIC_MAP;
|
||||||
public static final String[] HTML_ENTITIES;
|
public static final String[] HTML_ENTITIES;
|
||||||
public static final String[] NUMERIC_ENTITIES;
|
public static final String[] NUMERIC_ENTITIES;
|
||||||
|
|
||||||
@@ -260,6 +262,7 @@ public class HtmlEntities {
|
|||||||
map.put("‍", "‍");
|
map.put("‍", "‍");
|
||||||
map.put("‌", "‌");
|
map.put("‌", "‌");
|
||||||
|
|
||||||
|
HTML_TO_NUMERIC_MAP = Collections.unmodifiableMap(map);
|
||||||
HTML_ENTITIES = map.keySet().toArray(new String[map.size()]);
|
HTML_ENTITIES = map.keySet().toArray(new String[map.size()]);
|
||||||
NUMERIC_ENTITIES = map.values().toArray(new String[map.size()]);
|
NUMERIC_ENTITIES = map.values().toArray(new String[map.size()]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import javax.persistence.Lob;
|
|||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import org.hibernate.annotations.Type;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "FEEDENTRYCONTENTS")
|
@Table(name = "FEEDENTRYCONTENTS")
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@@ -28,7 +28,7 @@ public class FeedEntryContent extends AbstractModel {
|
|||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length = Integer.MAX_VALUE)
|
@Column(length = Integer.MAX_VALUE)
|
||||||
@Type(type = "org.hibernate.type.StringClobType")
|
@Type(type = "org.hibernate.type.TextType")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
@Column(length = 40)
|
@Column(length = 40)
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import javax.persistence.Lob;
|
|||||||
import javax.persistence.OneToOne;
|
import javax.persistence.OneToOne;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import org.hibernate.annotations.Type;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "USERSETTINGS")
|
@Table(name = "USERSETTINGS")
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@@ -27,7 +27,7 @@ public class UserSettings extends AbstractModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum ReadingOrder {
|
public enum ReadingOrder {
|
||||||
asc, desc
|
asc, desc, abc, zyx
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ViewMode {
|
public enum ViewMode {
|
||||||
@@ -61,7 +61,7 @@ public class UserSettings extends AbstractModel {
|
|||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length = Integer.MAX_VALUE)
|
@Column(length = Integer.MAX_VALUE)
|
||||||
@Type(type = "org.hibernate.type.StringClobType")
|
@Type(type = "org.hibernate.type.TextType")
|
||||||
private String customCss;
|
private String customCss;
|
||||||
|
|
||||||
@Column(name = "scroll_speed")
|
@Column(name = "scroll_speed")
|
||||||
|
|||||||
@@ -8,18 +8,19 @@ import java.util.stream.Collectors;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
|
||||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||||
import com.commafeed.backend.model.FeedCategory;
|
import com.commafeed.backend.model.FeedCategory;
|
||||||
import com.commafeed.backend.model.FeedSubscription;
|
import com.commafeed.backend.model.FeedSubscription;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.google.common.base.MoreObjects;
|
|
||||||
import com.rometools.opml.feed.opml.Attribute;
|
import com.rometools.opml.feed.opml.Attribute;
|
||||||
import com.rometools.opml.feed.opml.Opml;
|
import com.rometools.opml.feed.opml.Opml;
|
||||||
import com.rometools.opml.feed.opml.Outline;
|
import com.rometools.opml.feed.opml.Outline;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class OPMLExporter {
|
public class OPMLExporter {
|
||||||
@@ -35,11 +36,11 @@ public class OPMLExporter {
|
|||||||
|
|
||||||
List<FeedCategory> categories = feedCategoryDAO.findAll(user);
|
List<FeedCategory> categories = feedCategoryDAO.findAll(user);
|
||||||
Collections.sort(categories,
|
Collections.sort(categories,
|
||||||
(e1, e2) -> MoreObjects.firstNonNull(e1.getPosition(), 0) - MoreObjects.firstNonNull(e2.getPosition(), 0));
|
(e1, e2) -> ObjectUtils.firstNonNull(e1.getPosition(), 0) - ObjectUtils.firstNonNull(e2.getPosition(), 0));
|
||||||
|
|
||||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findAll(user);
|
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findAll(user);
|
||||||
Collections.sort(subscriptions,
|
Collections.sort(subscriptions,
|
||||||
(e1, e2) -> MoreObjects.firstNonNull(e1.getPosition(), 0) - MoreObjects.firstNonNull(e2.getPosition(), 0));
|
(e1, e2) -> ObjectUtils.firstNonNull(e1.getPosition(), 0) - ObjectUtils.firstNonNull(e2.getPosition(), 0));
|
||||||
|
|
||||||
// export root categories
|
// export root categories
|
||||||
for (FeedCategory cat : categories.stream().filter(c -> c.getParent() == null).collect(Collectors.toList())) {
|
for (FeedCategory cat : categories.stream().filter(c -> c.getParent() == null).collect(Collectors.toList())) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.commafeed.backend.service;
|
package com.commafeed.backend.service;
|
||||||
|
|
||||||
|
import java.time.Year;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -91,6 +92,8 @@ public class FeedEntryFilteringService {
|
|||||||
context.set("url", entry.getUrl() == null ? "" : entry.getUrl().toLowerCase());
|
context.set("url", entry.getUrl() == null ? "" : entry.getUrl().toLowerCase());
|
||||||
context.set("categories", entry.getContent().getCategories() == null ? "" : entry.getContent().getCategories().toLowerCase());
|
context.set("categories", entry.getContent().getCategories() == null ? "" : entry.getContent().getCategories().toLowerCase());
|
||||||
|
|
||||||
|
context.set("year", Year.now().getValue());
|
||||||
|
|
||||||
Callable<Object> callable = script.callable(context);
|
Callable<Object> callable = script.callable(context);
|
||||||
Future<Object> future = executor.submit(callable);
|
Future<Object> future = executor.submit(callable);
|
||||||
Object result = null;
|
Object result = null;
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
package com.commafeed.backend.service;
|
package com.commafeed.backend.service;
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl;
|
|
||||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
|
||||||
import org.hibernate.internal.SessionFactoryImpl;
|
|
||||||
|
|
||||||
import com.commafeed.CommaFeedApplication;
|
import com.commafeed.CommaFeedApplication;
|
||||||
import com.commafeed.CommaFeedConfiguration;
|
import com.commafeed.CommaFeedConfiguration;
|
||||||
@@ -31,7 +27,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class StartupService implements Managed {
|
public class StartupService implements Managed {
|
||||||
|
|
||||||
@@ -50,17 +46,10 @@ public class StartupService implements Managed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateSchema() {
|
private void updateSchema() {
|
||||||
try {
|
Session session = sessionFactory.openSession();
|
||||||
Connection connection = null;
|
session.doWork(connection -> {
|
||||||
try {
|
try {
|
||||||
Thread currentThread = Thread.currentThread();
|
|
||||||
ClassLoader classLoader = currentThread.getContextClassLoader();
|
|
||||||
ResourceAccessor accessor = new ClassLoaderResourceAccessor(classLoader);
|
|
||||||
|
|
||||||
DataSource dataSource = getDataSource(sessionFactory);
|
|
||||||
connection = dataSource.getConnection();
|
|
||||||
JdbcConnection jdbcConnection = new JdbcConnection(connection);
|
JdbcConnection jdbcConnection = new JdbcConnection(connection);
|
||||||
|
|
||||||
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(jdbcConnection);
|
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(jdbcConnection);
|
||||||
|
|
||||||
if (database instanceof PostgresDatabase) {
|
if (database instanceof PostgresDatabase) {
|
||||||
@@ -73,17 +62,14 @@ public class StartupService implements Managed {
|
|||||||
database.setConnection(jdbcConnection);
|
database.setConnection(jdbcConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceAccessor accessor = new ClassLoaderResourceAccessor(Thread.currentThread().getContextClassLoader());
|
||||||
Liquibase liq = new Liquibase("migrations.xml", accessor, database);
|
Liquibase liq = new Liquibase("migrations.xml", accessor, database);
|
||||||
liq.update("prod");
|
liq.update("prod");
|
||||||
} finally {
|
} catch (Exception e) {
|
||||||
if (connection != null) {
|
throw new RuntimeException(e);
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
} catch (Exception e) {
|
session.close();
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialData() {
|
private void initialData() {
|
||||||
@@ -103,15 +89,4 @@ public class StartupService implements Managed {
|
|||||||
public void stop() throws Exception {
|
public void stop() throws Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DataSource getDataSource(SessionFactory sessionFactory) {
|
|
||||||
if (sessionFactory instanceof SessionFactoryImpl) {
|
|
||||||
ConnectionProvider cp = ((SessionFactoryImpl) sessionFactory).getConnectionProvider();
|
|
||||||
if (cp instanceof DatasourceConnectionProviderImpl) {
|
|
||||||
return ((DatasourceConnectionProviderImpl) cp).getDataSource();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.commafeed.backend.urlprovider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to find a feed url given the url and page content
|
||||||
|
*/
|
||||||
|
public interface FeedURLProvider {
|
||||||
|
|
||||||
|
String get(String url, String urlContent);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.commafeed.backend.urlprovider;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
public class InPageReferenceFeedURLProvider implements FeedURLProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String url, String urlContent) {
|
||||||
|
String foundUrl = null;
|
||||||
|
|
||||||
|
Document doc = Jsoup.parse(urlContent, url);
|
||||||
|
String root = doc.children().get(0).tagName();
|
||||||
|
if ("html".equals(root)) {
|
||||||
|
Elements atom = doc.select("link[type=application/atom+xml]");
|
||||||
|
Elements rss = doc.select("link[type=application/rss+xml]");
|
||||||
|
if (!atom.isEmpty()) {
|
||||||
|
foundUrl = atom.get(0).attr("abs:href");
|
||||||
|
} else if (!rss.isEmpty()) {
|
||||||
|
foundUrl = rss.get(0).attr("abs:href");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.commafeed.backend.urlprovider;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workaround for Youtube channels
|
||||||
|
*
|
||||||
|
* converts the channel URL https://www.youtube.com/channel/CHANNEL_ID to the valid feed URL
|
||||||
|
* https://www.youtube.com/feeds/videos.xml?channel_id=CHANNEL_ID
|
||||||
|
*/
|
||||||
|
public class YoutubeFeedURLProvider implements FeedURLProvider {
|
||||||
|
|
||||||
|
private static final Pattern REGEXP = Pattern.compile("(.*\\byoutube\\.com)\\/channel\\/([^\\/]+)", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String url, String urlContent) {
|
||||||
|
Matcher matcher = REGEXP.matcher(url);
|
||||||
|
return matcher.find() ? matcher.group(1) + "/feeds/videos.xml?channel_id=" + matcher.group(2) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,28 +9,28 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Entry details")
|
@ApiModel(description = "Entry details")
|
||||||
@Data
|
@Data
|
||||||
public class Category implements Serializable {
|
public class Category implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty("category id")
|
@ApiModelProperty(value = "category id", required = true)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@ApiModelProperty("parent category id")
|
@ApiModelProperty(value = "parent category id")
|
||||||
private String parentId;
|
private String parentId;
|
||||||
|
|
||||||
@ApiModelProperty("category id")
|
@ApiModelProperty(value = "category id", required = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("category children categories")
|
@ApiModelProperty(value = "category children categories", required = true)
|
||||||
private List<Category> children = new ArrayList<>();
|
private List<Category> children = new ArrayList<>();
|
||||||
|
|
||||||
@ApiModelProperty("category feeds")
|
@ApiModelProperty(value = "category feeds", required = true)
|
||||||
private List<Subscription> feeds = new ArrayList<>();
|
private List<Subscription> feeds = new ArrayList<>();
|
||||||
|
|
||||||
@ApiModelProperty("wether the category is expanded or collapsed")
|
@ApiModelProperty(value = "wether the category is expanded or collapsed", required = true)
|
||||||
private boolean expanded;
|
private boolean expanded;
|
||||||
|
|
||||||
@ApiModelProperty("position of the category in the list")
|
@ApiModelProperty(value = "position of the category in the list", required = true)
|
||||||
private Integer position;
|
private Integer position;
|
||||||
}
|
}
|
||||||
@@ -9,38 +9,40 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("List of entries with some metadata")
|
@ApiModel(description = "List of entries with some metadata")
|
||||||
@Data
|
@Data
|
||||||
public class Entries implements Serializable {
|
public class Entries implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty("name of the feed or the category requested")
|
@ApiModelProperty(value = "name of the feed or the category requested", required = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("error or warning message")
|
@ApiModelProperty(value = "error or warning message")
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
@ApiModelProperty("times the server tried to refresh the feed and failed")
|
@ApiModelProperty(value = "times the server tried to refresh the feed and failed", required = true)
|
||||||
private int errorCount;
|
private int errorCount;
|
||||||
|
|
||||||
@ApiModelProperty("URL of the website, extracted from the feed")
|
@ApiModelProperty(value = "URL of the website, extracted from the feed", required = true)
|
||||||
private String feedLink;
|
private String feedLink;
|
||||||
|
|
||||||
@ApiModelProperty("list generation timestamp")
|
@ApiModelProperty(value = "list generation timestamp", required = true)
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
|
|
||||||
@ApiModelProperty("if the query has more elements")
|
@ApiModelProperty(value = "if the query has more elements", required = true)
|
||||||
private boolean hasMore;
|
private boolean hasMore;
|
||||||
|
|
||||||
@ApiModelProperty("the requested offset")
|
@ApiModelProperty(value = "the requested offset")
|
||||||
private int offset;
|
private int offset;
|
||||||
|
|
||||||
@ApiModelProperty("the requested limit")
|
@ApiModelProperty(value = "the requested limit")
|
||||||
private int limit;
|
private int limit;
|
||||||
|
|
||||||
@ApiModelProperty("list of entries")
|
@ApiModelProperty(value = "list of entries", required = true)
|
||||||
private List<Entry> entries = new ArrayList<>();
|
private List<Entry> entries = new ArrayList<>();
|
||||||
|
|
||||||
@ApiModelProperty("if true, the unread flag was ignored in the request, all entries are returned regardless of their read status")
|
@ApiModelProperty(
|
||||||
|
value = "if true, the unread flag was ignored in the request, all entries are returned regardless of their read status",
|
||||||
|
required = true)
|
||||||
private boolean ignoredReadStatus;
|
private boolean ignoredReadStatus;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Entry details")
|
@ApiModel(description = "Entry details")
|
||||||
@Data
|
@Data
|
||||||
public class Entry implements Serializable {
|
public class Entry implements Serializable {
|
||||||
|
|
||||||
@@ -58,7 +58,8 @@ public class Entry implements Serializable {
|
|||||||
entry.setAuthor(content.getAuthor());
|
entry.setAuthor(content.getAuthor());
|
||||||
entry.setEnclosureType(content.getEnclosureType());
|
entry.setEnclosureType(content.getEnclosureType());
|
||||||
entry.setEnclosureUrl(proxyImages && StringUtils.contains(content.getEnclosureType(), "image")
|
entry.setEnclosureUrl(proxyImages && StringUtils.contains(content.getEnclosureType(), "image")
|
||||||
? FeedUtils.proxyImage(content.getEnclosureUrl(), publicUrl) : content.getEnclosureUrl());
|
? FeedUtils.proxyImage(content.getEnclosureUrl(), publicUrl)
|
||||||
|
: content.getEnclosureUrl());
|
||||||
entry.setCategories(content.getCategories());
|
entry.setCategories(content.getCategories());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +71,7 @@ public class Entry implements Serializable {
|
|||||||
|
|
||||||
entry.setUri(getGuid());
|
entry.setUri(getGuid());
|
||||||
entry.setTitle(getTitle());
|
entry.setTitle(getTitle());
|
||||||
|
entry.setAuthor(getAuthor());
|
||||||
|
|
||||||
SyndContentImpl content = new SyndContentImpl();
|
SyndContentImpl content = new SyndContentImpl();
|
||||||
content.setValue(getContent());
|
content.setValue(getContent());
|
||||||
@@ -87,66 +89,66 @@ public class Entry implements Serializable {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiModelProperty("entry id")
|
@ApiModelProperty(value = "entry id", required = true)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@ApiModelProperty("entry guid")
|
@ApiModelProperty(value = "entry guid", required = true)
|
||||||
private String guid;
|
private String guid;
|
||||||
|
|
||||||
@ApiModelProperty("entry title")
|
@ApiModelProperty(value = "entry title", required = true)
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@ApiModelProperty("entry content")
|
@ApiModelProperty(value = "entry content", required = true)
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
@ApiModelProperty("comma-separated list of categories")
|
@ApiModelProperty(value = "comma-separated list of categories")
|
||||||
private String categories;
|
private String categories;
|
||||||
|
|
||||||
@ApiModelProperty("wether entry content and title are rtl")
|
@ApiModelProperty(value = "wether entry content and title are rtl", required = true)
|
||||||
private boolean rtl;
|
private boolean rtl;
|
||||||
|
|
||||||
@ApiModelProperty("entry author")
|
@ApiModelProperty(value = "entry author")
|
||||||
private String author;
|
private String author;
|
||||||
|
|
||||||
@ApiModelProperty("entry enclosure url, if any")
|
@ApiModelProperty(value = "entry enclosure url, if any")
|
||||||
private String enclosureUrl;
|
private String enclosureUrl;
|
||||||
|
|
||||||
@ApiModelProperty("entry enclosure mime type, if any")
|
@ApiModelProperty(value = "entry enclosure mime type, if any")
|
||||||
private String enclosureType;
|
private String enclosureType;
|
||||||
|
|
||||||
@ApiModelProperty("entry publication date")
|
@ApiModelProperty(value = "entry publication date", dataType = "number", required = true)
|
||||||
private Date date;
|
private Date date;
|
||||||
|
|
||||||
@ApiModelProperty("entry insertion date in the database")
|
@ApiModelProperty(value = "entry insertion date in the database", dataType = "number", required = true)
|
||||||
private Date insertedDate;
|
private Date insertedDate;
|
||||||
|
|
||||||
@ApiModelProperty("feed id")
|
@ApiModelProperty(value = "feed id", required = true)
|
||||||
private String feedId;
|
private String feedId;
|
||||||
|
|
||||||
@ApiModelProperty("feed name")
|
@ApiModelProperty(value = "feed name", required = true)
|
||||||
private String feedName;
|
private String feedName;
|
||||||
|
|
||||||
@ApiModelProperty("this entry's feed url")
|
@ApiModelProperty(value = "this entry's feed url", required = true)
|
||||||
private String feedUrl;
|
private String feedUrl;
|
||||||
|
|
||||||
@ApiModelProperty("this entry's website url")
|
@ApiModelProperty(value = "this entry's website url", required = true)
|
||||||
private String feedLink;
|
private String feedLink;
|
||||||
|
|
||||||
@ApiModelProperty(value = "The favicon url to use for this feed")
|
@ApiModelProperty(value = "The favicon url to use for this feed", required = true)
|
||||||
private String iconUrl;
|
private String iconUrl;
|
||||||
|
|
||||||
@ApiModelProperty("entry url")
|
@ApiModelProperty(value = "entry url", required = true)
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
@ApiModelProperty("read sttaus")
|
@ApiModelProperty(value = "read status", required = true)
|
||||||
private boolean read;
|
private boolean read;
|
||||||
|
|
||||||
@ApiModelProperty("starred status")
|
@ApiModelProperty(value = "starred status", required = true)
|
||||||
private boolean starred;
|
private boolean starred;
|
||||||
|
|
||||||
@ApiModelProperty("wether the entry is still markable (old entry statuses are discarded)")
|
@ApiModelProperty(value = "wether the entry is still markable (old entry statuses are discarded)", required = true)
|
||||||
private boolean markable;
|
private boolean markable;
|
||||||
|
|
||||||
@ApiModelProperty("tags")
|
@ApiModelProperty(value = "tags", required = true)
|
||||||
private List<String> tags;
|
private List<String> tags;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,18 @@ package com.commafeed.frontend.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Feed details")
|
@ApiModel(description = "Feed details")
|
||||||
@Data
|
@Data
|
||||||
public class FeedInfo implements Serializable {
|
public class FeedInfo implements Serializable {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "url", required = true)
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "title", required = true)
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,30 @@ package com.commafeed.frontend.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Server infos")
|
@ApiModel(description = "Server infos")
|
||||||
@Data
|
@Data
|
||||||
public class ServerInfo implements Serializable {
|
public class ServerInfo implements Serializable {
|
||||||
|
|
||||||
|
@ApiModelProperty
|
||||||
private String announcement;
|
private String announcement;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private String gitCommit;
|
private String gitCommit;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean allowRegistrations;
|
private boolean allowRegistrations;
|
||||||
|
|
||||||
|
@ApiModelProperty
|
||||||
private String googleAnalyticsCode;
|
private String googleAnalyticsCode;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean smtpEnabled;
|
private boolean smtpEnabled;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("User settings")
|
@ApiModel(description = "User settings")
|
||||||
@Data
|
@Data
|
||||||
public class Settings implements Serializable {
|
public class Settings implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty(value = "user's preferred language, english if none")
|
@ApiModelProperty(value = "user's preferred language, english if none", required = true)
|
||||||
private String language;
|
private String language;
|
||||||
|
|
||||||
@ApiModelProperty(value = "user reads all entries or unread entries only", allowableValues = "all,unread", required = true)
|
@ApiModelProperty(value = "user reads all entries or unread entries only", allowableValues = "all,unread", required = true)
|
||||||
@@ -35,18 +35,37 @@ public class Settings implements Serializable {
|
|||||||
@ApiModelProperty(value = "user's custom css for the website")
|
@ApiModelProperty(value = "user's custom css for the website")
|
||||||
private String customCss;
|
private String customCss;
|
||||||
|
|
||||||
@ApiModelProperty(value = "user's preferred scroll speed when navigating between entries")
|
@ApiModelProperty(value = "user's preferred scroll speed when navigating between entries", required = true)
|
||||||
private int scrollSpeed;
|
private int scrollSpeed;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean email;
|
private boolean email;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean gmail;
|
private boolean gmail;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean facebook;
|
private boolean facebook;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean twitter;
|
private boolean twitter;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean googleplus;
|
private boolean googleplus;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean tumblr;
|
private boolean tumblr;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean pocket;
|
private boolean pocket;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean instapaper;
|
private boolean instapaper;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean buffer;
|
private boolean buffer;
|
||||||
|
|
||||||
|
@ApiModelProperty(required = true)
|
||||||
private boolean readability;
|
private boolean readability;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("User information")
|
@ApiModel(description = "User information")
|
||||||
@Data
|
@Data
|
||||||
public class Subscription implements Serializable {
|
public class Subscription implements Serializable {
|
||||||
|
|
||||||
@@ -51,10 +51,13 @@ public class Subscription implements Serializable {
|
|||||||
@ApiModelProperty(value = "error count", required = true)
|
@ApiModelProperty(value = "error count", required = true)
|
||||||
private int errorCount;
|
private int errorCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "last time the feed was refreshed", required = true)
|
@ApiModelProperty(value = "last time the feed was refreshed", dataType = "number", required = true)
|
||||||
private Date lastRefresh;
|
private Date lastRefresh;
|
||||||
|
|
||||||
@ApiModelProperty(value = "next time the feed refresh is planned, null if refresh is already queued", required = true)
|
@ApiModelProperty(
|
||||||
|
value = "next time the feed refresh is planned, null if refresh is already queued",
|
||||||
|
dataType = "number",
|
||||||
|
required = true)
|
||||||
private Date nextRefresh;
|
private Date nextRefresh;
|
||||||
|
|
||||||
@ApiModelProperty(value = "this subscription's feed url", required = true)
|
@ApiModelProperty(value = "this subscription's feed url", required = true)
|
||||||
@@ -63,7 +66,7 @@ public class Subscription implements Serializable {
|
|||||||
@ApiModelProperty(value = "this subscription's website url", required = true)
|
@ApiModelProperty(value = "this subscription's website url", required = true)
|
||||||
private String feedLink;
|
private String feedLink;
|
||||||
|
|
||||||
@ApiModelProperty(value = "The favicon url to use for this feed")
|
@ApiModelProperty(value = "The favicon url to use for this feed", required = true)
|
||||||
private String iconUrl;
|
private String iconUrl;
|
||||||
|
|
||||||
@ApiModelProperty(value = "unread count", required = true)
|
@ApiModelProperty(value = "unread count", required = true)
|
||||||
@@ -75,7 +78,7 @@ public class Subscription implements Serializable {
|
|||||||
@ApiModelProperty("position of the subscription's in the list")
|
@ApiModelProperty("position of the subscription's in the list")
|
||||||
private Integer position;
|
private Integer position;
|
||||||
|
|
||||||
@ApiModelProperty("date of the newest item")
|
@ApiModelProperty(value = "date of the newest item", dataType = "number")
|
||||||
private Date newestItemTime;
|
private Date newestItemTime;
|
||||||
|
|
||||||
@ApiModelProperty(value = "JEXL string evaluated on new entries to mark them as read if they do not match")
|
@ApiModelProperty(value = "JEXL string evaluated on new entries to mark them as read if they do not match")
|
||||||
|
|||||||
@@ -4,15 +4,21 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Unread count")
|
@ApiModel(description = "Unread count")
|
||||||
@Data
|
@Data
|
||||||
public class UnreadCount implements Serializable {
|
public class UnreadCount implements Serializable {
|
||||||
|
|
||||||
|
@ApiModelProperty
|
||||||
private long feedId;
|
private long feedId;
|
||||||
|
|
||||||
|
@ApiModelProperty
|
||||||
private long unreadCount;
|
private long unreadCount;
|
||||||
|
|
||||||
|
@ApiModelProperty(dataType = "number")
|
||||||
private Date newestItemTime;
|
private Date newestItemTime;
|
||||||
|
|
||||||
public UnreadCount() {
|
public UnreadCount() {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("User information")
|
@ApiModel(description = "User information")
|
||||||
@Data
|
@Data
|
||||||
public class UserModel implements Serializable {
|
public class UserModel implements Serializable {
|
||||||
|
|
||||||
@@ -27,16 +27,16 @@ public class UserModel implements Serializable {
|
|||||||
@ApiModelProperty(value = "user password, never returned by the api")
|
@ApiModelProperty(value = "user password, never returned by the api")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@ApiModelProperty(value = "account status")
|
@ApiModelProperty(value = "account status", required = true)
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
@ApiModelProperty(value = "account creation date")
|
@ApiModelProperty(value = "account creation date", dataType = "number", required = true)
|
||||||
private Date created;
|
private Date created;
|
||||||
|
|
||||||
@ApiModelProperty(value = "last login date")
|
@ApiModelProperty(value = "last login date", dataType = "number")
|
||||||
private Date lastLogin;
|
private Date lastLogin;
|
||||||
|
|
||||||
@ApiModelProperty(value = "user is admin")
|
@ApiModelProperty(value = "user is admin", required = true)
|
||||||
private boolean admin;
|
private boolean admin;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Add Category Request")
|
@ApiModel(description = "Add Category Request")
|
||||||
@Data
|
@Data
|
||||||
public class AddCategoryRequest implements Serializable {
|
public class AddCategoryRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Category modification request")
|
@ApiModel(description = "Category modification request")
|
||||||
@Data
|
@Data
|
||||||
public class CategoryModificationRequest implements Serializable {
|
public class CategoryModificationRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Mark Request")
|
@ApiModel(description = "Mark Request")
|
||||||
@Data
|
@Data
|
||||||
public class CollapseRequest implements Serializable {
|
public class CollapseRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Feed information request")
|
@ApiModel(description = "Feed information request")
|
||||||
@Data
|
@Data
|
||||||
public class FeedInfoRequest implements Serializable {
|
public class FeedInfoRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Feed merge Request")
|
@ApiModel(description = "Feed merge Request")
|
||||||
@Data
|
@Data
|
||||||
public class FeedMergeRequest implements Serializable {
|
public class FeedMergeRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Feed modification request")
|
@ApiModel(description = "Feed modification request")
|
||||||
@Data
|
@Data
|
||||||
public class FeedModificationRequest implements Serializable {
|
public class FeedModificationRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class IDRequest implements Serializable {
|
public class IDRequest implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty
|
@ApiModelProperty(required = true)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Mark Request")
|
@ApiModel(description = "Mark Request")
|
||||||
@Data
|
@Data
|
||||||
public class MarkRequest implements Serializable {
|
public class MarkRequest implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty(value = "entry id, category id, 'all' or 'starred'", required = true)
|
@ApiModelProperty(value = "entry id, category id, 'all' or 'starred'", required = true)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "mark as read or unread")
|
@ApiModelProperty(value = "mark as read or unread", required = true)
|
||||||
private boolean read;
|
private boolean read;
|
||||||
|
|
||||||
@ApiModelProperty(
|
@ApiModelProperty(
|
||||||
@@ -25,7 +25,7 @@ public class MarkRequest implements Serializable {
|
|||||||
|
|
||||||
@ApiModelProperty(value = "only mark read if a feed has these keywords in the title or rss content", required = false)
|
@ApiModelProperty(value = "only mark read if a feed has these keywords in the title or rss content", required = false)
|
||||||
private String keywords;
|
private String keywords;
|
||||||
|
|
||||||
@ApiModelProperty(value = "if marking a category or 'all', exclude those subscriptions from the marking", required = false)
|
@ApiModelProperty(value = "if marking a category or 'all', exclude those subscriptions from the marking", required = false)
|
||||||
private List<Long> excludedSubscriptions;
|
private List<Long> excludedSubscriptions;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Multiple Mark Request")
|
@ApiModel(description = "Multiple Mark Request")
|
||||||
@Data
|
@Data
|
||||||
public class MultipleMarkRequest implements Serializable {
|
public class MultipleMarkRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Profile modification request")
|
@ApiModel(description = "Profile modification request")
|
||||||
@Data
|
@Data
|
||||||
public class ProfileModificationRequest implements Serializable {
|
public class ProfileModificationRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Star Request")
|
@ApiModel(description = "Star Request")
|
||||||
@Data
|
@Data
|
||||||
public class StarRequest implements Serializable {
|
public class StarRequest implements Serializable {
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ public class StarRequest implements Serializable {
|
|||||||
@ApiModelProperty(value = "feed id", required = true)
|
@ApiModelProperty(value = "feed id", required = true)
|
||||||
private Long feedId;
|
private Long feedId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "starred or not")
|
@ApiModelProperty(value = "starred or not", required = true)
|
||||||
private boolean starred;
|
private boolean starred;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Subscription request")
|
@ApiModel(description = "Subscription request")
|
||||||
@Data
|
@Data
|
||||||
public class SubscribeRequest implements Serializable {
|
public class SubscribeRequest implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
@ApiModel("Tag Request")
|
@ApiModel(description = "Tag Request")
|
||||||
@Data
|
@Data
|
||||||
public class TagRequest implements Serializable {
|
public class TagRequest implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty(value = "entry id", required = true)
|
@ApiModelProperty(value = "entry id", required = true)
|
||||||
private Long entryId;
|
private Long entryId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "tags")
|
@ApiModelProperty(value = "tags", required = true)
|
||||||
private List<String> tags;
|
private List<String> tags;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@Api(value = "/admin")
|
@Api(value = "/admin")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AdminREST {
|
public class AdminREST {
|
||||||
|
|
||||||
@@ -62,7 +62,8 @@ public class AdminREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Save or update a user", notes = "Save or update a user. If the id is not specified, a new user will be created")
|
@ApiOperation(value = "Save or update a user", notes = "Save or update a user. If the id is not specified, a new user will be created")
|
||||||
@Timed
|
@Timed
|
||||||
public Response save(@SecurityCheck(Role.ADMIN) User user, @ApiParam(required = true) UserModel userModel) {
|
public Response adminSaveUser(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user,
|
||||||
|
@ApiParam(required = true) UserModel userModel) {
|
||||||
Preconditions.checkNotNull(userModel);
|
Preconditions.checkNotNull(userModel);
|
||||||
Preconditions.checkNotNull(userModel.getName());
|
Preconditions.checkNotNull(userModel.getName());
|
||||||
|
|
||||||
@@ -117,7 +118,8 @@ public class AdminREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get user information", notes = "Get user information", response = UserModel.class)
|
@ApiOperation(value = "Get user information", notes = "Get user information", response = UserModel.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getUser(@SecurityCheck(Role.ADMIN) User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
public Response adminGetUser(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user,
|
||||||
|
@ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
||||||
Preconditions.checkNotNull(id);
|
Preconditions.checkNotNull(id);
|
||||||
User u = userDAO.findById(id);
|
User u = userDAO.findById(id);
|
||||||
UserModel userModel = new UserModel();
|
UserModel userModel = new UserModel();
|
||||||
@@ -134,7 +136,7 @@ public class AdminREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get all users", notes = "Get all users", response = UserModel.class, responseContainer = "List")
|
@ApiOperation(value = "Get all users", notes = "Get all users", response = UserModel.class, responseContainer = "List")
|
||||||
@Timed
|
@Timed
|
||||||
public Response getUsers(@SecurityCheck(Role.ADMIN) User user) {
|
public Response adminGetUsers(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
|
||||||
Map<Long, UserModel> users = new HashMap<>();
|
Map<Long, UserModel> users = new HashMap<>();
|
||||||
for (UserRole role : userRoleDAO.findAll()) {
|
for (UserRole role : userRoleDAO.findAll()) {
|
||||||
User u = role.getUser();
|
User u = role.getUser();
|
||||||
@@ -162,7 +164,8 @@ public class AdminREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Delete a user", notes = "Delete a user, and all his subscriptions")
|
@ApiOperation(value = "Delete a user", notes = "Delete a user, and all his subscriptions")
|
||||||
@Timed
|
@Timed
|
||||||
public Response delete(@SecurityCheck(Role.ADMIN) User user, @ApiParam(required = true) IDRequest req) {
|
public Response adminDeleteUser(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user,
|
||||||
|
@ApiParam(required = true) IDRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -182,7 +185,7 @@ public class AdminREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", response = ApplicationSettings.class)
|
@ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", response = ApplicationSettings.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getSettings(@SecurityCheck(Role.ADMIN) User user) {
|
public Response getApplicationSettings(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
|
||||||
return Response.ok(config.getApplicationSettings()).build();
|
return Response.ok(config.getApplicationSettings()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +194,7 @@ public class AdminREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Retrieve server metrics")
|
@ApiOperation(value = "Retrieve server metrics")
|
||||||
@Timed
|
@Timed
|
||||||
public Response getMetrics(@SecurityCheck(Role.ADMIN) User user) {
|
public Response getMetrics(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
|
||||||
return Response.ok(metrics).build();
|
return Response.ok(metrics).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CategoryREST {
|
public class CategoryREST {
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get category entries", notes = "Get a list of category entries", response = Entries.class)
|
@ApiOperation(value = "Get category entries", notes = "Get a list of category entries", response = Entries.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getCategoryEntries(@SecurityCheck User user,
|
public Response getCategoryEntries(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
@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(
|
@ApiParam(
|
||||||
value = "all entries or only unread ones",
|
value = "all entries or only unread ones",
|
||||||
@@ -103,7 +103,9 @@ public class CategoryREST {
|
|||||||
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
|
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
|
||||||
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
|
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
|
||||||
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
|
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
|
||||||
@ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
|
@ApiParam(
|
||||||
|
value = "ordering",
|
||||||
|
allowableValues = "asc,desc,abc,zyx") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
|
||||||
@ApiParam(
|
@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,
|
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 = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds,
|
||||||
@@ -191,7 +193,7 @@ public class CategoryREST {
|
|||||||
@ApiOperation(value = "Get category entries as feed", notes = "Get a feed of category entries")
|
@ApiOperation(value = "Get category entries as feed", notes = "Get a feed of category entries")
|
||||||
@Produces(MediaType.APPLICATION_XML)
|
@Produces(MediaType.APPLICATION_XML)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getCategoryEntriesAsFeed(@SecurityCheck(apiKeyAllowed = true) User user,
|
public Response getCategoryEntriesAsFeed(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
|
||||||
@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(
|
@ApiParam(
|
||||||
value = "all entries or only unread ones",
|
value = "all entries or only unread ones",
|
||||||
@@ -238,7 +240,7 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Mark category entries", notes = "Mark feed entries of this category as read")
|
@ApiOperation(value = "Mark category entries", notes = "Mark feed entries of this category as read")
|
||||||
@Timed
|
@Timed
|
||||||
public Response markCategoryEntries(@SecurityCheck User user,
|
public Response markCategoryEntries(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
@ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
|
@ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
@@ -280,7 +282,7 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Add a category", notes = "Add a new feed category", response = Long.class)
|
@ApiOperation(value = "Add a category", notes = "Add a new feed category", response = Long.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response addCategory(@SecurityCheck User user, @ApiParam(required = true) AddCategoryRequest req) {
|
public Response addCategory(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) AddCategoryRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getName());
|
Preconditions.checkNotNull(req.getName());
|
||||||
|
|
||||||
@@ -304,7 +306,7 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Delete a category", notes = "Delete an existing feed category")
|
@ApiOperation(value = "Delete a category", notes = "Delete an existing feed category")
|
||||||
@Timed
|
@Timed
|
||||||
public Response deleteCategory(@SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
|
public Response deleteCategory(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
|
||||||
|
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
@@ -337,7 +339,8 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Rename a category", notes = "Rename an existing feed category")
|
@ApiOperation(value = "Rename a category", notes = "Rename an existing feed category")
|
||||||
@Timed
|
@Timed
|
||||||
public Response modifyCategory(@SecurityCheck User user, @ApiParam(required = true) CategoryModificationRequest req) {
|
public Response modifyCategory(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(required = true) CategoryModificationRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -392,7 +395,7 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Collapse a category", notes = "Save collapsed or expanded status for a category")
|
@ApiOperation(value = "Collapse a category", notes = "Save collapsed or expanded status for a category")
|
||||||
@Timed
|
@Timed
|
||||||
public Response collapse(@SecurityCheck User user, @ApiParam(required = true) CollapseRequest req) {
|
public Response collapseCategory(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) CollapseRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -411,7 +414,7 @@ public class CategoryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get unread count for feed subscriptions", response = UnreadCount.class, responseContainer = "List")
|
@ApiOperation(value = "Get unread count for feed subscriptions", response = UnreadCount.class, responseContainer = "List")
|
||||||
@Timed
|
@Timed
|
||||||
public Response getUnreadCount(@SecurityCheck User user) {
|
public Response getUnreadCount(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
Map<Long, UnreadCount> unreadCount = feedSubscriptionService.getUnreadCount(user);
|
Map<Long, UnreadCount> unreadCount = feedSubscriptionService.getUnreadCount(user);
|
||||||
return Response.ok(Lists.newArrayList(unreadCount.values())).build();
|
return Response.ok(Lists.newArrayList(unreadCount.values())).build();
|
||||||
}
|
}
|
||||||
@@ -419,9 +422,9 @@ public class CategoryREST {
|
|||||||
@GET
|
@GET
|
||||||
@Path("/get")
|
@Path("/get")
|
||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get feed categories", notes = "Get all categories and subscriptions of the user", response = Category.class)
|
@ApiOperation(value = "Get root category", notes = "Get all categories and subscriptions of the user", response = Category.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getSubscriptions(@SecurityCheck User user) {
|
public Response getRootCategory(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
Category root = cache.getUserRootCategory(user);
|
Category root = cache.getUserRootCategory(user);
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
log.debug("tree cache miss for {}", user.getId());
|
log.debug("tree cache miss for {}", user.getId());
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@Api(value = "/entry")
|
@Api(value = "/entry")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EntryREST {
|
public class EntryREST {
|
||||||
|
|
||||||
@@ -47,7 +47,8 @@ public class EntryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||||
@Timed
|
@Timed
|
||||||
public Response markFeedEntry(@SecurityCheck User user, @ApiParam(value = "Mark Request", required = true) MarkRequest req) {
|
public Response markEntry(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "Mark Request", required = true) MarkRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -60,13 +61,13 @@ public class EntryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Mark multiple feed entries", notes = "Mark feed entries as read/unread")
|
@ApiOperation(value = "Mark multiple feed entries", notes = "Mark feed entries as read/unread")
|
||||||
@Timed
|
@Timed
|
||||||
public Response markFeedEntries(@SecurityCheck User user,
|
public Response markEntries(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
@ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
|
@ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getRequests());
|
Preconditions.checkNotNull(req.getRequests());
|
||||||
|
|
||||||
for (MarkRequest r : req.getRequests()) {
|
for (MarkRequest r : req.getRequests()) {
|
||||||
markFeedEntry(user, r);
|
markEntry(user, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
@@ -77,7 +78,8 @@ public class EntryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||||
@Timed
|
@Timed
|
||||||
public Response starFeedEntry(@SecurityCheck User user, @ApiParam(value = "Star Request", required = true) StarRequest req) {
|
public Response starEntry(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "Star Request", required = true) StarRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
Preconditions.checkNotNull(req.getFeedId());
|
Preconditions.checkNotNull(req.getFeedId());
|
||||||
@@ -92,7 +94,7 @@ public class EntryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get list of tags for the user", notes = "Get list of tags for the user")
|
@ApiOperation(value = "Get list of tags for the user", notes = "Get list of tags for the user")
|
||||||
@Timed
|
@Timed
|
||||||
public Response getTags(@SecurityCheck User user) {
|
public Response getTags(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
List<String> tags = feedEntryTagDAO.findByUser(user);
|
List<String> tags = feedEntryTagDAO.findByUser(user);
|
||||||
return Response.ok(tags).build();
|
return Response.ok(tags).build();
|
||||||
}
|
}
|
||||||
@@ -102,7 +104,8 @@ public class EntryREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||||
@Timed
|
@Timed
|
||||||
public Response tagFeedEntry(@SecurityCheck User user, @ApiParam(value = "Tag Request", required = true) TagRequest req) {
|
public Response tagEntry(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "Tag Request", required = true) TagRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getEntryId());
|
Preconditions.checkNotNull(req.getEntryId());
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FeedREST {
|
public class FeedREST {
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get feed entries", notes = "Get a list of feed entries", response = Entries.class)
|
@ApiOperation(value = "Get feed entries", notes = "Get a list of feed entries", response = Entries.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getFeedEntries(@SecurityCheck User user,
|
public Response getFeedEntries(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
|
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "all entries or only unread ones",
|
value = "all entries or only unread ones",
|
||||||
@@ -141,7 +141,9 @@ public class FeedREST {
|
|||||||
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
|
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
|
||||||
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
|
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
|
||||||
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
|
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
|
||||||
@ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
|
@ApiParam(
|
||||||
|
value = "ordering",
|
||||||
|
allowableValues = "asc,desc,abc,zyx") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
|
||||||
@ApiParam(
|
@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,
|
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 = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds) {
|
||||||
@@ -200,7 +202,7 @@ public class FeedREST {
|
|||||||
@ApiOperation(value = "Get feed entries as a feed", notes = "Get a feed of feed entries")
|
@ApiOperation(value = "Get feed entries as a feed", notes = "Get a feed of feed entries")
|
||||||
@Produces(MediaType.APPLICATION_XML)
|
@Produces(MediaType.APPLICATION_XML)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getFeedEntriesAsFeed(@SecurityCheck(apiKeyAllowed = true) User user,
|
public Response getFeedEntriesAsFeed(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
|
||||||
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
|
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "all entries or only unread ones",
|
value = "all entries or only unread ones",
|
||||||
@@ -260,7 +262,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Fetch a feed", notes = "Fetch a feed by its url", response = FeedInfo.class)
|
@ApiOperation(value = "Fetch a feed", notes = "Fetch a feed by its url", response = FeedInfo.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response fetchFeed(@SecurityCheck User user, @ApiParam(value = "feed url", required = true) FeedInfoRequest req) {
|
public Response fetchFeed(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "feed url", required = true) FeedInfoRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getUrl());
|
Preconditions.checkNotNull(req.getUrl());
|
||||||
|
|
||||||
@@ -279,7 +282,7 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Queue all feeds of the user for refresh", notes = "Manually add all feeds of the user to the refresh queue")
|
@ApiOperation(value = "Queue all feeds of the user for refresh", notes = "Manually add all feeds of the user to the refresh queue")
|
||||||
@Timed
|
@Timed
|
||||||
public Response queueAllForRefresh(@SecurityCheck User user) {
|
public Response queueAllForRefresh(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
feedSubscriptionService.refreshAll(user);
|
feedSubscriptionService.refreshAll(user);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
@@ -289,7 +292,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Queue a feed for refresh", notes = "Manually add a feed to the refresh queue")
|
@ApiOperation(value = "Queue a feed for refresh", notes = "Manually add a feed to the refresh queue")
|
||||||
@Timed
|
@Timed
|
||||||
public Response queueForRefresh(@SecurityCheck User user, @ApiParam(value = "Feed id") IDRequest req) {
|
public Response queueForRefresh(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "Feed id", required = true) IDRequest req) {
|
||||||
|
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
@@ -308,7 +312,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Mark feed entries", notes = "Mark feed entries as read (unread is not supported)")
|
@ApiOperation(value = "Mark feed entries", notes = "Mark feed entries as read (unread is not supported)")
|
||||||
@Timed
|
@Timed
|
||||||
public Response markFeedEntries(@SecurityCheck User user, @ApiParam(value = "Mark request") MarkRequest req) {
|
public Response markFeedEntries(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "Mark request", required = true) MarkRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -326,9 +331,10 @@ public class FeedREST {
|
|||||||
@GET
|
@GET
|
||||||
@Path("/get/{id}")
|
@Path("/get/{id}")
|
||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "", notes = "")
|
@ApiOperation(value = "get feed", response = Subscription.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response get(@SecurityCheck User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
public Response getFeed(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
||||||
|
|
||||||
Preconditions.checkNotNull(id);
|
Preconditions.checkNotNull(id);
|
||||||
FeedSubscription sub = feedSubscriptionDAO.findById(user, id);
|
FeedSubscription sub = feedSubscriptionDAO.findById(user, id);
|
||||||
@@ -344,7 +350,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Fetch a feed's icon", notes = "Fetch a feed's icon")
|
@ApiOperation(value = "Fetch a feed's icon", notes = "Fetch a feed's icon")
|
||||||
@Timed
|
@Timed
|
||||||
public Response getFavicon(@SecurityCheck User user, @ApiParam(value = "subscription id") @PathParam("id") Long id) {
|
public Response getFeedFavicon(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "subscription id", required = true) @PathParam("id") Long id) {
|
||||||
|
|
||||||
Preconditions.checkNotNull(id);
|
Preconditions.checkNotNull(id);
|
||||||
FeedSubscription subscription = feedSubscriptionDAO.findById(user, id);
|
FeedSubscription subscription = feedSubscriptionDAO.findById(user, id);
|
||||||
@@ -374,7 +381,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
|
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
|
||||||
@Timed
|
@Timed
|
||||||
public Response subscribe(@SecurityCheck User user, @ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
|
public Response subscribe(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getTitle());
|
Preconditions.checkNotNull(req.getTitle());
|
||||||
Preconditions.checkNotNull(req.getUrl());
|
Preconditions.checkNotNull(req.getUrl());
|
||||||
@@ -401,7 +409,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
|
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
|
||||||
@Timed
|
@Timed
|
||||||
public Response subscribe(@SecurityCheck User user, @ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
|
public Response subscribeFromUrl(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Preconditions.checkNotNull(url);
|
Preconditions.checkNotNull(url);
|
||||||
@@ -429,7 +438,7 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Unsubscribe from a feed", notes = "Unsubscribe from a feed")
|
@ApiOperation(value = "Unsubscribe from a feed", notes = "Unsubscribe from a feed")
|
||||||
@Timed
|
@Timed
|
||||||
public Response unsubscribe(@SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
|
public Response unsubscribe(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -446,7 +455,8 @@ public class FeedREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Modify a subscription", notes = "Modify a feed subscription")
|
@ApiOperation(value = "Modify a subscription", notes = "Modify a feed subscription")
|
||||||
@Timed
|
@Timed
|
||||||
public Response modify(@SecurityCheck User user, @ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
|
public Response modifyFeed(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
|
||||||
Preconditions.checkNotNull(req);
|
Preconditions.checkNotNull(req);
|
||||||
Preconditions.checkNotNull(req.getId());
|
Preconditions.checkNotNull(req.getId());
|
||||||
|
|
||||||
@@ -506,7 +516,8 @@ public class FeedREST {
|
|||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@ApiOperation(value = "OPML import", notes = "Import an OPML file, posted as a FORM with the 'file' name")
|
@ApiOperation(value = "OPML import", notes = "Import an OPML file, posted as a FORM with the 'file' name")
|
||||||
@Timed
|
@Timed
|
||||||
public Response importOpml(@SecurityCheck User user, @FormDataParam("file") InputStream input) {
|
public Response importOpml(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "ompl file", required = true) @FormDataParam("file") InputStream input) {
|
||||||
|
|
||||||
String publicUrl = config.getApplicationSettings().getPublicUrl();
|
String publicUrl = config.getApplicationSettings().getPublicUrl();
|
||||||
if (StringUtils.isBlank(publicUrl)) {
|
if (StringUtils.isBlank(publicUrl)) {
|
||||||
@@ -533,7 +544,7 @@ public class FeedREST {
|
|||||||
@Produces(MediaType.APPLICATION_XML)
|
@Produces(MediaType.APPLICATION_XML)
|
||||||
@ApiOperation(value = "OPML export", notes = "Export an OPML file of the user's subscriptions")
|
@ApiOperation(value = "OPML export", notes = "Export an OPML file of the user's subscriptions")
|
||||||
@Timed
|
@Timed
|
||||||
public Response exportOpml(@SecurityCheck User user) {
|
public Response exportOpml(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
Opml opml = opmlExporter.export(user);
|
Opml opml = opmlExporter.export(user);
|
||||||
WireFeedOutput output = new WireFeedOutput();
|
WireFeedOutput output = new WireFeedOutput();
|
||||||
String opmlString = null;
|
String opmlString = null;
|
||||||
|
|||||||
@@ -25,13 +25,14 @@ import com.commafeed.frontend.model.ServerInfo;
|
|||||||
import io.dropwizard.hibernate.UnitOfWork;
|
import io.dropwizard.hibernate.UnitOfWork;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import io.swagger.annotations.ApiParam;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@Path("/server")
|
@Path("/server")
|
||||||
@Api(value = "/server")
|
@Api(value = "/server")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ServerREST {
|
public class ServerREST {
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ public class ServerREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Get server infos", notes = "Get server infos", response = ServerInfo.class)
|
@ApiOperation(value = "Get server infos", notes = "Get server infos", response = ServerInfo.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response get() {
|
public Response getServerInfos() {
|
||||||
ServerInfo infos = new ServerInfo();
|
ServerInfo infos = new ServerInfo();
|
||||||
infos.setAnnouncement(config.getApplicationSettings().getAnnouncement());
|
infos.setAnnouncement(config.getApplicationSettings().getAnnouncement());
|
||||||
infos.setVersion(config.getVersion());
|
infos.setVersion(config.getVersion());
|
||||||
@@ -60,7 +61,8 @@ public class ServerREST {
|
|||||||
@ApiOperation(value = "proxy image")
|
@ApiOperation(value = "proxy image")
|
||||||
@Produces("image/png")
|
@Produces("image/png")
|
||||||
@Timed
|
@Timed
|
||||||
public Response get(@SecurityCheck User user, @QueryParam("u") String url) {
|
public Response getProxiedImage(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(value = "image url", required = true) @QueryParam("u") String url) {
|
||||||
if (!config.getApplicationSettings().getImageProxyEnabled()) {
|
if (!config.getApplicationSettings().getImageProxyEnabled()) {
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
@Singleton
|
@Singleton
|
||||||
public class UserREST {
|
public class UserREST {
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Retrieve user settings", notes = "Retrieve user settings", response = Settings.class)
|
@ApiOperation(value = "Retrieve user settings", notes = "Retrieve user settings", response = Settings.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response getSettings(@SecurityCheck User user) {
|
public Response getUserSettings(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
UserSettings settings = userSettingsDAO.findByUser(user);
|
UserSettings settings = userSettingsDAO.findByUser(user);
|
||||||
if (settings != null) {
|
if (settings != null) {
|
||||||
@@ -138,7 +138,7 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Save user settings", notes = "Save user settings")
|
@ApiOperation(value = "Save user settings", notes = "Save user settings")
|
||||||
@Timed
|
@Timed
|
||||||
public Response saveSettings(@SecurityCheck User user, @ApiParam(required = true) Settings settings) {
|
public Response saveUserSettings(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) Settings settings) {
|
||||||
Preconditions.checkNotNull(settings);
|
Preconditions.checkNotNull(settings);
|
||||||
|
|
||||||
UserSettings s = userSettingsDAO.findByUser(user);
|
UserSettings s = userSettingsDAO.findByUser(user);
|
||||||
@@ -177,7 +177,7 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Retrieve user's profile", response = UserModel.class)
|
@ApiOperation(value = "Retrieve user's profile", response = UserModel.class)
|
||||||
@Timed
|
@Timed
|
||||||
public Response get(@SecurityCheck User user) {
|
public Response getUserProfile(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
UserModel userModel = new UserModel();
|
UserModel userModel = new UserModel();
|
||||||
userModel.setId(user.getId());
|
userModel.setId(user.getId());
|
||||||
userModel.setName(user.getName());
|
userModel.setName(user.getName());
|
||||||
@@ -197,7 +197,8 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Save user's profile")
|
@ApiOperation(value = "Save user's profile")
|
||||||
@Timed
|
@Timed
|
||||||
public Response save(@SecurityCheck User user, @ApiParam(required = true) ProfileModificationRequest request) {
|
public Response saveUserProfile(@ApiParam(hidden = true) @SecurityCheck User user,
|
||||||
|
@ApiParam(required = true) ProfileModificationRequest request) {
|
||||||
Preconditions.checkArgument(StringUtils.isBlank(request.getPassword()) || request.getPassword().length() >= 6);
|
Preconditions.checkArgument(StringUtils.isBlank(request.getPassword()) || request.getPassword().length() >= 6);
|
||||||
if (StringUtils.isNotBlank(request.getEmail())) {
|
if (StringUtils.isNotBlank(request.getEmail())) {
|
||||||
User u = userDAO.findByEmail(request.getEmail());
|
User u = userDAO.findByEmail(request.getEmail());
|
||||||
@@ -217,7 +218,7 @@ public class UserREST {
|
|||||||
if (request.isNewApiKey()) {
|
if (request.isNewApiKey()) {
|
||||||
user.setApiKey(userService.generateApiKey(user));
|
user.setApiKey(userService.generateApiKey(user));
|
||||||
}
|
}
|
||||||
userDAO.saveOrUpdate(user);
|
userDAO.update(user);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +227,8 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Register a new account")
|
@ApiOperation(value = "Register a new account")
|
||||||
@Timed
|
@Timed
|
||||||
public Response register(@Valid @ApiParam(required = true) RegistrationRequest req, @Context SessionHelper sessionHelper) {
|
public Response registerUser(@Valid @ApiParam(required = true) RegistrationRequest req,
|
||||||
|
@Context @ApiParam(hidden = true) SessionHelper sessionHelper) {
|
||||||
try {
|
try {
|
||||||
User registeredUser = userService.register(req.getName(), req.getPassword(), req.getEmail(), Arrays.asList(Role.USER));
|
User registeredUser = userService.register(req.getName(), req.getPassword(), req.getEmail(), Arrays.asList(Role.USER));
|
||||||
userService.login(req.getName(), req.getPassword());
|
userService.login(req.getName(), req.getPassword());
|
||||||
@@ -243,7 +245,7 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Login and create a session")
|
@ApiOperation(value = "Login and create a session")
|
||||||
@Timed
|
@Timed
|
||||||
public Response login(@ApiParam(required = true) LoginRequest req, @Context SessionHelper sessionHelper) {
|
public Response login(@ApiParam(required = true) LoginRequest req, @ApiParam(hidden = true) @Context SessionHelper sessionHelper) {
|
||||||
Optional<User> user = userService.login(req.getName(), req.getPassword());
|
Optional<User> user = userService.login(req.getName(), req.getPassword());
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
sessionHelper.setLoggedInUser(user.get());
|
sessionHelper.setLoggedInUser(user.get());
|
||||||
@@ -258,7 +260,7 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "send a password reset email")
|
@ApiOperation(value = "send a password reset email")
|
||||||
@Timed
|
@Timed
|
||||||
public Response sendPasswordReset(@Valid PasswordResetRequest req) {
|
public Response sendPasswordReset(@Valid @ApiParam(required = true) PasswordResetRequest req) {
|
||||||
User user = userDAO.findByEmail(req.getEmail());
|
User user = userDAO.findByEmail(req.getEmail());
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return Response.status(Status.PRECONDITION_FAILED).entity("Email not found.").type(MediaType.TEXT_PLAIN).build();
|
return Response.status(Status.PRECONDITION_FAILED).entity("Email not found.").type(MediaType.TEXT_PLAIN).build();
|
||||||
@@ -294,7 +296,8 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@Produces(MediaType.TEXT_HTML)
|
@Produces(MediaType.TEXT_HTML)
|
||||||
@Timed
|
@Timed
|
||||||
public Response passwordRecoveryCallback(@QueryParam("email") String email, @QueryParam("token") String token) {
|
public Response passwordRecoveryCallback(@ApiParam(required = true) @QueryParam("email") String email,
|
||||||
|
@ApiParam(required = true) @QueryParam("token") String token) {
|
||||||
Preconditions.checkNotNull(email);
|
Preconditions.checkNotNull(email);
|
||||||
Preconditions.checkNotNull(token);
|
Preconditions.checkNotNull(token);
|
||||||
|
|
||||||
@@ -330,7 +333,7 @@ public class UserREST {
|
|||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
@ApiOperation(value = "Delete the user account")
|
@ApiOperation(value = "Delete the user account")
|
||||||
@Timed
|
@Timed
|
||||||
public Response delete(@SecurityCheck User user) {
|
public Response deleteUser(@ApiParam(hidden = true) @SecurityCheck User user) {
|
||||||
if (CommaFeedApplication.USERNAME_ADMIN.equals(user.getName()) || CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
|
if (CommaFeedApplication.USERNAME_ADMIN.equals(user.getName()) || CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,18 @@ public class NextUnreadServlet extends HttpServlet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ReadingOrder order = StringUtils.equals(orderParam, "asc") ? ReadingOrder.asc : ReadingOrder.desc;
|
final ReadingOrder order = (StringUtils.equals(orderParam, "asc") ?
|
||||||
|
ReadingOrder.asc :
|
||||||
|
(
|
||||||
|
StringUtils.equals(orderParam, "desc") ?
|
||||||
|
ReadingOrder.desc :
|
||||||
|
(
|
||||||
|
StringUtils.equals(orderParam, "abc") ?
|
||||||
|
ReadingOrder.abc :
|
||||||
|
(ReadingOrder.zyx)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
FeedEntryStatus status = UnitOfWork.call(sessionFactory, () -> {
|
FeedEntryStatus status = UnitOfWork.call(sessionFactory, () -> {
|
||||||
FeedEntryStatus s = null;
|
FeedEntryStatus s = null;
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.commafeed.frontend.session;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.servlet.SessionTrackingMode;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.session.DefaultSessionCache;
|
||||||
|
import org.eclipse.jetty.server.session.FileSessionDataStore;
|
||||||
|
import org.eclipse.jetty.server.session.SessionCache;
|
||||||
|
import org.eclipse.jetty.server.session.SessionHandler;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import io.dropwizard.util.Duration;
|
||||||
|
|
||||||
|
public class SessionHandlerFactory {
|
||||||
|
|
||||||
|
private String path = "sessions";
|
||||||
|
private Duration cookieMaxAge = Duration.days(30);
|
||||||
|
private Duration cookieRefreshAge = Duration.days(1);
|
||||||
|
private Duration maxInactiveInterval = Duration.days(30);
|
||||||
|
private Duration savePeriod = Duration.minutes(5);
|
||||||
|
|
||||||
|
public SessionHandler build() {
|
||||||
|
SessionHandler sessionHandler = new SessionHandler() {
|
||||||
|
{
|
||||||
|
// no setter available for maxCookieAge
|
||||||
|
_maxCookieAge = (int) cookieMaxAge.toSeconds();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SessionCache sessionCache = new DefaultSessionCache(sessionHandler);
|
||||||
|
sessionHandler.setSessionCache(sessionCache);
|
||||||
|
FileSessionDataStore dataStore = new FileSessionDataStore();
|
||||||
|
sessionCache.setSessionDataStore(dataStore);
|
||||||
|
|
||||||
|
sessionHandler.setHttpOnly(true);
|
||||||
|
sessionHandler.setSessionTrackingModes(ImmutableSet.of(SessionTrackingMode.COOKIE));
|
||||||
|
sessionHandler.setMaxInactiveInterval((int) maxInactiveInterval.toSeconds());
|
||||||
|
sessionHandler.setRefreshCookieAge((int) cookieRefreshAge.toSeconds());
|
||||||
|
|
||||||
|
dataStore.setDeleteUnrestorableFiles(true);
|
||||||
|
dataStore.setStoreDir(new File(path));
|
||||||
|
dataStore.setSavePeriodSec((int) savePeriod.toSeconds());
|
||||||
|
|
||||||
|
return sessionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package com.commafeed.frontend.session;
|
|
||||||
|
|
||||||
import io.dropwizard.util.Duration;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.SessionTrackingMode;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.SessionManager;
|
|
||||||
import org.eclipse.jetty.server.session.HashSessionManager;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class SessionManagerFactory {
|
|
||||||
|
|
||||||
private String path = "sessions";
|
|
||||||
private Duration cookieMaxAge = Duration.days(30);
|
|
||||||
private Duration cookieRefreshAge = Duration.days(1);
|
|
||||||
private Duration maxInactiveInterval = Duration.days(30);
|
|
||||||
private Duration idleSavePeriod = Duration.hours(2);
|
|
||||||
private Duration savePeriod = Duration.minutes(5);
|
|
||||||
private Duration scavengePeriod = Duration.minutes(5);
|
|
||||||
|
|
||||||
public SessionManager build() throws IOException {
|
|
||||||
HashSessionManager manager = new HashSessionManager();
|
|
||||||
manager.setSessionTrackingModes(ImmutableSet.of(SessionTrackingMode.COOKIE));
|
|
||||||
manager.setHttpOnly(true);
|
|
||||||
manager.getSessionCookieConfig().setHttpOnly(true);
|
|
||||||
manager.setDeleteUnrestorableSessions(true);
|
|
||||||
|
|
||||||
manager.setStoreDirectory(new File(getPath()));
|
|
||||||
manager.getSessionCookieConfig().setMaxAge((int) cookieMaxAge.toSeconds());
|
|
||||||
manager.setRefreshCookieAge((int) cookieRefreshAge.toSeconds());
|
|
||||||
manager.setMaxInactiveInterval((int) maxInactiveInterval.toSeconds());
|
|
||||||
manager.setIdleSavePeriod((int) idleSavePeriod.toSeconds());
|
|
||||||
manager.setSavePeriod((int) savePeriod.toSeconds());
|
|
||||||
manager.setScavengePeriod((int) scavengePeriod.toSeconds());
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
<changeSet author="athou" id="create-app-settings">
|
<changeSet author="athou" id="create-app-settings">
|
||||||
<validCheckSum>7:6d3ad493d25dd9c50067e804efc9ffcc</validCheckSum>
|
<validCheckSum>7:6d3ad493d25dd9c50067e804efc9ffcc</validCheckSum>
|
||||||
<validCheckSum>7:896a68c1651397288c40f717ce0397b4</validCheckSum>
|
<validCheckSum>7:896a68c1651397288c40f717ce0397b4</validCheckSum>
|
||||||
|
<validCheckSum>8:1b0879c4739d483c3b1d779e08fe770b</validCheckSum>
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
||||||
<not>
|
<not>
|
||||||
<tableExists tableName="APPLICATIONSETTINGS" />
|
<tableExists tableName="APPLICATIONSETTINGS" />
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
<column name="id" type="BIGINT">
|
<column name="id" type="BIGINT">
|
||||||
<constraints nullable="false" primaryKey="true" />
|
<constraints nullable="false" primaryKey="true" />
|
||||||
</column>
|
</column>
|
||||||
<column name="allowRegistrations" type="BIT">
|
<column name="allowRegistrations" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="backgroundThreads" type="INT">
|
<column name="backgroundThreads" type="INT">
|
||||||
@@ -29,20 +30,20 @@
|
|||||||
<column name="smtpPort" type="INT">
|
<column name="smtpPort" type="INT">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="smtpTls" type="BIT">
|
<column name="smtpTls" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="smtpUserName" type="VARCHAR(255)" />
|
<column name="smtpUserName" type="VARCHAR(255)" />
|
||||||
<column name="googleAnalyticsDomainName" type="VARCHAR(255)" />
|
<column name="googleAnalyticsDomainName" type="VARCHAR(255)" />
|
||||||
<column name="googleAnalyticsTrackingCode" type="VARCHAR(255)" />
|
<column name="googleAnalyticsTrackingCode" type="VARCHAR(255)" />
|
||||||
<column name="announcement" type="VARCHAR(255)" />
|
<column name="announcement" type="VARCHAR(255)" />
|
||||||
<column name="feedbackButton" type="BIT">
|
<column name="feedbackButton" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="heavyLoad" type="BIT">
|
<column name="heavyLoad" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="pubsubhubbub" type="BIT">
|
<column name="pubsubhubbub" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="databaseUpdateThreads" type="INT">
|
<column name="databaseUpdateThreads" type="INT">
|
||||||
@@ -79,6 +80,7 @@
|
|||||||
<changeSet author="athou" id="create-cat">
|
<changeSet author="athou" id="create-cat">
|
||||||
<validCheckSum>7:93155e15f0feabe936e1de35711bf85b</validCheckSum>
|
<validCheckSum>7:93155e15f0feabe936e1de35711bf85b</validCheckSum>
|
||||||
<validCheckSum>7:c52f258e54d34156208cbfd2d8547fbd</validCheckSum>
|
<validCheckSum>7:c52f258e54d34156208cbfd2d8547fbd</validCheckSum>
|
||||||
|
<validCheckSum>8:c59e763e4cc7d59ae58d843937cf4e77</validCheckSum>
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
||||||
<not>
|
<not>
|
||||||
<tableExists tableName="FEEDCATEGORIES" />
|
<tableExists tableName="FEEDCATEGORIES" />
|
||||||
@@ -88,7 +90,7 @@
|
|||||||
<column name="id" type="BIGINT">
|
<column name="id" type="BIGINT">
|
||||||
<constraints nullable="false" primaryKey="true" />
|
<constraints nullable="false" primaryKey="true" />
|
||||||
</column>
|
</column>
|
||||||
<column name="collapsed" type="BIT">
|
<column name="collapsed" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="name" type="VARCHAR(128)">
|
<column name="name" type="VARCHAR(128)">
|
||||||
@@ -160,6 +162,7 @@
|
|||||||
<changeSet author="athou" id="create-statuses">
|
<changeSet author="athou" id="create-statuses">
|
||||||
<validCheckSum>7:a9cf194a01c16b937a897aea934f09ae</validCheckSum>
|
<validCheckSum>7:a9cf194a01c16b937a897aea934f09ae</validCheckSum>
|
||||||
<validCheckSum>7:6a386e0b08e98bdba9ce55e26ab90eba</validCheckSum>
|
<validCheckSum>7:6a386e0b08e98bdba9ce55e26ab90eba</validCheckSum>
|
||||||
|
<validCheckSum>8:ccfbff3df6f16c8686229c2da514e8b1</validCheckSum>
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
||||||
<not>
|
<not>
|
||||||
<tableExists tableName="FEEDENTRYSTATUSES" />
|
<tableExists tableName="FEEDENTRYSTATUSES" />
|
||||||
@@ -169,8 +172,8 @@
|
|||||||
<column name="id" type="BIGINT">
|
<column name="id" type="BIGINT">
|
||||||
<constraints nullable="false" primaryKey="true" />
|
<constraints nullable="false" primaryKey="true" />
|
||||||
</column>
|
</column>
|
||||||
<column name="read_status" type="BIT" />
|
<column name="read_status" type="BOOLEAN" />
|
||||||
<column name="starred" type="BIT">
|
<column name="starred" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="entry_id" type="BIGINT">
|
<column name="entry_id" type="BIGINT">
|
||||||
@@ -298,6 +301,8 @@
|
|||||||
|
|
||||||
<changeSet author="athou" id="create-users">
|
<changeSet author="athou" id="create-users">
|
||||||
<validCheckSum>7:750e0990a8edebd0252df7d4adc7aa7c</validCheckSum>
|
<validCheckSum>7:750e0990a8edebd0252df7d4adc7aa7c</validCheckSum>
|
||||||
|
<validCheckSum>8:dd1676f356c3c70822d69d5103947948</validCheckSum>
|
||||||
|
<validCheckSum>8:ca2d6edef0263a78cab9cc0942972d50</validCheckSum>
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
||||||
<not>
|
<not>
|
||||||
<tableExists tableName="USERS" />
|
<tableExists tableName="USERS" />
|
||||||
@@ -307,17 +312,17 @@
|
|||||||
<column name="id" type="BIGINT">
|
<column name="id" type="BIGINT">
|
||||||
<constraints nullable="false" primaryKey="true" />
|
<constraints nullable="false" primaryKey="true" />
|
||||||
</column>
|
</column>
|
||||||
<column name="disabled" type="BIT">
|
<column name="disabled" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="email" type="VARCHAR(255)" />
|
<column name="email" type="VARCHAR(255)" />
|
||||||
<column name="name" type="VARCHAR(32)">
|
<column name="name" type="VARCHAR(32)">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="password" type="BLOB">
|
<column name="password" type="${blob_type}">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="salt" type="BLOB">
|
<column name="salt" type="${blob_type}">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="lastLogin" type="DATETIME" />
|
<column name="lastLogin" type="DATETIME" />
|
||||||
@@ -333,6 +338,7 @@
|
|||||||
<changeSet author="athou" id="create-user-settings">
|
<changeSet author="athou" id="create-user-settings">
|
||||||
<validCheckSum>7:985d6607a4350e032ea345d9a2f2f0c0</validCheckSum>
|
<validCheckSum>7:985d6607a4350e032ea345d9a2f2f0c0</validCheckSum>
|
||||||
<validCheckSum>7:722eaff49d04d43c5b26da0929d3f707</validCheckSum>
|
<validCheckSum>7:722eaff49d04d43c5b26da0929d3f707</validCheckSum>
|
||||||
|
<validCheckSum>8:451004f3bc72abac6a38d813881d3a87</validCheckSum>
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
<preConditions onFail="MARK_RAN" onFailMessage="existing table skipping">
|
||||||
<not>
|
<not>
|
||||||
<tableExists tableName="USERSETTINGS" />
|
<tableExists tableName="USERSETTINGS" />
|
||||||
@@ -349,16 +355,16 @@
|
|||||||
<column name="readingOrder" type="VARCHAR(255)">
|
<column name="readingOrder" type="VARCHAR(255)">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="showRead" type="BIT">
|
<column name="showRead" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="user_id" type="BIGINT">
|
<column name="user_id" type="BIGINT">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="socialButtons" type="BIT">
|
<column name="socialButtons" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="scrollMarks" type="BIT">
|
<column name="scrollMarks" type="BOOLEAN">
|
||||||
<constraints nullable="false" />
|
<constraints nullable="false" />
|
||||||
</column>
|
</column>
|
||||||
<column name="viewMode" type="VARCHAR(255)">
|
<column name="viewMode" type="VARCHAR(255)">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<column name="read_status" />
|
<column name="read_status" />
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="drop-fes-index">
|
<changeSet author="athou" id="drop-fes-index">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="index not found, skip drop index">
|
<preConditions onFail="MARK_RAN" onFailMessage="index not found, skip drop index">
|
||||||
<indexExists tableName="FEEDENTRYSTATUSES" indexName="subscription_id" />
|
<indexExists tableName="FEEDENTRYSTATUSES" indexName="subscription_id" />
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
<column name="logLevel" type="VARCHAR(255)" />
|
<column name="logLevel" type="VARCHAR(255)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-push-hub">
|
<changeSet author="athou" id="add-push-hub">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
<column name="pushHub" type="VARCHAR(2048)" />
|
<column name="pushHub" type="VARCHAR(2048)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-push-topic">
|
<changeSet author="athou" id="add-push-topic">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
<column name="pushTopic" type="VARCHAR(2048)" />
|
<column name="pushTopic" type="VARCHAR(2048)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-push-lastping">
|
<changeSet author="athou" id="add-push-lastping">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
<column name="pushLastPing" type="DATETIME" />
|
<column name="pushLastPing" type="DATETIME" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-lastpublished">
|
<changeSet author="athou" id="add-lastpublished">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -113,8 +113,8 @@
|
|||||||
<addColumn tableName="FEEDS">
|
<addColumn tableName="FEEDS">
|
||||||
<column name="lastPublishedDate" type="DATETIME" />
|
<column name="lastPublishedDate" type="DATETIME" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-lastcontenthash">
|
<changeSet author="athou" id="add-lastcontenthash">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -125,8 +125,8 @@
|
|||||||
<addColumn tableName="FEEDS">
|
<addColumn tableName="FEEDS">
|
||||||
<column name="lastContentHash" type="VARCHAR(40)" />
|
<column name="lastContentHash" type="VARCHAR(40)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-lastinterval">
|
<changeSet author="athou" id="add-lastinterval">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -137,8 +137,8 @@
|
|||||||
<addColumn tableName="FEEDS">
|
<addColumn tableName="FEEDS">
|
||||||
<column name="averageEntryInterval" type="BIGINT" />
|
<column name="averageEntryInterval" type="BIGINT" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-lastentrydate">
|
<changeSet author="athou" id="add-lastentrydate">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
<column name="lastEntryDate" type="DATETIME" />
|
<column name="lastEntryDate" type="DATETIME" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-cat-position">
|
<changeSet author="athou" id="add-cat-position">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
<column name="position" type="INT" />
|
<column name="position" type="INT" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-sub-position">
|
<changeSet author="athou" id="add-sub-position">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
<preConditions onFail="MARK_RAN" onFailMessage="column already exists">
|
||||||
<not>
|
<not>
|
||||||
@@ -174,26 +174,26 @@
|
|||||||
<column name="position" type="INT" />
|
<column name="position" type="INT" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="drop-sequence">
|
<changeSet author="athou" id="drop-sequence">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="table does not exist">
|
<preConditions onFail="MARK_RAN" onFailMessage="table does not exist">
|
||||||
<tableExists tableName="hibernate_sequence" />
|
<tableExists tableName="hibernate_sequence" />
|
||||||
</preConditions>
|
</preConditions>
|
||||||
<dropTable tableName="hibernate_sequence" />
|
<dropTable tableName="hibernate_sequence" />
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="drop-old-pushinfos">
|
<changeSet author="athou" id="drop-old-pushinfos">
|
||||||
<preConditions onFail="MARK_RAN" onFailMessage="table does not exist">
|
<preConditions onFail="MARK_RAN" onFailMessage="table does not exist">
|
||||||
<tableExists tableName="FEEDPUSHINFOS" />
|
<tableExists tableName="FEEDPUSHINFOS" />
|
||||||
</preConditions>
|
</preConditions>
|
||||||
<dropTable tableName="FEEDPUSHINFOS" />
|
<dropTable tableName="FEEDPUSHINFOS" />
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-topic-hash">
|
<changeSet author="athou" id="add-topic-hash">
|
||||||
<addColumn tableName="FEEDS">
|
<addColumn tableName="FEEDS">
|
||||||
<column name="push_topic_hash" type="VARCHAR(40)" />
|
<column name="push_topic_hash" type="VARCHAR(40)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
|
|
||||||
<createIndex tableName="FEEDS" indexName="push_topic_hash_index">
|
<createIndex tableName="FEEDS" indexName="push_topic_hash_index">
|
||||||
<column name="push_topic_hash"></column>
|
<column name="push_topic_hash"></column>
|
||||||
</createIndex>
|
</createIndex>
|
||||||
@@ -203,83 +203,85 @@
|
|||||||
<addColumn tableName="FEEDENTRIES">
|
<addColumn tableName="FEEDENTRIES">
|
||||||
<column name="author" type="VARCHAR(128)" />
|
<column name="author" type="VARCHAR(128)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-inserted-index">
|
<changeSet author="athou" id="add-inserted-index">
|
||||||
<createIndex tableName="FEEDENTRIES" indexName="inserted_index">
|
<createIndex tableName="FEEDENTRIES" indexName="inserted_index">
|
||||||
<column name="inserted"></column>
|
<column name="inserted"></column>
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="rename-lang">
|
<changeSet author="athou" id="rename-lang">
|
||||||
<renameColumn tableName="USERSETTINGS" oldColumnName="language" newColumnName="user_lang" columnDataType="VARCHAR(4)" />
|
<renameColumn tableName="USERSETTINGS" oldColumnName="language" newColumnName="user_lang" columnDataType="VARCHAR(4)" />
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="norwegian-migration">
|
<changeSet author="athou" id="norwegian-migration">
|
||||||
<sql>update USERSETTINGS set user_lang='nb' where user_lang='no'</sql>
|
<sql>update USERSETTINGS set user_lang='nb' where user_lang='no'</sql>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-user-created">
|
<changeSet author="athou" id="add-user-created">
|
||||||
<validCheckSum>3:b1bbf8d559ac25b785751704f2d24a91</validCheckSum>
|
<validCheckSum>3:b1bbf8d559ac25b785751704f2d24a91</validCheckSum>
|
||||||
<validCheckSum>7:5bd8b28aadce012b56f003539ce99957</validCheckSum>
|
<validCheckSum>7:5bd8b28aadce012b56f003539ce99957</validCheckSum>
|
||||||
<addColumn tableName="USERS">
|
<addColumn tableName="USERS">
|
||||||
<column name="created" type="DATETIME" />
|
<column name="created" type="DATETIME" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-proxy-setting">
|
<changeSet author="athou" id="add-proxy-setting">
|
||||||
<validCheckSum>7:ffca06665d2dc182bd3cb718e62e98f0</validCheckSum>
|
<validCheckSum>7:ffca06665d2dc182bd3cb718e62e98f0</validCheckSum>
|
||||||
|
<validCheckSum>8:a1b2bfccb0b37fec8eb107220f76e3bd</validCheckSum>
|
||||||
<addColumn tableName="APPLICATIONSETTINGS">
|
<addColumn tableName="APPLICATIONSETTINGS">
|
||||||
<column name="imageProxyEnabled" type="BIT" />
|
<column name="imageProxyEnabled" type="BOOLEAN" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<update tableName="APPLICATIONSETTINGS">
|
<update tableName="APPLICATIONSETTINGS">
|
||||||
<column name="imageProxyEnabled" valueBoolean="false"></column>
|
<column name="imageProxyEnabled" valueBoolean="false"></column>
|
||||||
</update>
|
</update>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-query-timeout-setting">
|
<changeSet author="athou" id="add-query-timeout-setting">
|
||||||
<addColumn tableName="APPLICATIONSETTINGS">
|
<addColumn tableName="APPLICATIONSETTINGS">
|
||||||
<column name="queryTimeout" type="INT" />
|
<column name="queryTimeout" type="INT" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<update tableName="APPLICATIONSETTINGS">
|
<update tableName="APPLICATIONSETTINGS">
|
||||||
<column name="queryTimeout" valueNumeric="0"></column>
|
<column name="queryTimeout" valueNumeric="0"></column>
|
||||||
</update>
|
</update>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-normalized-url">
|
<changeSet author="athou" id="add-normalized-url">
|
||||||
<addColumn tableName="FEEDS">
|
<addColumn tableName="FEEDS">
|
||||||
<column name="normalizedUrl" type="VARCHAR(2048)" />
|
<column name="normalizedUrl" type="VARCHAR(2048)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="FEEDS">
|
<addColumn tableName="FEEDS">
|
||||||
<column name="normalizedUrlHash" type="VARCHAR(40)" />
|
<column name="normalizedUrlHash" type="VARCHAR(40)" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<createIndex indexName="norm_url_hash_index" tableName="FEEDS"
|
<createIndex indexName="norm_url_hash_index" tableName="FEEDS"
|
||||||
unique="false">
|
unique="false">
|
||||||
<column name="normalizedUrlHash" />
|
<column name="normalizedUrlHash" />
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-pause-crawling">
|
<changeSet author="athou" id="add-pause-crawling">
|
||||||
|
<validCheckSum>8:4473505a94945268fcca0f2d77e4be4a</validCheckSum>
|
||||||
<addColumn tableName="APPLICATIONSETTINGS">
|
<addColumn tableName="APPLICATIONSETTINGS">
|
||||||
<column name="crawlingPaused" type="BIT" />
|
<column name="crawlingPaused" type="BOOLEAN" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<update tableName="APPLICATIONSETTINGS">
|
<update tableName="APPLICATIONSETTINGS">
|
||||||
<column name="crawlingPaused" valueBoolean="false"></column>
|
<column name="crawlingPaused" valueBoolean="false"></column>
|
||||||
</update>
|
</update>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-content-hash-index">
|
<changeSet author="athou" id="add-content-hash-index">
|
||||||
<createIndex tableName="FEEDS" indexName="last_content_hash_index">
|
<createIndex tableName="FEEDS" indexName="last_content_hash_index">
|
||||||
<column name="lastContentHash"></column>
|
<column name="lastContentHash"></column>
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="create-settings-index">
|
<changeSet author="athou" id="create-settings-index">
|
||||||
<createIndex tableName="USERSETTINGS" indexName="user_id_index" unique="true">
|
<createIndex tableName="USERSETTINGS" indexName="user_id_index" unique="true">
|
||||||
<column name="user_id"></column>
|
<column name="user_id"></column>
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="denormalize-statuses">
|
<changeSet author="athou" id="denormalize-statuses">
|
||||||
<validCheckSum>7:c73f70fbcbc8bb30f9629028ec8ddb06</validCheckSum>
|
<validCheckSum>7:c73f70fbcbc8bb30f9629028ec8ddb06</validCheckSum>
|
||||||
<addColumn tableName="FEEDENTRYSTATUSES">
|
<addColumn tableName="FEEDENTRYSTATUSES">
|
||||||
@@ -290,18 +292,18 @@
|
|||||||
<column name="entryUpdated" type="DATETIME" />
|
<column name="entryUpdated" type="DATETIME" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="populate-status-dates">
|
<changeSet author="athou" id="populate-status-dates">
|
||||||
<validCheckSum>7:d6b5ab6920948b0a84e614870128e2f5</validCheckSum>
|
<validCheckSum>7:d6b5ab6920948b0a84e614870128e2f5</validCheckSum>
|
||||||
<sql>update FEEDENTRYSTATUSES SET entryUpdated = (select e.updated from FEEDENTRIES e where e.id = FEEDENTRYSTATUSES.entry_id)</sql>
|
<sql>update FEEDENTRYSTATUSES SET entryUpdated = (select e.updated from FEEDENTRIES e where e.id = FEEDENTRYSTATUSES.entry_id)</sql>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="populate-status-users">
|
<changeSet author="athou" id="populate-status-users">
|
||||||
<validCheckSum>7:4227fdf2e7b9fe8e59544d536a7ee963</validCheckSum>
|
<validCheckSum>7:4227fdf2e7b9fe8e59544d536a7ee963</validCheckSum>
|
||||||
<sql>update FEEDENTRYSTATUSES SET user_id = (select sub.user_id from FEEDSUBSCRIPTIONS sub where sub.id = FEEDENTRYSTATUSES.subscription_id)</sql>
|
<sql>update FEEDENTRYSTATUSES SET user_id = (select sub.user_id from FEEDSUBSCRIPTIONS sub where sub.id = FEEDENTRYSTATUSES.subscription_id)</sql>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="recreate-fes-index-2">
|
<changeSet author="athou" id="recreate-fes-index-2">
|
||||||
<createIndex indexName="sub_entry_index" tableName="FEEDENTRYSTATUSES">
|
<createIndex indexName="sub_entry_index" tableName="FEEDENTRYSTATUSES">
|
||||||
<column name="subscription_id" />
|
<column name="subscription_id" />
|
||||||
<column name="entry_id" />
|
<column name="entry_id" />
|
||||||
@@ -317,28 +319,28 @@
|
|||||||
<column name="entryUpdated" />
|
<column name="entryUpdated" />
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="drop-fes-index-2">
|
<changeSet author="athou" id="drop-fes-index-2">
|
||||||
<dropIndex tableName="FEEDENTRYSTATUSES" indexName="sub_entry_read_index" />
|
<dropIndex tableName="FEEDENTRYSTATUSES" indexName="sub_entry_read_index" />
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-entry-updated-to-ffe">
|
<changeSet author="athou" id="add-entry-updated-to-ffe">
|
||||||
<addColumn tableName="FEED_FEEDENTRIES">
|
<addColumn tableName="FEED_FEEDENTRIES">
|
||||||
<column name="entryUpdated" type="DATETIME"></column>
|
<column name="entryUpdated" type="DATETIME"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="populate-entry-dates">
|
<changeSet author="athou" id="populate-entry-dates">
|
||||||
<sql>update FEED_FEEDENTRIES SET entryUpdated = (select e.updated from FEEDENTRIES e where e.id = FEED_FEEDENTRIES.feedentry_id)</sql>
|
<sql>update FEED_FEEDENTRIES SET entryUpdated = (select e.updated from FEEDENTRIES e where e.id = FEED_FEEDENTRIES.feedentry_id)</sql>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="create-ffe-entry-updated-index">
|
<changeSet author="athou" id="create-ffe-entry-updated-index">
|
||||||
<createIndex tableName="FEED_FEEDENTRIES" indexName="feed_updated_index">
|
<createIndex tableName="FEED_FEEDENTRIES" indexName="feed_updated_index">
|
||||||
<column name="FEED_ID"></column>
|
<column name="FEED_ID"></column>
|
||||||
<column name="entryUpdated"></column>
|
<column name="entryUpdated"></column>
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="create-count-index">
|
<changeSet author="athou" id="create-count-index">
|
||||||
<createIndex indexName="user_read_sub_index" tableName="FEEDENTRYSTATUSES">
|
<createIndex indexName="user_read_sub_index" tableName="FEEDENTRYSTATUSES">
|
||||||
<column name="user_id" />
|
<column name="user_id" />
|
||||||
@@ -346,21 +348,21 @@
|
|||||||
<column name="subscription_id" />
|
<column name="subscription_id" />
|
||||||
</createIndex>
|
</createIndex>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="add-trim-status-setting">
|
<changeSet author="athou" id="add-trim-status-setting">
|
||||||
<addColumn tableName="APPLICATIONSETTINGS">
|
<addColumn tableName="APPLICATIONSETTINGS">
|
||||||
<column name="keepStatusDays" type="INT" />
|
<column name="keepStatusDays" type="INT" />
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<update tableName="APPLICATIONSETTINGS">
|
<update tableName="APPLICATIONSETTINGS">
|
||||||
<column name="keepStatusDays" valueNumeric="0"></column>
|
<column name="keepStatusDays" valueNumeric="0"></column>
|
||||||
</update>
|
</update>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="athou" id="status-cleanup">
|
<changeSet author="athou" id="status-cleanup">
|
||||||
<validCheckSum>7:cf40ae235c2d4086c5fa6ac64102c6a9</validCheckSum>
|
<validCheckSum>7:cf40ae235c2d4086c5fa6ac64102c6a9</validCheckSum>
|
||||||
<delete tableName="FEEDENTRYSTATUSES">
|
<delete tableName="FEEDENTRYSTATUSES">
|
||||||
<where>read_status = false and starred = false</where>
|
<where>read_status = false and starred = false</where>
|
||||||
</delete>
|
</delete>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
@@ -3,35 +3,36 @@
|
|||||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
|
|
||||||
<changeSet id="add-detailed-social-options" author="athou">
|
<changeSet id="add-detailed-social-options" author="athou">
|
||||||
|
<validCheckSum>8:58e8060bba0ec9d448f4346eb35d815c</validCheckSum>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="email" type="BIT"></column>
|
<column name="email" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="gmail" type="BIT"></column>
|
<column name="gmail" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="facebook" type="BIT"></column>
|
<column name="facebook" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="twitter" type="BIT"></column>
|
<column name="twitter" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="googleplus" type="BIT"></column>
|
<column name="googleplus" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="tumblr" type="BIT"></column>
|
<column name="tumblr" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="pocket" type="BIT"></column>
|
<column name="pocket" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="instapaper" type="BIT"></column>
|
<column name="instapaper" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="buffer" type="BIT"></column>
|
<column name="buffer" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USERSETTINGS">
|
<addColumn tableName="USERSETTINGS">
|
||||||
<column name="readability" type="BIT"></column>
|
<column name="readability" type="BOOLEAN"></column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
|
|
||||||
<dropColumn tableName="USERSETTINGS" columnName="socialButtons" />
|
<dropColumn tableName="USERSETTINGS" columnName="socialButtons" />
|
||||||
@@ -49,7 +50,7 @@
|
|||||||
<column name="readability" valueBoolean="true"></column>
|
<column name="readability" valueBoolean="true"></column>
|
||||||
</update>
|
</update>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet id="delete-settings" author="athou">
|
<changeSet id="delete-settings" author="athou">
|
||||||
<dropTable tableName="APPLICATIONSETTINGS" />
|
<dropTable tableName="APPLICATIONSETTINGS" />
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user