removed wicket and tomee, use dropwizard instead. remove wro4j, use gulp instead

This commit is contained in:
Athou
2014-08-08 16:49:02 +02:00
parent bbcd79e49f
commit 986fd25942
357 changed files with 2178 additions and 19556 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

20
src/main/app/app-icon.svg Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg height="512" width="512" viewBox="0 0 6.5625 6.5625" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd">
<sodipodi:namedview guidetolerance="10">
<sodipodi:guide position="154.17325,117.15254" orientation="0,1"/>
<sodipodi:guide position="154.17325,166.44575" orientation="0,1"/>
<sodipodi:guide position="154.17325,288.40369" orientation="0,1"/>
<sodipodi:guide position="380.44742,392.71992" orientation="0,1"/>
<sodipodi:guide position="101.9661,166.44575" orientation="1,0"/>
<sodipodi:guide position="276.13119,288.40369" orientation="1,0"/>
<sodipodi:guide position="380.44742,165.67871" orientation="1,0"/>
<sodipodi:guide position="154.17325,288.40369" orientation="1,0"/>
<sodipodi:guide position="154.17325,166.44575" orientation="-0.70710678,0.70710678"/>
<sodipodi:guide position="123.21968,135.49218" orientation="1,0"/>
<sodipodi:guide position="123.21968,135.49218" orientation="0,1"/>
</sodipodi:namedview>
<rect fill="#f88a14" rx="0.7" ry="0.7" height="6.5625" width="6.5625"/>
<path d="m1.9761,1.5289c2.9002,0,2.9002,2.9101,2.9002,2.9101" fill="none" stroke="#FFF" stroke-linecap="round" stroke-width="0.78125"/>
<path d="m1.9688,2.875c1.5705-0.00908,1.5705,1.5639,1.5705,1.5639" fill="none" stroke="#FFF" stroke-linecap="round" stroke-width="0.78125"/>
<path d="m2.6503,4.4062c0,0.23366-0.10712,0.47418-0.24663,0.6537-0.1814,0.2333-0.5705,0.5618-0.6913,0.5653,0.0402-0.0662,0.263-0.5654,0.2563-0.5654-0.36423,0-0.6595-0.29265-0.6595-0.65365s0.29527-0.65365,0.6595-0.65365,0.68159,0.29265,0.68159,0.65365z" fill="#FFF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/main/app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

73
src/main/app/index.html Normal file
View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>CommaFeed</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
<link rel="apple-touch-icon" href="app-icon-57.png" />
<link rel="apple-touch-icon" sizes="72x72" href="app-icon-72.png" />
<link rel="apple-touch-icon" sizes="114x114" href="app-icon-114.png" />
<link rel="apple-touch-icon" sizes="144x144" href="app-icon-144.png" />
<link rel="icon" sizes="32x32" href="app-icon-32.png" />
<link rel="icon" sizes="64x64" href="app-icon-64.png" />
<link rel="icon" sizes="128x128" href="app-icon-128.png" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
<meta name="application-name" content="CommaFeed" />
<meta name="msapplication-navbutton-color" content="#F88A14" />
<meta name="msapplication-starturl" content="/" />
<meta name="msapplication-square70x70logo" content="metro-icon-70.png" />
<meta name="msapplication-square150x150logo" content="metro-icon-150.png" />
<link rel="fluid-icon" href="app-icon-512.png" title="CommaFeed" />
<link rel="logo" type="image/svg" href="app-icon.svg" />
<!-- build:css css/app.css -->
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="lib/font-awesome/css/font-awesome.css" />
<link rel="stylesheet" href="lib/select2/select2.css" />
<link rel="stylesheet" href="lib/ng-grid/ng-grid.css" />
<link rel="stylesheet" href="lib/jquery-ui/themes/smoothness/jquery-ui.css" />
<link rel="stylesheet" href="lib/angular-loading-bar/build/loading-bar.css" />
<link rel="stylesheet" href="css/app.css" />
<!-- endbuild -->
</head>
<body>
<div ng-app="commafeed" id="main" class="main">
<div ui-view></div>
</div>
<!-- build:js js/app.js -->
<script type="text/javascript" src="lib/lodash/dist/lodash.js"></script>
<script type="text/javascript" src="lib/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="lib/jquery-ui/jquery-ui.js"></script>
<script type="text/javascript" src="lib/jquery-mousewheel/jquery.mousewheel.js"></script>
<script type="text/javascript" src="lib/bootstrap/dist/js/bootstrap.js"></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angular-route/angular-route.js"></script>
<script type="text/javascript" src="lib/angular-resource/angular-resource.js"></script>
<script type="text/javascript" src="lib/angular-sanitize/angular-sanitize.js"></script>
<script type="text/javascript" src="lib/angular-touch/angular-touch.js"></script>
<script type="text/javascript" src="lib/angular-animate/angular-animate.js"></script>
<script type="text/javascript" src="lib/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script type="text/javascript" src="lib/angular-loading-bar/build/loading-bar.js"></script>
<script type="text/javascript" src="lib/ngInfiniteScroll/build/ng-infinite-scroll.js"></script>
<script type="text/javascript" src="lib/ng-grid/build/ng-grid.js"></script>
<script type="text/javascript" src="lib/angular-ui-router/release/angular-ui-router.js"></script>
<script type="text/javascript" src="lib/angular-ui-utils/ui-utils.js"></script>
<script type="text/javascript" src="lib/angular-ui-select2/src/select2.js"></script>
<script type="text/javascript" src="lib/select2/select2.js"></script>
<script type="text/javascript" src="lib/mousetrap/mousetrap.js"></script>
<script type="text/javascript" src="lib/momentjs/min/moment-with-langs.js"></script>
<script type="text/javascript" src="lib/device.js/lib/device.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/filters.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<script type="text/javascript" src="js/services.js"></script>
<script type="text/javascript" src="js/templates.js"></script>
<!-- endbuild -->
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,361 @@
var module = angular.module('commafeed.directives', []);
module.directive('focus', ['$timeout', function($timeout) {
return {
restrict : 'A',
link : function(scope, element, attrs) {
scope.$watch(attrs.focus, function(value) {
if (!value)
return;
$timeout(function() {
$(element).focus();
});
});
}
};
}]);
module.directive('confirmClick', [function() {
return {
priority : -1,
restrict : 'A',
link : function(scope, element, attrs) {
element.bind('click', function(e) {
var message = attrs.confirmClick;
if (message && !confirm(message)) {
e.stopImmediatePropagation();
e.preventDefault();
}
});
}
};
}]);
/**
* Open a popup window pointing to the url in the href attribute
*/
module.directive('popup', function() {
var opts = 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=800';
return {
link : function(scope, elm, attrs) {
elm.bind('click', function(event) {
window.open(this.href, '', opts);
event.preventDefault();
});
}
};
});
/**
* entry tag handling
*/
module.directive('tags', function() {
return {
restrict : 'E',
scope : {
entry : '='
},
replace : true,
templateUrl : 'templates/_tags.html',
controller : ['$scope', 'EntryService', function($scope, EntryService) {
$scope.select2Options = {
'multiple' : true,
'simple_tags' : true,
'maximumInputLength' : 40,
tags : EntryService.tags
};
$scope.$watch('entry.tags', function(newValue, oldValue) {
if (oldValue && newValue != oldValue) {
var data = {
entryId : $scope.entry.id,
tags : []
};
if (newValue) {
data.tags = newValue.split(',');
}
EntryService.tag(data);
}
}, true);
}]
};
});
/**
* Reusable favicon component
*/
module.directive('favicon', function() {
var tpl = '<img ng-src="{{url}}" class="favicon"></img>';
return {
restrict : 'E',
scope : {
url : '='
},
replace : true,
template : tpl
};
});
/**
* Support for the blur event
*/
module.directive('ngBlur', function() {
return {
restrict : 'A',
link : function(scope, elm, attrs) {
elm.bind('blur', function() {
scope.$apply(attrs.ngBlur);
});
}
};
});
/**
* Prevent mousewheel scrolling from propagating to the parent when scrollbar
* reaches top or bottom
*/
module.directive('mousewheelScrolling', function() {
return {
restrict : 'A',
link : function(scope, elem, attr) {
elem.bind('mousewheel', function(e, d) {
var t = $(this);
if (d > 0 && t.scrollTop() === 0) {
e.preventDefault();
} else {
if (d < 0 && (t.scrollTop() == t.get(0).scrollHeight - t.innerHeight())) {
e.preventDefault();
}
}
});
}
};
});
/**
* Needed to use recursive directives. Wrap a recursive element with a
* <recursive> tag
*/
module.directive('recursive', ['$compile', function($compile) {
return {
restrict : 'E',
priority : 100000,
compile : function(tElement, tAttr) {
var contents = tElement.contents().remove();
var compiledContents = null;
return function(scope, iElement, iAttr) {
if (!compiledContents) {
compiledContents = $compile(contents);
}
iElement.append(compiledContents(scope, function(clone) {
return clone;
}));
};
}
};
}]);
/**
* Reusable category component
*/
module.directive('category', [function() {
return {
scope : {
node : '=',
level : '=',
selectedType : '=',
selectedId : '=',
showLabel : '=',
showChildren : '=',
unreadCount : '&',
tag : '='
},
restrict : 'E',
replace : true,
templateUrl : 'templates/_category.html',
controller : ['$scope', '$state', 'FeedService', 'CategoryService', 'SettingsService', 'MobileService',
function($scope, $state, FeedService, CategoryService, SettingsService, MobileService) {
$scope.settingsService = SettingsService;
$scope.getClass = function(level) {
if ($scope.showLabel) {
return 'indent' + level;
}
};
$scope.categoryLabel = function(category) {
return $scope.showLabel !== true ? $scope.showLabel : category.name;
};
$scope.categoryCountLabel = function(category) {
var count = $scope.unreadCount({
category : category
});
var label = '';
if (count > 0) {
label = '(' + count + ')';
}
return label;
};
$scope.feedCountLabel = function(feed) {
var label = '';
if (feed.unread > 0) {
label = '(' + feed.unread + ')';
}
return label;
};
$scope.feedClicked = function(id, event) {
// Could be called by a middle click
if (!event || (!event.ctrlKey && event.which == 1)) {
MobileService.toggleLeftMenu();
if ($scope.selectedType == 'feed' && id == $scope.selectedId) {
$scope.$emit('emitReload');
} else {
$state.transitionTo('feeds.view', {
_type : 'feed',
_id : id
});
}
if (event) {
event.preventDefault();
event.stopPropagation();
}
}
};
$scope.categoryClicked = function(id, isTag) {
MobileService.toggleLeftMenu();
var type = isTag ? 'tag' : 'category';
if ($scope.selectedType == type && id == $scope.selectedId) {
$scope.$emit('emitReload');
} else {
$state.transitionTo('feeds.view', {
_type : type,
_id : id
});
}
};
$scope.showFeedDetails = function(feed) {
$state.transitionTo('feeds.feed_details', {
_id : feed.id
});
};
$scope.showCategoryDetails = function(id, isTag) {
if (isTag) {
$state.transitionTo('feeds.tag_details', {
_id : id
});
} else {
$state.transitionTo('feeds.category_details', {
_id : id
});
}
};
$scope.toggleCategory = function(category, event) {
event.preventDefault();
event.stopPropagation();
category.expanded = !category.expanded;
if (category.id == 'all') {
return;
}
CategoryService.collapse({
id : category.id,
collapse : !category.expanded
});
};
}]
};
}]);
module.directive('draggable', function() {
return {
restrict : 'A',
link : function(scope, element, attrs) {
element.draggable({
revert : 'invalid',
helper : 'clone',
distance : 10,
axis : 'y'
}).data('source', scope.$eval(attrs.draggable));
}
};
});
module.directive('droppable', ['CategoryService', 'FeedService', function(CategoryService, FeedService) {
return {
restrict : 'A',
link : function(scope, element, attrs) {
element.droppable({
tolerance : 'pointer',
over : function(event, ui) {
},
drop : function(event, ui) {
var draggable = angular.element(ui.draggable);
var source = draggable.data('source');
var target = scope.$eval(attrs.droppable);
if (angular.equals(source, target)) {
return;
}
var data = {
id : source.id,
name : source.name
};
if (source.children) {
// source is a category
} else {
// source is a feed
if (target.children) {
// target is a category
data.categoryId = target.id;
data.position = 0;
} else {
// target is a feed
data.categoryId = target.categoryId;
data.position = target.position;
}
FeedService.modify(data, function() {
CategoryService.init();
});
}
scope.$apply();
}
});
}
};
}]);
module.directive('metricMeter', function() {
return {
scope : {
metric : '=',
label : '='
},
restrict : 'E',
templateUrl : 'templates/_metrics.meter.html'
};
});
module.directive('metricGauge', function() {
return {
scope : {
metric : '=',
label : '='
},
restrict : 'E',
templateUrl : 'templates/_metrics.gauge.html'
};
});

113
src/main/app/js/filters.js Normal file
View File

