diff options
-rw-r--r-- | coffee/controllers/addnewcontroller.coffee | 20 | ||||
-rw-r--r-- | coffee/controllers/controllers.coffee | 11 | ||||
-rw-r--r-- | coffee/controllers/feedcontroller.coffee | 55 | ||||
-rw-r--r-- | coffee/controllers/settingscontroller.coffee | 82 | ||||
-rw-r--r-- | coffee/directives/addfolderselect.coffee | 33 | ||||
-rw-r--r-- | coffee/directives/droppable.coffee | 4 | ||||
-rw-r--r-- | coffee/lib/owncloud.coffee | 4 | ||||
-rw-r--r-- | controller/news.controller.php | 11 | ||||
-rw-r--r-- | css/addnew.css | 25 | ||||
-rw-r--r-- | css/feeds.css | 82 | ||||
-rw-r--r-- | css/items.css | 299 | ||||
-rw-r--r-- | css/owncloud.css | 259 | ||||
-rw-r--r-- | css/settings.css | 11 | ||||
-rw-r--r-- | css/showall.css | 19 | ||||
-rw-r--r-- | js/app.js | 256 | ||||
-rw-r--r-- | lib/api.php | 7 | ||||
-rw-r--r-- | templates/main.php | 78 | ||||
-rw-r--r-- | templates/part.addnew.php | 35 | ||||
-rw-r--r-- | templates/part.feed.starred.php | 17 | ||||
-rw-r--r-- | templates/part.feed.unread.php | 20 | ||||
-rw-r--r-- | templates/part.listfeed.php | 17 | ||||
-rw-r--r-- | templates/part.listfolder.php | 25 | ||||
-rw-r--r-- | templates/part.settings.php | 123 | ||||
-rw-r--r-- | templates/part.showall.php | 7 |
24 files changed, 1132 insertions, 368 deletions
diff --git a/coffee/controllers/addnewcontroller.coffee b/coffee/controllers/addnewcontroller.coffee new file mode 100644 index 000000000..348b1ecb1 --- /dev/null +++ b/coffee/controllers/addnewcontroller.coffee @@ -0,0 +1,20 @@ +### +# ownCloud news app +# +# @author Alessandro Cosentino +# @author Bernhard Posselt +# Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +# Copyright (c) 2012 - Bernhard Posselt <nukeawhale@gmail.com> +# +# This file is licensed under the Affero General Public License version 3 or +# later. +# +# See the COPYING-README file +# +### +angular.module('News').factory '_AddNewController', +['Controller', (Controller) -> + + class AddNewController extends Controller + +]
\ No newline at end of file diff --git a/coffee/controllers/controllers.coffee b/coffee/controllers/controllers.coffee index 606ad9ac4..62476443f 100644 --- a/coffee/controllers/controllers.coffee +++ b/coffee/controllers/controllers.coffee @@ -18,9 +18,8 @@ angular.module('News').controller 'SettingsController', 'FolderModel', 'FeedModel', 'OPMLParser', (_SettingsController, $scope, $rootScope, ShowAll, PersistenceNews, FolderModel, FeedModel, OPMLParser) -> - return new _SettingsController($scope, $rootScope, ShowAll, - PersistenceNews, FolderModel, FeedModel, - OPMLParser) + return new _SettingsController($scope, $rootScope, PersistenceNews, + OPMLParser) ] angular.module('News').controller 'ItemController', @@ -43,4 +42,10 @@ StarredCount, ShowAll, ItemModel, GarbageRegistry, $rootScope, Loading, Config) ActiveFeed, PersistenceNews, StarredCount, ShowAll, ItemModel, GarbageRegistry, $rootScope, Loading, Config) +] + +angular.module('News').controller 'AddNewController', +['_AddNewController', '$scope', +(_AddNewController, $scope) -> + return new _AddNewController($scope) ]
\ No newline at end of file diff --git a/coffee/controllers/feedcontroller.coffee b/coffee/controllers/feedcontroller.coffee index 6ce5ef5c0..4717a6594 100644 --- a/coffee/controllers/feedcontroller.coffee +++ b/coffee/controllers/feedcontroller.coffee @@ -25,7 +25,62 @@ angular.module('News').factory '_FeedController', ['Controller', (Controller) -> @$scope.feeds = @feedModel.getItems() @$scope.folders = @folderModel.getItems() @$scope.feedType = @feedType + + @$scope.getShowAll = => + return @showAll.showAll + + @$scope.setShowAll = (value) => + @showAll.showAll = value + @persistence.showAll(value) + @$rootScope.$broadcast('triggerHideRead') + + @$scope.addFeed = (url, folder) => + @$scope.feedEmptyError = false + @$scope.feedExistsError = false + @$scope.feedError = false + if url == undefined or url.trim() == '' + @$scope.feedEmptyError = true + else + url = url.trim() + for feed in @feedModel.getItems() + if url == feed.url # FIXME: can we really compare this + @$scope.feedExistsError = true + + if not (@$scope.feedEmptyError or @$scope.feedExistsError) + if folder == undefined + folderId = 0 + else + folderId = folder.id + @addingFeed = true + onSuccess = => + @$scope.feedUrl = '' + @addingFeed = false + onError = => + @$scope.feedError = true + @addingFeed = false + @persistence.createFeed(url, folderId, onSuccess, onError) + + + @$scope.addFolder = (name) => + @$scope.folderEmptyError = false + @$scope.folderExistsError = false + + if name == undefined or name.trim() == '' + @$scope.folderEmptyError = true + else + name = name.trim() + for folder in @folderModel.getItems() + if name.toLowerCase() == folder.name.toLowerCase() + @$scope.folderExistsError = true + + if not (@$scope.folderEmptyError or @$scope.folderExistsError) + @addingFolder = true + onSuccess = => + @$scope.folderName = '' + @addingFolder = false + @persistence.createFolder(name, onSuccess) + @$scope.toggleFolder = (folderId) => folder = @folderModel.getItemById(folderId) folder.open = !folder.open diff --git a/coffee/controllers/settingscontroller.coffee b/coffee/controllers/settingscontroller.coffee index 38036f89f..9afda5407 100644 --- a/coffee/controllers/settingscontroller.coffee +++ b/coffee/controllers/settingscontroller.coffee @@ -18,94 +18,16 @@ angular.module('News').factory '_SettingsController', ['Controller', class SettingsController extends Controller - constructor: (@$scope, @$rootScope, @showAll, @persistence, @folderModel, - @feedModel, @opmlParser) -> + constructor: (@$scope, @$rootScope, @persistence, @opmlParser) -> @add = false @settings = false @addingFeed = false @addingFolder = false - @$scope.getFolders = => - return @folderModel.getItems() - - @$scope.getShowAll = => - return @showAll.showAll - - @$scope.setShowAll = (value) => - @showAll.showAll = value - @persistence.showAll(value) - @$rootScope.$broadcast('triggerHideRead') - - @$scope.toggleSettings = => - @settings = !@settings - - @$scope.toggleAdd = => - @add = !@add - - @$scope.addIsShown = => - return @add - - @$scope.settingsAreShown = => - return @settings - - @$scope.isAddingFeed = => - return @addingFeed - - @$scope.isAddingFolder = => - return @addingFolder - - @$scope.addFeed = (url, folder) => - @$scope.feedEmptyError = false - @$scope.feedExistsError = false - @$scope.feedError = false - - if url == undefined or url.trim() == '' - @$scope.feedEmptyError = true - else - url = url.trim() - for feed in @feedModel.getItems() - if url == feed.url # FIXME: can we really compare this - @$scope.feedExistsError = true - - if not (@$scope.feedEmptyError or @$scope.feedExistsError) - if folder == undefined - folderId = 0 - else - folderId = folder.id - @addingFeed = true - onSuccess = => - @$scope.feedUrl = '' - @addingFeed = false - onError = => - @$scope.feedError = true - @addingFeed = false - @persistence.createFeed(url, folderId, onSuccess, onError) - - - @$scope.addFolder = (name) => - @$scope.folderEmptyError = false - @$scope.folderExistsError = false - - if name == undefined or name.trim() == '' - @$scope.folderEmptyError = true - else - name = name.trim() - for folder in @folderModel.getItems() - if name.toLowerCase() == folder.name.toLowerCase() - @$scope.folderExistsError = true - - if not (@$scope.folderEmptyError or @$scope.folderExistsError) - @addingFolder = true - onSuccess = => - @$scope.folderName = '' - @addingFolder = false - @persistence.createFolder(name, onSuccess) - @$scope.$on 'readFile', (scope, fileContent) => structure = @opmlParser.parseXML(fileContent) - @parseOPMLStructure(structure) - + @parseOPMLStructure(structure) @$scope.$on 'hidesettings', => @add = false diff --git a/coffee/directives/addfolderselect.coffee b/coffee/directives/addfolderselect.coffee new file mode 100644 index 000000000..1aa77c556 --- /dev/null +++ b/coffee/directives/addfolderselect.coffee @@ -0,0 +1,33 @@ +### +# ownCloud news app +# +# @author Alessandro Cosentino +# @author Bernhard Posselt +# Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +# Copyright (c) 2012 - Bernhard Posselt <nukeawhale@gmail.com> +# +# This file is licensed under the Affero General Public License version 3 or +# later. +# +# See the COPYING-README file +# +### + +### +Turns a normal select into a folder select with the ability to create new folders +### +angular.module('News').directive 'addFolderSelect', ['$rootScope', -> + + return (scope, elm, attr) -> + + options = + singleSelect: true + selectedFirst: true + createText: $(elm).data('create') + createdCallback: (selected, value) -> + console.log selected + console.log value + + $(elm).multiSelect(options) + +]
\ No newline at end of file diff --git a/coffee/directives/droppable.coffee b/coffee/directives/droppable.coffee index e00545d31..a9c134096 100644 --- a/coffee/directives/droppable.coffee +++ b/coffee/directives/droppable.coffee @@ -20,11 +20,11 @@ angular.module('News').directive 'droppable', ['$rootScope', ($rootScope) -> details = accept: '.feed' - hoverClass: 'dnd_over' + hoverClass: 'drag-and-drop' greedy: true drop: (event, ui) -> # in case jquery ui did something weird - $('.dnd_over').removeClass('dnd_over') + $('.drag-and-drop').removeClass('drag-and-drop') data = folderId: parseInt($elem.data('id'), 10) diff --git a/coffee/lib/owncloud.coffee b/coffee/lib/owncloud.coffee index 537499135..aaed235a3 100644 --- a/coffee/lib/owncloud.coffee +++ b/coffee/lib/owncloud.coffee @@ -34,11 +34,11 @@ angular.module('OC', []).config ['$httpProvider', ($httpProvider) -> return $.param(data) ] -angular.module('OC').init ['$rootScope', 'Router', ($rootScope, Router) -> +angular.module('OC').run ['$rootScope', 'Router', ($rootScope, Router) -> init = -> $rootScope.$broadcast('routesLoaded') # this registers a callback that is executed once the routes have # finished loading. Before this you cant really do request - OC.Router.registerLoadedCallback(init) + Router.registerLoadedCallback(init) ]
\ No newline at end of file diff --git a/controller/news.controller.php b/controller/news.controller.php index e13cfe979..127a05701 100644 --- a/controller/news.controller.php +++ b/controller/news.controller.php @@ -56,8 +56,15 @@ class NewsController extends Controller { $this->api->add3rdPartyScript('angular-1.0.2/angular.min'); $this->api->add3rdPartyScript('moment.min'); $this->api->addScript('app'); - $this->api->addStyle('news'); - + $this->api->addScript('multiselect', 'core'); + + $this->api->addStyle('owncloud'); + $this->api->addStyle('addnew'); + $this->api->addStyle('feeds'); + $this->api->addStyle('items'); + $this->api->addStyle('settings'); + $this->api->addStyle('addnew'); + $this->api->addStyle('showall'); if($urlParams['feedid']){ $this->api->setUserValue('lastViewedFeed', $urlParams['feedid']); diff --git a/css/addnew.css b/css/addnew.css new file mode 100644 index 000000000..edcad6ec6 --- /dev/null +++ b/css/addnew.css @@ -0,0 +1,25 @@ +.add-new { + overflow: hidden; +} + +.add-new > a { + background-image: url('%appswebroot%/news/img/add.svg'); +} + +.add-new-popup { + -moz-transition: padding-bottom 500ms ease 0s; + -o-transition: padding-bottom 500ms ease 0s; + -webkit-transition: padding-bottom 500ms ease 0s; + -ms-transition: padding-bottom 500ms ease 0s; + transition: height 500ms ease 0s; + height: 0; + padding: 0 15px; +} + +.add-new-popup.open { + height: 170px; +} + +.add-new-popup .personalblock:first-child legend { + padding-top: 15px; +}
\ No newline at end of file diff --git a/css/feeds.css b/css/feeds.css new file mode 100644 index 000000000..5ae430aec --- /dev/null +++ b/css/feeds.css @@ -0,0 +1,82 @@ +.starred-icon { + background-image: url('%appswebroot%/news/img/starred.png'); +} + +.subscriptions-icon { + background-image: url('%appswebroot%/news/img/rss.svg'); +} + +.unread { + font-weight: bold; +} + +#left-content .unread > a { + padding-right: 32px; +} + + + +#left-content .utils { + position: absolute; + right: 0; + top: 0; + bottom: 0; + display: none; +} + +#left-content .utils button { + margin: 5px 0 0 0; + background-position: center; + background-repeat: no-repeat; + background-color: transparent; + border: 0; + box-shadow: none; +} + +.unread-counter { + padding: 6px 8px 5px; + position: absolute; + z-index: 5; + right: 0; + top: 0; + overflow: hidden; + text-overflow: ellipsis; + text-align: center; + font-size: 9pt; + display: none; +} + +#left-content li:hover .utils > .unread-counter { + display: none; +} + +.unread .unread-counter { + display: block; +} + + +/* general */ +button.action { + opacity: .5; +} + +button.action:hover { + opacity: 1; +} + + +#left-content li:hover > .utils { + display: block; +} + +.delete-icon { + background-image: url('%webroot%/core/img/actions/delete.svg'); +} + +.edit-icon { + background-image: url('%webroot%/core/img/actions/rename.svg'); +} + +.mark-read-icon { + background-image: url('%appswebroot%/news/img/mark_read.svg'); +} diff --git a/css/items.css b/css/items.css new file mode 100644 index 000000000..3d13e8e57 --- /dev/null +++ b/css/items.css @@ -0,0 +1,299 @@ +#right-content:after { + content: ''; + display: block; + height: 100%; +} + +#right-content.loading { + background-image: url('%webroot%/core/img/loading.gif'); + background-position: center; + background-repeat: no-repeat; +} + +#right-content.loading > ul { + display: none; +} + + +/** + * Rules for a single feed item + */ +.feed_item { + border-top: 1px solid #ccc; + min-height: 100px; + background-image: linear-gradient(top, rgb(248,248,248) 0, rgb(255,255,255) 6em); + background-image: -o-linear-gradient(top, rgb(248,248,248) 0, rgb(255,255,255) 6em); + background-image: -moz-linear-gradient(top, rgb(248,248,248) 0, rgb(255,255,255) 6em); + background-image: -webkit-linear-gradient(top, rgb(248,248,248) 0, rgb(255,255,255) 6em); + background-image: -ms-linear-gradient(top, rgb(248,248,248) 0, rgb(255,255,255) 6em); + padding: 2.5em 0 0 0; + cursor: default; +} + +.feed_item.viewed { + border-right: 5px solid #F28627; +} + + +.feed_item:first-child { + border-top: 0; +} + + /** + * Utils panel + */ + .utils { + height: 2em; + margin: 0 0 0 1em; + float: left; + } + + /** + * Primary feed utils which are always shown + */ + .feed_item .primary_item_utils { + float: left; + } + + .feed_item .primary_item_utils li { + display: inline-block; + line-height: 1.5em; + font-size: 1em; + color: #aaa; + float: left; + margin-left: ; + cursor: default; + } + + .feed_item .primary_item_utils li:first-child { margin: 0} + .feed_item .primary_item_utils li.star { + background-image: url('%appswebroot%/news/img/inactive_star.svg'); + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + width: 1.5em; + height: 1.5em; + cursor: pointer; + } + + .feed_item .primary_item_utils li.star.important, + .feed_item .primary_item_utils li.star:hover { + background-image: url('%appswebroot%/news/img/active_star.svg'); + } + + /** + * Feed title + */ + .feed_item h1.item_title { + font-size: 1.5em; + margin: 0 13em 0 2.1em; + font-weight: bold; + word-break: break-all; + } + + .feed_item h1.item_title a { + color: #222; + } + .feed_item h1.item_title a:hover { + color: #222; + text-decoration: underline; + } + + /** + * Feed title when read + */ + .feed_item.read h1.item_title { + font-weight: normal; + } + + .feed_item.read h1.item_title a { + color: #888; + } + + /** + * Title of the feed to which the item belongs + */ + .feed_item h2.item_feed_title { + color: #aaa; + font-size: 1.1em; + margin-left: 3em; + } + + /** + * Author of the item + */ + .feed_item h2.item_author { + color: #aaa; + font-size: 1.1em; + margin: .2em 0 0 3em; + } + + .feed_item h2.item_author a { + color: inherit; + } + + .feed_item h2.item_author a:hover { + text-decoration: underline; + } + + .timestamp { + display: none; + } + + /** + * Feed timestamp + */ + .timeago { + float: right; + color: #aaa; + margin: 0 1.2em 0 0; + font-size: 1.1em; + } + + /** + * Body of the feed item + */ + .feed_item .enclosure { + padding: 1em 3em 0 3.5em; + } + + .feed_item div.body { + padding: .75em 3em 0 3em; + max-width: 55em; + font-size: 1.1em; + clear: both; + overflow: auto; + } + + .feed_item div.body p { + line-height: 1.5; + margin: .5em 0 1em 0; + } + + .feed_item div.body img, .feed_item div.body table { + max-width: 100%; + height: auto; + overflow: auto; + word-wrap: break-word; + } + + .feed_item div.body > img:first-child { + padding: 0 1em 0 0; + float: left; + } + + .feed_item div.body h1, .feed_item div.body h2 { + font-size: 1.25em; + font-weight: bold; + color: #222; + margin: 1.5em 0 0 0; + } + + .feed_item div.body h3 { + font-size: 1.1em; + font-weight: bold; + color: #222; + margin: 1.5em 0 0 0; + text-decoration: underline; + } + + .feed_item div.body > div { + margin: .5em 0; + } + + .feed_item div.body a { + color: #0000ff; + text-decoration: underline; + } + + .feed_item div.body ul { + margin: .5em 0; + padding-left: 1em; + list-style-type: disc; + } + + .feed_item div.body ol { + margin: .5em 0; + padding-left: 1.5em; + } + + .feed_item div.body ul li { + cursor: default; + line-height: 1.5em; + } + + .feed_item div.body pre { + padding: .5em .5em .5em 1em; + background-color: #dadada; + border: 1px solid #ccc; + margin: .5em 0 1em 0; + background-image: linear-gradient(top, rgb(215,215,215) 0%, rgb(220,220,220) 100%); + background-image: -o-linear-gradient(top, rgb(215,215,215) 0%, rgb(220,220,220) 100%); + background-image: -moz-linear-gradient(top, rgb(215,215,215) 0%, rgb(220,220,220) 100%); + background-image: -webkit-linear-gradient(top, rgb(215,215,215) 0%, rgb(220,220,220) 100%); + background-image: -ms-linear-gradient(top, rgb(215,215,215) 0%, rgb(220,220,220) 100%); + overflow-y: auto; + } + + .feed_item div.body pre code { + font-family: monospace; + font-size: 1.5em; + } + .feed_item div.body > *:last-child { + margin-bottom: 0; + } + +/** + * Line with utils at the bottom + */ +.bottom_utils { + width: 100%; + height: 2.5em; + margin: 0; + padding: 0; + box-sizing: border-box; + -moz-box-sizing: border-box; +} + + /** + * Secondary feed items which are only shown on hover + */ + .feed_item .secondary_item_utils { + float: right; + margin: 0 1.2em; + } + + + .feed_item .secondary_item_utils, .feed_item .secondary_item_utils a { + color: #000; + } + + .feed_item:hover .secondary_item_utils li { + display: inline-block; + } + + .feed_item .secondary_item_utils li { + padding-left: 25px; + display: none; + } + + /** + * Secondary feed items which are only shown on hover + */ + .feed_item .show_keep_unread .keep_unread{ + display: block; + } + + .feed_item li.share_link { + background-image: url('%webroot%/core/img/actions/share.svg'); + background-repeat: no-repeat; + background-position: right center; + padding-right: 20px; + } + + .feed_item:hover .secondary_item_utils li.keep_unread { + cursor: pointer; + } + + .feed_item .secondary_item_utils li input[type=checkbox]{ + margin-left: 5px; + } diff --git a/css/owncloud.css b/css/owncloud.css new file mode 100644 index 000000000..65ac19f70 --- /dev/null +++ b/css/owncloud.css @@ -0,0 +1,259 @@ +/** + * ownCloud + * + * @author Bernhard Posselt + * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * Contains default left-content design stuff + */ + +/* needed for angularjs */ +#app { + height: 100%; + width: 100%; +} + +/* Basic layout */ +#left-content { + width: 250px; + height: 100%; + float: left; + -moz-box-sizing: border-box; box-sizing: border-box; |