From 59c17a3c6c26d6b487e2ec5e02caa3fb26f9ff9c Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 27 Sep 2014 08:20:13 -0400 Subject: Fix read all shortcut Before, the read all shortcut raised a javascript exception when we use the confirmation option. The confirmation was not even displayed. The code was failling since there was a missing variable. Now, the shortcut ask for confirmation when the option is selected in the reading configuration page. The definition of the shortcut was buggy since the confirmation was handled properly in an other location. I simplified the code by removing the confirmation code in the shortcut. --- p/scripts/main.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'p/scripts') diff --git a/p/scripts/main.js b/p/scripts/main.js index f6d5d2907..8a45ae896 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -538,14 +538,7 @@ function init_shortcuts() { }); shortcut.add("shift+" + shortcuts.mark_read, function () { // on marque tout comme lu - var btn = $(".nav_menu .read_all"); - if (btn.hasClass('confirm')) { - if (confirm(str_confirmation)) { - btn.click(); - } - } else { - btn.click(); - } + $(".nav_menu .read_all").click(); }, { 'disable_in_input': true }); -- cgit v1.2.3 From 7481887db746fd2d6eefab021776b8abd4076429 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Oct 2014 10:06:04 +0200 Subject: Load feed configuration on the same page Need improvements See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/Controllers/configureController.php | 4 ++++ app/views/configure/categorize.phtml | 5 ++++- app/views/configure/feed.phtml | 8 ++++++-- p/scripts/main.js | 30 ++++++++++++++++++++++++++++++ p/themes/base-theme/template.css | 5 +++++ 5 files changed, 49 insertions(+), 3 deletions(-) (limited to 'p/scripts') diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index a7def6d9a..dd7a0a441 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -90,6 +90,10 @@ class FreshRSS_configure_Controller extends Minz_ActionController { * Default values are empty strings unless specified. */ public function feedAction() { + if (Minz_Request::param('ajax')) { + $this->view->_useLayout(false); + } + $catDAO = new FreshRSS_CategoryDAO(); $this->view->categories = $catDAO->listCategories(false); diff --git a/app/views/configure/categorize.phtml b/app/views/configure/categorize.phtml index 8f77f9724..008dc8c98 100644 --- a/app/views/configure/categorize.phtml +++ b/app/views/configure/categorize.phtml @@ -73,7 +73,7 @@ $empty = $feed->nbEntries() == 0 ? ' empty' : ''; ?>
  • - + ✇ name(); ?>
  • + +
    +
    diff --git a/app/views/configure/feed.phtml b/app/views/configure/feed.phtml index e96a28739..f58ac65af 100644 --- a/app/views/configure/feed.phtml +++ b/app/views/configure/feed.phtml @@ -1,8 +1,12 @@ -partial ('aside_feed'); ?> +partial('aside_feed'); + } +?> flux) { ?>
    - +

    flux->name (); ?>

    flux->description (); ?> diff --git a/p/scripts/main.js b/p/scripts/main.js index f6d5d2907..7fed7a819 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1240,6 +1240,35 @@ function faviconNbUnread(n) { } } +function init_slider_observers() { + var slider = $('#slider'); + if (slider.length < 1) { + return; + } + + $('.open-slider').on('click', function() { + if (ajax_loading) { + return false; + } + + ajax_loading = true; + + var url_slide = $(this).attr('href'); + + $.ajax({ + type: 'GET', + url: url_slide, + data : { ajax: true } + }).done(function (data) { + slider.html(data); + slider.show(); + ajax_loading = false; + }); + + return false; + }) +} + function init_all() { if (!(window.$ && window.url_freshrss)) { if (window.console) { @@ -1275,6 +1304,7 @@ function init_all() { init_feed_observers(); init_password_observers(); init_stats_observers(); + init_slider_observers(); } if (window.console) { diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index a5a29ab23..397f943a6 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -645,6 +645,11 @@ br + br + br { display: none; } +/*=== Slider */ +#slider { + min-height: 50px; +} + /*=== DIVERS */ /*===========*/ .nav-login, -- cgit v1.2.3 From 405f23050b18e8388edb6f8be90aa59c17ada421 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Oct 2014 13:55:30 +0200 Subject: Design of the slider See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/views/subscription/index.phtml | 5 +++-- p/scripts/main.js | 14 ++++++++++---- p/themes/base-theme/template.css | 24 +++++++++++++++++++++++- 3 files changed, 36 insertions(+), 7 deletions(-) (limited to 'p/scripts') diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 2d55890f7..10578bdd3 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -134,9 +134,10 @@
    -
    + +
    feed) ? ' class="active"' : ''; ?>> feed) && $this->feed) { + if (isset($this->feed)) { $this->renderHelper('feed/update'); } ?> diff --git a/p/scripts/main.js b/p/scripts/main.js index 7fed7a819..925a93650 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1241,7 +1241,8 @@ function faviconNbUnread(n) { } function init_slider_observers() { - var slider = $('#slider'); + var slider = $('#slider'), + closer = $('#close-slider'); if (slider.length < 1) { return; } @@ -1252,7 +1253,6 @@ function init_slider_observers() { } ajax_loading = true; - var url_slide = $(this).attr('href'); $.ajax({ @@ -1261,12 +1261,18 @@ function init_slider_observers() { data : { ajax: true } }).done(function (data) { slider.html(data); - slider.show(); + closer.addClass('active'); + slider.addClass('active'); ajax_loading = false; }); return false; - }) + }); + + closer.on('click', function() { + closer.removeClass('active'); + slider.removeClass('active'); + }); } function init_all() { diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index 397f943a6..e6c832ee4 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -647,7 +647,29 @@ br + br + br { /*=== Slider */ #slider { - min-height: 50px; + position: fixed; + top: 0; bottom: 0; + left: 100%; right: 0; + overflow: auto; + background: #fff; + border-left: 1px solid #aaa; + transition: left 200ms linear; + -moz-transition: left 200ms linear; + -webkit-transition: left 200ms linear; + -o-transition: left 200ms linear; + -ms-transition: left 200ms linear; +} +#slider.active { + left: 40%; +} +#close-slider { + position: fixed; + top: 0; bottom: 0; + left: 100%; right: 0; + cursor: pointer; +} +#close-slider.active { + left: 0; } /*=== DIVERS */ -- cgit v1.2.3 From fe655e0d9d2fb1173099d77c478bbb2f7ac8b1e1 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Oct 2014 13:58:09 +0200 Subject: Fix close slider when a feed is selected See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/views/subscription/index.phtml | 5 +++-- p/scripts/main.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'p/scripts') diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 10578bdd3..577ddd972 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -134,8 +134,9 @@
    - -
    feed) ? ' class="active"' : ''; ?>> +feed) ? ' class="active"' : ''; ?> +> +
    > feed)) { $this->renderHelper('feed/update'); diff --git a/p/scripts/main.js b/p/scripts/main.js index 925a93650..005dc961b 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1272,6 +1272,7 @@ function init_slider_observers() { closer.on('click', function() { closer.removeClass('active'); slider.removeClass('active'); + return false; }); } -- cgit v1.2.3 From 9b2ad32e98e4720d5ee422fccd3069f086ee8563 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 10:05:26 +0200 Subject: Fix a bug in main.js In global view, there is no ".category.all>a" element so we tried to apply str2int on an undefined value. In consequence, we were not able to mark several articles as read This patch need to apply on 0.8.1 and 0.9.1 See https://github.com/marienfressinaud/FreshRSS/issues/649 --- p/scripts/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p/scripts') diff --git a/p/scripts/main.js b/p/scripts/main.js index 7cd53c745..c9e8dd299 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -33,7 +33,7 @@ function needsScroll($elem) { } function str2int(str) { - if (str == '') { + if (str == '' || str === undefined) { return 0; } return parseInt(str.replace(/\D/g, ''), 10) || 0; -- cgit v1.2.3 From db4da3babc0864099c5ab48e3583d0546a2759d8 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 11:39:51 +0200 Subject: First draft for drag and drop We can change feed category by drag and drop! Need improvements... See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/Controllers/feedController.php | 15 ++++++++ app/Controllers/subscriptionController.php | 2 ++ app/views/subscription/index.phtml | 4 +-- p/scripts/category.js | 55 ++++++++++++++++++++++++++++++ p/scripts/main.js | 2 +- p/themes/Origine/origine.css | 9 +++++ 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 p/scripts/category.js (limited to 'p/scripts') diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index e4859b110..315665ef3 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -378,6 +378,21 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } } + public function moveAction() { + if (Minz_Request::isPost()) { + $feed_id = Minz_Request::param('f_id'); + $cat_id = Minz_Request::param('c_id'); + + $feedDAO = FreshRSS_Factory::createFeedDao(); + + $values = array( + 'category' => $cat_id, + ); + + $feedDAO->updateFeed($feed_id, $values); + } + } + public function deleteAction() { if (Minz_Request::isPost()) { $id = Minz_Request::param('id'); diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index aabae7b8f..7cc8179a0 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -30,6 +30,8 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { * It displays categories and associated feeds. */ public function indexAction() { + Minz_View::appendScript(Minz_Url::display('/scripts/category.js?' . + @filemtime(PUBLIC_PATH . '/scripts/category.js'))); Minz_View::prependTitle(_t('subscription_management') . ' · '); $id = Minz_Request::param('id'); diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 577ddd972..3a79a34e6 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -113,14 +113,14 @@
    -
      +
        inError() ? ' error' : ''; $empty = $feed->nbEntries() == 0 ? ' empty' : ''; ?> -
      • +
      • ✇ name(); ?>
      • diff --git a/p/scripts/category.js b/p/scripts/category.js new file mode 100644 index 000000000..fe80c3b22 --- /dev/null +++ b/p/scripts/category.js @@ -0,0 +1,55 @@ +"use strict"; + + +function init_draggable() { + var feeds_draggable = '.box-content > .feed', + box_dropzone = '.box-content'; + + $('.box').on('dragstart', feeds_draggable, function(e) { + e.originalEvent.dataTransfer.effectAllowed = 'move'; + e.originalEvent.dataTransfer.setData('html', e.target.outerHTML); + e.originalEvent.dataTransfer.setData('feed-id', e.target.getAttribute('data-feed-id')); + }); + $('.box').on('dragend', feeds_draggable, function(e) { + var parent = e.target.parentNode; + parent.removeChild(e.target); + }); + + $('.box').on('dragenter', box_dropzone, function(e) { + $(e.target).addClass('drag-hover'); + }); + $('.box').on('dragleave', box_dropzone, function(e) { + $(e.target).removeClass('drag-hover'); + }); + $('.box').on('dragover', box_dropzone, function(e) { + e.originalEvent.dataTransfer.dropEffect = "move"; + + return false; + }); + $('.box').on('drop', box_dropzone, function(e) { + var feed_id = e.originalEvent.dataTransfer.getData('feed-id'), + cat_id = e.target.parentNode.getAttribute('data-cat-id'); + + $.ajax({ + type: 'POST', + url: './?c=feed&a=move', + data : { + f_id: feed_id, + c_id: cat_id + } + }); + + $(e.target).after(e.originalEvent.dataTransfer.getData('html')); + $(e.target).removeClass('drag-hover'); + return false; + }); +} + + +if (document.readyState && document.readyState !== 'loading') { + init_draggable(); +} else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', function () { + init_draggable(); + }, false); +} diff --git a/p/scripts/main.js b/p/scripts/main.js index 005dc961b..e8055e00f 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1247,7 +1247,7 @@ function init_slider_observers() { return; } - $('.open-slider').on('click', function() { + $('.post').on('click', '.open-slider', function() { if (ajax_loading) { return false; } diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css index e3ae85075..cf6c9a2ef 100644 --- a/p/themes/Origine/origine.css +++ b/p/themes/Origine/origine.css @@ -497,6 +497,15 @@ a.btn { visibility: visible; } +/*=== Draggable */ +.drag-hover { + background: #dfd; + transition: all linear 0.2s; +} +[draggable=true] { + cursor: grab; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ -- cgit v1.2.3 From 50f07febaed5e839d4e7d56a664c8a208bc2aaf5 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 12:13:16 +0200 Subject: Add dataTransfer property to event for JQuery See https://github.com/marienfressinaud/FreshRSS/issues/646 --- p/scripts/category.js | 15 +++++++++------ p/themes/Origine/origine.css | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'p/scripts') diff --git a/p/scripts/category.js b/p/scripts/category.js index fe80c3b22..4378aa9cd 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -2,17 +2,20 @@ function init_draggable() { + $.event.props.push('dataTransfer'); + var feeds_draggable = '.box-content > .feed', box_dropzone = '.box-content'; $('.box').on('dragstart', feeds_draggable, function(e) { - e.originalEvent.dataTransfer.effectAllowed = 'move'; - e.originalEvent.dataTransfer.setData('html', e.target.outerHTML); - e.originalEvent.dataTransfer.setData('feed-id', e.target.getAttribute('data-feed-id')); + e.dataTransfer.effectAllowed = 'move'; + e.dataTransfer.setData('html', e.target.outerHTML); + e.dataTransfer.setData('feed-id', e.target.getAttribute('data-feed-id')); }); $('.box').on('dragend', feeds_draggable, function(e) { var parent = e.target.parentNode; parent.removeChild(e.target); + }); $('.box').on('dragenter', box_dropzone, function(e) { @@ -22,12 +25,12 @@ function init_draggable() { $(e.target).removeClass('drag-hover'); }); $('.box').on('dragover', box_dropzone, function(e) { - e.originalEvent.dataTransfer.dropEffect = "move"; + e.dataTransfer.dropEffect = "move"; return false; }); $('.box').on('drop', box_dropzone, function(e) { - var feed_id = e.originalEvent.dataTransfer.getData('feed-id'), + var feed_id = e.dataTransfer.getData('feed-id'), cat_id = e.target.parentNode.getAttribute('data-cat-id'); $.ajax({ @@ -39,7 +42,7 @@ function init_draggable() { } }); - $(e.target).after(e.originalEvent.dataTransfer.getData('html')); + $(e.target).after(e.dataTransfer.getData('html')); $(e.target).removeClass('drag-hover'); return false; }); diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css index cf6c9a2ef..c79f6cc4c 100644 --- a/p/themes/Origine/origine.css +++ b/p/themes/Origine/origine.css @@ -481,6 +481,7 @@ a.btn { border-radius: 5px 5px 0 0; } .box .box-content { + min-height: 2.5em; max-height: 260px; } -- cgit v1.2.3 From 6effa82cef4ea8fd98178e72b270de6ea4f9f80f Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 15:02:42 +0200 Subject: Improve drag and drop - Refactoring - Better design - Item doesn't disappear if action is not completed See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/views/subscription/index.phtml | 11 ++++--- p/scripts/category.js | 63 +++++++++++++++++++++++++++++--------- p/themes/Origine/origine.css | 9 ------ p/themes/base-theme/template.css | 12 ++++++++ 4 files changed, 67 insertions(+), 28 deletions(-) (limited to 'p/scripts') diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 3a79a34e6..2c56f79ed 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -1,6 +1,6 @@ partial('aside_subscription'); ?> -
        +

        @@ -113,21 +113,24 @@
        -
          +
            inError() ? ' error' : ''; $empty = $feed->nbEntries() == 0 ? ' empty' : ''; ?> -
          • +
          • ✇ name(); ?>
          • -
          • +
        diff --git a/p/scripts/category.js b/p/scripts/category.js index 4378aa9cd..37ad36b17 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -1,38 +1,66 @@ "use strict"; +var loading = false, + dnd_successful = false; + +function dragend_process(t) { + if (loading) { + window.setTimeout(function() { + dragend_process(t); + }, 50); + } + + if (!dnd_successful) { + t.style.opacity = 1.0; + } else { + t.parentNode.removeChild(t); + } +} + function init_draggable() { + if (!(window.$ && window.url_freshrss)) { + if (window.console) { + console.log('FreshRSS waiting for JS…'); + } + window.setTimeout(init_draggable, 50); + return; + } + $.event.props.push('dataTransfer'); - var feeds_draggable = '.box-content > .feed', - box_dropzone = '.box-content'; + var draggable = '[draggable="true"]', + dropzone = '[dropzone="move"]'; - $('.box').on('dragstart', feeds_draggable, function(e) { + $('.drop-section').on('dragstart', draggable, function(e) { e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.setData('html', e.target.outerHTML); - e.dataTransfer.setData('feed-id', e.target.getAttribute('data-feed-id')); + e.dataTransfer.setData('text/html', e.target.outerHTML); + e.dataTransfer.setData('text', e.target.getAttribute('data-feed-id')); + e.target.style.opacity = 0.3; + + dnd_successful = false; }); - $('.box').on('dragend', feeds_draggable, function(e) { - var parent = e.target.parentNode; - parent.removeChild(e.target); - + $('.drop-section').on('dragend', draggable, function(e) { + dragend_process(e.target); }); - $('.box').on('dragenter', box_dropzone, function(e) { + $('.drop-section').on('dragenter', dropzone, function(e) { $(e.target).addClass('drag-hover'); }); - $('.box').on('dragleave', box_dropzone, function(e) { + $('.drop-section').on('dragleave', dropzone, function(e) { $(e.target).removeClass('drag-hover'); }); - $('.box').on('dragover', box_dropzone, function(e) { + $('.drop-section').on('dragover', dropzone, function(e) { e.dataTransfer.dropEffect = "move"; return false; }); - $('.box').on('drop', box_dropzone, function(e) { - var feed_id = e.dataTransfer.getData('feed-id'), + $('.drop-section').on('drop', dropzone, function(e) { + var feed_id = e.dataTransfer.getData('text'), cat_id = e.target.parentNode.getAttribute('data-cat-id'); + loading = true; + $.ajax({ type: 'POST', url: './?c=feed&a=move', @@ -40,10 +68,15 @@ function init_draggable() { f_id: feed_id, c_id: cat_id } + }).success(function() { + $(e.target).after(e.dataTransfer.getData('text/html')); + loading = false; + }).complete(function() { + dnd_successful = true; }); - $(e.target).after(e.dataTransfer.getData('html')); $(e.target).removeClass('drag-hover'); + return false; }); } diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css index c79f6cc4c..b25deab0c 100644 --- a/p/themes/Origine/origine.css +++ b/p/themes/Origine/origine.css @@ -498,15 +498,6 @@ a.btn { visibility: visible; } -/*=== Draggable */ -.drag-hover { - background: #dfd; - transition: all linear 0.2s; -} -[draggable=true] { - cursor: grab; -} - /*=== STRUCTURE */ /*===============*/ /*=== Header */ diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index e6c832ee4..06874c9fe 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -304,6 +304,10 @@ a.btn { .box .box-content .item { display: block; } +.box .box-content .item.disabled { + text-align: center; + font-style: italic; +} .box .box-content-centered { padding: 30px 5px; @@ -313,6 +317,14 @@ a.btn { margin: 20px 0 0; } +/*=== Draggable */ +.drag-hover { + margin: 0 0 5px; + border-bottom: 2px solid #ccc; +} +[draggable=true] { + cursor: grab; +} /*=== STRUCTURE */ /*===============*/ -- cgit v1.2.3 From 408ac31dd8751eba037db216243958d396df1c8e Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 19:02:43 +0200 Subject: Hack for dragleave (triggered on children!) See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/Controllers/feedController.php | 7 ++++++- p/scripts/category.js | 33 ++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 8 deletions(-) (limited to 'p/scripts') diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 315665ef3..b2b53185e 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -389,7 +389,12 @@ class FreshRSS_feed_Controller extends Minz_ActionController { 'category' => $cat_id, ); - $feedDAO->updateFeed($feed_id, $values); + if (!$feedDAO->updateFeed($feed_id, $values)) { + Minz_Error::error( + 404, + array('error' => array(_t('error_occurred'))) + ); + } } } diff --git a/p/scripts/category.js b/p/scripts/category.js index 37ad36b17..872d14490 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -4,6 +4,8 @@ var loading = false, dnd_successful = false; function dragend_process(t) { + t.style.display = 'none'; + if (loading) { window.setTimeout(function() { dragend_process(t); @@ -11,13 +13,13 @@ function dragend_process(t) { } if (!dnd_successful) { + t.style.display = 'block'; t.style.opacity = 1.0; } else { t.parentNode.removeChild(t); } } - function init_draggable() { if (!(window.$ && window.url_freshrss)) { if (window.console) { @@ -45,14 +47,31 @@ function init_draggable() { }); $('.drop-section').on('dragenter', dropzone, function(e) { - $(e.target).addClass('drag-hover'); + $(this).addClass('drag-hover'); + + e.preventDefault(); }); $('.drop-section').on('dragleave', dropzone, function(e) { - $(e.target).removeClass('drag-hover'); + var pos_this = $(this).position(), + scroll_top = $(document).scrollTop(), + top = pos_this.top, + left = pos_this.left, + right = left + $(this).width(), + bottom = top + $(this).height(), + mouse_x = e.originalEvent.screenX, + mouse_y = e.originalEvent.clientY + scroll_top; + + if (left <= mouse_x && mouse_x <= right && + top <= mouse_y && mouse_y <= bottom) { + // HACK because dragleave is triggered when hovering children! + return; + } + $(this).removeClass('drag-hover'); }); $('.drop-section').on('dragover', dropzone, function(e) { e.dataTransfer.dropEffect = "move"; + e.preventDefault(); return false; }); $('.drop-section').on('drop', dropzone, function(e) { @@ -70,14 +89,14 @@ function init_draggable() { } }).success(function() { $(e.target).after(e.dataTransfer.getData('text/html')); - loading = false; - }).complete(function() { dnd_successful = true; + }).complete(function() { + loading = false; }); - $(e.target).removeClass('drag-hover'); + $(this).removeClass('drag-hover'); - return false; + e.preventDefault(); }); } -- cgit v1.2.3 From ce43b1761b810c89e5e8660e8ae2638e97ca6339 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 19:47:02 +0200 Subject: Fix box when no feed in category See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/views/helpers/javascript_vars.phtml | 1 + p/scripts/category.js | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'p/scripts') diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 1139eb446..71798369d 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -54,6 +54,7 @@ echo 'authType="', $authType, '",', echo 'str_confirmation_default="', Minz_Translate::t('confirm_action'), '"', ",\n"; echo 'str_notif_title_articles="', Minz_Translate::t('notif_title_new_articles'), '"', ",\n"; echo 'str_notif_body_articles="', Minz_Translate::t('notif_body_new_articles'), '"', ",\n"; +echo 'str_category_empty="', Minz_Translate::t('category_empty'), '"', ",\n"; echo 'html5_notif_timeout=', $this->conf->html5_notif_timeout,",\n"; diff --git a/p/scripts/category.js b/p/scripts/category.js index 872d14490..dc5df67e4 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -16,7 +16,12 @@ function dragend_process(t) { t.style.display = 'block'; t.style.opacity = 1.0; } else { - t.parentNode.removeChild(t); + var parent = $(t.parentNode); + $(t).remove(); + + if (parent.children().length <= 0) { + parent.append('
      • ' + str_category_empty + '
      • '); + } } } @@ -89,6 +94,9 @@ function init_draggable() { } }).success(function() { $(e.target).after(e.dataTransfer.getData('text/html')); + if ($(e.target).hasClass('disabled')) { + $(e.target).remove(); + } dnd_successful = true; }).complete(function() { loading = false; -- cgit v1.2.3 From 91cc88209c710e64cd8a10397e56d006d4566624 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 4 Oct 2014 08:45:57 -0400 Subject: Remove debugging code --- p/scripts/main.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'p/scripts') diff --git a/p/scripts/main.js b/p/scripts/main.js index 37281a907..02d16ca64 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -384,8 +384,6 @@ function collapse_entry() { } function user_filter(key) { - console.log('user filter'); - console.warn(key); var filter = $('#dropdown-query'); var filters = filter.siblings('.dropdown-menu').find('.item.query a'); if (typeof key === "undefined") { -- cgit v1.2.3 From 7a59568dfc20589c0495235679a96a375e36cfee Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 4 Oct 2014 08:46:11 -0400 Subject: Fix library with code provided in the comments of the library page. The fix was given by the owner of the project (I assume) but was never integrated in the code. There is no bug tracker so I couldn't open a ticket. It looks like the project is dead since there is modification to the library. --- p/scripts/shortcut.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'p/scripts') diff --git a/p/scripts/shortcut.js b/p/scripts/shortcut.js index debaffbaa..4137172c3 100644 --- a/p/scripts/shortcut.js +++ b/p/scripts/shortcut.js @@ -43,7 +43,9 @@ shortcut = { //Find Which key is pressed if (e.keyCode) code = e.keyCode; else if (e.which) code = e.which; - var character = String.fromCharCode(code).toLowerCase(); + if( code == 32 || (code >= 48 && code <= 90) || (code >= 96 && code <= 111) || (code >= 186 && code <= 192) || (code >= 219 && code <= 222)) { + var character = String.fromCharCode(code).toLowerCase(); + } if(code == 188) character=","; //If the user presses , when the type is onkeydown if(code == 190) character="."; //If the user presses , when the type is onkeydown -- cgit v1.2.3 From 38a6f0c4b29e5a53c21f345dd839a4fa0b2a6f47 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 4 Oct 2014 09:06:35 -0400 Subject: Add a shortcut to close drop-down lists --- app/Models/Configuration.php | 1 + app/i18n/en.php | 1 + app/i18n/fr.php | 1 + app/views/configure/shortcut.phtml | 7 +++++++ app/views/helpers/javascript_vars.phtml | 3 ++- p/scripts/main.js | 6 ++++++ 6 files changed, 18 insertions(+), 1 deletion(-) (limited to 'p/scripts') diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php index 95f819779..feba3d2f6 100644 --- a/app/Models/Configuration.php +++ b/app/Models/Configuration.php @@ -47,6 +47,7 @@ class FreshRSS_Configuration { 'focus_search' => 'a', 'user_filter' => 'u', 'help' => 'f1', + 'close_dropdown' => 'escape', ), 'topline_read' => true, 'topline_favorite' => true, diff --git a/app/i18n/en.php b/app/i18n/en.php index 28104196e..0456049a9 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -191,6 +191,7 @@ return array ( 'user_filter' => 'Access user filters', 'user_filter_help' => 'If there is only one user filter, it is used. Else filters are accessible by their number.', 'help' => 'Display documentation', + 'close_dropdown' => 'Close drop-down lists', 'file_to_import' => 'File to import
        (OPML, Json or Zip)', 'file_to_import_no_zip' => 'File to import
        (OPML or Json)', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index c72fc3e93..adc79d0e2 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -191,6 +191,7 @@ return array ( 'user_filter' => 'Accéder aux filtres utilisateur', 'user_filter_help' => 'S’il n’y a qu’un filtre utilisateur, celui ci est utilisé automatiquement. Sinon ils sont accessibles par leur numéro.', 'help' => 'Afficher la documentation', + 'close_dropdown' => 'Fermer les listes déroulantes', 'file_to_import' => 'Fichier à importer
        (OPML, Json ou Zip)', 'file_to_import_no_zip' => 'Fichier à importer
        (OPML ou Json)', diff --git a/app/views/configure/shortcut.phtml b/app/views/configure/shortcut.phtml index a4029b676..44727e62b 100644 --- a/app/views/configure/shortcut.phtml +++ b/app/views/configure/shortcut.phtml @@ -111,6 +111,13 @@
    +
    + +
    + +
    +
    +
    diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 71798369d..4f7e3db0c 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -28,7 +28,8 @@ echo ',shortcuts={', 'auto_share:"', $s['auto_share'], '",', 'focus_search:"', $s['focus_search'], '",', 'user_filter:"', $s['user_filter'], '",', - 'help:"', $s['help'], '"', + 'help:"', $s['help'], '",', + 'close_dropdown:"', $s['close_dropdown'], '"', "},\n"; if (Minz_Request::param ('output') === 'global') { diff --git a/p/scripts/main.js b/p/scripts/main.js index 37281a907..0d90d3d39 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -663,6 +663,12 @@ function init_shortcuts() { 'disable_in_input': true }); + shortcut.add(shortcuts.close_dropdown, function () { + window.location.hash = null; + }, { + 'disable_in_input': true + }); + } function init_stream(divStream) { -- cgit v1.2.3 From 6e6d7b3c870975b2981f653b6f53a31f800f56ec Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 5 Oct 2014 01:43:29 +0200 Subject: Minor JavaScript --- p/scripts/main.js | 2 +- p/scripts/shortcut.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'p/scripts') diff --git a/p/scripts/main.js b/p/scripts/main.js index 79a34ec29..5793bb50b 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -33,7 +33,7 @@ function needsScroll($elem) { } function str2int(str) { - if (str == '' || str === undefined) { + if (!str) { return 0; } return parseInt(str.replace(/\D/g, ''), 10) || 0; diff --git a/p/scripts/shortcut.js b/p/scripts/shortcut.js index 4137172c3..e78cf6f5e 100644 --- a/p/scripts/shortcut.js +++ b/p/scripts/shortcut.js @@ -43,7 +43,7 @@ shortcut = { //Find Which key is pressed if (e.keyCode) code = e.keyCode; else if (e.which) code = e.which; - if( code == 32 || (code >= 48 && code <= 90) || (code >= 96 && code <= 111) || (code >= 186 && code <= 192) || (code >= 219 && code <= 222)) { + if (code == 32 || (code >= 48 && code <= 90) || (code >= 96 && code <= 111) || (code >= 186 && code <= 192) || (code >= 219 && code <= 222)) { //FreshRSS var character = String.fromCharCode(code).toLowerCase(); } -- cgit v1.2.3 From d8ed718aab99ad47897fb70ea9086fa704bb912b Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 5 Oct 2014 17:29:09 +0200 Subject: Refactor javascript_vars.phtml Introduce kind of context objectin JavaScript See https://github.com/marienfressinaud/FreshRSS/issues/634 See https://github.com/marienfressinaud/FreshRSS/issues/655 --- app/views/helpers/javascript_vars.phtml | 79 ++++++++++++++++----------------- p/scripts/category.js | 4 +- p/scripts/global_view.js | 2 +- p/scripts/main.js | 66 ++++++++++++--------------- 4 files changed, 70 insertions(+), 81 deletions(-) (limited to 'p/scripts') diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 011b17b7a..cdbf24eab 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -1,21 +1,30 @@ +"use strict"; conf->mark_when; -echo 'var ', - 'help_url="', FRESHRSS_WIKI, '"', - ',hide_posts=', ($this->conf->display_posts || Minz_Request::param('output') === 'reader') ? 'false' : 'true', - ',display_order="', Minz_Request::param('order', $this->conf->sort_order), '"', - ',auto_mark_article=', $mark['article'] ? 'true' : 'false', - ',auto_mark_site=', $mark['site'] ? 'true' : 'false', - ',auto_mark_scroll=', $mark['scroll'] ? 'true' : 'false', - ',auto_load_more=', $this->conf->auto_load_more ? 'true' : 'false', - ',does_lazyload=', $this->conf->lazyload ? 'true' : 'false', - ',sticky_post=', $this->conf->sticky_post ? 'true' : 'false'; - +$mail = Minz_Session::param ('mail', false); +$auto_actualize = Minz_Session::param('actualize_feeds', false); +$hide_posts = ($this->conf->display_posts || + Minz_Request::param('output') === 'reader'); $s = $this->conf->shortcuts; -echo ',shortcuts={', + +echo 'var context={', + 'hide_posts:', $hide_posts ? 'false' : 'true', ',', + 'display_order:"', Minz_Request::param('order', $this->conf->sort_order), '",', + 'auto_mark_article:', $mark['article'] ? 'true' : 'false', ',', + 'auto_mark_site:', $mark['site'] ? 'true' : 'false', ',', + 'auto_mark_scroll:', $mark['scroll'] ? 'true' : 'false', ',', + 'auto_load_more:', $this->conf->auto_load_more ? 'true' : 'false', ',', + 'auto_actualize_feeds:', $auto_actualize ? 'true' : 'false', ',', + 'does_lazyload:', $this->conf->lazyload ? 'true' : 'false', ',', + 'sticky_post:', $this->conf->sticky_post ? 'true' : 'false', ',', + 'html5_notif_timeout:', $this->conf->html5_notif_timeout, ',', + 'auth_type:"', Minz_Configuration::authType(), '",', + 'current_user_mail:', $mail ? ('"' . $mail . '"') : 'null', ',', + 'current_view:"', Minz_Request::param('output', 'normal'), '"', +"},\n"; + +echo 'shortcuts={', 'mark_read:"', $s['mark_read'], '",', 'mark_favorite:"', $s['mark_favorite'], '",', 'go_website:"', $s['go_website'], '",', @@ -32,32 +41,20 @@ echo ',shortcuts={', 'close_dropdown:"', $s['close_dropdown'], '"', "},\n"; -if (Minz_Request::param ('output') === 'global') { - echo "iconClose='", _i('close'), "',\n"; -} - -$authType = Minz_Configuration::authType(); -if ($authType === 'persona') { - // If user is disconnected, current_user_mail MUST be null - $mail = Minz_Session::param ('mail', false); - if ($mail) { - echo 'current_user_mail="' . $mail . '",'; - } else { - echo 'current_user_mail=null,'; - } -} - -echo 'authType="', $authType, '",', - 'url_freshrss="', _url ('index', 'index'), '",', - 'url_login="', _url ('index', 'login'), '",', - 'url_logout="', _url ('index', 'logout'), '",'; - -echo 'str_confirmation_default="', _t('confirm_action'), '"', ",\n"; -echo 'str_notif_title_articles="', _t('notif_title_new_articles'), '"', ",\n"; -echo 'str_notif_body_articles="', _t('notif_body_new_articles'), '"', ",\n"; -echo 'str_category_empty="', _t('category_empty'), '"', ",\n"; -echo 'html5_notif_timeout=', $this->conf->html5_notif_timeout,",\n"; +echo 'url={', + 'index:"', _url('index', 'index'), '",', + 'login:"', _url('index', 'login'), '",', + 'logout:"', _url('index', 'logout'), '",', + 'help:"', FRESHRSS_WIKI, '"', +"},\n"; +echo 'i18n={', + 'confirmation_default:"', _t('confirm_action'), '",', + 'notif_title_articles:"', _t('notif_title_new_articles'), '",', + 'notif_body_articles:"', _t('notif_body_new_articles'), '",', + 'category_empty:"', _t('category_empty'), '"', +"},\n"; -$autoActualise = Minz_Session::param('actualize_feeds', false); -echo 'auto_actualize_feeds=', $autoActualise ? 'true' : 'false', ";\n"; +echo 'icons={', + 'close:\'', _i('close'), '\'', +"}\n"; \ No newline at end of file diff --git a/p/scripts/category.js b/p/scripts/category.js index dc5df67e4..c33e68528 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -20,13 +20,13 @@ function dragend_process(t) { $(t).remove(); if (parent.children().length <= 0) { - parent.append('
  • ' + str_category_empty + '
  • '); + parent.append('
  • ' + i18n['category_empty'] + '
  • '); } } } function init_draggable() { - if (!(window.$ && window.url_freshrss)) { + if (!(window.$ && window.i18n)) { if (window.console) { console.log('FreshRSS waiting for JS…'); } diff --git a/p/scripts/global_view.js b/p/scripts/global_view.js index 7105520a6..6e1f61066 100644 --- a/p/scripts/global_view.js +++ b/p/scripts/global_view.js @@ -40,7 +40,7 @@ function load_panel(link) { function init_close_panel() { $("#panel .close").click(function () { - $("#panel").html('' + window.iconClose + ''); + $("#panel").html('' + icons['close'] + ''); init_close_panel(); $("#panel").slideToggle(); $("#overlay").fadeOut(); diff --git a/p/scripts/main.js b/p/scripts/main.js index 5793bb50b..ad33f6c57 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -4,14 +4,6 @@ var $stream = null, shares = 0, ajax_loading = false; -function is_normal_mode() { - return $stream.hasClass('normal'); -} - -function is_global_mode() { - return $stream.hasClass('global'); -} - function redirect(url, new_tab) { if (url) { if (new_tab) { @@ -226,7 +218,7 @@ function toggleContent(new_active, old_active) { return; } - if (does_lazyload) { + if (context['does_lazyload']) { new_active.find('img[data-original], iframe[data-original]').each(function () { this.setAttribute('src', this.getAttribute('data-original')); this.removeAttribute('data-original'); @@ -245,12 +237,12 @@ function toggleContent(new_active, old_active) { var box_to_move = "html,body", relative_move = false; - if (is_global_mode()) { + if (context['current_view'] == 'global') { box_to_move = "#panel"; relative_move = true; } - if (sticky_post) { + if (context['sticky_post']) { var prev_article = new_active.prevAll('.flux'), new_pos = new_active.position().top, old_scroll = $(box_to_move).scrollTop(); @@ -259,7 +251,7 @@ function toggleContent(new_active, old_active) { new_pos = prev_article.position().top; } - if (hide_posts) { + if (context['hide_posts']) { if (relative_move) { new_pos += old_scroll; } @@ -278,7 +270,7 @@ function toggleContent(new_active, old_active) { } } - if (auto_mark_article && new_active.hasClass('active')) { + if (context['auto_mark_article'] && new_active.hasClass('active')) { mark_read(new_active, true); } } @@ -378,7 +370,7 @@ function collapse_entry() { var flux_current = $(".flux.current"); flux_current.toggleClass("active"); - if (isCollapsed && auto_mark_article) { + if (isCollapsed && context['auto_mark_article']) { mark_read(flux_current, true); } } @@ -457,12 +449,12 @@ function inMarkViewport(flux, box_to_follow, relative_follow) { function init_posts() { var box_to_follow = $(window), relative_follow = false; - if (is_global_mode()) { + if (context['current_view'] == 'global') { box_to_follow = $("#panel"); relative_follow = true; } - if (auto_mark_scroll) { + if (context['auto_mark_scroll']) { box_to_follow.scroll(function () { $('.not_read:visible').each(function () { if ($(this).children(".flux_content").is(':visible') && inMarkViewport($(this), box_to_follow, relative_follow)) { @@ -472,7 +464,7 @@ function init_posts() { }); } - if (auto_load_more) { + if (context['auto_load_more']) { box_to_follow.scroll(function () { var load_more = $("#load_more"); if (!load_more.is(':visible')) { @@ -492,7 +484,7 @@ function init_posts() { } function init_column_categories() { - if (!is_normal_mode()) { + if (context['current_view'] !== 'normal') { return; } $('#aside_flux').on('click', '.category>a.dropdown-toggle', function () { @@ -632,7 +624,7 @@ function init_shortcuts() { shortcut.add(shortcuts.go_website, function () { var url_website = $('.flux.current > .flux_header > .title > a').attr("href"); - if (auto_mark_site) { + if (context['auto_mark_site']) { $(".flux.current").each(function () { mark_read($(this), true); }); @@ -656,7 +648,7 @@ function init_shortcuts() { }); shortcut.add(shortcuts.help, function () { - redirect(help_url, true); + redirect(url['help'], true); }, { 'disable_in_input': true }); @@ -678,7 +670,7 @@ function init_stream(divStream) { new_active = $(this).parent(); isCollapsed = true; if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone - if (auto_mark_article) { + if (context['auto_mark_article']) { mark_read(new_active, true); } return true; @@ -724,7 +716,7 @@ function init_stream(divStream) { $(this).attr('target', '_blank'); }); - if (auto_mark_site) { + if (context['auto_mark_site']) { // catch mouseup instead of click so we can have the correct behaviour // with middle button click (scroll button). divStream.on('mouseup', '.flux .link > a', function (e) { @@ -784,7 +776,7 @@ function init_actualize() { return false; }); - if (auto_actualize_feeds) { + if (context['auto_actualize_feeds']) { auto = true; $("#actualize").click(); } @@ -855,9 +847,9 @@ function notifs_html5_show(nb) { return } - var notification = new window.Notification(str_notif_title_articles, { + var notification = new window.Notification(i18n['notif_title_articles'], { icon: "../themes/icons/favicon-256.png", - body: str_notif_body_articles.replace("\d", nb), + body: i18n['notif_body_articles.replace("\d", nb)'], tag: "freshRssNewArticles" }); @@ -865,10 +857,10 @@ function notifs_html5_show(nb) { window.location.reload(); } - if (html5_notif_timeout !== 0){ + if (context['html5_notif_timeout'] !== 0){ setTimeout(function() { notification.close(); - }, html5_notif_timeout * 1000); + }, context['html5_notif_timeout'] * 1000); } } @@ -922,7 +914,7 @@ function load_more_posts() { $.get(url_load_more, function (data) { box_load_more.children('.flux:last').after($('#stream', data).children('.flux, .day')); $('.pagination').replaceWith($('.pagination', data)); - if (display_order === 'ASC') { + if (context['display_order'] === 'ASC') { $('#nav_menu_read_all > .read_all').attr( 'formaction', $('#bigMarkAsRead').attr('formaction') ); @@ -953,7 +945,7 @@ function focus_search() { function init_load_more(box) { box_load_more = box; - if (!does_lazyload) { + if (!context['does_lazyload']) { $('img[postpone], audio[postpone], iframe[postpone], video[postpone]').each(function () { this.removeAttribute('postpone'); }); @@ -1062,7 +1054,7 @@ function init_persona() { }); navigator.id.watch({ - loggedInUser: current_user_mail, + loggedInUser: context['current_user_mail'], onlogin: function(assertion) { // A user has logged in! Here you need to: @@ -1070,13 +1062,13 @@ function init_persona() { // 2. Update your UI. $.ajax ({ type: 'POST', - url: url_login, + url: url['login'], data: {assertion: assertion}, success: function(res, status, xhr) { /*if (res.status === 'failure') { alert (res_obj.reason); } else*/ if (res.status === 'okay') { - location.href = url_freshrss; + location.href = url['index']; } }, error: function(res, status, xhr) { @@ -1091,9 +1083,9 @@ function init_persona() { // (That's a literal JavaScript null. Not false, 0, or undefined. null.) $.ajax ({ type: 'POST', - url: url_logout, + url: url['logout'], success: function(res, status, xhr) { - location.href = url_freshrss; + location.href = url['index']; }, error: function(res, status, xhr) { //alert("logout failure" + res); @@ -1108,7 +1100,7 @@ function init_confirm_action() { $('body').on('click', '.confirm', function () { var str_confirmation = $(this).attr('data-str-confirm'); if (!str_confirmation) { - str_confirmation = str_confirmation_default; + str_confirmation = i18n['confirmation_default']; } return confirm(str_confirmation); @@ -1274,7 +1266,7 @@ function init_slider_observers() { } function init_all() { - if (!(window.$ && window.url_freshrss)) { + if (!(window.$ && window.context)) { if (window.console) { console.log('FreshRSS waiting for JS…'); } @@ -1282,7 +1274,7 @@ function init_all() { return; } init_notifications(); - switch (authType) { + switch (context['auth_type']) { case 'persona': init_persona(); break; -- cgit v1.2.3 From 3831961b2e515ff7d8d352c0f7b6a15b3a613c25 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 5 Oct 2014 18:03:32 +0200 Subject: Fix bug of i18n in JavaScript See https://github.com/marienfressinaud/FreshRSS/issues/655 --- p/scripts/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p/scripts') diff --git a/p/scripts/main.js b/p/scripts/main.js index ad33f6c57..b01a3a34d 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -849,7 +849,7 @@ function notifs_html5_show(nb) { var notification = new window.Notification(i18n['notif_title_articles'], { icon: "../themes/icons/favicon-256.png", - body: i18n['notif_body_articles.replace("\d", nb)'], + body: i18n['notif_body_articles'].replace("\d", nb), tag: "freshRssNewArticles" }); -- cgit v1.2.3 From 1252b3dd867e59917cf303f0c39c7da938b8ce32 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Tue, 7 Oct 2014 16:37:10 +0200 Subject: Authentication system moved + Persona comes back! AuthController is dedicated to auhentication. Persona is back, greater than ever! See https://github.com/marienfressinaud/FreshRSS/issues/655 --- app/Controllers/authController.php | 182 ++++++++++++++++++++++++++++++++ app/Controllers/indexController.php | 90 +--------------- app/FreshRSS.php | 8 ++ app/Models/Auth.php | 21 +++- app/layout/header.phtml | 23 ++-- app/views/auth/formLogin.phtml | 28 +++++ app/views/auth/logout.phtml | 0 app/views/auth/personaLogin.phtml | 24 +++++ app/views/helpers/javascript_vars.phtml | 13 ++- app/views/index/formLogin.phtml | 46 -------- p/scripts/main.js | 65 ------------ p/scripts/persona.js | 76 +++++++++++++ 12 files changed, 356 insertions(+), 220 deletions(-) create mode 100644 app/Controllers/authController.php create mode 100644 app/views/auth/formLogin.phtml create mode 100644 app/views/auth/logout.phtml create mode 100644 app/views/auth/personaLogin.phtml delete mode 100644 app/views/index/formLogin.phtml create mode 100644 p/scripts/persona.js (limited to 'p/scripts') diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php new file mode 100644 index 000000000..2b67e34b8 --- /dev/null +++ b/app/Controllers/authController.php @@ -0,0 +1,182 @@ + 'index', 'a' => 'index'), true); + } + + $auth_type = Minz_Configuration::authType(); + switch ($auth_type) { + case 'form': + Minz_Request::forward(array('c' => 'auth', 'a' => 'formLogin')); + break; + case 'persona': + Minz_Request::forward(array('c' => 'auth', 'a' => 'personaLogin')); + break; + case 'http_auth': + case 'none': + // It should not happened! + Minz_Error::error(404); + default: + // TODO load plugin instead + Minz_Error::error(404); + } + } + + /** + * This action handles form login page. + * + * If this action is reached through a POST request, username and password + * are compared to login the current user. + * + * Parameters are: + * - nonce (default: false) + * - username (default: '') + * - challenge (default: '') + * - keep_logged_in (default: false) + */ + public function formLoginAction() { + invalidateHttpCache(); + + $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'); + Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . $file_mtime)); + + if (Minz_Request::isPost()) { + $nonce = Minz_Session::param('nonce'); + $username = Minz_Request::param('username', ''); + $challenge = Minz_Request::param('challenge', ''); + try { + $conf = new FreshRSS_Configuration($username); + } catch(Minz_Exception $e) { + // $username is not a valid user, nor the configuration file! + Minz_Log::warning('Login failure: ' . $e->getMessage()); + Minz_Request::bad(_t('invalid_login'), + array('c' => 'auth', 'a' => 'login')); + } + + $ok = FreshRSS_FormAuth::checkCredentials( + $username, $conf->passwordHash, $nonce, $challenge + ); + if ($ok) { + // Set session parameter to give access to the user. + Minz_Session::_param('currentUser', $username); + Minz_Session::_param('passwordHash', $conf->passwordHash); + FreshRSS_Auth::giveAccess(); + + // Set cookie parameter if nedded. + if (Minz_Request::param('keep_logged_in')) { + FreshRSS_FormAuth::makeCookie($username, $conf->passwordHash); + } else { + FreshRSS_FormAuth::deleteCookie(); + } + + // All is good, go back to the index. + Minz_Request::good(_t('login'), + array('c' => 'index', 'a' => 'index')); + } else { + Minz_Log::warning('Password mismatch for' . + ' user=' . $username . + ', nonce=' . $nonce . + ', c=' . $challenge); + Minz_Request::bad(_t('invalid_login'), + array('c' => 'auth', 'a' => 'login')); + } + } + } + + /** + * This action handles Persona login page. + * + * If this action is reached through a POST request, assertion from Persona + * is verificated and user connected if all is ok. + * + * Parameter is: + * - assertion (default: false) + * + * @todo: Persona system should be moved to a plugin + */ + public function personaLoginAction() { + $this->view->res = false; + + if (Minz_Request::isPost()) { + $this->view->_useLayout(false); + + $assert = Minz_Request::param('assertion'); + $url = 'https://verifier.login.persona.org/verify'; + $params = 'assertion=' . $assert . '&audience=' . + urlencode(Minz_Url::display(null, 'php', true)); + $ch = curl_init(); + $options = array( + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => TRUE, + CURLOPT_POST => 2, + CURLOPT_POSTFIELDS => $params + ); + curl_setopt_array($ch, $options); + $result = curl_exec($ch); + curl_close($ch); + + $res = json_decode($result, true); + + $login_ok = false; + $reason = ''; + if ($res['status'] === 'okay') { + $email = filter_var($res['email'], FILTER_VALIDATE_EMAIL); + if ($email != '') { + $persona_file = DATA_PATH . '/persona/' . $email . '.txt'; + if (($current_user = @file_get_contents($persona_file)) !== false) { + $current_user = trim($current_user); + try { + $conf = new FreshRSS_Configuration($current_user); + $login_ok = strcasecmp($email, $conf->mail_login) === 0; + } catch (Minz_Exception $e) { + //Permission denied or conf file does not exist + $reason = 'Invalid configuration for user ' . + '[' . $current_user . '] ' . $e->getMessage(); + } + } + } else { + $reason = 'Invalid email format [' . $res['email'] . ']'; + } + } else { + $reason = $res['reason']; + } + + if ($login_ok) { + Minz_Session::_param('currentUser', $current_user); + Minz_Session::_param('mail', $email); + FreshRSS_Auth::giveAccess(); + invalidateHttpCache(); + } else { + Minz_Log::error($reason); + + $res = array(); + $res['status'] = 'failure'; + $res['reason'] = _t('invalid_login'); + } + + header('Content-Type: application/json; charset=UTF-8'); + $this->view->res = $res; + } + } + + /** + * This action removes all accesses of the current user. + */ + public function logoutAction() { + invalidateHttpCache(); + FreshRSS_Auth::removeAccess(); + Minz_Request::good(_t('disconnected'), + array('c' => 'index', 'a' => 'index')); + } +} diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index 3006480f9..5b490e672 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -20,7 +20,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { } elseif ($output !== 'rss') { // "hard" redirection is not required, just ask dispatcher to // forward to the login form without 302 redirection - Minz_Request::forward(array('c' => 'index', 'a' => 'login')); + Minz_Request::forward(array('c' => 'auth', 'a' => 'login')); return; } } @@ -228,92 +228,4 @@ class FreshRSS_index_Controller extends Minz_ActionController { $this->view->logsPaginator->_nbItemsPerPage(50); $this->view->logsPaginator->_currentPage($page); } - - /** - * This action handles the login page. - */ - public function loginAction() { - if (FreshRSS_Auth::hasAccess()) { - Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); - } - - invalidateHttpCache(); - - $auth_type = Minz_Configuration::authType(); - switch ($auth_type) { - case 'form': - Minz_Request::forward(array('c' => 'index', 'a' => 'formLogin')); - break; - case 'http_auth': - case 'none': - // It should not happened! - Minz_Error::error(404); - default: - // TODO load plugin instead - Minz_Error::error(404); - } - } - - /** - * - */ - public function formLoginAction() { - if (FreshRSS_Auth::hasAccess()) { - Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); - } - - invalidateHttpCache(); - - $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'); - Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . $file_mtime)); - - if (Minz_Request::isPost()) { - $nonce = Minz_Session::param('nonce'); - $username = Minz_Request::param('username', ''); - $challenge = Minz_Request::param('challenge', ''); - try { - $conf = new FreshRSS_Configuration($username); - } catch(Minz_Exception $e) { - // $username is not a valid user, nor the configuration file! - Minz_Log::warning('Login failure: ' . $e->getMessage()); - Minz_Request::bad(_t('invalid_login'), - array('c' => 'index', 'a' => 'login')); - } - - $ok = FreshRSS_FormAuth::checkCredentials( - $username, $conf->passwordHash, $nonce, $challenge - ); - if ($ok) { - // Set session parameter to give access to the user. - Minz_Session::_param('currentUser', $username); - Minz_Session::_param('passwordHash', $conf->passwordHash); - FreshRSS_Auth::giveAccess(); - - // Set cookie parameter if nedded. - if (Minz_Request::param('keep_logged_in', false)) { - FreshRSS_FormAuth::makeCookie($username, $conf->passwordHash); - } else { - FreshRSS_FormAuth::deleteCookie(); - } - - // All is good, go back to the index. - Minz_Request::good(_t('login'), - array('c' => 'index', 'a' => 'index')); - } else { - Minz_Log::warning('Password mismatch for' . - ' user=' . $username . - ', nonce=' . $nonce . - ', c=' . $challenge); - Minz_Request::bad(_t('invalid_login'), - array('c' => 'index', 'a' => 'login')); - } - } - } - - public function logoutAction() { - invalidateHttpCache(); - FreshRSS_Auth::removeAccess(); - Minz_Request::good(_t('disconnected'), - array('c' => 'index', 'a' => 'index')); - } } diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 35a37b887..6b7a813bf 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -64,6 +64,14 @@ class FreshRSS extends Minz_FrontController { Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); + + if (Minz_Configuration::authType() === 'persona') { + // TODO move it in a plugin + // Needed for login AND logout with Persona. + Minz_View::appendScript('https://login.persona.org/include.js'); + $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/persona.js'); + Minz_View::appendScript(Minz_Url::display('/scripts/persona.js?' . $file_mtime)); + } } private function loadNotifications() { diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 992b444a5..cc23d7974 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -20,7 +20,7 @@ class FreshRSS_Auth { Minz_Session::_param('currentUser', $current_user); } - $access_ok = self::accessControl($current_user); + $access_ok = self::accessControl(); if ($access_ok) { self::giveAccess(); @@ -36,10 +36,9 @@ class FreshRSS_Auth { * Required session parameters are also set in this method (such as * currentUser). * - * @param string $username username of the user to check access. * @return boolean true if user can be connected, false else. */ - public static function accessControl($username) { + public static function accessControl() { if (self::$login_ok) { return true; } @@ -61,6 +60,16 @@ class FreshRSS_Auth { Minz_Session::_param('currentUser', $current_user); } return $login_ok; + case 'persona': + $email = filter_var(Minz_Session::param('mail'), FILTER_VALIDATE_EMAIL); + $persona_file = DATA_PATH . '/persona/' . $email . '.txt'; + if (($current_user = @file_get_contents($persona_file)) !== false) { + $current_user = trim($current_user); + Minz_Session::_param('currentUser', $current_user); + Minz_Session::_param('mail', $email); + return true; + } + return false; case 'none': return true; default: @@ -87,6 +96,9 @@ class FreshRSS_Auth { case 'http_auth': self::$login_ok = strcasecmp($current_user, httpAuthUser()) === 0; break; + case 'persona': + self::$login_ok = strcasecmp(Minz_Session::param('mail'), $conf->mail_login) === 0; + break; case 'none': self::$login_ok = true; break; @@ -131,6 +143,9 @@ class FreshRSS_Auth { Minz_Session::_param('passwordHash'); FreshRSS_FormAuth::deleteCookie(); break; + case 'persona': + Minz_Session::_param('mail'); + break; case 'http_auth': case 'none': // Nothing to do... diff --git a/app/layout/header.phtml b/app/layout/header.phtml index 12c86d61d..deb21edc9 100644 --- a/app/layout/header.phtml +++ b/app/layout/header.phtml @@ -2,9 +2,9 @@ if (Minz_Configuration::canLogIn()) { ?>
  • -
  • -
    + +
    + +
    + diff --git a/app/views/auth/formLogin.phtml b/app/views/auth/formLogin.phtml new file mode 100644 index 000000000..0194a11a5 --- /dev/null +++ b/app/views/auth/formLogin.phtml @@ -0,0 +1,28 @@ +
    +

    + +
    +
    + + +
    +
    + + +
    + +
    +
    + +
    +
    +
    + +
    +
    + +

    +
    diff --git a/app/views/auth/logout.phtml b/app/views/auth/logout.phtml new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/auth/personaLogin.phtml b/app/views/auth/personaLogin.phtml new file mode 100644 index 000000000..d62fe5818 --- /dev/null +++ b/app/views/auth/personaLogin.phtml @@ -0,0 +1,24 @@ +res === false) { ?> +
    +

    + +

    + + +

    + + + + + +

    + +

    +
    +res); +} +?> diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 8f615ed87..3bbcc3848 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -8,6 +8,15 @@ $hide_posts = ($this->conf->display_posts || Minz_Request::param('output') === 'reader'); $s = $this->conf->shortcuts; +$url_login = Minz_Url::display(array( + 'c' => 'auth', + 'a' => 'login' +), 'php'); +$url_logout = Minz_Url::display(array( + 'c' => 'auth', + 'a' => 'logout' +), 'php'); + echo 'var context={', 'hide_posts:', $hide_posts ? 'false' : 'true', ',', 'display_order:"', Minz_Request::param('order', $this->conf->sort_order), '",', @@ -43,8 +52,8 @@ echo 'shortcuts={', echo 'url={', 'index:"', _url('index', 'index'), '",', - 'login:"', _url('index', 'login'), '",', - 'logout:"', _url('index', 'logout'), '",', + 'login:"', $url_login, '",', + 'logout:"', $url_logout, '",', 'help:"', FRESHRSS_WIKI, '"', "},\n"; diff --git a/app/views/index/formLogin.phtml b/app/views/index/formLogin.phtml deleted file mode 100644 index b05cdced4..000000000 --- a/app/views/index/formLogin.phtml +++ /dev/null @@ -1,46 +0,0 @@ -
    -

    -
    - - -
    -
    - - -
    - -
    -
    - -
    -
    -
    - -
    -

    -

    - - - - - -

    - -

    -
    diff --git a/p/scripts/main.js b/p/scripts/main.js index b01a3a34d..77e1e3f77 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1034,67 +1034,7 @@ function init_crypto_form() { } // -// -function init_persona() { - if (!(navigator.id)) { - if (window.console) { - console.log('FreshRSS waiting for Persona…'); - } - window.setTimeout(init_persona, 100); - return; - } - $('a.signin').click(function() { - navigator.id.request(); - return false; - }); - - $('a.signout').click(function() { - navigator.id.logout(); - return false; - }); - navigator.id.watch({ - loggedInUser: context['current_user_mail'], - - onlogin: function(assertion) { - // A user has logged in! Here you need to: - // 1. Send the assertion to your backend for verification and to create a session. - // 2. Update your UI. - $.ajax ({ - type: 'POST', - url: url['login'], - data: {assertion: assertion}, - success: function(res, status, xhr) { - /*if (res.status === 'failure') { - alert (res_obj.reason); - } else*/ if (res.status === 'okay') { - location.href = url['index']; - } - }, - error: function(res, status, xhr) { - alert("Login failure: " + res); - } - }); - }, - onlogout: function() { - // A user has logged out! Here you need to: - // Tear down the user's session by redirecting the user or making a call to your backend. - // Also, make sure loggedInUser will get set to null on the next page load. - // (That's a literal JavaScript null. Not false, 0, or undefined. null.) - $.ajax ({ - type: 'POST', - url: url['logout'], - success: function(res, status, xhr) { - location.href = url['index']; - }, - error: function(res, status, xhr) { - //alert("logout failure" + res); - } - }); - } - }); -} -// function init_confirm_action() { $('body').on('click', '.confirm', function () { @@ -1274,11 +1214,6 @@ function init_all() { return; } init_notifications(); - switch (context['auth_type']) { - case 'persona': - init_persona(); - break; - } init_confirm_action(); $stream = $('#stream'); if ($stream.length > 0) { diff --git a/p/scripts/persona.js b/p/scripts/persona.js new file mode 100644 index 000000000..36aeeaf56 --- /dev/null +++ b/p/scripts/persona.js @@ -0,0 +1,76 @@ +"use strict"; + +function init_persona() { + if (!(navigator.id && window.$)) { + if (window.console) { + console.log('FreshRSS (Persona) waiting for JS…'); + } + window.setTimeout(init_persona, 100); + return; + } + + $('a.signin').click(function() { + navigator.id.request(); + return false; + }); + + $('a.signout').click(function() { + navigator.id.logout(); + return false; + }); + + navigator.id.watch({ + loggedInUser: context['current_user_mail'], + + onlogin: function(assertion) { + // A user has logged in! Here you need to: + // 1. Send the assertion to your backend for verification and to create a session. + // 2. Update your UI. + $.ajax ({ + type: 'POST', + url: url['login'], + data: {assertion: assertion}, + success: function(res, status, xhr) { + if (res.status === 'failure') { + openNotification(res.reason, 'bad'); + } else if (res.status === 'okay') { + location.href = url['index']; + } + }, + error: function(res, status, xhr) { + // alert(res); + } + }); + }, + onlogout: function() { + // A user has logged out! Here you need to: + // Tear down the user's session by redirecting the user or making a call to your backend. + // Also, make sure loggedInUser will get set to null on the next page load. + // (That's a literal JavaScript null. Not false, 0, or undefined. null.) + $.ajax ({ + type: 'POST', + url: url['logout'], + success: function(res, status, xhr) { + location.href = url['index']; + }, + error: function(res, status, xhr) { + // alert(res); + } + }); + } + }); +} + +if (document.readyState && document.readyState !== 'loading') { + if (window.console) { + console.log('FreshRSS (Persona) immediate init…'); + } + init_persona(); +} else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', function () { + if (window.console) { + console.log('FreshRSS (Persona) waiting for DOMContentLoaded…'); + } + init_persona(); + }, false); +} -- cgit v1.2.3 From 2796cc9ae559842a90fa15cba65c94a11b29195e Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 16 Oct 2014 16:43:37 +0200 Subject: User list load a new page Beginning of more options for administrator! --- app/Controllers/userController.php | 4 ++++ app/views/stats/repartition.phtml | 2 +- app/views/user/manage.phtml | 41 +++++++++++++++++++------------------- p/scripts/main.js | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) (limited to 'p/scripts') diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index c516246c9..00b51cc3d 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -88,6 +88,10 @@ class FreshRSS_user_Controller extends Minz_ActionController { */ public function manageAction() { Minz_View::prependTitle(_t('users.manage') . ' · '); + + $this->view->current_user = Minz_Request::param( + 'u', Minz_Session::param('currentUser', '_') + ); } public function createAction() { diff --git a/app/views/stats/repartition.phtml b/app/views/stats/repartition.phtml index 670714707..32268a546 100644 --- a/app/views/stats/repartition.phtml +++ b/app/views/stats/repartition.phtml @@ -5,7 +5,7 @@

    - categories as $category) { $feeds = $category->feeds(); diff --git a/app/views/user/manage.phtml b/app/views/user/manage.phtml index 03746cabb..fb569872b 100644 --- a/app/views/user/manage.phtml +++ b/app/views/user/manage.phtml @@ -3,27 +3,6 @@
    -
    - - -
    - -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    @@ -71,6 +50,26 @@
    + + +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    diff --git a/p/scripts/main.js b/p/scripts/main.js index 77e1e3f77..1e13ff16a 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1086,7 +1086,7 @@ function init_share_observers() { } function init_stats_observers() { - $('#feed_select').on('change', function(e) { + $('.select-change').on('change', function(e) { redirect($(this).find(':selected').data('url')); }); } -- cgit v1.2.3 From 8a7bab3a55442f85553ab1d897084e89c10f7e05 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Mon, 20 Oct 2014 19:35:22 +0200 Subject: Refactoring of indexController Global view has been moved to a different action (all is not working) See https://github.com/marienfressinaud/FreshRSS/issues/634 and https://github.com/marienfressinaud/FreshRSS/issues/655 --- app/Controllers/errorController.php | 2 +- app/Controllers/indexController.php | 33 +++++++++++++++----- app/layout/nav_menu.phtml | 2 +- app/views/helpers/view/global_view.phtml | 53 -------------------------------- app/views/index/global.phtml | 46 +++++++++++++++++++++++++++ app/views/index/index.phtml | 2 -- lib/lib_rss.php | 4 +++ p/scripts/global_view.js | 3 +- 8 files changed, 79 insertions(+), 66 deletions(-) delete mode 100644 app/views/helpers/view/global_view.phtml create mode 100644 app/views/index/global.phtml (limited to 'p/scripts') diff --git a/app/Controllers/errorController.php b/app/Controllers/errorController.php index 76ab930e0..6c080bea8 100644 --- a/app/Controllers/errorController.php +++ b/app/Controllers/errorController.php @@ -37,7 +37,7 @@ class FreshRSS_error_Controller extends Minz_ActionController { if ($this->view->errorMessage == '') { switch($code_int) { case 403: - $this->view->errorMessage = _t('forbidden_access'); + $this->view->errorMessage = _t('access_denied'); break; case 404: default: diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index f994e257c..e1ce71b28 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -1,5 +1,8 @@ array(_t('access_denied'))) - ); + Minz_Error::error(403); return; } elseif ($output !== 'rss') { // "hard" redirection is not required, just ask dispatcher to @@ -201,17 +201,34 @@ class FreshRSS_index_Controller extends Minz_ActionController { return false; } } + + /** + * This action displays the global view of FreshRSS. + */ + public function globalAction() { + if (!FreshRSS_Auth::hasAccess() && !Minz_Configuration::allowAnonymous()) { + Minz_Error::error(403); + } + + Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); + + $catDAO = new FreshRSS_CategoryDAO(); + $this->view->categories = $catDAO->listCategories(); + } + /** + * This action displays the about page of FreshRSS. + */ public function aboutAction() { Minz_View::prependTitle(_t('about') . ' · '); } + /** + * This action displays logs of FreshRSS for the current user. + */ public function logsAction() { if (!FreshRSS_Auth::hasAccess()) { - Minz_Error::error( - 403, - array('error' => array(_t('access_denied'))) - ); + Minz_Error::error(403); } Minz_View::prependTitle(_t('logs') . ' · '); diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index bb9468ab1..1a26422df 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -240,7 +240,7 @@ - + diff --git a/app/views/helpers/view/global_view.phtml b/app/views/helpers/view/global_view.phtml deleted file mode 100644 index ae8af820d..000000000 --- a/app/views/helpers/view/global_view.phtml +++ /dev/null @@ -1,53 +0,0 @@ -partial('nav_menu'); ?> - -entries)) { ?> -
    - 'index', 'a' => 'index', 'params' => array()); - if (FreshRSS_Context::$conf->view_mode !== 'normal') { - $arUrl['params']['output'] = 'normal'; - } - $p = Minz_Request::param('state', ''); - if (($p != '') && (FreshRSS_Context::$conf->default_view !== $p)) { - $arUrl['params']['state'] = $p; - } - - foreach ($this->cat_aside as $cat) { - $feeds = $cat->feeds(); - if (!empty($feeds)) { -?> -
    - - -
    - -
    - -
    -
    display_posts ? '' : ' class="hide_posts"'; ?>> - -
    - - -
    -

    -

    -
    - diff --git a/app/views/index/global.phtml b/app/views/index/global.phtml new file mode 100644 index 000000000..a72e431df --- /dev/null +++ b/app/views/index/global.phtml @@ -0,0 +1,46 @@ +partial('nav_menu'); ?> + +
    + 'index', + 'a' => 'index', + 'params' => array( + 'state' => FreshRSS_Context::$state + ) + ); + + foreach ($this->categories as $cat) { + $feeds = $cat->feeds(); + $url_base['params']['get'] = 'c_' . $cat->id(); + + if (!empty($feeds)) { +?> +
    + + +
      + nbNotRead(); + $error = $feed->inError() ? 'error ' : ''; + $empty = $feed->nbEntries() === 0 ? 'empty ' : ''; + $url_base['params']['get'] = 'f_' . $feed->id(); + ?> +
    • + ✇ + name(); ?> +
    • + +
    +
    + +
    + +
    +
    display_posts ? '' : ' class="hide_posts"'; ?>> + +
    diff --git a/app/views/index/index.phtml b/app/views/index/index.phtml index a59063557..8b93461dd 100644 --- a/app/views/index/index.phtml +++ b/app/views/index/index.phtml @@ -7,8 +7,6 @@ if (FreshRSS_Auth::hasAccess() || Minz_Configuration::allowAnonymous()) { $this->renderHelper('view/normal_view'); } elseif ($output === 'reader') { $this->renderHelper('view/reader_view'); - } elseif ($output === 'global') { - $this->renderHelper('view/global_view'); } elseif ($output === 'rss') { $this->renderHelper('view/rss_view'); } else { diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 9abdf18ce..80eb206d2 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -60,6 +60,10 @@ function formatNumber($n, $precision = 0) { return str_replace(' ', ' ', //Espace insécable //TODO: remplacer par une espace _fine_ insécable number_format($n, $precision, '.', ' ')); //number_format does not seem to be Unicode-compatible } +function format_number($n, $precision = 0) { + // TODO: coding style, prefer THIS function. Remove formatNumber. + return formatNumber($n, $precision); +} function formatBytes($bytes, $precision = 2, $system = 'IEC') { if ($system === 'IEC') { diff --git a/p/scripts/global_view.js b/p/scripts/global_view.js index 6e1f61066..8c2e6c1a2 100644 --- a/p/scripts/global_view.js +++ b/p/scripts/global_view.js @@ -50,7 +50,8 @@ function init_close_panel() { } function init_global_view() { - $("#stream .box-category a").click(function () { + // TODO: should be based on generic classes. + $(".box a").click(function () { var link = $(this).attr("href"); load_panel(link); -- cgit v1.2.3 From 8769931a68d0dddb134674c86a43dec75b39bf83 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 23 Oct 2014 09:32:02 +0200 Subject: Rename aside_flux in aside_feed. --- app/layout/aside_feed.phtml | 95 ++++++++++++++++++++++++++++++++++++++++ app/layout/aside_flux.phtml | 95 ---------------------------------------- app/layout/nav_menu.phtml | 2 +- app/views/index/normal.phtml | 2 +- p/scripts/main.js | 26 +++++------ p/themes/Origine/origine.css | 8 ++-- p/themes/base-theme/base.css | 8 ++-- p/themes/base-theme/template.css | 22 +++++----- 8 files changed, 129 insertions(+), 129 deletions(-) create mode 100644 app/layout/aside_feed.phtml delete mode 100644 app/layout/aside_flux.phtml (limited to 'p/scripts') diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml new file mode 100644 index 000000000..66b7b51af --- /dev/null +++ b/app/layout/aside_feed.phtml @@ -0,0 +1,95 @@ +hide_read_feeds && + FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) && + !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) { + $class = ' state_unread'; + } +?> + +
    + + + +
    + + +
    + + + + + + +
      +
    • +
      + +
      +
    • + +
    • +
      + +
      +
    • + + categories as $cat) { + $feeds = $cat->feeds(); + if (!empty($feeds)) { + $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); + $c_show = $c_active && (!FreshRSS_Context::$conf->display_categories || + FreshRSS_Context::$current_get['feed']); + ?> +
    • + + + +
    • + +
    +
    + + diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml deleted file mode 100644 index 30f362348..000000000 --- a/app/layout/aside_flux.phtml +++ /dev/null @@ -1,95 +0,0 @@ -hide_read_feeds && - FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) && - !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) { - $class = ' state_unread'; - } -?> - -
    - - - -
    - - -
    - - - - - - -
      -
    • -
      - -
      -
    • - -
    • -
      - -
      -
    • - - categories as $cat) { - $feeds = $cat->feeds(); - if (!empty($feeds)) { - $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); - $c_show = $c_active && (!FreshRSS_Context::$conf->display_categories || - FreshRSS_Context::$current_get['feed']); - ?> -
    • - - - -
    • - -
    -
    - - diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 2c9f8724d..6f555c3d0 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -2,7 +2,7 @@