@@ -0,0 +1,113 @@
var module = angular.module('commafeed.filters', []);
/**
* smart date formatter
*/
module.filter('entryDate', function() {
return function(timestamp, defaultValue) {
if (!timestamp) {
return defaultValue;
}
var d = moment(timestamp);
var now = moment();
var formatted;
if (Math.abs(d.diff(now)) < 86400000) {
formatted = d.fromNow();
} else {
formatted = d.format('YYYY-MM-DD HH:mm');
}
return formatted;
};
});
/**
* rewrites iframes to use https if commafeed uses https
*/
module.filter('iframeHttpsRewrite', function() {
return function(html) {
var result = html;
if (location.protocol === 'https:') {
var wrapper = $('<div></div>').html(html);
$('iframe', wrapper).each(function(i, elem) {
var e = $(elem);
e.attr('src', e.attr('src').replace(/^http:\/\//i, 'https://'));
});
result = wrapper.html();
}
return result;
};
});
/**
* inserts title or alt-text after images, if any
*/
module.filter('appendImageTitles', function() {
return function(html) {
var result = html;
var wrapper = $('<div></div>').html(html);
$('img', wrapper).each(function(i, elem) {
var e = $(elem);
var title = e.attr('title') || e.attr('alt');
if (title) {
var text = $('<span style="font-style: italic;"></span>').text(title);
e.after(text);
}
});
result = wrapper.html();
return result;
};
});
/**
* escapes the url
*/
module.filter('escape', function() {
return encodeURIComponent;
});
/**
* returns a trusted html content
*/
module.filter('trustHtml', ['$sce', function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
}]);
/**
* returns a trusted url
*/
module.filter('trustUrl', ['$sce', function($sce) {
return function(val) {
return $sce.trustAsResourceUrl(val);
};
}]);
/**
* add the 'highlight-search' class to text matching keywords
*/
module.filter('highlight', function() {
return function(html, keywords) {
if (keywords) {
var handleKeyword = function(token, html) {
var expr = new RegExp(token, 'gi');
var container = $('<span>').html(html);
var elements = container.find('*').addBack();
var textNodes = elements.not('iframe').contents().not(elements);
textNodes.each(function() {
var replaced = this.nodeValue.replace(expr, '<span class="highlight-search">$&</span>');
$('<span>').html(replaced).insertBefore(this);
$(this).remove();
});
return container.html();
};
var tokens = keywords.split(' ');
for (var i = 0; i < tokens.length; i++) {
html = handleKeyword(tokens[i], html);
}
}
return html;
};
});

131
src/main/app/js/main.js Normal file
View File

@@ -0,0 +1,131 @@
var app = angular.module('commafeed', ['ngRoute', 'ngTouch', 'ngAnimate', 'ui.utils', 'ui.bootstrap', 'ui.router', 'ui.select2',
'commafeed.directives', 'commafeed.controllers', 'commafeed.services', 'commafeed.filters', 'ngSanitize', 'infinite-scroll',
'ngGrid', 'chieffancypants.loadingBar']);
app.config(['$routeProvider', '$stateProvider', '$urlRouterProvider', '$httpProvider', '$compileProvider', 'cfpLoadingBarProvider',
function($routeProvider, $stateProvider, $urlRouterProvider, $httpProvider, $compileProvider, cfpLoadingBarProvider) {
cfpLoadingBarProvider.includeSpinner = false;
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|javascript):/);
var interceptor = ['$rootScope', '$q', function(scope, $q) {
var success = function(response) {
return response;
};
var error = function(response) {
var status = response.status;
if (status == 401) {
window.location = 'logout';
return;
} else {
return $q.reject(response);
}
};
var promise = function(promise) {
return promise.then(success, error);
};
return promise;
}];
$httpProvider.responseInterceptors.push(interceptor);
$stateProvider.state('feeds', {
'abstract' : true,
url : '/feeds',
templateUrl : 'templates/feeds.html'
});
$stateProvider.state('feeds.view', {
url : '/view/:_type/:_id',
templateUrl : 'templates/feeds.view.html',
controller : 'FeedListCtrl'
});
$stateProvider.state('feeds.subscribe', {
url : '/subscribe',
templateUrl : 'templates/feeds.subscribe.html',
controller : 'SubscribeCtrl'
});
$stateProvider.state('feeds.new_category', {
url : '/add_category',
templateUrl : 'templates/feeds.new_category.html',
controller : 'NewCategoryCtrl'
});
$stateProvider.state('feeds.import', {
url : '/import',
templateUrl : 'templates/feeds.import.html',
controller : 'ImportCtrl'
});
$stateProvider.state('feeds.search', {
url : '/search/:_keywords',
templateUrl : 'templates/feeds.view.html',
controller : 'FeedListCtrl'
});
$stateProvider.state('feeds.feed_details', {
url : '/details/feed/:_id',
templateUrl : 'templates/feeds.feed_details.html',
controller : 'FeedDetailsCtrl'
});
$stateProvider.state('feeds.category_details', {
url : '/details/category/:_id',
templateUrl : 'templates/feeds.category_details.html',
controller : 'CategoryDetailsCtrl'
});
$stateProvider.state('feeds.tag_details', {
url : '/details/tag/:_id',
templateUrl : 'templates/feeds.tag_details.html',
controller : 'TagDetailsCtrl'
});
$stateProvider.state('feeds.help', {
url : '/help',
templateUrl : 'templates/feeds.help.html',
controller : 'HelpController'
});
$stateProvider.state('feeds.settings', {
url : '/settings',
templateUrl : 'templates/settings.html',
controller : 'SettingsCtrl'
});
$stateProvider.state('feeds.profile', {
url : '/profile',
templateUrl : 'templates/profile.html',
controller : 'ProfileCtrl'
});
$stateProvider.state('admin', {
'abstract' : true,
url : '/admin',
templateUrl : 'templates/admin.html'
});
$stateProvider.state('admin.userlist', {
url : '/user/list',
templateUrl : 'templates/admin.userlist.html',
controller : 'ManageUsersCtrl'
});
$stateProvider.state('admin.useradd', {
url : '/user/add',
templateUrl : 'templates/admin.useradd.html',
controller : 'ManageUserCtrl'
});
$stateProvider.state('admin.useredit', {
url : '/user/edit/:_id',
templateUrl : 'templates/admin.useredit.html',
controller : 'ManageUserCtrl'
});
$stateProvider.state('admin.settings', {
url : '/settings',
templateUrl : 'templates/admin.settings.html',
controller : 'ManageSettingsCtrl'
});
$stateProvider.state('admin.metrics', {
url : '/metrics',
templateUrl : 'templates/admin.metrics.html',
controller : 'MetricsCtrl'
});
$urlRouterProvider.when('/', '/feeds/view/category/all');
$urlRouterProvider.when('/admin', '/admin/settings');
$urlRouterProvider.otherwise('/');
}]);

323
src/main/app/js/services.js Normal file
View File

@@ -0,0 +1,323 @@
var module = angular.module('commafeed.services', ['ngResource']);
module.service('AnalyticsService', ['$state', function($state) {
this.track = function(path) {
if (typeof ga === 'undefined') {
return;
}
path = path || $state.$current.url.prefix;
ga('send', 'pageview', {
page : path
});
};
}]);
module.service('MobileService', ['$state', function($state) {
this.leftMenu = false;
this.rightMenu = false;
this.toggleLeftMenu = function() {
this.leftMenu = !this.leftMenu;
$('body').toggleClass('left-menu-active');
};
this.toggleRightMenu = function() {
this.rightMenu = !this.rightMenu;
$('body').toggleClass('right-menu-active');
};
this.mobile = device.mobile() || device.tablet();
}]);
module.factory('ProfileService', ['$resource', function($resource) {
var res = $resource('rest/user/profile/');
res.deleteAccount = $resource('rest/user/profile/deleteAccount').save;
return res;
}]);
module.factory('SettingsService', ['$resource', function($resource) {
var res = $resource('rest/user/settings');
var s = {};
s.settings = {};
s.save = function(callback) {
res.save(s.settings, function(data) {
if (callback) {
callback(data);
}
});
};
s.init = function(callback) {
res.get(function(data) {
s.settings = data;
var lang = s.settings.language || 'en';
if (lang === 'zh') {
lang = 'zh-cn';
} else if (lang === 'ms') {
lang = 'ms-my';
}
moment.lang(lang, {});
if (callback) {
callback(data);
}
});
};
s.init();
return s;
}]);
module.factory('FeedService', ['$resource', '$http', function($resource, $http) {
var actions = {
entries : {
method : 'GET',
params : {
_method : 'entries'
}
},
fetch : {
method : 'POST',
params : {
_method : 'fetch'
}
},
mark : {
method : 'POST',
params : {
_method : 'mark'
}
},
refresh : {
method : 'POST',
params : {
_method : 'refresh'
}
},
refreshAll : {
method : 'GET',
params : {
_method : 'refreshAll'
}
},
subscribe : {
method : 'POST',
params : {
_method : 'subscribe'
}
},
unsubscribe : {
method : 'POST',
params : {
_method : 'unsubscribe'
}
},
modify : {
method : 'POST',
params : {
_method : 'modify'
}
}
};
var res = $resource('rest/feed/:_method', {}, actions);
res.get = $resource('rest/feed/get/:id').get;
return res;
}]);
module.factory('CategoryService', ['$resource', '$http', function($resource, $http) {
var traverse = function(callback, category, parentName) {
callback(category, parentName);
var children = category.children;
if (children) {
for (var c = 0; c < children.length; c++) {
traverse(callback, children[c], category.name);
}
}
};
// flatten categories
var flatten = function(category) {
var array = [];
var callback = function(category, parentName) {
var name = category.name;
if (parentName) {
name += (' (in ' + parentName + ')');
}
array.push({
id : category.id,
name : name,
orig : category
});
};
traverse(callback, category);
return array;
};
// flatten feeds
var flatFeeds = function(category) {
var subs = [];
var callback = function(category) {
subs.push.apply(subs, category.feeds);
};
traverse(callback, category);
return subs;
};
// flatten everything
var flatAll = function(category, a) {
a.push([category.id, 'category']);
_.each(category.children, function(child) {
flatAll(child, a);
});
_.each(category.feeds, function(feed) {
a.push([feed.id, 'feed']);
});
};
var actions = {
get : {
method : 'GET',
ignoreLoadingBar: true,
params : {
_method : 'get'
}
},
entries : {
method : 'GET',
params : {
_method : 'entries'
}
},
mark : {
method : 'POST',
params : {
_method : 'mark'
}
},
add : {
method : 'POST',
params : {
_method : 'add'
}
},
remove : {
method : 'POST',
params : {
_method : 'delete'
}
},
modify : {
method : 'POST',
params : {
_method : 'modify'
}
},
collapse : {
method : 'POST',
params : {
_method : 'collapse'
}
}
};
var res = $resource('rest/category/:_method', {}, actions);
res.subscriptions = {};
res.flatCategories = {};
res.feeds = [];
res.init = function(callback) {
res.get(function(data) {
res.subscriptions = data;
res.flatCategories = flatten(data);
res.feeds = flatFeeds(data);
res.flatAll = [];
flatAll(data, res.flatAll);
res.flatAll.splice(1, 0, ['starred', 'category']);
if (callback)
callback(data);
});
};
res.refresh = function(callback) {
res.get(function(data) {
_.merge(res.subscriptions, data);
if (callback)
callback(data);
});
};
res.init();
return res;
}]);
module.factory('EntryService', ['$resource', '$http', function($resource, $http) {
var actions = {
search : {
method : 'GET',
params : {
_method : 'search'
}
},
mark : {
method : 'POST',
ignoreLoadingBar: true,
params : {
_method : 'mark'
}
},
markMultiple : {
method : 'POST',
params : {
_method : 'markMultiple'
}
},
star : {
method : 'POST',
params : {
_method : 'star'
}
},
tag : {
method : 'POST',
params : {
_method : 'tag'
}
}
};
var res = $resource('rest/entry/:_method', {}, actions);
res.tags = [];
var initTags = function() {
$http.get('rest/entry/tags').success(function(data) {
res.tags = [];
res.tags.push.apply(res.tags, data);
});
};
var oldTag = res.tag;
res.tag = function(data) {
oldTag(data, function() {
initTags();
});
};
initTags();
return res;
}]);
module.factory('AdminUsersService', ['$resource', function($resource) {
var res = {};
res.get = $resource('rest/admin/user/get/:id').get;
res.getAll = $resource('rest/admin/user/getAll').query;
res.save = $resource('rest/admin/user/save').save;
res.remove = $resource('rest/admin/user/delete').save;
return res;
}]);
module.factory('AdminSettingsService', ['$resource', function($resource) {
var res = $resource('rest/admin/settings/');
return res;
}]);
module.factory('AdminMetricsService', ['$resource', function($resource) {
var res = $resource('rest/admin/metrics/');
return res;
}]);
module.factory('ServerService', ['$resource', function($resource) {
var res = $resource('rest/server/get');
return res;
}]);

View File

@@ -0,0 +1,7 @@
$(function() {
var reg = $('#register-panel');
if (!reg) {
return;
}
$('#login-panel').height(reg.height());
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,22 @@
@import "generic/misc";
@import "generic/scrollbar";
@import "components/admin-panel";
@import "components/toolbar";
@import "components/entry-list";
@import "components/subscription-list";
@import "components/help";
@import "components/loading-bar";
@import "components/readabilicons";
@import "components/zocial";
@import "mobile/mobile";
@import "themes/test";
@import "themes/bootstrap";
@import "themes/ebraminio";
@import "themes/MRACHINI";
@import "themes/svetla";
@import "themes/dark";
@import "themes/third";

View File

View File

@@ -0,0 +1,4 @@
/* admin */
.admin .users-table {
height: 400px;
}

View File

@@ -0,0 +1,271 @@
.main-content {
margin-left: 250px;
padding-left: 15px;
}
.full-screen .main-content {
width: 100%;
margin-left: 0;
}
.entryList {
padding-top: 50px;
}
/* entry list*/
.entrylist-header {
border-bottom: 1px solid #eee;
}
.entrylist-header h3 {
margin: 0;
line-height: 40px;
}
.entrylist-header a {
color: inherit;
}
.expanded .entry-header,.expanded .entry-body-content {
padding-left: 25px;
padding-right: 25px;
}
.expanded .entry-header {
max-width: 650px;
}
.full-screen .expanded .entry-header {
max-width: 100%;
}
.rtl .entry-header,.rtl .entry-body-content,.rtl.entry-name {
direction: rtl;
}
.rtl ul,.rtl ol {
padding: 0;
margin: 0 25px 10px 0px;
}
#feed-accordion .entry {
border-bottom: 1px solid #CCCCCC;
}
#feed-accordion .no-entries {
text-align: center;
font-weight: bold;
margin-top: 80px;
}
#feed-accordion .entry-heading {
background-color: #ebebeb;
}
#feed-accordion .unread .entry-heading:hover {
background-color: #ebebeb;
}
#feed-accordion .unread .entry-heading {
background-color: #fff;
}
#feed-accordion .current.closed .entry-heading {
background-color: #ffc;
}
#feed-accordion .entry-heading-link {
color: black;
height: 32px;
display: block;
cursor: pointer;
padding: 6px 0px;
}
#feed-accordion .entry-heading .feed-name {
color: #555;
display: block;
overflow: hidden;
white-space: nowrap;
position: absolute;
width: 145px;
text-overflow: ellipsis;
}
#feed-accordion .entry-heading .entry-name {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 150px;
}
#feed-accordion .unread .entry-heading .entry-name {
font-weight: bold;
}
#feed-accordion .entry-heading .shrink {
margin-left: 150px;
}
#feed-accordion .entry-heading .entry-date {
display: block;
position: absolute;
right: 45px;
}
#feed-accordion a.entry-heading-link:hover {
text-decoration: none;
}
#feed-accordion .entry-external-link {
position: absolute;
right: 25px;
margin-top: -25px;
color: black;
}
#feed-accordion .entry-external-link:hover {
text-decoration: none;
}
#feed-accordion .entry-body .entry-title {
margin-top: 5px;
margin-bottom: 10px;
font-size: 130%;
font-weight: bold;
}
#feed-accordion .entry-body .entry-subtitle {
display: block;
font-size: 14px;
font-weight: normal;
}
#feed-accordion .entry-body-content {
max-width: 650px;
color: black;
padding-bottom: 10px;
}
.full-screen #feed-accordion .entry-body-content {
max-width: 100%;
}
#feed-accordion .entry-enclosure {
clear: both;
padding-top: 10px;
}
#feed-accordion .entry-buttons {
clear: both;
background-color: #fafafa;
padding: 3px 0px;
border-top: 1px solid #ebebeb;
}
#feed-accordion .entry-buttons .checkbox.inline {
padding-top: 0px;
margin-left: 5px;
}
#feed-accordion .entry-buttons .keep-unread label {
display: inline;
font-weight: inherit;
}
#feed-accordion .share-buttons a {
color: #333333;
padding-left: 5px;
}
#feed-accordion .share-buttons a:hover {
text-decoration: none;
}
#feed-accordion .tags-panel {
margin-left: 30px;
}
#feed-accordion .tags-panel .label{
margin-left: 5px;
}
.select2-container-multi .select2-choices .select2-search-field input {
padding: 2px
}
#feed-accordion .tag-input {
margin: 0 0 0 5px;
padding: 0;
width: 200px;
}
#feed-accordion .entry-buttons label {
margin-bottom: 0px;
font-size: 12px;
}
#feed-accordion a.mark-up-to {
color: #333333;
position: absolute;
right: 30px;
}
#feed-accordion a.mark-up-to:hover {
text-decoration: none;
cursor: pointer;
}
#feed-accordion .star {
text-decoration: none;
padding: 0px 5px;
}
#feed-accordion .icon-star-yellow {
color: gold;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
}
#feed-accordion .icon-star-empty {
color: #555;
}
#feed-accordion.expanded .entry {
margin-bottom: 40px;
border: 1px solid #ddd;
box-shadow: 0 0 4px #e3e5eb;
}
#feed-accordion.expanded .current {
border-left: 1px solid rgb(77, 144, 240);
}
#feed-accordion .current.entry-font-size-0 {
font-size: 14px;
}
#feed-accordion .current.entry-font-size-1 {
font-size: 15px;
}
#feed-accordion .current.entry-font-size-2 {
font-size: 16px;
}
#feed-accordion .current.entry-font-size-3 {
font-size: 17px;
}
#feed-accordion .current.entry-font-size-4 {
font-size: 18px;
}
#feed-accordion .current.entry-font-size-5 {
font-size: 19px;
}
#feed-accordion .highlight-search {
background-color: rgba(255, 255, 140, 0.5);
color: #333;
}

View File

@@ -0,0 +1,23 @@
.help {
font-size: 85%;
line-height: 15px;
}
.help .bookmarklet-select {
margin: 0;
padding: 0;
height: auto;
}
.help .about-module {
margin-bottom: 40px;
}
.donate-action {
margin-top:20px;
}
.donate-image {
padding-bottom:10px;
padding-right:16px;
}

View File

@@ -0,0 +1,12 @@
#loading-bar .bar {
background: #2c3e50;
}
#loading-bar .peg {
box-shadow: 0 0 10px #2c3e50, 0 0 5px #2c3e50;
}
#loading-bar-spinner .spinner-icon {
border-top-color: #2c3e50;
border-left-color: #2c3e50;
}

View File

@@ -0,0 +1,151 @@
/* feed search dialog */
.feed-search-dialog .modal-body {
overflow: hidden;
}
.feed-search-dialog .filter-input {
width: 90%;
}
.feed-search-dialog .feed-link {
font-size: large;
}
.feed-search-dialog a:hover {
text-decoration: none;
}
.feed-search-dialog .focus a {
color: black;
}
/* tree*/
.sidebar-nav-fixed {
margin-top: 10px;
width: 250px;
position: fixed;
top: 0;
bottom: 0;
overflow: hidden;
}
.sidebar-nav-fixed:hover {
overflow-y: auto;
}
.sidebar-nav-fixed .ui-resizable-e {
width: 5px;
right: 0;
}
.full-screen .left-menu {
display: none;
}
.css-treeview {
margin-top: 15px;
margin-bottom: 30px;
font-family: inherit;
font-size: 13px;
white-space: nowrap;
}
.css-treeview ul {
list-style: none;
margin-left: 0px;
padding: 0;
}
.css-treeview li {
line-height: 20px;
}
.css-treeview .fldr {
cursor: pointer;
display: inline-block;
width: 14px;
height: 14px;
line-height: 14px;
vertical-align: text-top;
margin-top: 1px;
}
.css-treeview .error {
color: red;
font-style: italic;
}
.css-treeview label {
overflow: hidden;
text-overflow: ellipsis;
display: block;
margin: 3px 0px 3px;
}
.css-treeview label,.css-treeview a,.css-treeview label::before {
font-family: inherit;
font-size: 12px;
white-space: nowrap;
}
.css-treeview .selected {
color: #d14836;
}
.css-treeview .unread {
font-weight: bold;
}
.css-treeview .unread-counter {
color: #666;
font-size: 11px;
}
.css-treeview a {
cursor: pointer;
color: black;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
.css-treeview a:hover {
text-decoration: none;
}
.css-treeview li .tree-item:hover {
background-color: #EBEBEB;
text-decoration: none;
}
.css-treeview .config {
display: none;
}
.css-treeview .tree-item:hover .config {
display: block;
padding-top: 3px;
margin-right: 5px;
width: 16px;
height: 16px;
}
.css-treeview .indent1 {
padding-left: 16px;
}
.css-treeview .indent2 {
padding-left: 32px;
}
.css-treeview .indent3 {
padding-left: 48px;
}
.css-treeview .indent4 {
padding-left: 64px;
}
.css-treeview .indent5 {
padding-left: 80px;
}

View File

@@ -0,0 +1,16 @@
.toolbar {
padding-top: 10px;
padding-bottom: 10px;
width: 100%;
z-index: 10;
position: fixed;
background-color: #FFF;
}
.toolbar .donate {
display: inline-block;
}
.toolbar .keywords {
width: 244px;
}

View File

@@ -0,0 +1,20 @@
@font-face {
font-family: 'readabilicons';
src: url('../font/readabilicons-regular.eot'); /* IE9 Compat Modes */
src: url('../font/readabilicons-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('../font/readabilicons-regular.woff') format('woff'), /* Modern Browsers */
url('../font/readabilicons-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('../font/readabilicons-regular.svg#readabiliconsregular') format('svg'); /* Legacy iOS */
font-style: normal;
font-weight: 400;
}
.icon-couch::before {
content: "\e018";
font-family: "readabilicons";
-webkit-font-smoothing: antialiased;
font-size: 21px;
top: 5px;
position: relative;
line-height: 0px;
}

View File

@@ -0,0 +1,47 @@
@charset "UTF-8";
/*!
Zocial Butons
http://zocial.smcllns.com
by Sam Collins (@smcllns)
License: http://opensource.org/licenses/mit-license.php
You are free to use and modify, as long as you keep this license comment intact or link back to zocial.smcllns.com on your site.
*/
/* Reference icons from font-files
** Base 64-encoded version recommended to resolve cross-site font-loading issues
*/
@font-face {
font-family: 'zocial';
src: url('../font/zocial-regular-webfont.eot'),
url('../font/zocial-regular-webfont.woff'), url('../font/zocial-regular-webfont.ttf')
format('truetype'), url('../font/zocial-regular-webfont.svg#zocialregular')
format('svg');
font-weight: normal;
font-style: normal;
}
.icon-instapaper:before {
font-style: normal;
font-family: 'zocial';
content: "I";
}
.icon-pocket:before {
font-style: normal;
font-family: 'zocial';
content: "\00E7";
}
.icon-buffer:before {
font-style: normal;
font-family: 'zocial';
content: "\00E5";
}
.icon-gmail:before {
font-style: normal;
font-family: 'zocial';
content: "m";
}

View File

@@ -0,0 +1,126 @@
.container-full {
width: 100%;
margin: 0 auto;
padding-right: 20px;
padding-left: 20px;
}
body img {
max-width: 100%;
height: auto;
}
body .modal {
display: block;
}
body .modal-backdrop {
opacity: 0.5;
}
label {
font-weight: inherit;
}
.pointer {
cursor: pointer;
}
.nolink {
color: inherit;
}
.nolink:hover {
text-decoration: none;
color: inherit;
}
.block {
display: block;
}
.form-horizontal .control-group {
margin-bottom: 10px;
}
.bidi-embed {
unicode-bidi: embed;
}
.bs-fb ul {
margin-bottom: 0px;
}
.horizontal-align {
padding-top: 5px;
line-height: 20px
}
.welcome .container-fluid {
margin-right: auto;
margin-left: auto;
max-width: 950px;
}
.welcome .header {
margin: 20px 0 40px 0;
}
.welcome .tagline {
color: #B3B3B3;
font-size: 28px;
padding-top: 110px;
}
.welcome .preview {
margin: 20px 0 20px 0;
max-width: 100%;
}
.welcome .demo {
font-size: 24px;
color: #B3B3B3;
}
.main .spinner {
display: inline-block;
margin-left: 11px;
top: -4px;
}
.icon {
width: 14px;
height: 14px;
display: block;
}
.main .dropdown-menu a {
cursor: pointer;
}
.favicon {
width: 16px;
height: 16px;
}
blockquote p {
font-size: 14px;
}
.btn,.btn-large,.btn-small,.btn-mini {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
.btn-group>.btn:first-child,.btn-group>.btn-large:first-child {
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
}
.btn-group>.btn:last-child,.btn-group>.btn-large:last-child,.btn-group>.dropdown-toggle
{
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}

View File

@@ -0,0 +1,21 @@
::-webkit-scrollbar {
height: 8px;
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
}
::-webkit-scrollbar-track:hover {
background-color: rgba(0, 0, 0, .05);
box-shadow: inset 1px 0 0 rgba(0, 0, 0, .1)
}
::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.5);
}

View File

@@ -0,0 +1,86 @@
html.mobile, html.tablet {
body {
padding-left: 0px;
padding-right: 0px;
}
.container-full {
padding-left: 5px;
padding-right: 5px;
}
.row {
margin-right: 0;
margin-left: 0;
}
.left-menu {
display: none !important;
}
.left-menu .feed-link, .left-menu .category-link {
line-height: 30px;
font-size: 105%;
}
.toolbar .toolbar-expand.btn-group {
display: inline-block !important;
}
.main-content {
display: block !important;
float: none !important;
width: 100% !important;
margin-left: 0 !important;
padding-left: 0;
padding-right: 0;
}
#feed-accordion .entry-heading .shrink {
margin-left: 0;
margin-right: 0;
}
#feed-accordion .entry-heading .feed-name {
width: 50%;
}
#feed-accordion .feed-name {
margin-top: 22px;
}
#feed-accordion .entry-external-link {
right: 15px;
margin-top: -24px;
}
#feed-accordion .entry-heading-link {
height: 52px;
}
#feed-accordion .entry-heading .entry-date {
right: 40px;
margin-top: 22px;
}
#feed-accordion .entry-buttons .checkbox, #feed-accordion .entry-buttons .form-group {
display: inline-block;
}
#feed-accordion .tags-panel {
display: block;
margin-left: 5px;
}
#feed-accordion a.mark-up-to {
right: 20px;
margin-top: -18px;
}
body.left-menu-active .left-menu {
display: block !important;
width: 100%;
}
body.left-menu-active .sidebar-nav-fixed {
width: 100%;
overflow: auto;
}
body.left-menu-active .main-content {
display: none !important;
}
body.right-menu-active .toolbar .actions {
margin-top: 5px;
margin-left: 0;
}
body.right-menu-active .toolbar .actions {
display: inherit !important;
}
#uvTab {
display: none;
}
}

View File

@@ -0,0 +1,34 @@
#theme-MRACHINI {
/*transitional hightlighting*/
.entry-title > a.ng-binding:link, .entry-body-content > div.ng-binding a:link{
-moz-transition: background-color 1s ease-in 0s;
-webkit-transition: background-color 1s ease-in 0s;
-o-transition: background-color 1s ease-in 0s;
}
.entry-title > a.ng-binding:hover, .entry-body-content > div.ng-binding a:hover{
background-color: lime;
-moz-transition: background-color 1s ease-out 0s;
-webkit-transition: background-color 1s ease-out 0s;
-o-transition: background-color 1s ease-out 0s;
}
.entry-title > a.ng-binding:active, .entry-body-content > div.ng-binding a:active{
background-color: lime;
-moz-transition: none;
-webkit-transition: none;
-o-transition: none;
}
/*hovered item*/
.entry-heading:hover{box-shadow: inset 0 0 40px 0px lime !important;}
/*hovered tree item*/
/*.css-treeview li .tree-item:hover{box-shadow: inset 0 0 20px 0px hsla(7,63%,52%,1) !important;}*/
.css-treeview li .tree-item:hover{box-shadow: inset 0 0 20px 0px lime !important;}
/*highlight current selected tree item*/
.css-treeview li .tree-item .selected{box-shadow: inset 0 0 20px 0px lime !important;}
.css-treeview .indent1{padding-left:10px}
.css-treeview .indent2{padding-left:20px}
.css-treeview .indent3{padding-left:30px}
.css-treeview .indent4{padding-left:40px}
.css-treeview .indent5{padding-left:50px}
}

