summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/appinfo/routes.php60
-rw-r--r--apps/files/js/app.js8
-rw-r--r--apps/files/js/navigation.js257
-rw-r--r--apps/files/js/tagsplugin.js134
-rw-r--r--apps/files/lib/AppInfo/Application.php4
-rw-r--r--apps/files/lib/Controller/ApiController.php175
-rw-r--r--apps/files/lib/Controller/ViewController.php83
-rw-r--r--apps/files/templates/appnavigation.php116
-rw-r--r--apps/files/tests/Controller/ViewControllerTest.php22
-rw-r--r--apps/files/tests/js/appSpec.js24
-rw-r--r--core/css/apps.scss17
11 files changed, 781 insertions, 119 deletions
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index 0d1449ff355..a9d8ba0a1b9 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -76,6 +76,66 @@ $application->registerRoutes(
'url' => '/ajax/getstoragestats.php',
'verb' => 'GET',
],
+ [
+ 'name' => 'API#showQuickAccess',
+ 'url' => '/api/v1/quickaccess/set/showList',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getShowQuickAccess',
+ 'url' => '/api/v1/quickaccess/get/showList',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getShowQuickaccessSettings',
+ 'url' => '/api/v1/quickaccess/showsettings',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#setShowQuickaccessSettings',
+ 'url' => '/api/v1/quickaccess/set/showsettings',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#setSortingStrategy',
+ 'url' => '/api/v1/quickaccess/set/SortingStrategy',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#setReverseQuickaccess',
+ 'url' => '/api/v1/quickaccess/set/ReverseList',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getSortingStrategy',
+ 'url' => '/api/v1/quickaccess/get/SortingStrategy',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getReverseQuickaccess',
+ 'url' => '/api/v1/quickaccess/get/ReverseList',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getFavoritesFolder',
+ 'url' => '/api/v1/quickaccess/get/FavoriteFolders/',
+ 'verb' => 'GET'
+ ],
+ [
+ 'name' => 'API#setSortingOrder',
+ 'url' => '/api/v1/quickaccess/set/CustomSortingOrder',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getSortingOrder',
+ 'url' => '/api/v1/quickaccess/get/CustomSortingOrder',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'API#getNodeType',
+ 'url' => '/api/v1/quickaccess/get/NodeType',
+ 'verb' => 'GET',
+ ],
]
]
);
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index 6a21bce975b..52c92645b2d 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -53,6 +53,8 @@
this.$showHiddenFiles = $('input#showhiddenfilesToggle');
var showHidden = $('#showHiddenFiles').val() === "1";
this.$showHiddenFiles.prop('checked', showHidden);
+
+
if ($('#fileNotFound').val() === "1") {
OC.Notification.show(t('files', 'File could not be found'), {type: 'error'});
}
@@ -219,7 +221,7 @@
},
/**
- * Persist show hidden preference on ther server
+ * Persist show hidden preference on the server
*
* @returns {undefined}
*/
@@ -237,8 +239,8 @@
var params;
if (e && e.itemId) {
params = {
- view: e.itemId,
- dir: '/'
+ view: typeof e.view === 'string' && e.view !== '' ? e.view : e.itemId,
+ dir: e.dir ? e.dir : '/'
};
this._changeUrl(params.view, params.dir);
OC.Apps.hideAppSidebar($('.detailsView'));
diff --git a/apps/files/js/navigation.js b/apps/files/js/navigation.js
index d213d0467b6..d4fa06cb45e 100644
--- a/apps/files/js/navigation.js
+++ b/apps/files/js/navigation.js
@@ -1,8 +1,9 @@
/*
- * Copyright (c) 2014
+ * @Copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* @author Vincent Petry
- * @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+ * @author Felix Nüsse <felix.nuesse@t-online.de>
+ *
*
* This file is licensed under the Affero General Public License version 3
* or later.
@@ -11,7 +12,7 @@
*
*/
-(function() {
+(function () {
/**
* @class OCA.Files.Navigation
@@ -19,7 +20,7 @@
*
* @param $el element containing the navigation
*/
- var Navigation = function($el) {
+ var Navigation = function ($el) {
this.initialize($el);
};
@@ -39,23 +40,47 @@
$currentContent: null,
/**
+ * Strategy by which the quickaccesslist is sorted
+ *
+ * Possible Strategies:
+ * customorder
+ * datemodified
+ * date
+ * alphabet
+ *
+ */
+ $sortingStrategy: 'alphabet',
+
+ /**
+ * Key for the quick-acces-list
+ */
+ $quickAccessListKey: 'sublist-favorites',
+ /**
* Initializes the navigation from the given container
*
* @private
* @param $el element containing the navigation
*/
- initialize: function($el) {
+ initialize: function ($el) {
this.$el = $el;
this._activeItem = null;
this.$currentContent = null;
this._setupEvents();
+
+ var scope=this;
+ $.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/SortingStrategy"), function (data, status) {
+ scope.$sortingStrategy=data;
+ scope.setInitialQuickaccessSettings();
+ });
+
},
/**
* Setup UI events
*/
- _setupEvents: function() {
- this.$el.on('click', 'li a', _.bind(this._onClickItem, this));
+ _setupEvents: function () {
+ this.$el.on('click', 'li a', _.bind(this._onClickItem, this))
+ this.$el.on('click', 'li button', _.bind(this._onClickMenuButton, this));
},
/**
@@ -63,16 +88,16 @@
*
* @return app container
*/
- getActiveContainer: function() {
+ getActiveContainer: function () {
return this.$currentContent;
},
/**
* Returns the currently active item
- *
+ *
* @return item ID
*/
- getActiveItem: function() {
+ getActiveItem: function () {
return this._activeItem;
},
@@ -83,29 +108,42 @@
* @param string itemId id of the navigation item to select
* @param array options "silent" to not trigger event
*/
- setActiveItem: function(itemId, options) {
+ setActiveItem: function (itemId, options) {
+ var currentItem = this.$el.find('li[data-id=' + itemId + ']');
+ var itemDir = currentItem.data('dir');
+ var itemView = currentItem.data('view');
var oldItemId = this._activeItem;
if (itemId === this._activeItem) {
if (!options || !options.silent) {
this.$el.trigger(
- new $.Event('itemChanged', {itemId: itemId, previousItemId: oldItemId})
+ new $.Event('itemChanged', {
+ itemId: itemId,
+ previousItemId: oldItemId,
+ dir: itemDir,
+ view: itemView
+ })
);
}
return;
}
- this.$el.find('li').removeClass('active');
+ this.$el.find('li a').removeClass('active');
if (this.$currentContent) {
this.$currentContent.addClass('hidden');
this.$currentContent.trigger(jQuery.Event('hide'));
}
this._activeItem = itemId;
- this.$el.find('li[data-id=' + itemId + ']').addClass('active');
- this.$currentContent = $('#app-content-' + itemId);
+ currentItem.children('a').addClass('active');
+ this.$currentContent = $('#app-content-' + (typeof itemView === 'string' && itemView !== '' ? itemView : itemId));
this.$currentContent.removeClass('hidden');
if (!options || !options.silent) {
this.$currentContent.trigger(jQuery.Event('show'));
this.$el.trigger(
- new $.Event('itemChanged', {itemId: itemId, previousItemId: oldItemId})
+ new $.Event('itemChanged', {
+ itemId: itemId,
+ previousItemId: oldItemId,
+ dir: itemDir,
+ view: itemView
+ })
);
}
},
@@ -113,23 +151,206 @@
/**
* Returns whether a given item exists
*/
- itemExists: function(itemId) {
+ itemExists: function (itemId) {
return this.$el.find('li[data-id=' + itemId + ']').length;
},
/**
* Event handler for when clicking on an item.
*/
- _onClickItem: function(ev) {
+ _onClickItem: function (ev) {
var $target = $(ev.target);
var itemId = $target.closest('li').attr('data-id');
if (!_.isUndefined(itemId)) {
this.setActiveItem(itemId);
}
ev.preventDefault();
+ },
+
+ /**
+ * Event handler for clicking a button
+ */
+ _onClickMenuButton: function (ev) {
+ var $target = $(ev.target);
+ var itemId = $target.closest('button').attr('id');
+
+ var collapsibleToggles = [];
+ var dotmenuToggles = [];
+
+ // The collapsibleToggles-Array consists of a list of Arrays. Every subarray must contain the Button to listen to at the 0th index,
+ // and the parent, which should be toggled at the first arrayindex.
+ collapsibleToggles.push(["#button-collapse-favorites", "#button-collapse-parent-favorites"]);
+
+ // The dotmenuToggles-Array consists of a list of Arrays. Every subarray must contain the Button to listen to at the 0th index,
+ // and the parent, which should be toggled at the first arrayindex.
+ dotmenuToggles.push(["#dotmenu-button-favorites", "dotmenu-content-favorites"]);
+
+ collapsibleToggles.forEach(function foundToggle (item) {
+ if (item[0] === ("#" + itemId)) {
+ $(item[1]).toggleClass('open');
+ var show = 1;
+ if (!$(item[1]).hasClass('open')) {
+ show = 0;
+ }
+ $.get(OC.generateUrl("/apps/files/api/v1/quickaccess/set/showList"), {show: show}, function (data, status) {
+ });
+ }
+ });
+
+ dotmenuToggles.forEach(function foundToggle (item) {
+ if (item[0] === ("#" + itemId)) {
+ document.getElementById(item[1]).classList.toggle('open');
+ }
+ });
+
+ ev.preventDefault();
+ },
+
+ /**
+ * Sort initially as setup of sidebar for QuickAccess
+ */
+ setInitialQuickaccessSettings: function () {
+
+ var quickAccesKey = this.$quickAccessListKey;
+ var list = document.getElementById(quickAccesKey).getElementsByTagName('li');
+
+ var sort = true;
+ var reverse = false;
+ if (this.$sortingStrategy === 'datemodified') {
+ sort = false;
+ reverse = false;
+
+ var scope = this;
+ $.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/FavoriteFolders/"), function (data, status) {
+ for (var i = 0; i < data.favoriteFolders.length; i++) {
+ for (var j = 0; j < list.length; j++) {
+ if (scope.getCompareValue(list, j, 'alphabet').toLowerCase() === data.favoriteFolders[i].name.toLowerCase()) {
+ list[j].setAttribute("mtime", data.favoriteFolders[i].mtime);
+ }
+ }
+ }
+ scope.QuickSort(list, 0, list.length - 1);
+ scope.reverse(list);
+ });
+
+ } else if (this.$sortingStrategy === 'alphabet') {
+ sort = true;
+ } else if (this.$sortingStrategy === 'date') {
+ sort = true;
+ } else if (this.$sortingStrategy === 'customorder') {
+ var scope = this;
+ $.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/CustomSortingOrder"), function (data, status) {
+ var ordering = JSON.parse(data);
+ for (var i = 0; i < ordering.length; i++) {
+ for (var j = 0; j < list.length; j++) {
+ if (scope.getCompareValue(list, j, 'alphabet').toLowerCase() === ordering[i].name.toLowerCase()) {
+ list[j].setAttribute("folderPosition", ordering[i].id);
+ }
+ }
+ }
+ scope.QuickSort(list, 0, list.length - 1);
+ });
+ sort = false;
+ }
+
+ if (sort) {
+ this.QuickSort(list, 0, list.length - 1);
+ }
+ if (reverse) {
+ this.reverse(list);
+ }
+
+ },
+
+ /**
+ * Sorting-Algorithm for QuickAccess
+ */
+ QuickSort: function (list, start, end) {
+ var lastMatch;
+ if (list.length > 1) {
+ lastMatch = this.quicksort_helper(list, start, end);
+ if (start < lastMatch - 1) {
+ this.QuickSort(list, start, lastMatch - 1);
+ }
+ if (lastMatch < end) {
+ this.QuickSort(list, lastMatch, end);
+ }
+ }
+ },
+
+ /**
+ * Sorting-Algorithm-Helper for QuickAccess
+ */
+ quicksort_helper: function (list, start, end) {
+ var pivot = Math.floor((end + start) / 2);
+ var pivotElement = this.getCompareValue(list, pivot);
+ var i = start;
+ var j = end;
+
+ while (i <= j) {
+ while (this.getCompareValue(list, i) < pivotElement) {
+ i++;
+ }
+ while (this.getCompareValue(list, j) > pivotElement) {
+ j--;
+ }
+ if (i <= j) {
+ this.swap(list, i, j);
+ i++;
+ j--;
+ }
+ }
+ return i;
+ },
+
+ /**
+ * Sorting-Algorithm-Helper for QuickAccess
+ * This method allows easy access to the element which is sorted by.
+ */
+ getCompareValue: function (nodes, int, strategy) {
+
+ if ((typeof strategy === 'undefined')) {
+ strategy = this.$sortingStrategy;
+ }
+
+ if (strategy === 'alphabet') {
+ return nodes[int].getElementsByTagName('a')[0].innerHTML.toLowerCase();
+ } else if (strategy === 'date') {
+ return nodes[int].getAttribute('folderPosition').toLowerCase();
+ } else if (strategy === 'datemodified') {
+ return nodes[int].getAttribute('mtime');
+ } else if (strategy === 'customorder') {
+ return nodes[int].getAttribute('folderPosition');
+ }
+ return nodes[int].getElementsByTagName('a')[0].innerHTML.toLowerCase();
+ },
+
+ /**
+ * Sorting-Algorithm-Helper for QuickAccess
+ * This method allows easy swapping of elements.
+ */
+ swap: function (list, j, i) {
+ list[i].before(list[j]);
+ list[j].before(list[i]);
+ },
+
+ /**
+ * Reverse QuickAccess-List
+ */
+ reverse: function (list) {
+ var len = list.length - 1;
+ for (var i = 0; i < len / 2; i++) {
+ this.swap(list, i, len - i);
+ }
}
+
};
OCA.Files.Navigation = Navigation;
})();
+
+
+
+
+
diff --git a/apps/files/js/tagsplugin.js b/apps/files/js/tagsplugin.js
index b174aa7d766..bc1396b5104 100644
--- a/apps/files/js/tagsplugin.js
+++ b/apps/files/js/tagsplugin.js
@@ -10,11 +10,11 @@
/* global Handlebars */
-(function(OCA) {
+(function (OCA) {
_.extend(OC.Files.Client, {
- PROPERTY_TAGS: '{' + OC.Files.Client.NS_OWNCLOUD + '}tags',
- PROPERTY_FAVORITE: '{' + OC.Files.Client.NS_OWNCLOUD + '}favorite'
+ PROPERTY_TAGS: '{' + OC.Files.Client.NS_OWNCLOUD + '}tags',
+ PROPERTY_FAVORITE: '{' + OC.Files.Client.NS_OWNCLOUD + '}favorite'
});
var TEMPLATE_FAVORITE_MARK =
@@ -30,7 +30,7 @@
* @param {boolean} state true if starred, false otherwise
* @return {string} icon class for star image
*/
- function getStarIconClass(state) {
+ function getStarIconClass (state) {
return state ? 'icon-starred' : 'icon-star';
}
@@ -40,7 +40,7 @@
* @param {boolean} state true if starred, false otherwise
* @return {Object} jQuery object
*/
- function renderStar(state) {
+ function renderStar (state) {
if (!this._template) {
this._template = Handlebars.compile(TEMPLATE_FAVORITE_MARK);
}
@@ -57,11 +57,95 @@
* @param {Object} $favoriteMarkEl favorite mark element
* @param {boolean} state true if starred, false otherwise
*/
- function toggleStar($favoriteMarkEl, state) {
+ function toggleStar ($favoriteMarkEl, state) {
$favoriteMarkEl.removeClass('icon-star icon-starred').addClass(getStarIconClass(state));
$favoriteMarkEl.toggleClass('permanent', state);
}
+ /**
+ * Remove Item from Quickaccesslist
+ *
+ * @param {String} appfolder folder to be removed
+ */
+ function removeFavoriteFromList (appfolder) {
+
+ var quickAccessList = 'sublist-favorites';
+ var collapsibleButtonId = 'button-collapse-favorites';
+ var listULElements = document.getElementById(quickAccessList);
+ if (!listULElements) {
+ return;
+ }
+ var listLIElements = listULElements.getElementsByTagName('li');
+
+ var apppath=appfolder;
+ if(appfolder.startsWith("//")){
+ apppath=appfolder.substring(1, appfolder.length);
+ }
+
+ for (var i = 0; i <= listLIElements.length - 1; i++) {
+ if (listLIElements[i].getElementsByTagName('a')[0].href.endsWith("dir=" + apppath)) {
+ listLIElements[i].remove();
+ }
+ }
+
+ if (listULElements.childElementCount === 0) {
+ var collapsibleButton = document.getElementById("button-collapse-favorites");
+ collapsibleButton.style.display = 'none';
+ $("#button-collapse-parent-favorites").removeClass('collapsible');
+ }
+ }
+
+ /**
+ * Add Item to Quickaccesslist
+ *
+ * @param {String} appfolder folder to be added
+ */
+ function addFavoriteToList (appfolder) {
+ var quickAccessList = 'sublist-favorites';
+ var collapsibleButtonId = 'button-collapse-favorites';
+ var listULElements = document.getElementById(quickAccessList);
+ if (!listULElements) {
+ return;
+ }
+ var listLIElements = listULElements.getElementsByTagName('li');
+
+ var appName = appfolder.substring(appfolder.lastIndexOf("/") + 1, appfolder.length);
+ var apppath=appfolder;
+
+ if(appfolder.startsWith("//")){
+ apppath=appfolder.substring(1, appfolder.length);
+ }
+ var url=OC.generateUrl('/apps/files/?dir=')+apppath;
+
+
+ var innerTagA = document.createElement('A');
+ innerTagA.setAttribute("href", url);
+ innerTagA.setAttribute("class", "nav-icon-files svg");
+ innerTagA.innerHTML = appName;
+
+ var length = listLIElements.length + 1;
+ var innerTagLI = document.createElement('li');
+ innerTagLI.setAttribute("data-id", url);
+ innerTagLI.setAttribute("class", "nav-" + appName);
+ innerTagLI.setAttribute("folderpos", length.toString());
+ innerTagLI.appendChild(innerTagA);
+
+ $.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/NodeType"),{folderpath: apppath}, function (data, status) {
+ if (data === "dir") {
+ if (listULElements.childElementCount <= 0) {
+ listULElements.appendChild(innerTagLI);
+ var collapsibleButton = document.getElementById(collapsibleButtonId);
+ collapsibleButton.style.display = '';
+
+ $("#button-collapse-parent-favorites").addClass('collapsible');
+ } else {
+ listLIElements[listLIElements.length - 1].after(innerTagLI);
+ }
+ }
+ }
+ );
+ }
+
OCA.Files = OCA.Files || {};
/**
@@ -83,12 +167,12 @@
'shares.link'
],
- _extendFileActions: function(fileActions) {
+ _extendFileActions: function (fileActions) {
var self = this;
fileActions.registerAction({
name: 'Favorite',
- displayName: function(context) {
+ displayName: function (context) {
var $file = context.$file;
var isFavorite = $file.data('favorite') === true;
@@ -105,7 +189,7 @@
mime: 'all',
order: -100,
permissions: OC.PERMISSION_NONE,
- iconClass: function(fileName, context) {
+ iconClass: function (fileName, context) {
var $file = context.$file;
var isFavorite = $file.data('favorite') === true;
@@ -115,12 +199,13 @@
return 'icon-starred';
},
- actionHandler: function(fileName, context) {
+ actionHandler: function (fileName, context) {
var $favoriteMarkEl = context.$file.find('.favorite-mark');
var $file = context.$file;
var fileInfo = context.fileList.files[$file.index()];
var dir = context.dir || context.fileList.getCurrentDirectory();
var tags = $file.attr('data-tags');
+
if (_.isUndefined(tags)) {
tags = '';
}
@@ -130,8 +215,10 @@
if (isFavorite) {
// remove tag from list
tags = _.without(tags, OC.TAG_FAVORITE);
+ removeFavoriteFromList(dir + '/' + fileName);
} else {
tags.push(OC.TAG_FAVORITE);
+ addFavoriteToList(dir + '/' + fileName);
}
// pre-toggle the star
@@ -144,7 +231,7 @@
tags,
$favoriteMarkEl,
isFavorite
- ).then(function(result) {
+ ).then(function (result) {
context.fileInfoModel.trigger('busy', context.fileInfoModel, false);
// response from server should contain updated tags
var newTags = result.tags;
@@ -160,10 +247,10 @@
});
},
- _extendFileList: function(fileList) {
+ _extendFileList: function (fileList) {
// extend row prototype
var oldCreateRow = fileList._createRow;
- fileList._createRow = function(fileData) {
+ fileList._createRow = function (fileData) {
var $tr = oldCreateRow.apply(this, arguments);
var isFavorite = false;
if (fileData.tags) {
@@ -178,7 +265,7 @@
return $tr;
};
var oldElementToFile = fileList.elementToFile;
- fileList.elementToFile = function($el) {
+ fileList.elementToFile = function ($el) {
var fileInfo = oldElementToFile.apply(this, arguments);
var tags = $el.attr('data-tags');
if (_.isUndefined(tags)) {
@@ -191,22 +278,22 @@
};
var oldGetWebdavProperties = fileList._getWebdavProperties;
- fileList._getWebdavProperties = function() {
+ fileList._getWebdavProperties = function () {
var props = oldGetWebdavProperties.apply(this, arguments);
props.push(OC.Files.Client.PROPERTY_TAGS);
props.push(OC.Files.Client.PROPERTY_FAVORITE);
return props;
};
- fileList.filesClient.addFileInfoParser(function(response) {
+ fileList.filesClient.addFileInfoParser(function (response) {
var data = {};
var props = response.propStat[0].properties;
var tags = props[OC.Files.Client.PROPERTY_TAGS];
var favorite = props[OC.Files.Client.PROPERTY_FAVORITE];
if (tags && tags.length) {
- tags = _.chain(tags).filter(function(xmlvalue) {
+ tags = _.chain(tags).filter(function (xmlvalue) {
return (xmlvalue.namespaceURI === OC.Files.Client.NS_OWNCLOUD && xmlvalue.nodeName.split(':')[1] === 'tag');
- }).map(function(xmlvalue) {
+ }).map(function (xmlvalue) {
return xmlvalue.textContent || xmlvalue.text;
}).value();
}
@@ -221,7 +308,7 @@
});
},
- attach: function(fileList) {
+ attach: function (fileList) {
if (this.allowedLists.indexOf(fileList.id) < 0) {
return;
}
@@ -237,7 +324,7 @@
* @param {Object} $favoriteMarkEl favorite mark element
* @param {boolean} isFavorite Was the item favorited before
*/
- applyFileTags: function(fileName, tagNames, $favoriteMarkEl, isFavorite) {
+ applyFileTags: function (fileName, tagNames, $favoriteMarkEl, isFavorite) {
var encodedPath = OC.encodePath(fileName);
while (encodedPath[0] === '/') {
encodedPath = encodedPath.substr(1);
@@ -250,10 +337,10 @@
}),
dataType: 'json',
type: 'POST'
- }).fail(function(response) {
+ }).fail(function (response) {
var message = '';
// show message if it is available
- if(response.responseJSON && response.responseJSON.message) {
+ if (response.responseJSON && response.responseJSON.message) {
message = ': ' + response.responseJSON.message;
}
OC.Notification.show(t('files', 'An error occurred while trying to update the tags' + message), {type: 'error'});
@@ -261,6 +348,7 @@
});
}
};
-})(OCA);
+})
+(OCA);
OC.Plugins.register('OCA.Files.FileList', OCA.Files.TagsPlugin);
diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php
index 064f2baa987..d4dac5befa8 100644
--- a/apps/files/lib/AppInfo/Application.php
+++ b/apps/files/lib/AppInfo/Application.php
@@ -26,6 +26,7 @@
*/
namespace OCA\Files\AppInfo;
+use OCA\Files\Activity\Helper;
use OCA\Files\Controller\ApiController;
use OCP\AppFramework\App;
use \OCA\Files\Service\TagService;
@@ -65,7 +66,8 @@ class Application extends App {
$server->getEventDispatcher(),
$server->getUserSession(),
$server->getAppManager(),
- $server->getRootFolder()
+ $server->getRootFolder(),
+ $c->query(Helper::class)
);
});
diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php
index a66b1b4d565..aae1bec2e78 100644
--- a/apps/files/lib/Controller/ApiController.php
+++ b/apps/files/lib/Controller/ApiController.php
@@ -11,7 +11,7 @@
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Tobias Kaminsky <tobias@kaminsky.me>
* @author Vincent Petry <pvince81@owncloud.com>
- *
+ * @author Felix Nüsse <felix.nuesse@t-online.de>
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
@@ -45,6 +45,7 @@ use OCP\IPreview;
use OCP\Share\IManager;
use OC\Files\Node\Node;
use OCP\IUserSession;
+use Sabre\VObject\Property\Boolean;
/**
* Class ApiController
@@ -54,7 +55,7 @@ use OCP\IUserSession;
class ApiController extends Controller {
/** @var TagService */
private $tagService;
- /** @var IManager **/
+ /** @var IManager * */
private $shareManager;
/** @var IPreview */
private $previewManager;
@@ -107,7 +108,7 @@ class ApiController extends Controller {
* @return DataResponse|FileDisplayResponse
*/
public function getThumbnail($x, $y, $file) {
- if($x < 1 || $y < 1) {
+ if ($x < 1 || $y < 1) {
return new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
}
@@ -199,6 +200,30 @@ class ApiController extends Controller {
}
/**
+ * Returns a list of favorites modifed folder.
+ *
+ * @NoAdminRequired
+ *
+ * @return DataResponse
+ */
+ public function getFavoritesFolder() {
+ $nodes = $this->userFolder->searchByTag('_$!<Favorite>!$_', $this->userSession->getUser()->getUID());
+
+ $favorites = [];
+ $i = 0;
+ foreach ($nodes as &$node) {
+
+ $favorites[$i]['id'] = $node->getId();
+ $favorites[$i]['name'] = $node->getName();
+ $favorites[$i]['path'] = $node->getInternalPath();
+ $favorites[$i]['mtime'] = $node->getMTime();
+ $i++;
+ }
+
+ return new DataResponse(['favoriteFolders' => $favorites]);
+ }
+
+ /**
* Return a list of share types for outgoing shares
*
* @param Node $node file node
@@ -261,8 +286,150 @@ class ApiController extends Controller {
* @param bool $show
*/
public function showHiddenFiles($show) {
- $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', (int) $show);
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', (int)$show);
+ return new Response();
+ }
+
+ /**
+ * Toggle default for showing/hiding QuickAccess folder
+ *
+ * @NoAdminRequired
+ *
+ * @param bool $show
+ *
+ * @return Response
+ */
+ public function showQuickAccess($show) {
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_Quick_Access', (int)$show);
+ return new Response();
+ }
+
+ /**
+ * Toggle default for showing/hiding QuickAccess folder
+ *
+ * @NoAdminRequired
+ *
+ * @return String
+ */
+ public function getShowQuickAccess() {
+
+ return $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_Quick_Access', 0);
+ }
+
+ /**
+ * quickaccess-sorting-strategy
+ *
+ * @NoAdminRequired
+ *
+ * @param string $strategy
+ * @return Response
+ */
+ public function setSortingStrategy($strategy) {
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_sorting_strategy', (String)$strategy);
return new Response();
}
+ /**
+ * Get reverse-state for quickaccess-list
+ *
+ * @NoAdminRequired
+ *
+ * @return String
+ */
+ public function getSortingStrategy() {
+ return $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_sorting_strategy', 'alphabet');
+ }
+
+ /**
+ * Toggle for reverse quickaccess-list
+ *
+ * @NoAdminRequired
+ *
+ * @param bool $reverse
+ * @return Response
+ */
+ public function setReverseQuickaccess($reverse) {
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_reverse_list', (int)$reverse);
+ return new Response();
+ }
+
+ /**
+ * Get reverse-state for quickaccess-list
+ *
+ * @NoAdminRequired
+ *
+ * @return bool
+ */
+ public function getReverseQuickaccess() {
+ if ($this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_reverse_list', false)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set state for show sorting menu
+ *
+ * @NoAdminRequired
+ *
+ * @param bool $show
+ * @return Response
+ */
+ public function setShowQuickaccessSettings($show) {
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_show_settings', (int)$show);
+ return new Response();
+ }
+
+ /**
+ * Get state for show sorting menu
+ *
+ * @NoAdminRequired
+ *
+ * @return bool
+ */
+ public function getShowQuickaccessSettings() {
+ if ($this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_show_settings', false)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set sorting-order for custom sorting
+ *
+ * @NoAdminRequired
+ *
+ * @param String $order
+ * @return Response
+ */
+ public function setSortingOrder($order) {
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_custom_sorting_order', (String)$order);
+ return new Response();
+ }
+
+ /**
+ * Get sorting-order for custom sorting
+ *
+ * @NoAdminRequired
+ *
+ * @return String
+ */
+ public function getSortingOrder() {
+ return $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'quickaccess_custom_sorting_order', "");
+ }
+
+ /**
+ * Get sorting-order for custom sorting
+ *
+ * @NoAdminRequired
+ *
+ * @param String
+ * @return String
+ */
+ public function getNodeType($folderpath) {
+ $node = $this->userFolder->get($folderpath);
+ return $node->getType();
+ }
+
+
}
diff --git a/apps/files/lib/Controller/ViewController.php b/apps/files/lib/Controller/ViewController.php
index 7cb0f112f72..f240e04c721 100644
--- a/apps/files/lib/Controller/ViewController.php
+++ b/apps/files/lib/Controller/ViewController.php
@@ -8,6 +8,7 @@
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vincent Petry <pvince81@owncloud.com>
+ * @author Felix Nüsse <felix.nuesse@t-online.de>
*
* @license AGPL-3.0
*
@@ -27,6 +28,7 @@
namespace OCA\Files\Controller;
+use OCA\Files\Activity\Helper;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\RedirectResponse;
@@ -67,19 +69,10 @@ class ViewController extends Controller {
protected $appManager;
/** @var IRootFolder */
protected $rootFolder;
+ /** @var Helper */
+ protected $activityHelper;
- /**
- * @param string $appName
- * @param IRequest $request
- * @param IURLGenerator $urlGenerator
- * @param IL10N $l10n
- * @param IConfig $config
- * @param EventDispatcherInterface $eventDispatcherInterface
- * @param IUserSession $userSession
- * @param IAppManager $appManager
- * @param IRootFolder $rootFolder
- */
- public function __construct($appName,
+ public function __construct(string $appName,
IRequest $request,
IURLGenerator $urlGenerator,
IL10N $l10n,
@@ -87,7 +80,8 @@ class ViewController extends Controller {
EventDispatcherInterface $eventDispatcherInterface,
IUserSession $userSession,
IAppManager $appManager,
- IRootFolder $rootFolder
+ IRootFolder $rootFolder,
+ Helper $activityHelper
) {
parent::__construct($appName, $request);
$this->appName = $appName;
@@ -99,6 +93,7 @@ class ViewController extends Controller {
$this->userSession = $userSession;
$this->appManager = $appManager;
$this->rootFolder = $rootFolder;
+ $this->activityHelper = $activityHelper;
}
/**
@@ -159,28 +154,68 @@ class ViewController extends Controller {
// FIXME: Make non static
$storageInfo = $this->getStorageInfo();
+ $user = $this->userSession->getUser()->getUID();
+
+ try {
+ $favElements = $this->activityHelper->getFavoriteFilePaths($this->userSession->getUser()->getUID());
+ } catch (\RuntimeException $e) {
+ $favElements['folders'] = null;
+ }
+
+ $collapseClasses = '';
+ if (count($favElements['folders']) > 0) {
+ $collapseClasses = 'collapsible';
+ }
+
+ $favoritesSublistArray = Array();
+
+ $navBarPositionPosition = 6;
+ $currentCount = 0;
+ foreach ($favElements['folders'] as $dir) {
+
+ $id = substr($dir, strrpos($dir, '/') + 1, strlen($dir));
+ $link = $this->urlGenerator->linkToRoute('files.view.index', ['dir' => $dir, 'view' => 'files']);
+ $sortingValue = ++$currentCount;
+ $element = [
+ 'id' => str_replace('/', '-', $dir),
+ 'view' => 'files',
+ 'href' => $link,
+ 'dir' => $dir,
+ 'order' => $navBarPositionPosition,
+ 'folderPosition' => $sortingValue,
+ 'name' => $id,
+ 'icon' => 'files',
+ 'quickaccesselement' => 'true'
+ ];
+
+ array_push($favoritesSublistArray, $element);
+ $navBarPositionPosition++;
+ }
+
+
+ // show_Quick_Access stored as string
+ $defaultExpandedState = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_Quick_Access', '0') === '1';
+
\OCA\Files\App::getNavigationManager()->add(
[
'id' => 'favorites',
'appname' => 'files',
'script' => 'simplelist.php',
+ 'classes' => $collapseClasses,
'order' => 5,
- 'name' => $this->l10n->t('Favorites')
+ 'name' => $this->l10n->t('Favorites'),
+ 'sublist' => $favoritesSublistArray,
+ 'defaultExpandedState' => $defaultExpandedState,
+ 'enableMenuButton' => 0,
]
);
$navItems = \OCA\Files\App::getNavigationManager()->getAll();
- usort($navItems, function($item1, $item2) {
+ usort($navItems, function ($item1, $item2) {
return $item1['order'] - $item2['order'];
});
- $nav->assign('navigationItems', $navItems);
- $webdavurl = $this->urlGenerator->linkTo('', 'remote.php') .
- '/dav/files/' .
- $this->userSession->getUser()->getUID() .
- '/';
- $webdavurl = $this->urlGenerator->getAbsoluteURL($webdavurl);
- $nav->assign('webdavurl', $webdavurl);
+ $nav->assign('navigationItems', $navItems);
$nav->assign('usage', \OC_Helper::humanFileSize($storageInfo['used']));
if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
@@ -215,10 +250,9 @@ class ViewController extends Controller {
$params['ownerDisplayName'] = $storageInfo['ownerDisplayName'];
$params['isPublic'] = false;
$params['allowShareWithLink'] = $this->config->getAppValue('core', 'shareapi_allow_links', 'yes');
- $user = $this->userSession->getUser()->getUID();
$params['defaultFileSorting'] = $this->config->getUserValue($user, 'files', 'file_sorting', 'name');
$params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc');
- $showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
+ $showHidden = (bool)$this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
$params['showHiddenFiles'] = $showHidden ? 1 : 0;
$params['fileNotFound'] = $fileNotFound ? 1 : 0;
$params['appNavigation'] = $nav;
@@ -234,6 +268,7 @@ class ViewController extends Controller {
$policy->addAllowedFrameDomain('\'self\'');
$response->setContentSecurityPolicy($policy);
+
return $response;
}
diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php
index c811ace8abe..0b9ac665901 100644
--- a/apps/files/templates/appnavigation.php
+++ b/apps/files/templates/appnavigation.php
@@ -1,18 +1,17 @@
<div id="app-navigation">
<ul class="with-icon">
- <?php $pinned = 0 ?>
- <?php foreach ($_['navigationItems'] as $item) {
- strpos($item['classes'], 'pinned')!==false ? $pinned++ : '';
+
+ <?php
+
+ $pinned = 0;
+ foreach ($_['navigationItems'] as $item) {
+ $pinned = NavigationListElements($item, $l, $pinned);
+ }
?>
- <li data-id="<?php p($item['id']) ?>" class="nav-<?php p($item['id']) ?> <?php p($item['classes']) ?> <?php p($pinned===1?'first-pinned':'') ?>">
- <a href="<?php p(isset($item['href']) ? $item['href'] : '#') ?>"
- class="nav-icon-<?php p($item['icon'] !== '' ? $item['icon'] : $item['id']) ?> svg">
- <?php p($item['name']);?>
- </a>
- </li>
- <?php } ?>
- <li id="quota" class="pinned <?php p($pinned===0?'first-pinned ':'') ?><?php
- if ($_['quota'] !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
+
+ <li id="quota"
+ class="pinned <?php p($pinned === 0 ? 'first-pinned ' : '') ?><?php
+ if ($_['quota'] !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
?>has-tooltip" title="<?php p($_['usage_relative'] . '%');
} ?>">
<a href="#" class="icon-quota svg">
@@ -23,26 +22,103 @@
p($l->t('%s used', [$_['usage']]));
} ?></p>
<div class="quota-container">
- <progress value="<?php p($_['usage_relative']); ?>" max="100"
- <?php if($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
+ <progress value="<?php p($_['usage_relative']); ?>"
+ max="100"
+ <?php if ($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
</div>
</a>
</li>
</ul>
<div id="app-settings">
<div id="app-settings-header">
- <button class="settings-button" data-apps-slide-toggle="#app-settings-content">
- <?php p($l->t('Settings'));?>
+ <button class="settings-button"
+ data-apps-slide-toggle="#app-settings-content">
+ <?php p($l->t('Settings')); ?>
</button>
</div>
<div id="app-settings-content">
<div id="files-setting-showhidden">
- <input class="checkbox" id="showhiddenfilesToggle" checked="checked" type="checkbox">
+ <input class="checkbox" id="showhiddenfilesToggle"
+ checked="checked" type="checkbox">
<label for="showhiddenfilesToggle"><?php p($l->t('Show hidden files')); ?></label>
</div>
- <label for="webdavurl"><?php p($l->t('WebDAV'));?></label>
- <input id="webdavurl" type="text" readonly="readonly" value="<?php p($_['webdavurl']); ?>" />
- <em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank" rel="noreferrer noopener">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em>
+ <label for="webdavurl"><?php p($l->t('WebDAV')); ?></label>
+ <input id="webdavurl" type="text" readonly="readonly"
+ value="<?php p(\OCP\Util::linkToRemote('webdav')); ?>"/>
+ <em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank" rel="noreferrer noopener">access your Files via WebDAV</a>', array(link_to_docs('user-webdav')))); ?></em>
</div>
</div>
+
</div>
+
+
+<?php
+
+/**
+ * Prints the HTML for a single Entry.
+ *
+ * @param $item The item to be added
+ * @param $l Translator
+ * @param $pinned IntegerValue to count the pinned entries at the bottom
+ *
+ * @return int Returns the pinned value
+ */
+function NavigationListElements($item, $l, $pinned) {
+ strpos($item['classes'], 'pinned') !== false ? $pinned++ : '';
+ ?>
+ <li <?php if (isset($item['sublist'])){ ?>id="button-collapse-parent-<?php p($item['id']); ?>"<?php } ?>
+ data-id="<?php p($item['id']) ?>" data-dir="<?php p($item['dir']) ?>" data-view="<?php p($item['view']) ?>"
+ class="nav-<?php p($item['id']) ?> <?php p($item['classes']) ?> <?php p($pinned === 1 ? 'first-pinned' : '') ?> <?php if ($item['defaultExpandedState']) { ?> open<?php } ?>"
+ <?php if (isset($item['folderPosition'])) { ?> folderposition="<?php p($item['folderPosition']); ?>" <?php } ?>>
+
+ <a href="<?php p(isset($item['href']) ? $item['href'] : '#') ?>"
+ class="nav-icon-<?php p($item['icon'] !== '' ? $item['icon'] : $item['id']) ?> svg"><?php p($item['name']); ?></a>
+
+
+ <?php
+ NavigationElementMenu($item);
+ if (isset($item['sublist'])) {
+ ?>
+ <button id="button-collapse-<?php p($item['id']); ?>"
+ class="collapse app-navigation-noclose" <?php if (sizeof($item['sublist']) == 0) { ?> style="display: none" <?php } ?>></button>
+ <ul id="sublist-<?php p($item['id']); ?>">
+ <?php
+ foreach ($item['sublist'] as $item) {
+ $pinned = NavigationListElements($item, $l, $pinned);
+ }
+ ?>
+ </ul>
+ <?php } ?>
+ </li>
+
+
+ <?php
+ return $pinned;
+}
+
+/**
+ * Prints the HTML for a dotmenu.
+ *
+ * @param $item The item to be added
+ *
+ * @return void
+ */
+function NavigationElementMenu($item) {
+ if ($item['menubuttons'] === 'true') {
+ ?>
+ <div id="dotmenu-<?php p($item['id']); ?>"
+ class="app-navigation-entry-utils" <?php if ($item['enableMenuButton'] === 0) { ?> style="display: none"<?php } ?>>
+ <ul>
+ <li class="app-navigation-entry-utils-menu-button svg">
+ <button id="dotmenu-button-<?php p($item['id']) ?>"></button>
+ </li>
+ </ul>
+ </div>
+ <div id="dotmenu-content-<?php p($item['id']) ?>"
+ class="app-navigation-entry-menu">
+ <ul>
+
+ </ul>
+ </div>
+ <?php }
+}
diff --git a/apps/files/tests/Controller/ViewControllerTest.php b/apps/files/tests/Controller/ViewControllerTest.php
index eae627fd6a4..8f077645808 100644
--- a/apps/files/tests/Controller/ViewControllerTest.php
+++ b/apps/files/tests/Controller/ViewControllerTest.php
@@ -29,6 +29,7 @@
namespace OCA\Files\Tests\Controller;
+use OCA\Files\Activity\Helper;
use OCA\Files\Controller\ViewController;
use OCP\AppFramework\Http;
use OCP\Files\File;
@@ -71,6 +72,8 @@ class ViewControllerTest extends TestCase {
private $appManager;
/** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */
private $rootFolder;
+ /** @var Helper|\PHPUnit_Framework_MockObject_MockObject */
+ private $activityHelper;
public function setUp() {
parent::setUp();
@@ -89,6 +92,7 @@ class ViewControllerTest extends TestCase {
->method('getUser')
->will($this->returnValue($this->user));
$this->rootFolder = $this->getMockBuilder('\OCP\Files\IRootFolder')->getMock();
+ $this->activityHelper = $this->createMock(Helper::class);
$this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController')
->setConstructorArgs([
'files',
@@ -99,7 +103,8 @@ class ViewControllerTest extends TestCase {
$this->eventDispatcher,
$this->userSession,
$this->appManager,
- $this->rootFolder
+ $this->rootFolder,
+ $this->activityHelper,
])
->setMethods([
'getStorageInfo',
@@ -120,7 +125,7 @@ class ViewControllerTest extends TestCase {
'owner' => 'MyName',
'ownerDisplayName' => 'MyDisplayName',
]));
- $this->config->expects($this->exactly(3))
+ $this->config
->method('getUserValue')
->will($this->returnValueMap([
[$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'],
@@ -138,7 +143,7 @@ class ViewControllerTest extends TestCase {
$nav->assign('usage', '123 B');
$nav->assign('quota', 100);
$nav->assign('total_space', '100 B');
- $nav->assign('webdavurl', '');
+ //$nav->assign('webdavurl', '');
$nav->assign('navigationItems', [
[
'id' => 'files',
@@ -172,6 +177,9 @@ class ViewControllerTest extends TestCase {
'icon' => '',
'type' => 'link',
'classes' => '',
+ 'sublist' => [],
+ 'defaultExpandedState' => false,
+ 'enableMenuButton' => 0,
],
[
'id' => 'sharingin',
@@ -299,6 +307,14 @@ class ViewControllerTest extends TestCase {
$policy = new Http\ContentSecurityPolicy();
$policy->addAllowedFrameDomain('\'self\'');
$expected->setContentSecurityPolicy($policy);
+
+ $this->activityHelper->method('getFavoriteFilePaths')
+ ->with($this->user->getUID())
+ ->willReturn([
+ 'item' => [],
+ 'folders' => [],
+ ]);
+
$this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView'));
}
diff --git a/apps/files/tests/js/appSpec.js b/apps/files/tests/js/appSpec.js
index 5728991e197..15297a029d4 100644
--- a/apps/files/tests/js/appSpec.js
+++ b/apps/files/tests/js/appSpec.js
@@ -239,38 +239,38 @@ describe('OCA.Files.App tests', function() {
expect(App.navigation.getActiveItem()).toEqual('other');
expect($('#app-content-files').hasClass('hidden')).toEqual(true);
expect($('#app-content-other').hasClass('hidden')).toEqual(false);
- expect($('li[data-id=files]').hasClass('active')).toEqual(false);
- expect($('li[data-id=other]').hasClass('active')).toEqual(true);
+ expect($('li[data-id=files] > a').hasClass('active')).toEqual(false);
+ expect($('li[data-id=other] > a').hasClass('active')).toEqual(true);
App._onPopState({view: 'files', dir: '/somedir'});
expect(App.navigation.getActiveItem()).toEqual('files');
expect($('#app-content-files').hasClass('hidden')).toEqual(false);
expect($('#app-content-other').hasClass('hidden')).toEqual(true);
- expect($('li[data-id=files]').hasClass('active')).toEqual(true);
- expect($('li[data-id=other]').hasClass('active')).toEqual(false);
+ expect($('li[data-id=files] > a').hasClass('active')).toEqual(true);
+ expect($('li[data-id=other] > a').hasClass('active')).toEqual(false);
});
it('clicking on navigation switches the panel visibility', function() {
- $('li[data-id=other]>a').click();
+ $('li[data-id=other] > a').click();
expect(App.navigation.getActiveItem()).toEqual('other');
expect($('#app-content-files').hasClass('hidden')).toEqual(true);
expect($('#app-content-other').hasClass('hidden')).toEqual(false);
- expect($('li[data-id=files]').hasClass('active')).toEqual(false);
- expect($('li[data-id=other]').hasClass('active')).toEqual(true);
+ expect($('li[data-id=files] > a').hasClass('active')).toEqual(false);
+ expect($('li[data-id=other] > a').hasClass('active')).toEqual(true);
- $('li[data-id=files]>a').click();
+ $('li[data-id=files] > a').click();
expect(App.navigation.getActiveItem()).toEqual('files');
expect($('#app-content-files').hasClass('hidden')).toEqual(false);
expect($('#app-content-other').hasClass('hidden')).toEqual(true);
- expect($('li[data-id=files]').hasClass('active')).toEqual(true);
- expect($('li[data-id=other]').hasClass('active')).toEqual(false);
+ expect($('li[data-id=files] > a').hasClass('active')).toEqual(true);
+ expect($('li[data-id=other] > a').hasClass('active')).toEqual(false);
});
it('clicking on navigation sends "show" and "urlChanged" event', function() {
var handler = sinon.stub();
var showHandler = sinon.stub();
$('#app-content-other').on('urlChanged', handler);
$('#app-content-other').on('show', showHandler);
- $('li[data-id=other]>a').click();
+ $('li[data-id=other] > a').click();
expect(handler.calledOnce).toEqual(true);
expect(handler.getCall(0).args[0].view).toEqual('other');
expect(handler.getCall(0).args[0].dir).toEqual('/');
@@ -281,7 +281,7 @@ describe('OCA.Files.App tests', function() {
var showHandler = sinon.stub();
$('#app-content-files').on('urlChanged', handler);
$('#app-content-files').on('show', showHandler);
- $('li[data-id=files]>a').click();
+ $('li[data-id=files] > a').click();
expect(handler.calledOnce).toEqual(true);
expect(handler.getCall(0).args[0].view).toEqual('files');
expect(handler.getCall(0).args[0].dir).toEqual('/');
diff --git a/core/css/apps.scss b/core/css/apps.scss
index 13b4c7eb9fc..6645b6868d5 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -144,11 +144,12 @@ kbd {
padding-left: 38px !important;
}
- &:hover,
- &:focus,
- &:active,
&.active,
- a.selected {
+ a:hover,
+ a:focus,
+ a:active,
+ a.selected ,
+ a.active {
&,
> a {
opacity: 1;
@@ -156,13 +157,6 @@ kbd {
}
}
- /* a instead of li is focused by keyboards */
- a:focus,
- a:active {
- opacity: 1;
- box-shadow: inset 4px 0 var(--color-primary);
- }
-
/* align loader */
&.icon-loading-small:after {
left: 22px;
@@ -691,6 +685,7 @@ kbd {
background-color: var(--color-main-background);
}
+
.settings-button {
display: block;
height: 44px;