diff options
-rw-r--r-- | ajax/loadfeed.php | 18 | ||||
-rw-r--r-- | ajax/setallitemsread.php | 41 | ||||
-rw-r--r-- | ajax/setitemstatus.php | 2 | ||||
-rw-r--r-- | css/news.css | 271 | ||||
-rw-r--r-- | js/news.js | 112 | ||||
-rw-r--r-- | templates/main.php | 4 | ||||
-rw-r--r-- | templates/part.items.php | 20 |
7 files changed, 322 insertions, 146 deletions
diff --git a/ajax/loadfeed.php b/ajax/loadfeed.php index 992e65019..020f7a706 100644 --- a/ajax/loadfeed.php +++ b/ajax/loadfeed.php @@ -17,19 +17,19 @@ OCP\JSON::callCheck(); $userid = OCP\USER::getUser(); -$feedid = trim($_POST['feedid']); +$feedId = trim($_POST['feedId']); $l = OC_L10N::get('news'); -$tmpl_items = new OCP\Template("news", "part.items"); -$tmpl_items->assign('feedid', $feedid); -$part_items = $tmpl_items->fetchPage(); +$itemsTpl = new OCP\Template("news", "part.items"); +$itemsTpl->assign('feedid', $feedId); +$feedItems = $itemsTpl->fetchPage(); -$tmpl_items_header = new OCP\Template("news", "part.items.header"); -$tmpl_items_header->assign('feedid', $feedid); -$items_header = $tmpl_items_header->fetchPage(); +$feedMapper = new OCA\News\FeedMapper(); +$feed = $feedMapper->findById($feedId); +$feedTitle = $feed->getTitle(); OCP\JSON::success(array('data' => array( 'message' => $l->t('Feed loaded!'), - 'items_header' => $items_header, - 'part_items' => $part_items ))); + 'feedTitle' => $feedTitle, + 'feedItems' => $feedItems ))); diff --git a/ajax/setallitemsread.php b/ajax/setallitemsread.php new file mode 100644 index 000000000..4c1876b50 --- /dev/null +++ b/ajax/setallitemsread.php @@ -0,0 +1,41 @@ +<?php +/** +* ownCloud - News app +* +* @author Bernhard Posselt +* 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 +* +*/ + +// Check if we are a user +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('news'); +OCP\JSON::callCheck(); + +$feedId = $_POST['feedId']; + +$itemMapper = new OCA\News\ItemMapper(); +$items = $itemMapper->findAllStatus($feedId, OCA\News\StatusFlag::Unread); + +// FIXME: maybe there is a way to set all items read in the +// FeedMapper instead of iterating through every item and updating as +// necessary +foreach($items as $item){ + $item->setRead(); + $success = $itemMapper->update($item); +} + +$l = OC_L10N::get('news'); + +if(!$success) { + OCP\JSON::error(array('data' => array('message' => $l->t('Error setting all items as read.')))); + OCP\Util::writeLog('news','ajax/setallitemsread.php: Error setting all items as read of feed '. $feedId, OCP\Util::ERROR); + exit(); +} + +//TODO: replace the following with a real success case. see contact/ajax/createaddressbook.php for inspirations +OCP\JSON::success(array('data' => array('feedId' => $feedId ))); + diff --git a/ajax/setitemstatus.php b/ajax/setitemstatus.php index 1d1849a5b..03dff7d94 100644 --- a/ajax/setitemstatus.php +++ b/ajax/setitemstatus.php @@ -44,7 +44,7 @@ $l = OC_L10N::get('news'); if(!$success) { OCP\JSON::error(array('data' => array('message' => $l->t('Error marking item as read.')))); - OCP\Util::writeLog('news','ajax/markitem.php: Error setting itemstatus to '. $status .': '.$_POST['itemid'], OCP\Util::ERROR); + OCP\Util::writeLog('news','ajax/setitemstatus.php: Error setting itemstatus to '. $status .': '.$_POST['itemid'], OCP\Util::ERROR); exit(); } diff --git a/css/news.css b/css/news.css index 44c21e0d5..025d203f5 100644 --- a/css/news.css +++ b/css/news.css @@ -48,87 +48,204 @@ ul.controls li { float: left; } /* item view */ -#rightcontent { top: 3.5em !important; padding: 0 0 0 5px; box-sizing: border-box; -moz-box-sizing: border-box; margin-top: 3.5em;} - -#rightcontent div.feed_controls { box-sizing: border-box; -moz-box-sizing: border-box; background: none repeat scroll 0 0 #FFFFFF; border-bottom: 1px solid #ccc; box-shadow: 0 3px 3px -3px #000000; text-align: right; overflow: hidden; position: fixed; left: 32.5em; right: 0; top: 3.5em; } -#rightcontent div.feed_controls div.feed_title { float: left; padding-left: 10px; } -#rightcontent div.feed_controls div.feed_title h1 { font-size: 1.7em; color: #444; padding-top: .5em; } - -#rightcontent #feed_items { +#rightcontent { + top: 3.5em !important; + padding: 0 0 0 5px; box-sizing: border-box; -moz-box-sizing: border-box; - overflow: auto; - height: 100%; -} - -#feed_items h1.item_title { - clear: both; - font-size: 1.5em; - padding: 0 0 0 10px; -} -#feed_items .title_unread h1.item_title { - font-weight: bold; -} -#feed_items h1.item_title a { color: #222; } -#feed_items h1.item_title a:hover { color: #222; text-decoration: underline; } -#feed_items .read h1.item_title { font-weight: normal;} -#feed_items .read h1.item_title a { color: #888; } - -#feed_items .item_utils { - border-top: 1px solid #ccc; - padding: 10px 0 5px 10px; - height: 1.8em; - width: 100%; -} -#feed_items .item_utils ul li { - display: inline-block; - line-height: 1.5em; - font-size: 1em; - color: #aaa; - float: left; - margin-left: 10px; - cursor: default; -} -#feed_items .item_utils ul li input[type=checkbox]{ - margin-left: .8em; + margin-top: 3.5em; } -#feed_items .item_utils ul.hidden_item_utils { - display: none; - float: right; - margin-right: 30px; -} -#feed_items .news_item:hover .item_utils ul.hidden_item_utils { - display: block; -} -#feed_items .news_item:hover .item_utils ul.hidden_item_utils li.keep_unread { - cursor: pointer; -} -#feed_items .item_utils ul li:first-child { margin: 0} -#feed_items .item_utils ul li.star { - background-image: url('%appswebroot%/news/img/inactive_star.svg'); - background-repeat: no-repeat; - background-size: 100%; - width: 1.5em; - height: 1.5em; - cursor: pointer; -} -#feed_items .item_utils ul li.star.important, -#feed_items .item_utils ul li.star:hover { - background-image: url('%appswebroot%/news/img/active_star.svg'); -} - - -#feed_items div.body { padding: 15px 25px 20px 25px; } -#feed_items div.body p { line-height: 1.5; margin: 10px 0; } -#feed_items div.body a { color: #0000ff; text-decoration: underline; } -#feed_items div.body ul { padding-left: 15px; list-style-type: disc; } -#feed_items div.body ul li { cursor: default; } -#feed_items li:active { background: none; } -#feed_items div.body pre { padding: 5px; background-color: #dadada; border: 1px solid #ccc; } -#feed_items div.body pre code { font-family: monospace; font-size: 1.5em; } - -#feed_items div.rightcontentmsg { padding-left: 10px; background-color: yellow; } + /** + * View above the feeds which shows the feed title + * and the controls + */ + #rightcontent div.feed_controls { + box-sizing: border-box; + -moz-box-sizing: border-box; + background: none repeat scroll 0 0 #FFFFFF; + border-bottom: 1px solid #ccc; + box-shadow: 0 3px 3px -3px #000000; + text-align: right; overflow: hidden; + position: fixed; + left: 32.5em; + right: 0; + top: 3.5em; + } + + #rightcontent div.feed_controls div.feed_title { + float: left; + padding-left: 10px; + } + + #rightcontent div.feed_controls div.feed_title h1 { + font-size: 1.7em; + color: #444; + padding-top: .5em; + } + + /** + * Area below the feed title and controls + */ + #rightcontent #feed_items { + box-sizing: border-box; + -moz-box-sizing: border-box; + overflow: auto; + height: 100%; + } + + #rightcontent #feed_items li:active { + background: none; + } + + /** + * Rules for a single feed item + */ + .feed_item { + border-top: 1px solid #ccc; + min-height: 100px; + } + + /** + * Utils panel + */ + .utils { + height: 2em; + margin: 0; + padding: 0.6em 0.5em 0.5em 0.5em; + background-image: linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -o-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -moz-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -webkit-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -ms-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + } + + /** + * 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: 100%; + 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'); + } + + /** + * Secondary feed items which are only shown on hover + */ + .feed_item .secondary_item_utils { + float: right; + color: #aaa; + } + /* + .feed_item:hover .secondary_item_utils { + display: block; + }*/ + + .feed_item:hover .secondary_item_utils li.keep_unread { + cursor: pointer; + } + + .feed_item .secondary_item_utils li input[type=checkbox]{ + margin-left: .8em; + } + + /** + * Feed title + */ + .feed_item h1.item_title { + font-size: 1.5em; + margin: 0 0 0 1.6em; + font-weight: bold; + } + + .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; + } + + /** + * Author of the feed + */ + .feed_item h2.item_author { + color: #aaa; + margin-left: 2.5em; + } + + + /** + * Body of the feed item + */ + .feed_item div.body { + padding: .5em 2.5em 2em 2.5em; + } + + .feed_item div.body p { + line-height: 1.5; + margin: 10px 0; + } + + .feed_item div.body a { + color: #0000ff; + text-decoration: underline; + } + + .feed_item div.body ul { + padding-left: 15px; + list-style-type: disc; + } + + .feed_item div.body ul li { + cursor: default; + } + + .feed_item div.body pre { + padding: 5px; + background-color: #dadada; + border: 1px solid #ccc; + } + + .feed_item div.body pre code { + font-family: monospace; + font-size: 1.5em; + } + /* dialog/menues */ diff --git a/js/news.js b/js/news.js index 22eb7195a..96a8fe56d 100644 --- a/js/news.js +++ b/js/news.js @@ -175,23 +175,35 @@ News={ }); return false; }, - setAllItemsRead:function() { - $("#feed_items li:not(.read)").each(function(){ - var itemId = $(this).data('id'); - var handler = new News.ItemStatusHandler(itemId); - handler.setRead(true); + setAllItemsRead:function(feedId) { + $.post(OC.filePath('news', 'ajax', 'setallitemsread.php'), { 'feedId' : feedId }, function(jsonData) { + if(jsonData.status == 'success'){ + // mark ui items as read + $("#feed_items .feed_item:not(.read)").each(function(){ + $(this).addClass('read'); + }); + + var $feedItemCounter = $('li.feed[data-id="'+feedId+'"]').find('.unreaditemcounter'); + $feedItemCounter.removeClass('nonzero').addClass('zero'); + $feedItemCounter.empty(); + } else { + OC.dialogs.alert(t('news', 'Error while loading the feed'), t('news', 'Error')); + } }); }, - load:function(feedid) { - $.post(OC.filePath('news', 'ajax', 'loadfeed.php'),{'feedid':feedid},function(jsondata) { - if(jsondata.status == 'success'){ - var rightcontent = $('div.rightcontent'); - rightcontent.empty(); - rightcontent.attr('data-id', feedid); - rightcontent.html(jsondata.data.items_header + jsondata.data.part_items); + load:function(feedId) { + $.post(OC.filePath('news', 'ajax', 'loadfeed.php'), { 'feedId' : feedId }, function(jsonData) { + if(jsonData.status == 'success'){ + var $rightContent = $(".rightcontent"); + $rightContent.attr('data-id', feedId); + var $feedItems = $('#feed_items'); + $feedItems.empty(); + $feedItems.html(jsonData.data.feedItems); + var $feedTitle = $(".feed_controls .feed_title h1"); + $feedTitle.html('ยป ' + jsonData.data.feedTitle); $('li#selected_feed').attr('id', ''); - $('li.feed[data-id="' + feedid + '"]').attr('id', 'selected_feed'); + $('li.feed[data-id="' + feedId + '"]').attr('id', 'selected_feed'); transformCollapsableTrigger(); bindItemEventListeners(); @@ -244,10 +256,10 @@ News={ // TODO: safe this on the server switch(value){ case 'all': - $("#feed_items li").show(); + $("#feed_items .feed_item").show(); break; case 'newest': - $("#feed_items li.title_read").hide(); + $("#feed_items .feed_item.read").hide(); break; default: break; @@ -259,8 +271,8 @@ News={ ItemStatusHandler: function(itemId){ var _itemId = itemId; var _$currentItem = $('#feed_items li[data-id="' + itemId + '"]'); - var _$currentItemStar = _$currentItem.children('.item_utils').children('ul').children('.star'); - var _$currentItemKeepUnread = _$currentItem.children('.item_utils').children('.hidden_item_utils').children('.keep_unread').children('input[type=checkbox]'); + var _$currentItemStar = _$currentItem.children('.utils').children('.primary_item_utils').children('.star'); + var _$currentItemKeepUnread = _$currentItem.children('.utils').children('.secondary_item_utils').children('.keep_unread').children('input[type=checkbox]'); var _feedId = _$currentItem.data('feedid'); var _read = _$currentItem.hasClass('read'); var _important = _$currentItemStar.hasClass('important'); @@ -342,18 +354,17 @@ News={ if (oldcount <= 1) { counterplace.removeClass('nonzero').addClass('zero'); title.removeClass('nonzero').addClass('zero'); - } - else { - counterplace.append(--oldcount); + } else { + counterplace.html(--oldcount); } } else { _$currentItem.removeClass('read'); - if (oldcount >= 1) { + if (oldcount === '') { counterplace.removeClass('zero').addClass('nonzero'); title.removeClass('zero').addClass('nonzero'); - } - else { - counterplace.append(--oldcount); + counterplace.html(1); + } else { + counterplace.html(++oldcount); } } @@ -439,26 +450,9 @@ function setupFeedList() { */ function bindItemEventListeners(){ - // mark items whose title was hid under the top edge as read - // when the bottom is reached, mark all items as read - $('#feed_items').scroll(function(){ - var boxHeight = $(this).height(); - var scrollHeight = $(this).prop('scrollHeight'); - var scrolled = $(this).scrollTop() + boxHeight; - - $(this).children('ul').children('li:not(.read)').each(function(){ - var itemOffset = $(this).position().top; - if(itemOffset <= 0 || scrolled >= scrollHeight){ - var itemId = $(this).data('id'); - var handler = new News.ItemStatusHandler(itemId); - handler.setRead(true); - } - }) - }); - // single hover on item should mark it as read too $('#feed_items h1.item_title a').click(function(){ - var $item = $(this).parent().parent('.news_item'); + var $item = $(this).parent().parent('.feed_item'); var itemId = $item.data('id'); var handler = new News.ItemStatusHandler(itemId); handler.setRead(true); @@ -466,7 +460,7 @@ function bindItemEventListeners(){ // mark or unmark as important $('#feed_items li.star').click(function(){ - var $item = $(this).parent().parent().parent('.news_item'); + var $item = $(this).parent().parent().parent('.feed_item'); var itemId = $item.data('id'); var handler = new News.ItemStatusHandler(itemId); handler.toggleImportant(); @@ -474,7 +468,7 @@ function bindItemEventListeners(){ // toggle logic for the keep unread handler $('#feed_items .keep_unread').click(function(){ - var $item = $(this).parent().parent().parent('.news_item'); + var $item = $(this).parent().parent().parent('.feed_item'); var itemId = $item.data('id'); var handler = new News.ItemStatusHandler(itemId); handler.toggleKeepUnread(); @@ -482,12 +476,8 @@ function bindItemEventListeners(){ // bind the mark all as read button $('#mark_all_as_read').click(function(){ - News.Feed.setAllItemsRead(); - }); - - // filter for newest or all items - $('#feed_filter').change(function(){ - News.Feed.filter($(this).val()); + var feedId = $('.rightcontent').data('id'); + News.Feed.setAllItemsRead(feedId); }); } @@ -523,6 +513,28 @@ $(document).ready(function(){ bindItemEventListeners(); + // filter for newest or all items + $('#feed_filter').change(function(){ + News.Feed.filter($(this).val()); + }); + + // mark items whose title was hid under the top edge as read + // when the bottom is reached, mark all items as read + $('#feed_items').scroll(function(){ + var boxHeight = $(this).height(); + var scrollHeight = $(this).prop('scrollHeight'); + var scrolled = $(this).scrollTop() + boxHeight; + + $(this).children('ul').children('.feed_item:not(.read)').each(function(){ + var itemOffset = $(this).position().top; + if(itemOffset <= 0 || scrolled >= scrollHeight){ + var itemId = $(this).data('id'); + var handler = new News.ItemStatusHandler(itemId); + handler.setRead(true); + } + }) + }); + }); $(document).click(function(event) { diff --git a/templates/main.php b/templates/main.php index e02a29277..5c066e599 100644 --- a/templates/main.php +++ b/templates/main.php @@ -35,7 +35,9 @@ if ($_['feedid']){ <div id="rightcontent" class="rightcontent" data-id="<?php echo $_['feedid']; ?>"> <?php echo $this->inc("part.items.header"); - echo $this->inc("part.items"); + echo '<div id="feed_items">'; + echo $this->inc("part.items"); + echo '</div>'; ?> <div id="appsettings" class="popup bottomleft hidden"></div> diff --git a/templates/part.items.php b/templates/part.items.php index 4099bac34..e481bd2d2 100644 --- a/templates/part.items.php +++ b/templates/part.items.php @@ -5,7 +5,6 @@ $feedid = isset($_['feedid']) ? $_['feedid'] : ''; $itemmapper = new OCA\News\ItemMapper(); $items = $itemmapper->findAll($feedid); -echo '<div id="feed_items">'; echo '<ul>'; foreach($items as $item) { @@ -23,20 +22,25 @@ foreach($items as $item) { $startTitle = $l->t('Mark as important'); } - echo '<li class="news_item ' . $newsItemClass .'" data-id="' . $item->getId() . '" data-feedid="' . $feedid . '">'; - echo '<div class="item_utils">'; - echo '<ul>'; + echo '<li class="feed_item ' . $newsItemClass .'" data-id="' . $item->getId() . '" data-feedid="' . $feedid . '">'; + + echo '<div class="utils">'; + echo '<ul class="primary_item_utils">'; echo '<li class="star ' . $starClass . '" title="' . $startTitle . '"></li>'; - echo '<li>' . parse_url($item->getUrl())['host'] . '</li>'; echo '</ul>'; - echo '<ul class="hidden_item_utils">'; + + echo '<ul class="secondary_item_utils">'; echo '<li class="keep_unread">' . $l->t('Keep unread') . '<input type="checkbox" /></li>'; echo '</ul>'; echo '</div>'; - echo '<h1 class="item_title"><a target="_blank" href="' . $item->getUrl() . '">' . $item->getTitle() . '</a></h1>'; + + echo '<h1 class="item_title"><a target="_blank" href="' . $item->getUrl() . '">' . $item->getTitle() . '</a></h1>'; + + echo '<h2 class="item_author">' . $l->t('from') . ' ' . parse_url($item->getUrl())['host'] . '</h2>'; + echo '<div class="body">' . $item->getBody() . '</div>'; + echo '</li>'; } echo '</ul>'; -echo '</div>'; |