View File

@@ -0,0 +1,348 @@
#theme-bootstrap{
/*!
* Bootstrap v3.1.1 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
border-color: #ccc;
}
.btn-default:hover,
.btn-default:focus {
background-color: #e0e0e0;
background-position: 0 -15px;
}
.btn-default:active,
.btn-default.active {
background-color: #e0e0e0;
border-color: #dbdbdb;
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #2b669a;
}
.btn-primary:hover,
.btn-primary:focus {
background-color: #2d6ca2;
background-position: 0 -15px;
}
.btn-primary:active,
.btn-primary.active {
background-color: #2d6ca2;
border-color: #2b669a;
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #3e8f3e;
}
.btn-success:hover,
.btn-success:focus {
background-color: #419641;
background-position: 0 -15px;
}
.btn-success:active,
.btn-success.active {
background-color: #419641;
border-color: #3e8f3e;
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #28a4c9;
}
.btn-info:hover,
.btn-info:focus {
background-color: #2aabd2;
background-position: 0 -15px;
}
.btn-info:active,
.btn-info.active {
background-color: #2aabd2;
border-color: #28a4c9;
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #e38d13;
}
.btn-warning:hover,
.btn-warning:focus {
background-color: #eb9316;
background-position: 0 -15px;
}
.btn-warning:active,
.btn-warning.active {
background-color: #eb9316;
border-color: #e38d13;
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #b92c28;
}
.btn-danger:hover,
.btn-danger:focus {
background-color: #c12e2a;
background-position: 0 -15px;
}
.btn-danger:active,
.btn-danger.active {
background-color: #c12e2a;
border-color: #b92c28;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #357ebd;
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
background-repeat: repeat-x;
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
}
.navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
}
.navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
background-image: linear-gradient(to bottom, #222 0%, #282828 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x;
border-color: #b2dba1;
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x;
border-color: #9acfea;
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x;
border-color: #f5e79e;
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x;
border-color: #dca7a7;
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x;
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #3071a9;
background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
background-repeat: repeat-x;
border-color: #3278b3;
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
background-repeat: repeat-x;
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x;
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x;
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x;
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x;
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
}
}

View File

@@ -0,0 +1,276 @@
#theme-dark {
* {
outline: 0;
text-decoration: none;
}
.btn {
border: none;
}
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
background: none;
text-shadow: none;
color: #424345;
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
-moz-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
-ms-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
-o-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
background: #e0e0e0;
}
.btn-default {
background: #c7cbcc;
}
.btn:hover {
background: #e0e0e0;
}
.dropdown-menu {
background: #c7cbcc;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
border: none;
color: #424345;
}
.dropdown-menu a {
color: inherit;
}
.dropdown-menu .divider {
display: none;
}
.btn-primary:hover {
color: #000;
}
.btn-primary:active {
color: #000;
}
.btn-primary:active:hover {
color: #000;
}
.btn-default:hover {
color: #000;
}
.btn-default:active {
color: #000;
}
.btn-default:active:hover {
color: #000;
}
.btn {
-webkit-transition: all 400ms linear;
-moz-transition: all 400ms linear;
-ms-transition: all 400ms linear;
-o-transition: all 400ms linear;
transition: all 400ms linear;
}
input[ng-model='keywords'] {
-webkit-transition: all 400ms linear;
-moz-transition: all 400ms linear;
-ms-transition: all 400ms linear;
-o-transition: all 400ms linear;
transition: all 400ms linear;
}
input[ng-model='keywords']:focus {
background: #c7cbcc;
}
a[ng-click^='tab'] {
-webkit-transition: all 390ms linear;
-moz-transition: all 390ms linear;
-ms-transition: all 390ms linear;
-o-transition: all 390ms linear;
transition: all 390ms linear;
}
a[ng-click^='tab']:hover {
color: #000;
}
.css-treeview li {
-webkit-transition: all 150ms linear;
-moz-transition: all 150ms linear;
-ms-transition: all 150ms linear;
-o-transition: all 150ms linear;
transition: all 150ms linear;
}
#uvTab {
-webkit-transition: all 260ms linear;
-moz-transition: all 260ms linear;
-ms-transition: all 260ms linear;
-o-transition: all 260ms linear;
transition: all 260ms linear;
}
body {
background: #788587;
color: #424345;
}
body a {
color: #e0e0e0;
}
body h3 {
color: #424345;
}
.toolbar {
background: #788587;
}
.page-header {
border: none;
}
.entrylist-header {
border: none;
}
.entrylist-header h3,
.entrylist-header a {
margin: 0;
}
#feed-accordion .entry {
border: none;
}
#feed-accordion .unread .entry-heading {
background: #c9c9c9;
}
#feed-accordion .unread:nth-of-type(2n) .entry-heading {
background: #ddd;
}
#feed-accordion .unread .entry-heading:hover,
#feed-accordion .unread:nth-of-type(2n):hover {
background: #ebebeb;
}
#feed-accordion .entry-heading-link {
color: #383838;
}
#feed-accordion .entry-heading-link:hover {
color: #000;
}
#feed-accordion .entry-body {
background: #c7cbcc;
padding: 15px 0 0 15px;
}
#feed-accordion .entry-body a:not([popup]) {
color: #2c4967;
}
#feed-accordion .entry-body a:not([popup]):visited {
color: #8d8e8e;
}
#feed-accordion .entry-body .entry-title {
display: none;
}
#feed-accordion .entry-body img {
-webkit-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
-moz-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
-ms-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
-o-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
}
#feed-accordion .highlight-search {
background: inherit;
}
#feed-accordion .entry-buttons {
background: #a68589;
margin-left: -15px;
border: none;
}
#feed-accordion.expanded .entry {
-webkit-box-shadow: none;
-moz-box-shadow: none;
-ms-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
border: none;
margin-bottom: 30px;
}
#feed-accordion.expanded .entry .entry-heading-link {
color: #a68589;
}
input[ng-model='keywords'] {
border: none;
height: 32px;
background: #9ba8aa;
}
.css-treeview .selected {
color: #905158 !important;
}
.css-treeview .unread-counter {
color: #000;
}
.css-treeview li .tree-item:hover {
background: #ebebeb;
}
.css-treeview a {
color: #383838;
}
.css-treeview a:hover {
font-size: 1.02em;
}
#uvTab {
margin-bottom: -23px;
}
#uvTab:hover {
margin-bottom: 0;
}
/*dangerous stuff*/
#feed-accordion.expanded .entry .entry-heading-link>.feed-name {
float: right;
display: block;
position: relative;
margin-right: 150px;
}
#feed-accordion.expanded .entry .entry-heading-link .entry-name {
margin-left: 40px;
color: #a68589;
}
@media only screen and (max-width: 800px) {
#toolbar {
display: none;
}
.sidebar-nav-fixed>.btn-group {
display: none;
}
.entryList {
padding-top: 10px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name {
float: left;
width: 50px;
font-size: 0;
position: initial;
display: block;
margin-right: 0;
margin-right: initial;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name .star {
font-size: 14px;
font-size: initial;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name img {
margin-top: -14px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name:after {
content: '';
display: block;
clear: left;
}
#feed-accordion.expanded .entry .entry-heading-link .entry-name {
margin-left: 55px;
color: #a68589;
}
}
}

View File

@@ -0,0 +1,17 @@
#theme-ebraminio {
/* My font setting, a bit specific for Persian but is okay in other languages */
body {
font-family: Tahoma, 'Iranian sans', 'DejaVu Sans', sans-serif;
}
input, button, select, textarea {
font-family: inherit; /* what said above */
}
/* Change source-codes in feeds background to white */
pre {
background-color: transparent;
}
/* 100% forever */
.expanded .entry-header, #feed-accordion .entry-body-content {
max-width: 100%;
}
}

View File

@@ -0,0 +1,378 @@
#theme-svetla {
* {
outline: 0;
text-decoration: none;
}
:focus {
outline: none !important;
}
::-moz-focus-inner {
border: 0 !important;
}
.btn {
border: none;
}
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
background: none;
text-shadow: none;
color: #788587;
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: 0 -5px 5px 0 rgba(238,232,213,0.2) inset , 0 5px 5px 0 rgba(238,232,213,0.2) inset;
-moz-box-shadow: 0 -5px 5px 0 rgba(238,232,213,0.2) inset , 0 5px 5px 0 rgba(238,232,213,0.2) inset;
-ms-box-shadow: 0 -5px 5px 0 rgba(238,232,213,0.2) inset , 0 5px 5px 0 rgba(238,232,213,0.2) inset;
-o-box-shadow: 0 -5px 5px 0 rgba(238,232,213,0.2) inset , 0 5px 5px 0 rgba(238,232,213,0.2) inset;
box-shadow: 0 -5px 5px 0 rgba(238,232,213,0.2) inset , 0 5px 5px 0 rgba(238,232,213,0.2) inset;
background: rgba(238,232,213,0.3);
color: #788587;
}
.btn-default {
background: #eee8d5;
}
.btn:hover {
background: #c4bea6;
}
.dropdown-menu {
background: #c7cbcc;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
border: none;
color: #424345;
-webkit-box-shadow: none;
-moz-box-shadow: none;
-ms-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
}
.dropdown-menu a {
color: inherit;
}
.dropdown-menu .divider {
display: none;
}
.btn-primary:hover {
color: #000;
}
.btn-primary:active {
color: #000;
}
.btn-primary:active:hover {
color: #000;
}
.btn-default:hover {
color: #000;
}
.btn-default:active {
color: #000;
}
.btn-default:active:hover {
color: #000;
}
.btn {
-webkit-transition: all 400ms linear;
-moz-transition: all 400ms linear;
-ms-transition: all 400ms linear;
-o-transition: all 400ms linear;
transition: all 400ms linear;
}
input[ng-model='keywords'] {
-webkit-transition: all 400ms linear;
-moz-transition: all 400ms linear;
-ms-transition: all 400ms linear;
-o-transition: all 400ms linear;
transition: all 400ms linear;
}
input[ng-model='keywords']:focus {
background: #c7cbcc;
}
a[ng-click^='tab'] {
-webkit-transition: all 390ms linear;
-moz-transition: all 390ms linear;
-ms-transition: all 390ms linear;
-o-transition: all 390ms linear;
transition: all 390ms linear;
}
a[ng-click^='tab']:hover {
color: #000;
}
.css-treeview li {
-webkit-transition: all 150ms linear;
-moz-transition: all 150ms linear;
-ms-transition: all 150ms linear;
-o-transition: all 150ms linear;
transition: all 150ms linear;
}
#uvTab {
-webkit-transition: all 260ms linear;
-moz-transition: all 260ms linear;
-ms-transition: all 260ms linear;
-o-transition: all 260ms linear;
transition: all 260ms linear;
}
body {
background: #fdf6e3;
color: #424345;
}
body a {
color: #788587;
}
.toolbar {
background: #fdf6e3;
}
.page-header {
border: none;
}
.entrylist-header {
border: none;
}
.entrylist-header h3,
.entrylist-header a {
margin: 0;
}
#feed-accordion .entry-heading {
background: #edeae6;
background: -webkit-moz-linear-gradient(rgba(238,232,213,0.7), #fdf6e3);
background: -moz-linear-gradient(rgba(238,232,213,0.7), #fdf6e3);
background: -ms-moz-linear-gradient(rgba(238,232,213,0.7), #fdf6e3);
background: linear-gradient(rgba(238,232,213,0.7), #fdf6e3);
}
#feed-accordion .entry-heading-link {
color: #786b47 !important;
font-style: italic !important;
}
#feed-accordion .entry {
border: none;
}
#feed-accordion .unread .entry-heading {
background: #fdf6e3;
}
#feed-accordion .unread .entry-heading .entry-heading-link {
color: #404141 !important;
font-style: normal !important;
}
#feed-accordion .unread:nth-of-type(2n) .entry-heading {
background: rgba(238,232,213,0.7);
}
#feed-accordion .entry-body {
background: #eee8d5;
padding: 2px 0 0 15px;
}
#feed-accordion .entry-body a.nolink.pointer {
color: #424345;
}
#feed-accordion .entry-body a:not([popup]) {
color: #6c6759;
}
#feed-accordion .entry-body a:not([popup]):visited {
color: #8d8e8e;
}
#feed-accordion .entry-body .entry-title {
font-size: 1em;
}
#feed-accordion .entry-body .entry-title .entry-subtitle {
display: inline;
}
#feed-accordion .entry-body .entry-title .entry-subtitle [class^='entry-author'] {
font-style: italic;
}
#feed-accordion .entry-body .entry-title .entry-subtitle .entry-source {
display: none;
}
#feed-accordion .entry-body .entry-title a {
color: #a7a083;
}
#feed-accordion .entry-body img {
-webkit-box-shadow: 0 0 2px 0 rgba(0,0,0,0.1);
-moz-box-shadow: 0 0 2px 0 rgba(0,0,0,0.1);
-ms-box-shadow: 0 0 2px 0 rgba(0,0,0,0.1);
-o-box-shadow: 0 0 2px 0 rgba(0,0,0,0.1);
box-shadow: 0 0 2px 0 rgba(0,0,0,0.1);
}
#feed-accordion .highlight-search {
background: inherit;
}
#feed-accordion .entry-buttons {
background: #a68589;
margin-left: -15px;
border: none;
}
#feed-accordion.expanded .entry {
-webkit-box-shadow: none;
-moz-box-shadow: none;
-ms-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
border: none;
}
input[ng-model='keywords'] {
border: none;
height: 32px;
-webkit-box-shadow: 0 0 2px 1px #eee8d5 inset;
-moz-box-shadow: 0 0 2px 1px #eee8d5 inset;
-ms-box-shadow: 0 0 2px 1px #eee8d5 inset;
-o-box-shadow: 0 0 2px 1px #eee8d5 inset;
box-shadow: 0 0 2px 1px #eee8d5 inset;
}
input[ng-model='keywords']:focus {
background: #fff;
}
.css-treeview .selected {
color: #a68589 !important;
}
.css-treeview .unread-counter {
color: #93a1a1;
}
.css-treeview li .tree-item:hover {
background: #ebebeb;
}
.css-treeview a {
color: #93a1a1;
}
.css-treeview a:hover {
font-size: 1.02em;
}
#uvTab {
margin-bottom: -23px;
}
#uvTab:hover {
margin-bottom: 0;
}
/* stuff */
#feed-accordion .entry-external-link {
position: absolute;
right: auto;
margin-left: 15px;
color: #c4bea6;
}
#feed-accordion .entry .entry-heading-link>.feed-name {
font-size: 0;
width: 50px;
margin-left: 35px;
}
#feed-accordion .entry .entry-heading-link>.feed-name .star {
font-size: 1em;
}
#feed-accordion .entry .entry-heading-link .entry-name {
margin-left: 100px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name {
font-size: 1em;
width: auto;
float: right;
display: block;
position: relative;
margin-right: 150px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name img {
margin-top: 0;
}
#feed-accordion.expanded .entry .entry-heading-link .entry-name {
margin-left: 40px;
}
#feed-accordion.expanded .entry .entry-body .entry-body-content {
padding-left: 0;
}
#feed-accordion.expanded .entry .entry-body .entry-title {
display: none;
}
@media only screen and (max-width: 800px) {
#toolbar {
display: none;
}
.sidebar-nav-fixed>.btn-group {
display: none;
}
.entryList {
padding-top: 10px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name {
float: left;
width: 50px;
font-size: 0;
position: initial;
display: block;
margin-right: 0;
margin-right: initial;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name .star {
font-size: 14px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name img {
margin-top: -10px;
}
#feed-accordion.expanded .entry .entry-heading-link>.feed-name:after {
content: '';
display: block;
clear: left;
}
#feed-accordion.expanded .entry .entry-heading-link .entry-name {
margin-left: 55px;
}
}
#feed-accordion:not(.expanded) .current .entry-heading {
background: #eee8d5;
}
#feed-accordion:not(.expanded) .current .entry-heading .entry-heading-link {
color: #a7a083 !important;
font-style: normal !important;
}
#feed-accordion:not(.expanded) .current .entry-heading .entry-heading-link .feed-name {
width: auto !important;
font-size: 1em !important;
font-style: normal;
color: #a7a083;
}
#feed-accordion:not(.expanded) .current .entry-heading .entry-heading-link .feed-name img {
margin-top: 0;
}
#feed-accordion:not(.expanded) .current .entry-heading .entry-heading-link .entry-name {
display: none;
}
#feed-accordion.expanded .current .entry-heading {
background: #eee8d5;
}
#feed-accordion.expanded .current .entry-heading .entry-heading-link {
color: #a7a083 !important;
font-style: normal !important;
}
#feed-accordion.expanded .current .entry-heading .entry-heading-link .feed-name {
font-style: inherit;
color: inherit;
}
#feed-accordion.expanded .current .entry-heading .entry-heading-link .entry-name {
color: inherit !important;
}
.nav-pills li.active a {
color: #424345 !important;
}
blockquote {
border-left: solid 5px #c4bea6 !important;
}
a[href^='http://da.feedsportal.com'] {
display: none;
}
br {
display: none;
}
}

View File

@@ -0,0 +1,5 @@
#theme-test {
body {
background-color: black;
}
}

View File

@@ -0,0 +1,262 @@
#theme-third {
* {
outline: 0;
text-decoration: none;
}
.btn {
border: none;
}
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
background: none;
text-shadow: none;
color: #424345;
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
-moz-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
-ms-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
-o-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.15) 0 1px 1px rgba(0,0,0,0.075);
background: #e0e0e0;
}
.btn-default {
background: #6e797c;
}
.btn:hover {
background: #e0e0e0;
}
.dropdown-menu {
background: #c7cbcc;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
border: none;
color: #424345;
}
.dropdown-menu a {
color: inherit;
}
.dropdown-menu .divider {
display: none;
}
.btn-primary:hover {
color: #000;
}
.btn-primary:active {
color: #000;
}
.btn-primary:active:hover {
color: #000;
}
.btn-default:hover {
color: #000;
}
.btn-default:active {
color: #000;
}
.btn-default:active:hover {
color: #000;
}
.btn {
-webkit-transition: all 400ms linear;
-moz-transition: all 400ms linear;
-ms-transition: all 400ms linear;
-o-transition: all 400ms linear;
transition: all 400ms linear;
}
input[ng-model='keywords'] {
-webkit-transition: all 400ms linear;
-moz-transition: all 400ms linear;
-ms-transition: all 400ms linear;
-o-transition: all 400ms linear;
transition: all 400ms linear;
}
input[ng-model='keywords']:focus {
background: #c7cbcc;
}
a[ng-click^='tab'] {
-webkit-transition: all 390ms linear;
-moz-transition: all 390ms linear;
-ms-transition: all 390ms linear;
-o-transition: all 390ms linear;
transition: all 390ms linear;
}
a[ng-click^='tab']:hover {
color: #000;
}
.css-treeview li {
-webkit-transition: all 150ms linear;
-moz-transition: all 150ms linear;
-ms-transition: all 150ms linear;
-o-transition: all 150ms linear;
transition: all 150ms linear;
}
#uvTab {
-webkit-transition: all 260ms linear;
-moz-transition: all 260ms linear;
-ms-transition: all 260ms linear;
-o-transition: all 260ms linear;
transition: all 260ms linear;
}
#toolbar {
-webkit-transition: all 280ms linear;
-moz-transition: all 280ms linear;
-ms-transition: all 280ms linear;
-o-transition: all 280ms linear;
transition: all 280ms linear;
}
body {
background: #788587;
color: #424345;
}
body a {
color: #e0e0e0;
}
body h3 {
color: #424345;
}
.toolbar {
background: #788587;
margin-top: -45px;
}
.toolbar:after {
display: block;
content: '...toolbar';
background: rgba(0,0,0,0.07);
}
.toolbar:hover {
margin: 0;
}
.toolbar:hover:after {
display: none;
}
.page-header {
border: none;
}
.entrylist-header {
border: none;
}
.entrylist-header h3,
.entrylist-header a {
margin: 0;
}
.entryList {
padding-top: 18px;
}
#feed-accordion .entry {
border: none;
}
#feed-accordion .unread .entry-heading {
background: #c9c9c9;
}
#feed-accordion .unread:nth-of-type(2n) .entry-heading {
background: #ddd;
}
#feed-accordion .unread .entry-heading:hover,
#feed-accordion .unread:nth-of-type(2n):hover {
background: #ebebeb;
}
#feed-accordion .entry-heading-link {
color: #5a6069 !important;
}
#feed-accordion .entry-heading-link:hover {
color: #000;
}
#feed-accordion .entry-body {
background: #c7cbcc;
padding-left: 15px;
}
#feed-accordion .entry-body a:not([popup]) {
color: #a68589;
}
#feed-accordion .entry-body a:not([popup]):visited {
color: #8d8e8e;
}
#feed-accordion .entry-body img {
-webkit-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
-moz-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
-ms-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
-o-box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
box-shadow: 0 0 2px 0 rgba(0,0,0,0.2);
}
#feed-accordion .highlight-search {
background: inherit;
}
#feed-accordion .entry-buttons {
background: #a68589;
margin-left: -15px;
border: none;
}
#feed-accordion.expanded .entry {
-webkit-box-shadow: none;
-moz-box-shadow: none;
-ms-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
border: none;
margin-bottom: 30px;
}
input[ng-model='keywords'] {
border: none;
height: 32px;
background: #9ba8aa;
}
.css-treeview .selected {
color: #2c4967;
text-decoration: underline;
}
.css-treeview .unread-counter {
color: #222;
}
.css-treeview li .tree-item:hover {
background: #ebebeb;
}
.css-treeview a {
color: #5a6069;
}
.css-treeview a:hover {
font-size: 1.02em;
}
.css-treeview a:hover img {
-webkit-border-radius: 1px;
-moz-border-radius: 1px;
-ms-border-radius: 1px;
-o-border-radius: 1px;
border-radius: 1px;
opacity: 1;
}
.css-treeview img {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
opacity: 0.85;
}
#uvTab {
margin-bottom: -23px;
}
#uvTab:hover {
margin-bottom: 0;
}
}

View File

@@ -0,0 +1,38 @@
<li>
<div class="pointer tree-item" ng-if="showLabel" ng-class="getClass(level - 1)" droppable="node">
<div class="dropdown pull-right">
<div class="pull-right" ng-click="showCategoryDetails(node.id, node.isTag)">
<i class="icon-wrench config pointer"></i>
</div>
</div>
<div class="category-link" ng-click="categoryClicked(node.id, node.isTag)" ng-dblclick="showCategoryDetails(node.id, node.isTag)">
<span class="fldr">
<i ng-class="{'icon-caret-right': !node.expanded, 'icon-caret-down': node.expanded}" ng-click="toggleCategory(node, $event)"
ng-show="showChildren"></i>
<i ng-class="{'icon-star' : node.id == 'starred', 'icon-inbox': node.id == 'all', 'icon-tag' : node.isTag}" ng-show="!showChildren"></i>
</span>
<span ng-class="{selected: (node.id == selectedId && (node.isTag ? selectedType == 'tag' : selectedType == 'category'))}">
<span ng-class="{unread: unreadCount({category:node})}" class="bidi-embed"> {{categoryLabel(node)}} </span>
<span class="unread-counter"> {{categoryCountLabel(node)}} </span>
</span>
</div>
</div>
<ul ng-show="node.expanded && showChildren">
<recursive> <category ng-repeat="child in node.children"
ng-show="settingsService.settings.showRead == true || unreadCount({category:node}) > 0" node="child" level="level + 1"
selected-type="selectedType" selected-id="selectedId" show-label="true" show-children="true"
unread-count="unreadCount({category:category})"> </category> </recursive>
<li ng-repeat="feed in node.feeds" ng-class="getClass(level)" class="tree-item" draggable="feed" droppable="feed"
ng-show="settingsService.settings.showRead == true || feed.unread > 0">
<div class="pull-right" ng-click="showFeedDetails(feed)">
<i class="icon-wrench config pointer"></i>
</div>
<a ng-click="feedClicked(feed.id, $event)" ng-dblclick="showFeedDetails(feed)" class="feed-link" href="{{feed.feedLink}}" target="_blank"
ng-class="{error: feed.message && feed.errorCount > 10, selected: (feed.id == selectedId && selectedType == 'feed') }">
<favicon url="feed.iconUrl" />
<span ng-class="{unread: feed.unread}" class="bidi-embed"> {{feed.name}} </span>
<span class="unread-counter"> {{feedCountLabel(feed)}} </span>
</a>
</li>
</ul>
</li>

View File

@@ -0,0 +1,29 @@
<div ng-controller="FeedSearchCtrl">
<div modal="feedSearchModal" close="close()" options="{dialogClass: 'modal feed-search-dialog'}">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="close()">&times;</button>
<h4>
<input ng-model="filter" class="filter-input"
ui-keydown="{'up': 'focusPrevious($event)', 'down': 'focusNext($event)', 'enter': 'openFocused()' }" placeholder="${feedsearch.hint}"
focus="feedSearchModal">
</h4>
<small>${feedsearch.help}</small>
</div>
<div class="modal-body">
<strong>${feedsearch.result_prefix}</strong>
<span ng-repeat="feed in (filtered = (CategoryService.feeds | filter:{name: filter} | limitTo:40))">
<span ng-class="{block: filter, focus: focus.id == feed.id}" class="feed-link">
<a class=" pointer" ng-click="goToFeed(feed.id)">
<favicon url="feed.iconUrl" />
&nbsp;{{feed.name}}
</a>
<span ng-show="!filter && !$last">&bull;</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<div ng-controller="FooterController">
<iframe ng-if="subToMeUrl" style="display: none;" ng-src='{{subToMeUrl}}'></iframe>
</div>

View File

@@ -0,0 +1,4 @@
<div>
<span>{{label}}</span>
<span>{{metric.value}}</span>
</div>

View File

@@ -0,0 +1,20 @@
<div>
<span>{{label}}</span>
<dl class="dl-horizontal">
<dt>Mean</dt>
<dd>{{metric.meanRate | number:2}}</dd>
<dt>1 min</dt>
<dd>{{metric.oneMinuteRate | number:2}}</dd>
<dt>5 min</dt>
<dd>{{metric.fiveMinuteRate | number:2}}</dd>
<dt>15 min</dt>
<dd>{{metric.fifteenMinuteRate | number:2}}</dd>
<dt>Total</dt>
<dd>{{metric.count}}</dd>
</dl>
</div>

View File

@@ -0,0 +1,71 @@
<dl class="dl-horizontal">
<dt>j</dt>
<dd>${about.shortcuts.open_next_entry}</dd>
<dt>k</dt>
<dd>${about.shortcuts.open_previous_entry}</dd>
<dt>${about.shortcuts.spacebar}</dt>
<dd>${about.shortcuts.move_page_down_up}</dd>
<dt>n</dt>
<dd>${about.shortcuts.focus_next_entry}</dd>
<dt>p</dt>
<dd>${about.shortcuts.focus_previous_entry}</dd>
<dt>shift+j,shift+n</dt>
<dd>${about.shortcuts.open_next_feed}</dd>
<dt>shift+k,shift+p</dt>
<dd>${about.shortcuts.open_previous_feed}</dd>
<dt>o, enter</dt>
<dd>${about.shortcuts.open_close_current_entry}</dd>
<dt>v</dt>
<dd>${about.shortcuts.open_current_entry_in_new_window}</dd>
<dt>b</dt>
<dd>${about.shortcuts.open_current_entry_in_new_window_background}</dd>
<dt>s</dt>
<dd>${about.shortcuts.star_unstar}</dd>
<dt>m</dt>
<dd>${about.shortcuts.mark_current_entry}</dd>
<dt>shift+a</dt>
<dd>${about.shortcuts.mark_all_as_read}</dd>
<dt>${about.shortcuts.mouse_middleclick}</dt>
<dd>${about.shortcuts.open_in_new_tab_mark_as_read}</dd>
<dt>f</dt>
<dd>${about.shortcuts.fullscreen}</dd>
<dt>+,-</dt>
<dd>${about.shortcuts.font_size}</dd>
<dt>
g
<i class="icon-arrow-right"></i>
a
</dt>
<dd>${about.shortcuts.go_to_all}</dd>
<dt>
g
<i class="icon-arrow-right"></i>
s
</dt>
<dd>${about.shortcuts.go_to_starred}</dd>
<dt>
g
<i class="icon-arrow-right"></i>
u
</dt>
<dd>${about.shortcuts.feed_search}</dd>
</dl>

View File

@@ -0,0 +1,12 @@
<span>
<a ng-click="edit_mode=!edit_mode" class="nolink pointer">
<i class="icon-tags"></i>
${global.tags}
</a>
<span ng-if="!edit_mode">
<span class="label label-info" ng-repeat="tag in entry.tags">{{tag}}</span>
</span>
<span ng-if="edit_mode">
<input type="text" ui-select2="select2Options" ng-model="entry.tags" class="tag-input" autofocus />
</span>
</span>

View File

@@ -0,0 +1,136 @@
<div ng-controller="ToolbarCtrl">
<div class="form-horizontal">
<div class="btn-group" ng-if="MobileService.mobile">
<button type="button" class="btn btn-default" ng-click="MobileService.toggleLeftMenu()">
<i class="icon-list-alt"></i>
</button>
</div>
<div class="btn-group">
<a type="button" class="btn btn-default" ng-click="previousEntry()" title="${toolbar.previous_entry}">
<i class="icon-chevron-up"></i>
</a>
<a type="button" class="btn btn-default" ng-click="nextEntry()" title="${toolbar.next_entry}">
<i class="icon-chevron-down"></i>
</a>
<div class="btn-group">
<a type="button" class="btn btn-default" ng-click="refresh()" title="${toolbar.refresh}">
<i class="icon-refresh"></i>
</a>
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
<li>
<a ng-click="refreshAll()">${toolbar.refresh_all}</a>
</li>
</ul>
</div>
</div>
<div class="btn-group">
<a type="button" class="btn btn-default" ng-click="markAllAsRead()" title="${toolbar.mark_all_as_read}">
<i class="icon-ok"></i>
</a>
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
<li>
<a ng-click="markAll12Hours()">${toolbar.mark_all_older_12_hours}</a>
</li>
<li>
<a ng-click="markAllDay()">${toolbar.mark_all_older_day}</a>
</li>
<li>
<a ng-click="markAllWeek()">${toolbar.mark_all_older_week}</a>
</li>
<li>
<a ng-click="markAllTwoWeeks()">${toolbar.mark_all_older_two_weeks}</a>
</li>
</ul>
</div>
<div class="btn-group toolbar-expand" ng-if="MobileService.mobile">
<button type="button" class="btn btn-default" ng-click="MobileService.toggleRightMenu()">
<i ng-class="{'icon-double-angle-right' : !MobileService.rightMenu, 'icon-double-angle-left': MobileService.rightMenu}"></i>
</button>
</div>
<div class="actions btn-group">
<div ng-if="!MobileService.mobile || MobileService.rightMenu">
<div class="btn-group read-mode">
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'unread'"
ng-class="{'active': settingsService.settings.readingMode == 'unread'}">${toolbar.unread}</button>
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'all'"
ng-class="{'active': settingsService.settings.readingMode == 'all'}">${toolbar.all}</button>
</div>
<div class="btn-group">
<a type="button" class="btn btn-default" ng-click="toggleOrder()" title="${toolbar.sort_by_asc_desc}">
<i
ng-class="{'icon-arrow-up' : settingsService.settings.readingOrder == 'asc', 'icon-arrow-down': settingsService.settings.readingOrder == 'desc'}"></i>
</a>
</div>
<div class="btn-group">
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'title'"
ng-class="{'active': settingsService.settings.viewMode == 'title'}" title="${toolbar.titles_only}">
<i class="icon-list"></i>
</a>
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'expanded'"
ng-class="{'active': settingsService.settings.viewMode == 'expanded'}" title="${toolbar.expanded_view}">
<i class="icon-th-list"></i>
</a>
</div>
<div class="btn-group">
<a class="btn btn-default" ng-click="toSettings()" title="${toolbar.settings}">
<i class="icon-cog"></i>
</a>
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
<li>
<a ng-click="toProfile()">
<i class="icon-user"></i>
${toolbar.profile}
</a>
</li>
<li ng-show="session.admin">
<a ng-click="toAdmin()">
<i class="icon-edit"></i>
${toolbar.admin}
</a>
</li>
<li class="divider"></li>
<li>
<a href="logout">
<i class="icon-off"></i>
${toolbar.logout}
</a>
</li>
</ul>
</div>
<div class="btn-group">
<form ng-submit="search()" class="input-group keywords" ng-if="!MobileService.mobile">
<input type="text" class="form-control" ng-model="keywords"></input>
<span class="input-group-btn">
<button class="btn btn-default" type="submit">
<i class="icon-search"></i>
</button>
</span>
</form>
</div>
<div class="btn-group donate">
<a class="btn btn-success" type="button" ng-click="toHelp()" title="${toolbar.about} / ${toolbar.donate}">
<i class="icon-info-sign"></i>
</a>
</div>
</div>
</div>
<span ng-if="!MobileService.mobile" ng-bind-html="ServerService.announcement | trustHtml"></span>
</div>
</div>

View File

@@ -0,0 +1,49 @@
<div ng-controller="CategoryTreeCtrl" class="sidebar-nav-fixed" mousewheel-scrolling ui-jq="resizable"
ui-options="{handles: 'e', resize: resizeCallback}">
<div class="btn-group">
<button class="btn btn-default" ui-sref="feeds.subscribe" ng-click="MobileService.toggleLeftMenu()">
<span class="icon-rss"></span>
${tree.subscribe}
</button>
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
<a ui-sref="feeds.new_category" ng-click="MobileService.toggleLeftMenu()">
<i class="icon-plus"></i>
${tree.new_category}
</a>
</li>
<li>
<a ui-sref="feeds.import" ng-click="MobileService.toggleLeftMenu()">
<i class="icon-arrow-down"></i>
${tree.import}
</a>
</li>
</ul>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default" ng-click="MobileService.toggleLeftMenu()" ng-if="MobileService.mobile">
<i class="icon-remove"></i>
${global.close}
</button>
</div>
<div class="css-treeview">
<ul>
<category node="CategoryService.subscriptions" show-label="'${tree.all}'" show-children="false" level="0" selected-type="selectedType"
selected-id="selectedId" unread-count="unreadCount(category)"> </category>
<category node="starred" show-label="'${tree.starred}'" show-children="false" level="0" selected-type="selectedType"
selected-id="selectedId" unread-count="unreadCount(category)"> </category>
<category node="CategoryService.subscriptions" show-label="false" show-children="true" level="0" selected-type="selectedType"
selected-id="selectedId" unread-count="unreadCount(category)"> </category>
<li ng-repeat="tag in tags | orderBy: 'name'">
<category node="tag" show-label="tag.name" show-children="false" level="0" selected-type="selectedType" selected-id="selectedId"
unread-count="unreadCount(category)"> </category>
</li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<div class="container">
<div class="admin" ui-view></div>
</div>

View File

@@ -0,0 +1,24 @@
<div>
<metric-meter metric="metrics.meters['com.commafeed.backend.feeds.FeedRefreshTaskGiver.refill']" label="'Refresh queue refill rate (/sec)'"></metric-meter>
<metric-meter metric="metrics.meters['com.commafeed.backend.feeds.FeedRefreshTaskGiver.feedRefreshed']" label="'Feed refreshed (/sec)'"></metric-meter>
<metric-meter metric="metrics.meters['com.commafeed.backend.feeds.FeedRefreshUpdater.feedUpdated']" label="'Feed updated (/sec)'"></metric-meter>
<metric-meter metric="metrics.meters['com.commafeed.backend.feeds.FeedRefreshUpdater.entryCacheHit']" label="'Entry cache hit (/sec)'"></metric-meter>
<metric-meter metric="metrics.meters['com.commafeed.backend.feeds.FeedRefreshUpdater.entryCacheMiss']" label="'Entry cache miss (/sec)'"></metric-meter>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshExecutor.feed-refresh-updater.active']"
label="'Feed Updater active'"></metric-gauge>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshExecutor.feed-refresh-updater.pending']"
label="'Feed Updater queued'"></metric-gauge>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshExecutor.feed-refresh-worker.active']"
label="'Feed Worker active'"></metric-gauge>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshExecutor.feed-refresh-worker.pending']"
label="'Feed Worker queued'"></metric-gauge>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshTaskGiver.addQueue']"
label="'Task Giver Add Queue'"></metric-gauge>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshTaskGiver.takeQueue']"
label="'Task Giver Take Queue'"></metric-gauge>
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feeds.FeedRefreshTaskGiver.giveBackQueue']"
label="'Task Giver Give Back Queue'"></metric-gauge>
</div>

View File

@@ -0,0 +1,182 @@
<div class="row">
<div class="page-header">
<h1>
Application settings
<small>
<a ng-click="toUsers()" class="pointer">Manage users</a>
</small>
</h1>
</div>
<div>
<form name="settingsForm" class="form-horizontal" ng-submit="save()">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="control-label col-sm-3" for="publicUrl">Public URL</label>
<div class="col-sm-9">
<input type="text" id="publicUrl" name="publicUrl" class="form-control" placeholder="http://localhost:8082/commafeed"
ng-model="settings.publicUrl" />
<span class="help-block">The URL in your address bar right now, up to the # (not included)</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="publicUrl">Allow registrations</label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" id="allowRegistrations" name="allowRegistrations" ng-model="settings.allowRegistrations" />
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="feedbackButton">Feedback button</label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" id="feedbackButton" name="feedbackButton" ng-model="settings.feedbackButton" />
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="googleClientId">Google client ID</label>
<div class="col-sm-9">
<input type="text" name="googleClientId" class="form-control" ng-model="settings.googleClientId" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="googleClientSecret">Google client secret</label>
<div class="col-sm-9">
<input type="text" name="googleClientSecret" class="form-control" ng-model="settings.googleClientSecret" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="googleAnalyticsTrackingCode">Google Analytics tracking code</label>
<div class="col-sm-9">
<input type="text" name="googleAnalyticsTrackingCode" class="form-control" ng-model="settings.googleAnalyticsTrackingCode" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="googleClientSecret">Background HTTP threads</label>
<div class="col-sm-9">
<input type="number" name="backgroundThreads" class="form-control" ng-model="settings.backgroundThreads" />
<span class="help-inline">Requires restart</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="databaseUpdateThreads">Database update threads</label>
<div class="col-sm-9">
<input type="number" name="databaseUpdateThreads" class="form-control" ng-model="settings.databaseUpdateThreads" />
<span class="help-inline">Requires restart</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="announcement">Announcement</label>
<div class="col-sm-9">
<textarea name="announcement" rows="10" class="form-control" ng-model="settings.announcement">
</textarea>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="control-label col-sm-3" for="announcement">SMTP Host</label>
<div class="col-sm-9">
<input type="text" name="smtpHost" class="form-control" ng-model="settings.smtpHost" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="announcement">SMTP Port</label>
<div class="col-sm-9">
<input type="text" name="smtpPort" class="form-control" ng-model="settings.smtpPort" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="smtpTls">SMTP TLS </label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" name="smtpTls" ng-model="settings.smtpTls" />
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="smtpUserName">SMTP Username</label>
<div class="col-sm-9">
<input type="text" name="smtpUserName" class="form-control" ng-model="settings.smtpUserName" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="smtpPassword">SMTP Password</label>
<div class="col-sm-9">
<input type="password" name="smtpPassword" class="form-control" ng-model="settings.smtpPassword" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="heavyLoad">Heavy load</label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" name="heavyLoad" ng-model="settings.heavyLoad" />
<span class="help-block">Don't use this unless you know what you're doing!</span>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="pubsubhubbub">PubSubHubbub</label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" name="pubsubhubbub" ng-model="settings.pubsubhubbub" />
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="imageProxyEnabled">Proxy entry images</label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" name="imageProxyEnabled" ng-model="settings.imageProxyEnabled" />
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="logLevel">Logging level</label>
<div class="col-sm-9">
<select name="logLevel" ng-model="settings.logLevel" class="form-control"
ng-options="level for level in ['DEBUG', 'INFO', 'WARN', 'ERROR']">
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="logLevel">Database query timeout (ms)</label>
<div class="col-sm-9">
<input type="number" name="queryTimeout" class="form-control" ng-model="settings.queryTimeout" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="keepStatusDays">Keep read status for (days)</label>
<div class="col-sm-9">
<input type="number" name="keepStatusDays" class="form-control" ng-model="settings.keepStatusDays" />
<span class="help-inline">0 = keep forever</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="refreshIntervalMinutes">Refresh feeds every (minutes)</label>
<div class="col-sm-9">
<input type="number" name="refreshIntervalMinutes" class="form-control" min="1" ng-model="settings.refreshIntervalMinutes" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="crawlingPaused">Pause crawling</label>
<div class="col-sm-9">
<div class="checkbox">
<input type="checkbox" name="crawlingPaused" ng-model="settings.crawlingPaused" />
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="text-center form-group">
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,40 @@
<div class="row">
<div class="page-header">
<h1>Add user</h1>
</div>
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
<form name="userAddForm" class="form-horizontal" ng-submit="save()">
<div class="form-group" ng-class="{error : !userAddForm.name.$valid}">
<label class="col-sm-2 control-label" for="name">User name</label>
<div class="col-sm-10">
<input type="text" id="name" name="name" ng-model="user.name" required class="form-control" />
</div>
</div>
<div class="form-group" ng-class="{error : !userAddForm.password.$valid}">
<label class="col-sm-2 control-label" for="password">Password</label>
<div class="col-sm-10">
<input type="password" id="password" name="password" class="form-control" ng-model="user.password" required />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="admin">Admin</label>
<div class="col-sm-10">
<input type="checkbox" name="admin" ng-model="user.admin" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="enabled">Enabled</label>
<div class="col-sm-10">
<input type="checkbox" name="enabled" ng-model="user.enabled" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,48 @@
<div class="row">
<div class="page-header">
<h1>Edit user</h1>
</div>
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
<form name="userAddForm" class="form-horizontal" ng-submit="save()">
<div class="form-group" ng-class="{error : !userAddForm.name.$valid}">
<label class="col-sm-2 control-label" for="name">User name</label>
<div class="col-sm-10">
<input type="text" id="name" name="name" ng-model="user.name" class="form-control" required />
</div>
</div>
<div class="form-group" ng-class="{error : !userAddForm.password.$valid}">
<label class="col-sm-2 control-label" for="password">Password</label>
<div class="col-sm-10">
<input type="password" id="password" name="password" class="form-control" ng-model="user.password" />
<span class="help-block">Leave blank if you don't want to change the password.</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="email">Email</label>
<div class="col-sm-10">
<input type="text" id="email" name="email" ng-model="user.email" class="form-control" required />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="admin">Admin</label>
<div class="col-sm-10">
<input type="checkbox" name="admin" ng-model="user.admin" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="enabled">Enabled</label>
<div class="col-sm-10">
<input type="checkbox" name="enabled" ng-model="user.enabled" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-danger" ng-click="remove()" confirm-click="Are you sure you want to delete this user?">Delete</button>
<button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,13 @@
<div class="row">
<div class="page-header">
<h1>Manage users</h1>
</div>
<div>
<div class="button-bar">
<button class="btn btn-default" ng-click="addUser()">Add user</button>
<button class="btn btn-default" ng-click="back()">Back</button>
</div>
<div class="users-table" ng-grid="gridOptions"></div>
</div>
</div>

View File

@@ -0,0 +1,49 @@
<div>
<div class="page-header">
<h3>${details.category_details}</h3>
</div>
<form name="form" class="form-horizontal" ng-submit="save()">
<div class="form-group" ng-class="{error : !form.name.$valid}" ng-if="!isMeta()">
<label class="col-sm-2 control-label">${details.name}</label>
<div class="col-sm-10">
<input type="text" name="name" ng-model="category.name" class="form-control" required></input>
<span class="help-block" ng-show="!form.name.$valid">${global.required}</span>
</div>
</div>
<div class="form-group" ng-class="{error : !form.category.$valid}" ng-if="!isMeta()">
<label class="col-sm-2 control-label">${details.parent_category}</label>
<div class="col-sm-10">
<select name="category" class="form-control" ng-model="category.parentId"
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories | filter: filterCurrent">
</select>
<span class="help-block" ng-show="!form.category.$valid">${global.required}</span>
</div>
</div>
<div class="form-group" ng-if="!isMeta()">
<label class="col-sm-2 control-label">${details.position}</label>
<div class="col-sm-10">
<input type="number" min="0" ng-model="category.position" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.feed_url}</label>
<div class="col-sm-10 checkbox">
<a ng-show="user.apiKey" href="{{'rest/category/entriesAsFeed?id=' + category.id + '&apiKey=' + user.apiKey}}" target="_blank">${global.link}</a>
<span ng-show="!user.apiKey">${details.generate_api_key_first}</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" ng-if="!isMeta()">${global.save}</button>
<button type="button" class="btn btn-danger" ng-click="deleteCategory()" ng-show="!isMeta()"
confirm-click="${details.delete_category_confirmation}">${global.delete}</button>
<button type="button" class="btn btn-default" ng-click="back()">${global.cancel}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,81 @@
<div>
<div class="page-header">
<h3>${details.feed_details}</h3>
</div>
<form name="form" class="form-horizontal" ng-submit="save()">
<div class="form-group">
<label class="col-sm-2 control-label">${details.url}</label>
<div class="col-sm-10 checkbox">
<a href="{{sub.feedUrl}}" target="_blank">{{sub.feedUrl}}</a>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.website}</label>
<div class="col-sm-10 checkbox">
<a href="{{sub.feedLink}}" target="_blank">{{sub.feedLink}}</a>
</div>
</div>
<div class="form-group" ng-class="{error : !form.name.$valid}">
<label class="col-sm-2 control-label">${details.name}</label>
<div class="col-sm-10">
<input type="text" name="name" ng-model="sub.name" class="form-control" required></input>
<span class="help-block" ng-show="!form.name.$valid">${global.required}</span>
</div>
</div>
<div class="form-group" ng-class="{error : !form.category.$valid}">
<label class="col-sm-2 control-label">${details.category}</label>
<div class="col-sm-10">
<select name="category" class="form-control" ng-model="sub.categoryId"
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories">
</select>
<span class="help-block" ng-show="!form.category.$valid">${global.required}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.position}</label>
<div class="col-sm-10">
<input type="number" min="0" ng-model="sub.position" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.last_refresh}</label>
<div class="col-sm-10 checkbox">
<span>{{sub.lastRefresh|entryDate}}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.next_refresh}</label>
<div class="col-sm-10 checkbox">
<span>{{sub.nextRefresh|entryDate:"${details.queued_for_refresh}" }}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.message}</label>
<div class="col-sm-10 checkbox">
<span>{{sub.message}}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">${details.feed_url}</label>
<div class="col-sm-10 checkbox">
<a ng-show="user.apiKey" href="{{'rest/feed/entriesAsFeed?id=' + sub.id + '&apiKey=' + user.apiKey}}" target="_blank">${global.link}</a>
<span ng-show="!user.apiKey">${details.generate_api_key_first}</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">${global.save}</button>
<button type="button" class="btn btn-danger" ng-click="unsubscribe()" confirm-click="${details.unsubscribe_confirmation}">${details.unsubscribe}</button>
<button type="button" class="btn btn-default" ng-click="back()">${global.cancel}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,144 @@
<div class="row help">
<div class="col-md-6">
<div class="about-module">
<h4>
<i class="icon-question-sign"></i>
${toolbar.about}
</h4>
<p>
${about.line1_prefix}
<a href="https://github.com/Athou/commafeed" target="_blank">GitHub</a>
${about.line1_suffix}
</p>
<p>
${about.line2_prefix}
<a href="https://github.com/Athou/commafeed/issues" target="_blank">GitHub</a>
${about.line2_suffix}
</p>
${about.version} {{infos.version}} ({{infos.gitCommit}})
</div>
<div class="about-module">
<h4>
<i class="icon-money"></i>
${toolbar.donate}
</h4>
<p>${about.line3}</p>
<form class="donate-action" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_donations">
<input type="hidden" name="business" value="9CNQHMJG2ZJVY">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="CommaFeed">
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donateCC_LG.gif:NonHosted">
<input type="image" class="donate-image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit"
alt="PayPal - The safer, easier way to pay online!">
<input type="hidden" name="currency_code" value="USD">
<select name="currency_code">
<option value="EUR">Euro</option>
<option value="USD">US Dollars</option>
</select>
</form>
${about.line4}
<code class="bitcoin-code">1dymfUxqCWpyD7a6rQSqNy4rLVDBsAr5e</code>
</div>
<div class="about-module">
<h4>
<i class="icon-puzzle-piece"></i>
${about.goodies}
</h4>
<p>
${about.goodies.android_app}:
<a href="https://github.com/Athou/commafeed-newsplus" target="_blank">News+ extension</a>
,
<a href="https://play.google.com/store/apps/details?id=com.commafeed.commafeedreader" target="_blank">CommaFeed Reader</a>
,
<a href="https://play.google.com/store/apps/details?id=com.mv.cloudfeedlr" target="_blank">Cloudfeedlr</a>
</p>
<p>
<a href="https://chrome.google.com/webstore/detail/commafeed/bpbfpjiciblcfeganojjkfapnllbhdga" target="_blank">${about.goodies.chrome_extension}</a>
</p>
<p>
<a href="https://addons.mozilla.org/en-US/firefox/addon/commafeed/" target="_blank">${about.goodies.firefox_extension}</a>
</p>
<p>
<a href="https://addons.opera.com/en/extensions/details/commafeed-extension-for-opera/" target="_blank">${about.goodies.opera_extension}</a>
</p>
<p>
${about.goodies.subscribe_url}:
<a href="rest/feed/subscribe?url=FEED_URL_HERE" target="_blank">rest/feed/subscribe?url=FEED_URL_HERE</a>
</p>
<p>
${about.goodies.subscribe_bookmarklet}:
<a href="https://www.subtome.com/settings.html" target="_blank">SubToMe</a>
</p>
<p>
${about.goodies.next_unread_bookmarklet}:
<br />
<br />
${subscribe.category}
<select ng-model="categoryId" ng-options="cat.id as cat.name for cat in CategoryService.flatCategories" class="bookmarklet-select">
</select>
<select ng-model="order" class="bookmarklet-select">
<option value="desc">${about.goodies.subscribe_bookmarklet_desc}</option>
<option value="asc">${about.goodies.subscribe_bookmarklet_asc}</option>
</select>
<a href="javascript:window.location.href='{{baseUrl}}next?category={{categoryId}}&order={{order}}&t='+new Date().getTime();"
target="_blank">${global.link}</a>
</p>
</div>
<div class="about-module">
<h4>
<i class="icon-globe"></i>
${about.translation}
</h4>
<p>${about.translation.message}</p>
<p>
<a href="https://github.com/Athou/commafeed#translate-commafeed-into-your-language" target="_blank"> ${about.translation.link} </a>
</p>
</div>
<div class="about-module">
<h4>
<i class="icon-rocket"></i>
${about.rest_api}
</h4>
<p>${about.rest_api.line1}</p>
<p>
<a href="api" target="_blank">${about.rest_api.link_to_documentation}</a>
</p>
</div>
</div>
<div class="col-md-6">
<div class="about-module">
<h4>
<i class="icon-keyboard"></i>
${about.keyboard_shortcuts}
</h4>
<div ng-include="'templates/_shortcuts.html'"></div>
</div>
<div class="about-module">
<h4>
<i class="icon-info-sign"></i>
${about.announcements}
</h4>
<a class="twitter-timeline" href="https://twitter.com/CommaFeed" data-widget-id="333897786657480704">Tweets by @CommaFeed</a>
<script>
!function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0], p = /^http:/.test(d.location) ? 'http' : 'https';
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = p + "://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");
</script>
</div>
</div>
</div>

View File

@@ -0,0 +1,13 @@
<div class="container-full">
<div class="left-menu">
<div ng-include="'templates/_tree.html'"></div>
<div ng-include="'templates/_feedsearch.html'"></div>
</div>
<div class="main-content">
<div id="toolbar" class="toolbar" ng-include="'templates/_toolbar.html'"></div>
<div class="entryList">
<div ui-view></div>
</div>
</div>
<div ng-include="'templates/_footer.html'"></div>
</div>

View File

@@ -0,0 +1,19 @@
<div>
<div class="page-header">
<h3>${tree.import}</h3>
</div>
<form class="form-horizontal" action="rest/feed/import" method="post" enctype="multipart/form-data">
<div class="form-group">
<label class="col-sm-2 control-label">${import.xml_file}</label>
<div class="col-sm-10 ">
<input type="file" name="file" class="form-control"></input>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-primary ok" type="submit">${tree.import}</button>
<button type="button" class="btn btn-default cancel" ng-click="back()">${global.cancel}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,29 @@
<div>
<div class="page-header">
<h3>${tree.new_category}</h3>
</div>
<form name="categoryForm" class="form-horizontal" ng-submit="saveCategory()">
<div class="form-group" ng-class="{error : !categoryForm.name.$valid}">
<label class="col-sm-2 control-label">${new_category.name}</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" ng-model="cat.name" required></input>
<span class="help-block" ng-show="!categoryForm.name.$valid">${global.required}</span>
</div>
</div>
<div class="form-group" ng-class="{error : !categoryForm.category.$valid}">
<label class="col-sm-2 control-label">${new_category.parent}</label>
<div class="col-sm-10">
<select name="category" ng-model="cat.parentId" class="form-control"
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories" required>
</select>
<span class="help-block" ng-show="!categoryForm.category.$valid">${global.required}</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-primary ok" type="submit">${global.save}</button>
<button type="button" class="btn btn-default cancel" ng-click="back()">${global.cancel}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,39 @@
<div>
<div class="page-header">
<h3>${tree.subscribe}</h3>
</div>
<form name="subscribeForm" class="form-horizontal" ng-submit="save()">
<div class="form-group" ng-class="{error : !subscribeForm.url.$valid}">
<label class="col-sm-2 control-label">${subscribe.feed_url}</label>
<div class="col-sm-10">
<input type="text" name="url" ng-model="sub.url" ng-blur="urlChanged()" placeholder="http://example.com/feed" class="form-control"
required ng-disabled="state=='loading'" autofocus></input>
<span class="help-block" ng-show="!subscribeForm.url.$valid">${global.required}</span>
</div>
</div>
<div class="form-group" ng-class="{error : !subscribeForm.title.$valid}">
<label class="col-sm-2 control-label">${subscribe.feed_name}</label>
<div class="col-sm-10">
<input type="text" name="title" ng-model="sub.title" class="form-control" required ng-disabled="state=='loading'"></input>
<span class="help-block" ng-show="!subscribeForm.title.$valid">${global.required}</span>
</div>
</div>
<div class="form-group" ng-class="{error : !subscribeForm.category.$valid}">
<label class="col-sm-2 control-label">${subscribe.category}</label>
<div class="col-sm-10">
<select name="category" ng-model="sub.categoryId" class="form-control"
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories" required>
</select>
<span class="help-block" ng-show="!subscribeForm.category.$valid">${global.required}</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-primary ok" type="submit" ng-disabled="state!='ok'">${global.save}</button>
<button class="btn btn-default cancel" ng-click="back()" type="button">${global.cancel}</button>
</div>
</div>
</form>
<pre ng-if="state == 'failed'">{{stacktrace}}</pre>
</div>

