summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Posselt <nukeawhale@gmail.com>2012-08-13 03:01:11 +0200
committerBernhard Posselt <nukeawhale@gmail.com>2012-08-13 03:01:11 +0200
commit6c327bd5f8cdbebf45c6aa87f2d54f3dd26663a2 (patch)
treead191891100d39c528bed77eb08a2e4b5573c5b1
parent7efe48d3d7d746b62ea8daf19edf8b3542520bb7 (diff)
new layout and design for feed items, mark all as read is now faster because it uses an own ajax request, css and javascript refactor, the titlebar is now only loaded once
-rw-r--r--ajax/loadfeed.php18
-rw-r--r--ajax/setallitemsread.php41
-rw-r--r--ajax/setitemstatus.php2
-rw-r--r--css/news.css271
-rw-r--r--js/news.js112
-rw-r--r--templates/main.php4
-rw-r--r--templates/part.items.php20
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>';