Merge pull request #10176 from nextcloud/newhinton/master
Add Quick-Access to favorite folder in left sidepanel in files-app #9720
This commit is contained in:
commit
052221abbe
11 changed files with 781 additions and 119 deletions
|
@ -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',
|
||||
],
|
||||
]
|
||||
]
|
||||
);
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -38,24 +39,48 @@
|
|||
*/
|
||||
$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;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -198,6 +199,30 @@ class ApiController extends Controller {
|
|||
return new DataResponse(['files' => $files]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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'));
|
||||
}
|
||||
|
||||
|
|
|
@ -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('/');
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue