From 8c83dfb4ff60fba3a94d2a6789904ad0839ecf17 Mon Sep 17 00:00:00 2001 From: Jonathan Treffler Date: Fri, 7 Aug 2020 11:06:13 +0200 Subject: renamed js into js old Signed-off-by: Jonathan Treffler --- js-old/.jshintignore | 2 + js-old/.jshintrc | 53 + js-old/README.md | 29 + js-old/admin/Admin.js | 104 ++ js-old/app/App.js | 18 + js-old/app/Config.js | 221 ++++ js-old/app/Run.js | 133 +++ js-old/controller/AppController.js | 22 + js-old/controller/ContentController.js | 219 ++++ js-old/controller/ExploreController.js | 57 + js-old/controller/NavigationController.js | 409 +++++++ js-old/controller/SettingsController.js | 86 ++ js-old/directive/AppNavigationEntryUtils.js | 37 + js-old/directive/NewsAddFeed.js | 32 + js-old/directive/NewsArticleActions.js | 28 + js-old/directive/NewsAutoFocus.js | 24 + js-old/directive/NewsBindUnsafeHtml.js | 18 + js-old/directive/NewsDraggable.js | 30 + js-old/directive/NewsDroppable.js | 34 + js-old/directive/NewsFinishedTransition.js | 20 + js-old/directive/NewsFocus.js | 22 + js-old/directive/NewsInstantNotification.js | 26 + js-old/directive/NewsOnActive.js | 23 + js-old/directive/NewsPlayOne.js | 30 + js-old/directive/NewsReadFile.js | 30 + js-old/directive/NewsRefreshMasonry.js | 29 + js-old/directive/NewsScroll.js | 111 ++ js-old/directive/NewsSearch.js | 48 + js-old/directive/NewsStickyMenu.js | 27 + js-old/directive/NewsStopPropagation.js | 20 + js-old/directive/NewsTimeout.js | 45 + js-old/directive/NewsTitleUnreadCount.js | 35 + js-old/directive/NewsToggleShow.js | 24 + js-old/directive/NewsTriggerClick.js | 19 + js-old/filter/TrustUrl.js | 16 + js-old/filter/UnreadCountFormatter.js | 19 + js-old/gui/ExternSubscription.js | 83 ++ js-old/gui/Fixes.js | 25 + js-old/gui/KeyboardShortcuts.js | 444 ++++++++ js-old/karma.conf.js | 81 ++ js-old/plugin/ArticleActionPlugin.js | 18 + js-old/protractor.conf.js | 46 + js-old/service/FeedResource.js | 347 ++++++ js-old/service/FolderResource.js | 123 +++ js-old/service/ItemResource.js | 223 ++++ js-old/service/Loading.js | 27 + js-old/service/OPMLImporter.js | 111 ++ js-old/service/OPMLParser.js | 90 ++ js-old/service/Publisher.js | 44 + js-old/service/Resource.js | 90 ++ js-old/service/SettingsResource.js | 85 ++ js-old/tests/e2e/main.js | 34 + js-old/tests/static/owncloud.org.rss | 639 +++++++++++ js-old/tests/unit/controller/AppControllerSpec.js | 56 + .../tests/unit/controller/ContentControllerSpec.js | 618 +++++++++++ .../tests/unit/controller/ExploreControllerSpec.js | 72 ++ .../unit/controller/NavigationControllerSpec.js | 1141 ++++++++++++++++++++ .../unit/controller/SettingsControllerSpec.js | 169 +++ .../tests/unit/filter/UnreadCountFormatterSpec.js | 27 + js-old/tests/unit/service/FeedResourceSpec.js | 338 ++++++ js-old/tests/unit/service/FolderResourceSpec.js | 148 +++ js-old/tests/unit/service/ItemResourceSpec.js | 387 +++++++ js-old/tests/unit/service/LoadingSpec.js | 26 + js-old/tests/unit/service/OPMLImporterSpec.js | 31 + js-old/tests/unit/service/OPMLParserSpec.js | 87 ++ js-old/tests/unit/service/PublisherSpec.js | 54 + js-old/tests/unit/service/ResourceSpec.js | 140 +++ js-old/tests/unit/service/SettingsResourceSpec.js | 101 ++ js-old/tests/unit/stubs/App.js | 10 + js-old/tests/unit/stubs/OC.js | 16 + js/.jshintignore | 2 - js/.jshintrc | 53 - js/README.md | 29 - js/admin/Admin.js | 104 -- js/app/App.js | 18 - js/app/Config.js | 221 ---- js/app/Run.js | 133 --- js/controller/AppController.js | 22 - js/controller/ContentController.js | 219 ---- js/controller/ExploreController.js | 57 - js/controller/NavigationController.js | 409 ------- js/controller/SettingsController.js | 86 -- js/directive/AppNavigationEntryUtils.js | 37 - js/directive/NewsAddFeed.js | 32 - js/directive/NewsArticleActions.js | 28 - js/directive/NewsAutoFocus.js | 24 - js/directive/NewsBindUnsafeHtml.js | 18 - js/directive/NewsDraggable.js | 30 - js/directive/NewsDroppable.js | 34 - js/directive/NewsFinishedTransition.js | 20 - js/directive/NewsFocus.js | 22 - js/directive/NewsInstantNotification.js | 26 - js/directive/NewsOnActive.js | 23 - js/directive/NewsPlayOne.js | 30 - js/directive/NewsReadFile.js | 30 - js/directive/NewsRefreshMasonry.js | 29 - js/directive/NewsScroll.js | 111 -- js/directive/NewsSearch.js | 48 - js/directive/NewsStickyMenu.js | 27 - js/directive/NewsStopPropagation.js | 20 - js/directive/NewsTimeout.js | 45 - js/directive/NewsTitleUnreadCount.js | 35 - js/directive/NewsToggleShow.js | 24 - js/directive/NewsTriggerClick.js | 19 - js/filter/TrustUrl.js | 16 - js/filter/UnreadCountFormatter.js | 19 - js/gui/ExternSubscription.js | 83 -- js/gui/Fixes.js | 25 - js/gui/KeyboardShortcuts.js | 444 -------- js/karma.conf.js | 81 -- js/plugin/ArticleActionPlugin.js | 18 - js/protractor.conf.js | 46 - js/service/FeedResource.js | 347 ------ js/service/FolderResource.js | 123 --- js/service/ItemResource.js | 223 ---- js/service/Loading.js | 27 - js/service/OPMLImporter.js | 111 -- js/service/OPMLParser.js | 90 -- js/service/Publisher.js | 44 - js/service/Resource.js | 90 -- js/service/SettingsResource.js | 85 -- js/tests/e2e/main.js | 34 - js/tests/static/owncloud.org.rss | 639 ----------- js/tests/unit/controller/AppControllerSpec.js | 56 - js/tests/unit/controller/ContentControllerSpec.js | 618 ----------- js/tests/unit/controller/ExploreControllerSpec.js | 72 -- .../unit/controller/NavigationControllerSpec.js | 1141 -------------------- js/tests/unit/controller/SettingsControllerSpec.js | 169 --- js/tests/unit/filter/UnreadCountFormatterSpec.js | 27 - js/tests/unit/service/FeedResourceSpec.js | 338 ------ js/tests/unit/service/FolderResourceSpec.js | 148 --- js/tests/unit/service/ItemResourceSpec.js | 387 ------- js/tests/unit/service/LoadingSpec.js | 26 - js/tests/unit/service/OPMLImporterSpec.js | 31 - js/tests/unit/service/OPMLParserSpec.js | 87 -- js/tests/unit/service/PublisherSpec.js | 54 - js/tests/unit/service/ResourceSpec.js | 140 --- js/tests/unit/service/SettingsResourceSpec.js | 101 -- js/tests/unit/stubs/App.js | 10 - js/tests/unit/stubs/OC.js | 16 - 140 files changed, 8031 insertions(+), 8031 deletions(-) create mode 100644 js-old/.jshintignore create mode 100644 js-old/.jshintrc create mode 100644 js-old/README.md create mode 100644 js-old/admin/Admin.js create mode 100644 js-old/app/App.js create mode 100644 js-old/app/Config.js create mode 100644 js-old/app/Run.js create mode 100644 js-old/controller/AppController.js create mode 100644 js-old/controller/ContentController.js create mode 100644 js-old/controller/ExploreController.js create mode 100644 js-old/controller/NavigationController.js create mode 100644 js-old/controller/SettingsController.js create mode 100644 js-old/directive/AppNavigationEntryUtils.js create mode 100644 js-old/directive/NewsAddFeed.js create mode 100644 js-old/directive/NewsArticleActions.js create mode 100644 js-old/directive/NewsAutoFocus.js create mode 100644 js-old/directive/NewsBindUnsafeHtml.js create mode 100644 js-old/directive/NewsDraggable.js create mode 100644 js-old/directive/NewsDroppable.js create mode 100644 js-old/directive/NewsFinishedTransition.js create mode 100644 js-old/directive/NewsFocus.js create mode 100644 js-old/directive/NewsInstantNotification.js create mode 100644 js-old/directive/NewsOnActive.js create mode 100644 js-old/directive/NewsPlayOne.js create mode 100644 js-old/directive/NewsReadFile.js create mode 100644 js-old/directive/NewsRefreshMasonry.js create mode 100644 js-old/directive/NewsScroll.js create mode 100644 js-old/directive/NewsSearch.js create mode 100644 js-old/directive/NewsStickyMenu.js create mode 100644 js-old/directive/NewsStopPropagation.js create mode 100644 js-old/directive/NewsTimeout.js create mode 100644 js-old/directive/NewsTitleUnreadCount.js create mode 100644 js-old/directive/NewsToggleShow.js create mode 100644 js-old/directive/NewsTriggerClick.js create mode 100644 js-old/filter/TrustUrl.js create mode 100644 js-old/filter/UnreadCountFormatter.js create mode 100644 js-old/gui/ExternSubscription.js create mode 100644 js-old/gui/Fixes.js create mode 100644 js-old/gui/KeyboardShortcuts.js create mode 100644 js-old/karma.conf.js create mode 100644 js-old/plugin/ArticleActionPlugin.js create mode 100644 js-old/protractor.conf.js create mode 100644 js-old/service/FeedResource.js create mode 100644 js-old/service/FolderResource.js create mode 100644 js-old/service/ItemResource.js create mode 100644 js-old/service/Loading.js create mode 100644 js-old/service/OPMLImporter.js create mode 100644 js-old/service/OPMLParser.js create mode 100644 js-old/service/Publisher.js create mode 100644 js-old/service/Resource.js create mode 100644 js-old/service/SettingsResource.js create mode 100644 js-old/tests/e2e/main.js create mode 100644 js-old/tests/static/owncloud.org.rss create mode 100644 js-old/tests/unit/controller/AppControllerSpec.js create mode 100644 js-old/tests/unit/controller/ContentControllerSpec.js create mode 100644 js-old/tests/unit/controller/ExploreControllerSpec.js create mode 100644 js-old/tests/unit/controller/NavigationControllerSpec.js create mode 100644 js-old/tests/unit/controller/SettingsControllerSpec.js create mode 100644 js-old/tests/unit/filter/UnreadCountFormatterSpec.js create mode 100644 js-old/tests/unit/service/FeedResourceSpec.js create mode 100644 js-old/tests/unit/service/FolderResourceSpec.js create mode 100644 js-old/tests/unit/service/ItemResourceSpec.js create mode 100644 js-old/tests/unit/service/LoadingSpec.js create mode 100644 js-old/tests/unit/service/OPMLImporterSpec.js create mode 100644 js-old/tests/unit/service/OPMLParserSpec.js create mode 100644 js-old/tests/unit/service/PublisherSpec.js create mode 100644 js-old/tests/unit/service/ResourceSpec.js create mode 100644 js-old/tests/unit/service/SettingsResourceSpec.js create mode 100644 js-old/tests/unit/stubs/App.js create mode 100644 js-old/tests/unit/stubs/OC.js delete mode 100644 js/.jshintignore delete mode 100644 js/.jshintrc delete mode 100644 js/README.md delete mode 100644 js/admin/Admin.js delete mode 100644 js/app/App.js delete mode 100644 js/app/Config.js delete mode 100644 js/app/Run.js delete mode 100644 js/controller/AppController.js delete mode 100644 js/controller/ContentController.js delete mode 100644 js/controller/ExploreController.js delete mode 100644 js/controller/NavigationController.js delete mode 100644 js/controller/SettingsController.js delete mode 100644 js/directive/AppNavigationEntryUtils.js delete mode 100644 js/directive/NewsAddFeed.js delete mode 100644 js/directive/NewsArticleActions.js delete mode 100644 js/directive/NewsAutoFocus.js delete mode 100644 js/directive/NewsBindUnsafeHtml.js delete mode 100644 js/directive/NewsDraggable.js delete mode 100644 js/directive/NewsDroppable.js delete mode 100644 js/directive/NewsFinishedTransition.js delete mode 100644 js/directive/NewsFocus.js delete mode 100644 js/directive/NewsInstantNotification.js delete mode 100644 js/directive/NewsOnActive.js delete mode 100644 js/directive/NewsPlayOne.js delete mode 100644 js/directive/NewsReadFile.js delete mode 100644 js/directive/NewsRefreshMasonry.js delete mode 100644 js/directive/NewsScroll.js delete mode 100644 js/directive/NewsSearch.js delete mode 100644 js/directive/NewsStickyMenu.js delete mode 100644 js/directive/NewsStopPropagation.js delete mode 100644 js/directive/NewsTimeout.js delete mode 100644 js/directive/NewsTitleUnreadCount.js delete mode 100644 js/directive/NewsToggleShow.js delete mode 100644 js/directive/NewsTriggerClick.js delete mode 100644 js/filter/TrustUrl.js delete mode 100644 js/filter/UnreadCountFormatter.js delete mode 100644 js/gui/ExternSubscription.js delete mode 100644 js/gui/Fixes.js delete mode 100644 js/gui/KeyboardShortcuts.js delete mode 100644 js/karma.conf.js delete mode 100644 js/plugin/ArticleActionPlugin.js delete mode 100644 js/protractor.conf.js delete mode 100644 js/service/FeedResource.js delete mode 100644 js/service/FolderResource.js delete mode 100644 js/service/ItemResource.js delete mode 100644 js/service/Loading.js delete mode 100644 js/service/OPMLImporter.js delete mode 100644 js/service/OPMLParser.js delete mode 100644 js/service/Publisher.js delete mode 100644 js/service/Resource.js delete mode 100644 js/service/SettingsResource.js delete mode 100644 js/tests/e2e/main.js delete mode 100644 js/tests/static/owncloud.org.rss delete mode 100644 js/tests/unit/controller/AppControllerSpec.js delete mode 100644 js/tests/unit/controller/ContentControllerSpec.js delete mode 100644 js/tests/unit/controller/ExploreControllerSpec.js delete mode 100644 js/tests/unit/controller/NavigationControllerSpec.js delete mode 100644 js/tests/unit/controller/SettingsControllerSpec.js delete mode 100644 js/tests/unit/filter/UnreadCountFormatterSpec.js delete mode 100644 js/tests/unit/service/FeedResourceSpec.js delete mode 100644 js/tests/unit/service/FolderResourceSpec.js delete mode 100644 js/tests/unit/service/ItemResourceSpec.js delete mode 100644 js/tests/unit/service/LoadingSpec.js delete mode 100644 js/tests/unit/service/OPMLImporterSpec.js delete mode 100644 js/tests/unit/service/OPMLParserSpec.js delete mode 100644 js/tests/unit/service/PublisherSpec.js delete mode 100644 js/tests/unit/service/ResourceSpec.js delete mode 100644 js/tests/unit/service/SettingsResourceSpec.js delete mode 100644 js/tests/unit/stubs/App.js delete mode 100644 js/tests/unit/stubs/OC.js diff --git a/js-old/.jshintignore b/js-old/.jshintignore new file mode 100644 index 000000000..3e2e84b08 --- /dev/null +++ b/js-old/.jshintignore @@ -0,0 +1,2 @@ +build/ +node_modules/ diff --git a/js-old/.jshintrc b/js-old/.jshintrc new file mode 100644 index 000000000..92f22ce7c --- /dev/null +++ b/js-old/.jshintrc @@ -0,0 +1,53 @@ +{ + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "forin": false, + "immed": true, + "indent": 4, + "latedef": true, + "newcap": true, + "noarg": true, + "noempty": true, + "nonew": true, + "plusplus": true, + "quotmark": "single", + "undef": true, + "unused": true, + "strict": true, + "maxparams": false, + "maxdepth": 3, + "maxlen": 120, + "browser": true, + "devel": true, + "jquery": true, + "globals": { + "angular": true, + "moment": true, + "app": true, + "OC": true, + "csrfToken": true, + "inject": true, + "module": true, + "protractor": true, + "browser": true, + "By": true, + "it": true, + "afterEach": true, + "jasmine": true, + "describe": true, + "beforeEach": true, + "expect": true, + "exports": true, + "reverse": true, + "items": true, + "enumerate": true, + "News": true, + "t": true, + "navigator": true, + "oc_requesttoken": true, + "_": true + } +} diff --git a/js-old/README.md b/js-old/README.md new file mode 100644 index 000000000..aa72e4977 --- /dev/null +++ b/js-old/README.md @@ -0,0 +1,29 @@ +# JavaScript Development +JavaScript is built and minified using gulp. + +Therefore you need to install **Node.js 6+ and npm**. Then use npm to install **gulp-cli**: + + sudo npm -g install gulp-cli + +Then install the local dependencies by running: + + npm install + +## Tasks +The following tasks are available: + +* **Build the JavaScript**: + + gulp + +* **Watch for changes and build JavaScript**: + + gulp watch + +* **Run JavaScript unit tests**: + + gulp karma + +* **Watch for changes and run JavaScript unit tests**: + + gulp watch-karma diff --git a/js-old/admin/Admin.js b/js-old/admin/Admin.js new file mode 100644 index 000000000..d60dd483f --- /dev/null +++ b/js-old/admin/Admin.js @@ -0,0 +1,104 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ + +/** + * Used to update the admin settings + */ +(function (window, document, $) { + 'use strict'; + + $(document).ready(function () { + var useCronUpdatesInput = + $('#news input[name="news-use-cron-updates"]'); + var autoPurgeMinimumIntervalInput = + $('#news input[name="news-auto-purge-minimum-interval"]'); + var autoPurgeCountInput = + $('#news input[name="news-auto-purge-count"]'); + var maxRedirectsInput = + $('#news input[name="news-max-redirects"]'); + var feedFetcherTimeoutInput = + $('#news input[name="news-feed-fetcher-timeout"]'); + var maxSizeInput = + $('#news input[name="news-max-size"]'); + var exploreUrlInput = + $('#news input[name="news-explore-url"]'); + var savedMessage = $('#news-saved-message'); + + var saved = function () { + if (savedMessage.is(':visible')) { + savedMessage.hide(); + } + + savedMessage.fadeIn(function () { + setTimeout(function () { + savedMessage.fadeOut(); + }, 5000); + }); + }; + + var submit = function () { + var autoPurgeMinimumInterval = autoPurgeMinimumIntervalInput.val(); + var autoPurgeCount = autoPurgeCountInput.val(); + var maxRedirects = maxRedirectsInput.val(); + var feedFetcherTimeout = feedFetcherTimeoutInput.val(); + var maxSize = maxSizeInput.val(); + var exploreUrl = exploreUrlInput.val(); + var useCronUpdates = useCronUpdatesInput.is(':checked'); + + var data = { + autoPurgeMinimumInterval: + parseInt(autoPurgeMinimumInterval, 10), + autoPurgeCount: parseInt(autoPurgeCount, 10), + maxRedirects: parseInt(maxRedirects, 10), + feedFetcherTimeout: parseInt(feedFetcherTimeout, 10), + maxSize: parseInt(maxSize, 10), + useCronUpdates: useCronUpdates, + exploreUrl: exploreUrl + }; + + var url = OC.generateUrl('/apps/news/admin'); + + $.ajax({ + type: 'PUT', + contentType: 'application/json; charset=utf-8', + url: url, + data: JSON.stringify(data), + dataType: 'json' + }).then(function (data) { + saved(); + autoPurgeMinimumIntervalInput + .val(data.autoPurgeMinimumInterval); + autoPurgeCountInput.val(data.autoPurgeCount); + maxRedirectsInput.val(data.maxRedirects); + maxSizeInput.val(data.maxSize); + feedFetcherTimeoutInput.val(data.feedFetcherTimeout); + useCronUpdatesInput.prop('checked', data.useCronUpdates); + exploreUrlInput.val(data.exploreUrl); + }); + + }; + + $('#news input[type="text"]').blur(submit); + $('#news input[type="checkbox"]').change(submit); + $('#news-migrate').click(function () { + var button = $(this); + button.addClass('loading'); + + $.post(OC.generateUrl('/apps/news/admin/migrate')) + .always(function () { + button.removeClass('loading'); + }); + + return false; + }); + }); + + +}(window, document, jQuery)); diff --git a/js-old/app/App.js b/js-old/app/App.js new file mode 100644 index 000000000..9e4ee5621 --- /dev/null +++ b/js-old/app/App.js @@ -0,0 +1,18 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ + +$('#content.app-news') + .attr('ng-app', 'News') + .attr('ng-cloak', '') + .attr('ng-strict-di', '') + .attr('ng-controller', 'AppController as App'); + +/* jshint unused: false */ +var app = angular.module('News', ['ngRoute', 'ngSanitize', 'ngAnimate']); diff --git a/js-old/app/Config.js b/js-old/app/Config.js new file mode 100644 index 000000000..f7c62e7ae --- /dev/null +++ b/js-old/app/Config.js @@ -0,0 +1,221 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.config(function ($routeProvider, $provide, $httpProvider, $locationProvider) { + 'use strict'; + + var feedType = { + FEED: 0, + FOLDER: 1, + STARRED: 2, + SUBSCRIPTIONS: 3, + SHARED: 4, + EXPLORE: 5, + UNREAD: 6 + }; + + // default hashPrefix changed in angular 1.6 to '!' + // change back to empty string to keep links working + $locationProvider.hashPrefix(''); + + // constants + $provide.constant('REFRESH_RATE', 60); // seconds + $provide.constant('ITEM_BATCH_SIZE', 40); // how many items should be + // fetched initially + $provide.constant('ITEM_AUTO_PAGE_SIZE', 20); + $provide.constant('BASE_URL', OC.generateUrl('/apps/news')); + $provide.constant('FEED_TYPE', feedType); + $provide.constant('MARK_READ_TIMEOUT', 0.5); + $provide.constant('SCROLL_TIMEOUT', 0.1); + + // make sure that the CSRF header is only sent to the Nextcloud domain + $provide.factory('CSRFInterceptor', function ($q, BASE_URL, $window) { + return { + request: function (config) { + const token = $window.document.getElementsByTagName('head')[0] + .getAttribute('data-requesttoken'); + const domain = + $window.location.href.split($window.location.pathname)[0]; + if (config.url.indexOf(BASE_URL) === 0 || + config.url.indexOf(domain) === 0) { + /*jshint camelcase: false */ + config.headers.requesttoken = token; + } + + return config || $q.when(config); + } + }; + }); + var errorMessages = { + 0: t('news', 'Request failed, network connection unavailable!'), + 401: t('news', 'Request unauthorized. Are you logged in?'), + 403: t('news', 'Request forbidden. Are you an admin?'), + 412: t('news', 'Token expired or app not enabled! Reload the page!'), + 500: t('news', 'Internal server error! Please check your ' + + 'data/nextcloud.log file for additional ' + + 'information!'), + 503: t('news', 'Request failed, Nextcloud is in currently ' + + 'in maintenance mode!') + }; + $provide.factory('ConnectionErrorInterceptor', function ($q, $timeout) { + var timer; + return { + responseError: function (response) { + // status 0 is a network error + function sendNotification() { + OC.Notification.showHtml(errorMessages[response.status]); + timer = $timeout(function () { + OC.Notification.hide(); + }, 5000); + } + if (response.status in errorMessages) { + if (timer) { + timer.then(function (){ + sendNotification(); + }); + } else { + sendNotification(); + } + } + return $q.reject(response); + } + }; + }); + $httpProvider.interceptors.push('CSRFInterceptor'); + $httpProvider.interceptors.push('ConnectionErrorInterceptor'); + + // routing + var getItemResolve = function (type) { + return { + // request to items also returns feeds + data: /* @ngInject */ function ( + $http, $route, $q, $location, BASE_URL, ITEM_BATCH_SIZE, FEED_TYPE, + SettingsResource, FeedResource) { + + var showAll = SettingsResource.get('showAll'); + var oldestFirst = SettingsResource.get('oldestFirst'); + var search = $location.search().search || ''; + + // if those two values are null it means we did not receive + // the settings request from the server so dont query the server + if (showAll === null || oldestFirst === null) { + return {}; + } else { + var parameters = { + type: type, + limit: ITEM_BATCH_SIZE, + showAll: showAll, + oldestFirst: oldestFirst, + search: search + }; + + if ($route.current !== undefined && + $route.current.params !== undefined && + $route.current.params.id !== undefined) { + parameters.id = $route.current.params.id; + } + + // check if a custom ordering is set + if (type === FEED_TYPE.FEED) { + var feed = FeedResource.getById(parameters.id); + + // on intial load, the feed ordering is undefined + if (feed === undefined || feed.ordering === 2) { + parameters.oldestFirst = false; + } else if (feed.ordering === 1) { + parameters.oldestFirst = true; + } + } + + return $http({ + url: BASE_URL + '/items', + method: 'GET', + params: parameters + }).then(function (response) { + return response.data; + }); + } + } + }; + }; + + var getExploreResolve = function () { + return { + sites: /* @ngInject */ function ( + $http, $q, BASE_URL, $location, Publisher, SettingsResource) { + // always use the code from the url + var language = $location.search().lang; + if (!language) { + language = SettingsResource.get('language'); + } + + return $http.get( + BASE_URL + '/settings').then(function (response) { + Publisher.publishAll(response.data); + + // get url and strip trailing slashes + var url = SettingsResource.get('exploreUrl') + .replace(/\/+$/, ''); + + var exploreUrl = url + '/feeds.' + language + '.json'; + var defaultExploreUrl = url + '/feeds.en.json'; + return $http + .get(exploreUrl) + .catch(function () { + return $http.get(defaultExploreUrl); + }); + + }).then(function (response) { + return response.data; + }); + } + }; + }; + + $routeProvider + .when('/items', { + controller: 'ContentController as Content', + templateUrl: 'content.html', + resolve: getItemResolve(feedType.SUBSCRIPTIONS), + type: feedType.SUBSCRIPTIONS + }) + .when('/items/starred', { + controller: 'ContentController as Content', + templateUrl: 'content.html', + resolve: getItemResolve(feedType.STARRED), + type: feedType.STARRED + }) + .when('/items/unread', { + controller: 'ContentController as Content', + templateUrl: 'content.html', + resolve: getItemResolve(feedType.UNREAD), + type: feedType.UNREAD + }) + .when('/items/feeds/:id', { + controller: 'ContentController as Content', + templateUrl: 'content.html', + resolve: getItemResolve(feedType.FEED), + type: feedType.FEED + }) + .when('/items/folders/:id', { + controller: 'ContentController as Content', + templateUrl: 'content.html', + resolve: getItemResolve(feedType.FOLDER), + type: feedType.FOLDER + }).when('/explore', { + controller: 'ExploreController as Explore', + templateUrl: 'explore.html', + resolve: getExploreResolve(), + type: feedType.EXPLORE + }).when('/shortcuts', { + templateUrl: 'shortcuts.html', + type: -1 + }); + +}); diff --git a/js-old/app/Run.js b/js-old/app/Run.js new file mode 100644 index 000000000..1a1572864 --- /dev/null +++ b/js-old/app/Run.js @@ -0,0 +1,133 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.run(function ($rootScope, $location, $http, $q, $interval, $route, Loading, ItemResource, FeedResource, + FolderResource, SettingsResource, Publisher, BASE_URL, FEED_TYPE, REFRESH_RATE) { + 'use strict'; + + // show Loading screen + Loading.setLoading('global', true); + + // listen to keys in returned queries to automatically distribute the + // incoming values to models + Publisher.subscribe(ItemResource).toChannels(['items', 'newestItemId', + 'starred', 'unread']); + Publisher.subscribe(FolderResource).toChannels(['folders']); + Publisher.subscribe(FeedResource).toChannels(['feeds']); + Publisher.subscribe(SettingsResource).toChannels(['settings']); + + // load feeds, settings and last read feed + var settingsPromise = $http.get(BASE_URL + '/settings').then(function (response) { + Publisher.publishAll(response.data); + return response.data; + }); + + var path = $location.path(); + var activeFeedPromise = $http.get(BASE_URL + '/feeds/active') + .then(function (response) { + var url; + switch (response.data.activeFeed.type) { + case FEED_TYPE.FEED: + url = '/items/feeds/' + response.data.activeFeed.id; + break; + + case FEED_TYPE.FOLDER: + url = '/items/folders/' + response.data.activeFeed.id; + break; + + case FEED_TYPE.STARRED: + url = '/items/starred'; + break; + + case FEED_TYPE.EXPLORE: + url = '/explore'; + break; + + case FEED_TYPE.UNREAD: + url = '/items/unread'; + break; + + default: + url = '/items'; + } + + // only redirect if url is empty or faulty + if (!/^\/items(\/(starred|unread|explore|feeds\/\d+|folders\/\d+))?\/?$/ + .test(path)) { + $location.path(url); + } + + return response.data; + }); + + var feeds; + var feedPromise = $http.get(BASE_URL + '/feeds').then(function (response) { + feeds = response.data; + return feeds; + }); + + var folders; + var folderPromise = $http.get(BASE_URL + '/folders') + .then(function (response) { + folders = response.data; + return folders; + }); + + $q.all([ + feedPromise, + folderPromise + ]).then(function () { + // first publish feeds to correctly update the folder resource unread + // cache + Publisher.publishAll(feeds); + Publisher.publishAll(folders); + if (feeds.feeds.length === 0 && folders.folders.length === 0) { + $location.path('/explore'); + } + }); + + // disable loading if all initial requests finished + $q.all( + [ + settingsPromise, + activeFeedPromise, + feedPromise, + folderPromise + ] + ) + .then(function () { + $route.reload(); + Loading.setLoading('global', false); + }); + + // refresh feeds and folders + $interval(function () { + $http.get(BASE_URL + '/feeds').then(function (response) { + Publisher.publishAll(response.data); + }); + $http.get(BASE_URL + '/folders').then(function (response) { + Publisher.publishAll(response.data); + }); + }, REFRESH_RATE * 1000); + + + $rootScope.$on('$routeChangeStart', function () { + Loading.setLoading('content', true); + }); + + $rootScope.$on('$routeChangeSuccess', function () { + Loading.setLoading('content', false); + }); + + // in case of wrong id etc show all items + $rootScope.$on('$routeChangeError', function () { + $location.path('/items'); + }); + +}); diff --git a/js-old/controller/AppController.js b/js-old/controller/AppController.js new file mode 100644 index 000000000..e962bd66a --- /dev/null +++ b/js-old/controller/AppController.js @@ -0,0 +1,22 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.controller('AppController', function (Loading, FeedResource, FolderResource) { + 'use strict'; + + this.loading = Loading; + + this.isFirstRun = function () { + return FeedResource.size() === 0 && FolderResource.size() === 0; + }; + + this.play = function (item) { + this.playingItem = item; + }; +}); diff --git a/js-old/controller/ContentController.js b/js-old/controller/ContentController.js new file mode 100644 index 000000000..74c475f4c --- /dev/null +++ b/js-old/controller/ContentController.js @@ -0,0 +1,219 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.controller('ContentController', function (Publisher, FeedResource, ItemResource, SettingsResource, data, $route, + $routeParams, $location, FEED_TYPE, ITEM_AUTO_PAGE_SIZE, Loading, + $filter) { + 'use strict'; + + var self = this; + ItemResource.clear(); + + // distribute data to models based on key + Publisher.publishAll(data); + + this.getFirstItem = function () { + var orderFilter = $filter('orderBy'); + var orderedItems = orderFilter(this.getItems(), this.orderBy()); + var firstItem = orderedItems[0]; + if (firstItem === undefined) { + return undefined; + } else { + return firstItem.id; + } + }; + + + this.isAutoPagingEnabled = true; + // the interface should show a hint if there are not enough items sent + // it's assumed that theres nothing to autpage + + this.isNothingMoreToAutoPage = ItemResource.size() < ITEM_AUTO_PAGE_SIZE; + + this.getItems = function () { + return ItemResource.getAll(); + }; + + this.isItemActive = function (id) { + return this.activeItem === id; + }; + + this.setItemActive = function (id) { + this.activeItem = id; + }; + + this.toggleStar = function (itemId) { + ItemResource.toggleStar(itemId); + }; + + this.toggleItem = function (item) { + // TODO: unittest + if (this.isCompactView()) { + item.show = !item.show; + } + }; + + this.isShowAll = function () { + return SettingsResource.get('showAll'); + }; + + this.markRead = function (itemId) { + var item = ItemResource.get(itemId); + + if (!item.keepUnread && item.unread === true) { + ItemResource.markItemRead(itemId); + FeedResource.markItemOfFeedRead(item.feedId); + } + }; + + this.getFeed = function (feedId) { + return FeedResource.getById(feedId); + }; + + this.toggleKeepUnread = function (itemId) { + var item = ItemResource.get(itemId); + if (!item.unread) { + FeedResource.markItemOfFeedUnread(item.feedId); + ItemResource.markItemRead(itemId, false); + } + + item.keepUnread = !item.keepUnread; + }; + + var getOrdering = function () { + var ordering = SettingsResource.get('oldestFirst'); + + if (self.isFeed()) { + var feed = FeedResource.getById($routeParams.id); + if (feed && feed.ordering === 1) { + ordering = true; + } else if (feed && feed.ordering === 2) { + ordering = false; + } + } + + return ordering; + }; + + this.orderBy = function () { + if (getOrdering()) { + return 'id'; + } else { + return '-id'; + } + }; + + this.isCompactView = function () { + return SettingsResource.get('compact'); + }; + + this.isCompactExpand = function () { + return SettingsResource.get('compactExpand'); + }; + + this.autoPagingEnabled = function () { + return this.isAutoPagingEnabled; + }; + + this.markReadEnabled = function () { + return !SettingsResource.get('preventReadOnScroll'); + }; + + this.scrollRead = function (itemIds) { + var ids = []; + var feedIds = []; + + itemIds.forEach(function (itemId) { + var item = ItemResource.get(itemId); + if (!item.keepUnread) { + ids.push(itemId); + feedIds.push(item.feedId); + } + }); + + if (ids.length > 0) { + FeedResource.markItemsOfFeedsRead(feedIds); + ItemResource.markItemsRead(ids); + } + }; + + this.isFeed = function () { + return $route.current.$$route.type === FEED_TYPE.FEED; + }; + + this.autoPage = function () { + if (this.isNothingMoreToAutoPage) { + return; + } + + // in case a subsequent autopage request comes in wait until + // the current one finished and execute a request immediately + // afterwards + if (!this.isAutoPagingEnabled) { + this.autoPageAgain = true; + return; + } + + this.isAutoPagingEnabled = false; + this.autoPageAgain = false; + + var type = $route.current.$$route.type; + var id = $routeParams.id; + var oldestFirst = getOrdering(); + var showAll = SettingsResource.get('showAll'); + var self = this; + var search = $location.search().search; + + Loading.setLoading('autopaging', true); + + ItemResource.autoPage(type, id, oldestFirst, showAll, search).then(function (response) { + Publisher.publishAll(response.data); + + if (response.data.items.length >= ITEM_AUTO_PAGE_SIZE) { + self.isAutoPagingEnabled = true; + } else { + self.isNothingMoreToAutoPage = true; + } + + if (self.isAutoPagingEnabled && self.autoPageAgain) { + self.autoPage(); + } + return response.data; + }, function () { + self.isAutoPagingEnabled = true; + }).finally(function () { + Loading.setLoading('autopaging', false); + }); + }; + + this.getRelativeDate = function (timestamp) { + if (timestamp !== undefined && timestamp !== '') { + var languageCode = SettingsResource.get('language'); + return moment.unix(timestamp).locale(languageCode).fromNow() + ''; + } else { + return ''; + } + }; + + this.refresh = function () { + $route.reload(); + }; + + this.getMediaType = function (type) { + if (type && type.indexOf('audio') === 0) { + return 'audio'; + } else if (type && type.indexOf('video') === 0) { + return 'video'; + } else { + return undefined; + } + }; + + this.activeItem = this.getFirstItem(); +}); \ No newline at end of file diff --git a/js-old/controller/ExploreController.js b/js-old/controller/ExploreController.js new file mode 100644 index 000000000..6d34efb40 --- /dev/null +++ b/js-old/controller/ExploreController.js @@ -0,0 +1,57 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.controller('ExploreController', function (sites, $rootScope, FeedResource, SettingsResource, $location) { + 'use strict'; + + this.sites = sites; + // join all sites + this.feeds = Object.keys(sites).map(function (key) { + return [key, sites[key]]; + }).reduce(function (xs, x) { + var category = x[0]; + var feedList = x[1]; + feedList.forEach(function (feed) { + feed.category = category; + }); + return xs.concat(feedList); + }, []); + + this.feedExists = function (location) { + return FeedResource.getByLocation(location) !== undefined; + }; + + this.subscribeTo = function (location) { + $rootScope.$broadcast('addFeed', location); + }; + + this.isCategoryShown = function (data) { + return data.filter(function (element) { + return FeedResource.getByLocation(element.feed) === undefined; + }).length > 0; + }; + + this.getSupportedLanguageCodes = function () { + return SettingsResource.getSupportedLanguageCodes(); + }; + + this.getCurrentLanguageCode = function () { + var language = $location.search().lang; + if (!language) { + language = SettingsResource.get('language'); + } + return language; + }; + + this.showLanguage = function (languageCode) { + $location.url('/explore/?lang=' + languageCode); + }; + + this.selectedLanguageCode = this.getCurrentLanguageCode(); +}); diff --git a/js-old/controller/NavigationController.js b/js-old/controller/NavigationController.js new file mode 100644 index 000000000..7467acffa --- /dev/null +++ b/js-old/controller/NavigationController.js @@ -0,0 +1,409 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.controller('NavigationController', function ($route, FEED_TYPE, FeedResource, FolderResource, ItemResource, + SettingsResource, Publisher, $rootScope, $location, $q) { + 'use strict'; + + this.feedError = ''; + this.showNewFolder = false; + this.renamingFolder = false; + this.addingFeed = false; + this.addingFolder = false; + this.folderError = ''; + this.renameError = ''; + this.feed = {}; + this.youtubeDetectorRegex = new RegExp(/youtube\.[a-z\.]{2,}\/(user|channel)\/(.*?)(\/|\?|$)/); + + var getRouteId = function () { + return parseInt($route.current.params.id, 10); + }; + + this.getLanguageCode = function () { + return SettingsResource.get('language'); + }; + + this.getFeeds = function () { + return FeedResource.getAll(); + }; + + this.getFolders = function () { + return FolderResource.getAll(); + }; + + this.markCurrentRead = function () { + var id = getRouteId(); + var type = $route.current.$$route.type; + + if(isNaN(id)) { + this.markRead(); + } else if(type === FEED_TYPE.FOLDER) { + this.markFolderRead(id); + } else if(type === FEED_TYPE.FEED) { + this.markFeedRead(id); + } + }; + + this.markFolderRead = function (folderId) { + FeedResource.markFolderRead(folderId); + + FeedResource.getByFolderId(folderId).forEach(function (feed) { + ItemResource.markFeedRead(feed.id); + }); + }; + + this.markFeedRead = function (feedId) { + ItemResource.markFeedRead(feedId); + FeedResource.markFeedRead(feedId); + }; + + this.markRead = function () { + ItemResource.markRead(); + FeedResource.markRead(); + }; + + this.isShowAll = function () { + return SettingsResource.get('showAll'); + }; + + this.getFeedsOfFolder = function (folderId) { + return FeedResource.getByFolderId(folderId); + }; + + this.getUnreadCount = function () { + return FeedResource.getUnreadCount(); + }; + + this.isUnread = function () { + return this.getUnreadCount() > 0; + }; + + this.getFeedUnreadCount = function (feedId) { + var feed = FeedResource.getById(feedId); + if (feed !== undefined) { + return feed.unreadCount; + } else { + return 0; + } + }; + + this.isFeedUnread = function (feedId) { + return this.getFeedUnreadCount(feedId) > 0; + }; + + this.getFolderUnreadCount = function (folderId) { + return FeedResource.getFolderUnreadCount(folderId); + }; + + this.isFolderUnread = function (folderId) { + return this.getFolderUnreadCount(folderId) > 0; + }; + + this.getStarredCount = function () { + return ItemResource.getStarredCount(); + }; + + this.isStarredUnread = function () { + return this.getStarredCount() > 0; + }; + + this.toggleFolder = function (folderName) { + FolderResource.toggleOpen(folderName); + }; + + this.hasFeeds = function (folderId) { + return FeedResource.getFolderUnreadCount(folderId) !== undefined; + }; + + this.subFeedActive = function (folderId) { + var type = $route.current.$$route.type; + + if (type === FEED_TYPE.FEED) { + var feed = FeedResource.getById(getRouteId()); + + if (feed !== undefined && feed.folderId === folderId) { + return true; + } + } + + return false; + }; + + this.isSubscriptionsActive = function () { + return $route.current && + $route.current.$$route.type === FEED_TYPE.SUBSCRIPTIONS; + }; + + this.isUnreadActive = function () { + return $route.current && + $route.current.$$route.type === FEED_TYPE.UNREAD; + }; + + this.isStarredActive = function () { + return $route.current && + $route.current.$$route.type === FEED_TYPE.STARRED; + }; + + this.isExploreActive = function () { + return $route.current && + $route.current.$$route.type === FEED_TYPE.EXPLORE; + }; + + this.isFolderActive = function (folderId) { + return $route.current && + $route.current.$$route.type === FEED_TYPE.FOLDER && + getRouteId() === folderId; + }; + + this.isFeedActive = function (feedId) { + return $route.current && + $route.current.$$route.type === FEED_TYPE.FEED && + getRouteId() === feedId; + }; + + this.folderNameExists = function (folderName) { + folderName = folderName || ''; + return FolderResource.get(folderName.trim()) !== undefined; + }; + + this.feedUrlExists = function (url) { + url = url || ''; + url = url.trim(); + return FeedResource.get(url) !== undefined || + FeedResource.get('http://' + url) !== undefined; + }; + + this.createFeed = function (feed) { + var self = this; + this.showNewFolder = false; + this.addingFeed = true; + + var newFolder = feed.newFolder; + var existingFolder = feed.existingFolder || {id: 0}; + + // we dont need to create a new folder + if (newFolder === undefined || newFolder === '') { + // this is set to display the feed in any folder, even if the folder + // is closed or has no unread articles + existingFolder.getsFeed = true; + + /** + * Transform youtube channel and user URL into their RSS feed + * (09/01/2020): Youtube feed url work as `https://www.youtube.com/feeds/videos.xml?user=` + */ + var regResult = this.youtubeDetectorRegex.exec(feed.url); + /** + * At this point: + * regResult[0] contain the match + * regResult[1] contain the type of youtube entity (channel or user) + * regResult[2] contain either the username or the channel id + */ + if (regResult && regResult[0] && regResult[1] && regResult[2]) { + feed.url = 'https://www.youtube.com/feeds/videos.xml?'; + feed.url += (regResult[1] === 'user') ? 'user=' : 'channel_id='; + feed.url += regResult[2]; + } + + FeedResource.create(feed.url, existingFolder.id, undefined, feed.user, feed.password).then(function (data) { + Publisher.publishAll(data); + + // set folder as default + $location.path('/items/feeds/' + data.feeds[0].id + '/'); + }).finally(function () { + existingFolder.getsFeed = undefined; + feed.url = ''; + feed.user = ''; + feed.password = ''; + self.addingFeed = false; + }); + + } else { + // create folder first and then the feed + FolderResource.create(newFolder).then(function (data) { + + Publisher.publishAll(data); + + // set the created folder on scope so its preselected for the + // next addition + feed.existingFolder = FolderResource.get(data.folders[0].name); + feed.newFolder = undefined; + self.createFeed(feed); + }); + } + + }; + + this.createFolder = function (folder) { + var self = this; + this.addingFolder = true; + FolderResource.create(folder.name).then(function (data) { + Publisher.publishAll(data); + }).finally(function () { + self.addingFolder = false; + folder.name = ''; + }); + }; + + this.moveFeed = function (feedId, folderId) { + var reload = false; + var feed = FeedResource.getById(feedId); + + if (feed.folderId === folderId) { + return; + } + + if (this.isFolderActive(feed.folderId) || + this.isFolderActive(folderId)) { + reload = true; + } + + FeedResource.move(feedId, folderId); + + if (reload) { + $route.reload(); + } + }; + + this.renameFeed = function (feed) { + FeedResource.patch(feed.id, {title: feed.title}); + feed.editing = false; + }; + + this.renameFolder = function (folder, name) { + folder.renameError = ''; + this.renamingFolder = true; + var self = this; + + if (folder.name === name) { + folder.renameError = ''; + folder.editing = false; + this.renamingFolder = false; + } else { + FolderResource.rename(folder.name, name).then(function () { + folder.renameError = ''; + folder.editing = false; + }, function (message) { + folder.renameError = message; + }).finally(function () { + self.renamingFolder = false; + }); + } + }; + + this.reversiblyDeleteFeed = function (feed) { + FeedResource.reversiblyDelete(feed.id).finally(function () { + $route.reload(); + }); + }; + + this.undoDeleteFeed = function (feed) { + FeedResource.undoDelete(feed.id).finally(function () { + $route.reload(); + }); + }; + + this.deleteFeed = function (feed) { + FeedResource.delete(feed.url); + }; + + + this.reversiblyDeleteFolder = function (folder) { + $q.all( + FeedResource.reversiblyDeleteFolder(folder.id), + FolderResource.reversiblyDelete(folder.name) + ).finally(function () { + $route.reload(); + }); + }; + + this.undoDeleteFolder = function (folder) { + $q.all( + FeedResource.undoDeleteFolder(folder.id), + FolderResource.undoDelete(folder.name) + ).finally(function () { + $route.reload(); + }); + }; + + this.deleteFolder = function (folder) { + FeedResource.deleteFolder(folder.id); + FolderResource.delete(folder.name); + }; + + this.setOrdering = function (feed, ordering) { + FeedResource.patch(feed.id, {ordering: ordering}); + $route.reload(); + }; + + this.togglePinned = function (feedId) { + var feed = FeedResource.getById(feedId); + if (feed) { + return FeedResource.patch(feedId, {pinned: !feed.pinned}); + } + }; + + this.setUpdateMode = function (feedId, updateMode) { + return FeedResource.patch(feedId, {updateMode: updateMode}); + }; + + this.toggleFullText = function (feed) { + $rootScope.$broadcast('$routeChangeStart'); + FeedResource.toggleFullText(feed.id).finally(function () { + $rootScope.$broadcast('$routeChangeSuccess'); + $route.reload(); + }); + }; + + this.search = function (value) { + if (value === '') { + $location.search('search', null); + } else { + $location.search('search', value); + } + }; + + var self = this; + + $rootScope.$on('moveFeedToFolder', function (scope, data) { + self.moveFeed(data.feedId, data.folderId); + }); + + // based on the route we want to preselect a folder in the add new feed + // drop down + var setSelectedFolderForRoute = function () { + var type; + if ($route.current) { + type = $route.current.$$route.type; + } + + var folderId = 0; + + if (type === FEED_TYPE.FOLDER) { + folderId = getRouteId(); + } else if (type === FEED_TYPE.FEED) { + var feed = FeedResource.getById(getRouteId()); + + if (feed) { + folderId = feed.folderId; + } + } + + var folder; + if (folderId !== 0) { + folder = FolderResource.getById(folderId); + } + + self.feed.existingFolder = folder; + }; + + $rootScope.$on('$routeChangeSuccess', function () { + setSelectedFolderForRoute(); + }); + +}); diff --git a/js-old/controller/SettingsController.js b/js-old/controller/SettingsController.js new file mode 100644 index 000000000..2f8a1107c --- /dev/null +++ b/js-old/controller/SettingsController.js @@ -0,0 +1,86 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.controller('SettingsController', function ($route, $q, SettingsResource, ItemResource, OPMLParser, OPMLImporter, + Publisher) { + 'use strict'; + this.isOPMLImporting = false; + this.isArticlesImporting = false; + this.opmlImportError = false; + this.articleImportError = false; + this.opmlImportEmptyError = false; + var self = this; + + var set = function (key, value) { + SettingsResource.set(key, value); + + if (['showAll', 'oldestFirst', 'compact'].indexOf(key) >= 0) { + $route.reload(); + } + }; + + this.toggleSetting = function (key) { + set(key, !this.getSetting(key)); + }; + + this.getSetting = function (key) { + return SettingsResource.get(key); + }; + + this.importOPML = function (fileContent) { + self.opmlImportError = false; + self.opmlImportEmptyError = false; + self.articleImportError = false; + + try { + this.isOPMLImporting = false; + var parsedContent = OPMLParser.parse(fileContent); + + var jobSize = 5; + + if (parsedContent.folders.length === 0 && + parsedContent.feeds.length === 0) { + self.opmlImportEmptyError = true; + } else { + OPMLImporter.importFolders(parsedContent).then(function (feedQueue) { + return OPMLImporter.importFeedQueue(feedQueue, jobSize); + }).finally(function () { + self.isOPMLImporting = false; + }); + } + + } catch (error) { + this.opmlImportError = true; + console.error(error); + this.isOPMLImporting = false; + } + }; + + this.importArticles = function (content) { + this.opmlImportError = false; + this.articleImportError = false; + + try { + this.isArticlesImporting = true; + var articles = JSON.parse(content); + + var self = this; + ItemResource.importArticles(articles).then(function (data) { + Publisher.publishAll(data); + }).finally(function () { + self.isArticlesImporting = false; + }); + + } catch (error) { + console.error(error); + this.articleImportError = true; + this.isArticlesImporting = false; + } + }; +}); diff --git a/js-old/directive/AppNavigationEntryUtils.js b/js-old/directive/AppNavigationEntryUtils.js new file mode 100644 index 000000000..cca7f310c --- /dev/null +++ b/js-old/directive/AppNavigationEntryUtils.js @@ -0,0 +1,37 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.run(function ($document, $rootScope) { + 'use strict'; + $document.click(function (event) { + $rootScope.$broadcast('documentClicked', event); + }); +}); + +app.directive('appNavigationEntryUtils', function () { + 'use strict'; + return { + restrict: 'C', + link: function (scope, elm) { + var menu = elm.siblings('.app-navigation-entry-menu'); + var button = $(elm) + .find('.app-navigation-entry-utils-menu-button button'); + + button.click(function () { + menu.toggleClass('open'); + }); + + scope.$on('documentClicked', function (scope, event) { + if (event.target !== button[0]) { + menu.removeClass('open'); + } + }); + } + }; +}); \ No newline at end of file diff --git a/js-old/directive/NewsAddFeed.js b/js-old/directive/NewsAddFeed.js new file mode 100644 index 000000000..c2d9e66a5 --- /dev/null +++ b/js-old/directive/NewsAddFeed.js @@ -0,0 +1,32 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.directive('newsAddFeed', function ($rootScope, $timeout) { + 'use strict'; + + return { + restrict: 'A', + link: function (scope, elem) { + $rootScope.$on('addFeed', function (_, url) { + + $timeout(function () { + if (elem.is(':animated')) { + elem.stop(true, true); + elem.show(); + } else if (!elem.is(':visible')) { + elem.slideDown(); + } + elem.find('[ng-model="Navigation.feed.url"]').focus(); + }); + + scope.Navigation.feed.url = url; + }); + } + }; +}); \ No newline at end of file diff --git a/js-old/directive/NewsArticleActions.js b/js-old/directive/NewsArticleActions.js new file mode 100644 index 000000000..31c418570 --- /dev/null +++ b/js-old/directive/NewsArticleActions.js @@ -0,0 +1,28 @@ +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ +app.directive('newsArticleActions', function () { + 'use strict'; + return { + restrict: 'A', + scope: { + newsArticleActions: '=', + noPlugins: '=' + }, + link: function (scope, elem) { + var plugins = News.getArticleActionPlugins(); + + for (var i=0; i