View File

@@ -0,0 +1,23 @@
<div>
<div class="page-header">
<h3>${details.tag_details}</h3>
</div>
<form name="form" class="form-horizontal" ng-submit="save()">
<div class="form-group">
<label class="col-sm-2 control-label">${details.feed_url}</label>
<div class="col-sm-10">
<div class="checkbox">
<a ng-show="user.apiKey" href="{{'rest/category/entriesAsFeed?id=all&tag=' + tag + '&apiKey=' + user.apiKey}}" target="_blank">${global.link}</a>
<span ng-show="!user.apiKey">${details.generate_api_key_first}</span>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" class="btn btn-default" ng-click="back()">${global.cancel}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,153 @@
<div ng-class="{expanded: settingsService.settings.viewMode == 'expanded'}">
<div class="entrylist-header" ng-if="name">
<h3>
<span ng-switch on="selectedId">
<span ng-switch-when="all">${tree.all}</span>
<span ng-switch-when="starred">${tree.starred}</span>
<span ng-switch-default>
<span ng-hide="feedLink">{{name}}</span>
<a ng-show="feedLink" href="{{feedLink}}" target="_blank">{{name}}</a>
</span>
</span>
<span ng-show="name"> &#187;</span>
<span ng-show="keywords">${view.search_for} '{{keywords}}'</span>
</h3>
</div>
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode"
infinite-scroll-distance="1" id="feed-accordion" ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
<div ng-show="message && errorCount > 10">${view.error_while_loading_feed} : {{message}}</div>
<div ng-repeat="entry in entries" class="entry entry-font-size-{{font_size}}" id="entry_{{entry.id}}"
ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen }">
<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)">
<span class="feed-name">
<span class="star" ng-mouseup="star(entry, !entry.starred, $event)">
<i ng-class="{'icon-star icon-star-yellow': entry.starred, 'icon-star-empty': !entry.starred}" class="pointer"></i>
</span>
<favicon url="entry.iconUrl" />
{{entry.feedName}}
</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>
</a>
<a href="{{entry.url}}" target="_blank" class="entry-external-link" ng-click="mark(entry, true)">
<i class="icon-external-link"></i>
</a>
</div>
<div class="entry-body" ng-if="settingsService.settings.viewMode == 'expanded' || (isOpen && current == entry)"
ng-mouseup="bodyClicked(entry, $event)" ng-class="{rtl: entry.rtl}">
<div class="entry-header">
<div class="entry-title">
<a href="{{entry.url}}" target="_blank" ng-bind-html="entry.title | highlight:keywords | trustHtml"></a>
<div class="entry-subtitle">
<span class="entry-source" ng-if="selectedType == 'category'">
<span class="entry-source-prefix">${view.entry_source}</span>
<a ng-click="goToFeed(entry.feedId)" class="pointer bidi-embed">
<span>{{entry.feedName}}</span>
</a>
</span>
<span class="entry-author" ng-if="entry.author">
<span class="entry-author-prefix">${view.entry_author}</span>
<span class="entry-author-name">{{entry.author}}</span>
</span>
</div>
</div>
</div>
<div class="entry-body-content">
<div ng-if="!MobileService.mobile" ng-bind-html="entry.content | iframeHttpsRewrite| highlight:keywords | trustHtml"></div>
<div ng-if="MobileService.mobile" ng-bind-html="entry.content | iframeHttpsRewrite| highlight:keywords | appendImageTitles | trustHtml"></div>
<div class="entry-enclosure" ng-if="entry.enclosureType">
<video controls ng-if="entry.enclosureType && entry.enclosureType.indexOf('video') == 0">
<source ng-src="{{entry.enclosureUrl | trustUrl}}" type="{{entry.enclosureType}}" />
</video>
<audio controls ng-if="entry.enclosureType && entry.enclosureType.indexOf('audio') == 0">
<source ng-src="{{entry.enclosureUrl | trustUrl}}" type="{{entry.enclosureType}}" />
</audio>
<div ng-if="entry.enclosureType && entry.enclosureType.indexOf('image') == 0">
<img ng-src="{{entry.enclosureUrl | trustUrl}}" />
</div>
<a ng-href="{{entry.enclosureUrl | trustUrl}}" target="_blank" ng-if="entry.enclosureType" download> ${global.download} </a>
</div>
</div>
<div class="entry-buttons form-inline">
<div class="form-group 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>
</div>
<div class="checkbox-inline keep-unread">
<label ng-if="entry.markable" class="pointer">
<input type="checkbox" ng-checked="!entry.read" ng-click="mark(entry, !entry.read)" class="mousetrap"></input>
${view.keep_unread}
</label>
</div>
<span class="share-buttons">
<a href="mailto:?subject={{entry.title|escape}}&body={{entry.url|escape}}" title="E-mail" popup ng-if="settingsService.settings.email">
<i class="icon-envelope"></i>
</a>
<a href="https://mail.google.com/mail/?view=cm&fs=1&tf=1&source=mailto&su={{entry.title|escape}}&body={{entry.url|escape}}"
title="Gmail" popup ng-if="settingsService.settings.gmail">
<i class="icon-gmail"></i>
</a>
<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>
</a>
<a href="http://twitter.com/share?text={{entry.title|escape}}&url={{entry.url|escape}}" title="Twitter" popup
ng-if="settingsService.settings.twitter">
<i class="icon-twitter"></i>
</a>
<a href="https://plus.google.com/share?url={{entry.url|escape}}" title="Google+" popup ng-if="settingsService.settings.googleplus">
<i class="icon-google-plus"></i>
</a>
<a href="http://www.tumblr.com/share/link?url={{entry.url|escape}}&name={{entry.title|escape}}" title="Tumblr" popup
ng-if="settingsService.settings.tumblr">
<i class="icon-tumblr"></i>
</a>
<a href="https://getpocket.com/save?url={{entry.url|escape}}&title={{entry.title|escape}}" title="Pocket" popup
ng-if="settingsService.settings.pocket">
<i class="icon-pocket"></i>
</a>
<a href="https://www.instapaper.com/hello2?url={{entry.url|escape}}&title={{entry.title|escape}}" title="Instapaper" popup
ng-if="settingsService.settings.instapaper">
<i class="icon-instapaper"></i>
</a>
<a href="https://bufferapp.com/add?url={{entry.url|escape}}&text={{entry.title|escape}}" title="Buffer" popup
ng-if="settingsService.settings.buffer">
<i class="icon-buffer"></i>
</a>
<a href="http://www.readability.com/save?url={{entry.url|escape}}" title="Readability" popup
ng-if="settingsService.settings.readability">
<i class="icon-couch"></i>
</a>
</span>
<span class="tags-panel">
<tags entry="entry"></tags>
</span>
<a ng-click="markUpTo(entry)" class="mark-up-to" title="${view.mark_up_to_here}">
<i class="icon-step-forward icon-rotate-90"></i>
</a>
</div>
</div>
</div>
<div class="no-entries" ng-show="name && entries.length == 0 && !busy">
<span ng-show="keywords">${view.no_search_results}</span>
<span ng-hide="keywords">"{{name}}" ${view.no_unread_items}</span>
</div>
<div modal="shortcutsModal" close="shortcutsModal=false" options="shortcutsOpts">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="shortcutsModal=false">&times;</button>
<h4>${about.keyboard_shortcuts}</h4>
</div>
<div class="modal-body" ng-include="'templates/_shortcuts.html'"></div>
</div>
</div>
</div>
</div>
<div style="height: 30px" ng-if="settingsService.settings.viewMode != 'expanded' && entries.length != 0"></div>
<div style="height: 1000px" ng-if="settingsService.settings.viewMode == 'expanded' && entries.length != 0"></div>
</div>

View File

@@ -0,0 +1,65 @@
<div class="profile">
<div class="page-header">
<h1>${toolbar.profile}</h1>
</div>
<form name="profileForm" ng-submit="save()" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label" for="email">${profile.user_name}</label>
<div class="col-sm-10 checkbox">
<span>{{user.name}}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="email">${profile.email}</label>
<div class="col-sm-10">
<input type="email" id="email" ng-model="user.email" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">${profile.change_password}</label>
<div class="col-sm-10">
<input type="password" name="password" id="password" ng-model="user.password" class="form-control" ng-minlength="6" />
<span class="help-inline" ng-show="profileForm.password.$error.minlength">${profile.minimum_6_chars}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">${profile.confirm_password}</label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password_c" id="password_c" ng-model="password_c"
ui-validate="'$value==user.password'" ui-validate-watch="'user.password'">
<span class="help-inline" ng-show="profileForm.password_c.$error.validator">${profile.passwords_do_not_match}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">${profile.api_key}</label>
<div class="col-sm-10">
<pre ng-show="user.apiKey">{{user.apiKey}}</pre>
<span class="help-block" ng-show="!user.apiKey">${profile.api_key_not_generated}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">${profile.generate_new_api_key}</label>
<div class="col-sm-10">
<div class="checkbox">
<input type="checkbox" name="newApiKey" id="newApiKey" ng-model="newApiKey">
<span class="help-inline">${profile.generate_new_api_key_info}</span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">${profile.opml_export}</label>
<div class="col-sm-10 checkbox">
<a href="rest/feed/export" download="commafeed_opml.xml">${global.download}</a>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">${global.save}</button>
<button type="button" class="btn btn-danger" ng-click="deleteAccount()" confirm-click="${profile.delete_account_confirmation}">${profile.delete_account}</button>
<button type="button" class="btn btn-default" ng-click="cancel()">${global.cancel}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,145 @@
<div class="settings">
<div class="page-header">
<h1>${toolbar.settings}</h1>
</div>
<form name="settingsForm" ng-submit="save()">
<div class="row">
<div class="col-md-2">
<ul class="nav nav-pills nav-stacked">
<li ng-class="{active: !tab || tab == 'general'}" class="pointer">
<a ng-click="tab = 'general'">${settings.general}</a>
</li>
<li ng-class="{active: tab == 'css'}" class="pointer">
<a ng-click="tab = 'css'">${settings.appearance}</a>
</li>
</ul>
</div>
<div class="col-md-10">
<div class="tab-content">
<div class="tab-pane" ng-class="{active: !tab || tab == 'general'}">
<div class="form-horizontal">
<div class="form-group">
<label>${settings.general.language}</label>
<select name="language" ng-model="settings.language" class="form-control"
ng-options="id as label for (id,label) in ServerService.supportedLanguages" required>
</select>
<span class="help-block">
<a href="https://github.com/Athou/commafeed#translate-commafeed-into-your-language" target="_blank">
${settings.general.language.contribute} </a>
</span>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="showRead" ng-model="settings.showRead" />
${settings.general.show_unread}
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="scrollMarks" ng-model="settings.scrollMarks" />
${settings.general.scroll_marks}
</label>
</div>
<div>
<h4>${settings.general.social_buttons}</h4>
<div>
<label>
<input type="checkbox" name="email" ng-model="settings.email" />
<i class="icon-envelope"></i>
E-Mail
</label>
</div>
<div>
<label>
<input type="checkbox" name="gmail" ng-model="settings.gmail" />
<i class="icon-gmail"></i>
GMail
</label>
</div>
<div>
<label>
<input type="checkbox" name="facebook" ng-model="settings.facebook" />
<i class="icon-facebook"></i>
Facebook
</label>
</div>
<div>
<label>
<input type="checkbox" name="twitter" ng-model="settings.twitter" />
<i class="icon-twitter"></i>
Twitter
</label>
</div>
<div>
<label>
<input type="checkbox" name="googleplus" ng-model="settings.googleplus" />
<i class="icon-google-plus"></i>
Google+
</label>
</div>
<div>
<label>
<input type="checkbox" name="tumblr" ng-model="settings.tumblr" />
<i class="icon-tumblr"></i>
Tumblr
</label>
</div>
<div>
<label>
<input type="checkbox" name="pocket" ng-model="settings.pocket" />
<i class="icon-pocket"></i>
Pocket
</label>
</div>
<div>
<label>
<input type="checkbox" name="instapaper" ng-model="settings.instapaper" />
<i class="icon-instapaper"></i>
Instapaper
</label>
</div>
<div>
<label>
<input type="checkbox" name="buffer" ng-model="settings.buffer" />
<i class="icon-buffer"></i>
Buffer
</label>
</div>
<div>
<label>
<input type="checkbox" name="readability" ng-model="settings.readability" />
<i class="icon-couch"></i>
Readability
</label>
</div>
</div>
</div>
</div>
<div class="tab-pane" ng-class="{active: tab == 'css'}">
<div class="form-group">
<label>${settings.scroll_speed}</label>
<input type="number" ng-model="settings.scrollSpeed" min="0" max="1000" class="form-control" />
<span class="help-inline">${settings.scroll_speed.help}</span>
</div>
<div class="form-group">
<label>${settings.theme}</label>
<select ng-model="settings.theme" ng-options="theme for theme in themes" class="form-control"></select>
<span class="help-block">
<a href="https://github.com/Athou/commafeed#themes" target="_blank"> ${settings.submit_your_theme} </a>
</span>
</div>
<div class="form-group">
<label>${settings.custom_css}</label>
<textarea ng-model="settings.customCss" class="form-control" rows="20">
</textarea>
</div>
</div>
</div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">${global.save}</button>
<button type="button" class="btn btn-default" ng-click="cancel()">${global.cancel}</button>
</div>
</form>
</div>