filter hidden files on the web interface

add checkbox to toggle show/hide hidden files

persist show hidden setting

fix settings menu layout

test ApiController::showHiddenFiles

don't show hidden files by default

Store config in Backbone model and inject it into FileList

Filter files only temporarily when rending the file list

Fix file rename validation
This commit is contained in:
Christoph Wurst 2016-04-12 17:10:09 +02:00 committed by Christoph Wurst
parent f8c55beaae
commit 6c5696d3a8
No known key found for this signature in database
GPG Key ID: FEECD2543CA6EAF0
13 changed files with 155 additions and 13 deletions

View File

@ -54,6 +54,11 @@ $application->registerRoutes(
'url' => '/api/v1/sorting', 'url' => '/api/v1/sorting',
'verb' => 'POST' 'verb' => 'POST'
), ),
array(
'name' => 'API#showHiddenFiles',
'url' => '/api/v1/showhidden',
'verb' => 'POST'
),
[ [
'name' => 'view#index', 'name' => 'view#index',
'url' => '/', 'url' => '/',

View File

@ -224,4 +224,16 @@ class ApiController extends Controller {
return new Response(); return new Response();
} }
/**
* Toggle default for showing/hiding hidden files
*
* @NoAdminRequired
*
* @param bool $show
*/
public function showHiddenFiles($show) {
$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', (int) $show);
return new Response();
}
} }

View File

@ -67,6 +67,7 @@ class ViewController extends Controller {
* @param IL10N $l10n * @param IL10N $l10n
* @param IConfig $config * @param IConfig $config
* @param EventDispatcherInterface $eventDispatcherInterface * @param EventDispatcherInterface $eventDispatcherInterface
* @param IUserSession $userSession
*/ */
public function __construct($appName, public function __construct($appName,
IRequest $request, IRequest $request,
@ -222,6 +223,8 @@ class ViewController extends Controller {
$user = $this->userSession->getUser()->getUID(); $user = $this->userSession->getUser()->getUID();
$params['defaultFileSorting'] = $this->config->getUserValue($user, 'files', 'file_sorting', 'name'); $params['defaultFileSorting'] = $this->config->getUserValue($user, 'files', 'file_sorting', 'name');
$params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc'); $params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc');
$showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
$params['showHiddenFiles'] = $showHidden ? 1 : 0;
$params['appNavigation'] = $nav; $params['appNavigation'] = $nav;
$params['appContents'] = $contentItems; $params['appContents'] = $contentItems;
$this->navigationManager->setActiveEntry('files_index'); $this->navigationManager->setActiveEntry('files_index');

View File

@ -2,6 +2,11 @@
This file is licensed under the Affero General Public License version 3 or later. This file is licensed under the Affero General Public License version 3 or later.
See the COPYING-README file. */ See the COPYING-README file. */
/* SETTINGS */
#files-setting-showhidden {
padding-bottom: 8px;
}
/* FILE MENU */ /* FILE MENU */
.actions { padding:5px; height:32px; display: inline-block; float: left; } .actions { padding:5px; height:32px; display: inline-block; float: left; }
.actions input, .actions button, .actions .button { margin:0; float:left; } .actions input, .actions button, .actions .button { margin:0; float:left; }

View File

@ -11,7 +11,7 @@
* *
*/ */
/* global dragOptions, folderDropOptions */ /* global dragOptions, folderDropOptions, OC */
(function() { (function() {
if (!OCA.Files) { if (!OCA.Files) {
@ -40,11 +40,23 @@
*/ */
fileList: null, fileList: null,
/**
* Backbone model for storing files preferences
*/
_filesConfig: null,
/** /**
* Initializes the files app * Initializes the files app
*/ */
initialize: function() { initialize: function() {
this.navigation = new OCA.Files.Navigation($('#app-navigation')); this.navigation = new OCA.Files.Navigation($('#app-navigation'));
this.$showHiddenFiles = $('input#showhiddenfilesToggle');
var showHidden = $('#showHiddenFiles').val() === "1";
this.$showHiddenFiles.prop('checked', showHidden);
this._filesConfig = new OC.Backbone.Model({
showhidden: showHidden
});
var urlParams = OC.Util.History.parseUrlQuery(); var urlParams = OC.Util.History.parseUrlQuery();
var fileActions = new OCA.Files.FileActions(); var fileActions = new OCA.Files.FileActions();
@ -76,7 +88,8 @@
sorting: { sorting: {
mode: $('#defaultFileSorting').val(), mode: $('#defaultFileSorting').val(),
direction: $('#defaultFileSortingDirection').val() direction: $('#defaultFileSortingDirection').val()
} },
config: this._filesConfig,
} }
); );
this.files.initialize(); this.files.initialize();
@ -90,6 +103,8 @@
this._setupEvents(); this._setupEvents();
// trigger URL change event handlers // trigger URL change event handlers
this._onPopState(urlParams); this._onPopState(urlParams);
this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200);
}, },
/** /**
@ -143,6 +158,14 @@
return this.navigation.getActiveItem(); return this.navigation.getActiveItem();
}, },
/**
*
* @returns {Backbone.Model}
*/
getFilesConfig: function() {
return this._filesConfig;
},
/** /**
* Setup events based on URL changes * Setup events based on URL changes
*/ */
@ -154,6 +177,30 @@
$('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this)); $('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this));
$('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this)); $('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this));
this.$showHiddenFiles.on('change', _.bind(this._onShowHiddenFilesChange, this));
},
/**
* Toggle showing hidden files according to the settings checkbox
*
* @returns {undefined}
*/
_onShowHiddenFilesChange: function() {
var show = this.$showHiddenFiles.is(':checked');
this._filesConfig.set('showhidden', show);
this._debouncedPersistShowHiddenFilesState();
},
/**
* Persist show hidden preference on ther server
*
* @returns {undefined}
*/
_persistShowHiddenFilesState: function() {
var show = this._filesConfig.get('showhidden');
$.post(OC.generateUrl('/apps/files/api/v1/showhidden'), {
show: show
});
}, },
/** /**

View File

@ -144,6 +144,11 @@
*/ */
_filter: '', _filter: '',
/**
* @type Backbone.Model
*/
_filesConfig: null,
/** /**
* Sort attribute * Sort attribute
* @type String * @type String
@ -198,6 +203,15 @@
return; return;
} }
if (options.config) {
this._filesConfig = options.config;
} else {
this._filesConfig = OCA.Files.App.getFilesConfig();
}
this._filesConfig.on('change:showhidden', function() {
self.setFiles(self.files);
});
if (options.dragOptions) { if (options.dragOptions) {
this._dragOptions = options.dragOptions; this._dragOptions = options.dragOptions;
} }
@ -847,6 +861,10 @@
* @return array of DOM elements of the newly added files * @return array of DOM elements of the newly added files
*/ */
_nextPage: function(animate) { _nextPage: function(animate) {
// Save full files list while rendering
var allFiles = this.files;
this.files = this._filterHiddenFiles(this.files);
var index = this.$fileList.children().length, var index = this.$fileList.children().length,
count = this.pageSize(), count = this.pageSize(),
hidden, hidden,
@ -893,6 +911,10 @@
} }
}, 0); }, 0);
} }
// Restore full files list after rendering
this.files = allFiles;
return newTrs; return newTrs;
}, },
@ -930,24 +952,46 @@
// clear "Select all" checkbox // clear "Select all" checkbox
this.$el.find('.select-all').prop('checked', false); this.$el.find('.select-all').prop('checked', false);
// Save full files list while rendering
var allFiles = this.files;
this.files = this._filterHiddenFiles(this.files);
this.isEmpty = this.files.length === 0; this.isEmpty = this.files.length === 0;
this._nextPage(); this._nextPage();
this.updateEmptyContent(); this.updateEmptyContent();
this.fileSummary.calculate(filesArray); this.fileSummary.calculate(this.files);
this._selectedFiles = {}; this._selectedFiles = {};
this._selectionSummary.clear(); this._selectionSummary.clear();
this.updateSelectionSummary(); this.updateSelectionSummary();
$(window).scrollTop(0); $(window).scrollTop(0);
// Restore full files list after rendering
this.files = allFiles;
this.$fileList.trigger(jQuery.Event('updated')); this.$fileList.trigger(jQuery.Event('updated'));
_.defer(function() { _.defer(function() {
self.$el.closest('#app-content').trigger(jQuery.Event('apprendered')); self.$el.closest('#app-content').trigger(jQuery.Event('apprendered'));
}); });
}, },
/**
* Filter hidden files of the given filesArray (dot-files)
*
* @param filesArray files to be filtered
* @returns {array}
*/
_filterHiddenFiles: function(files) {
if (this._filesConfig.get('showhidden')) {
return files;
}
return _.filter(files, function(file) {
return file.name.indexOf('.') !== 0;
});
},
/** /**
* Returns the icon URL matching the given file info * Returns the icon URL matching the given file info
* *

View File

@ -16,9 +16,13 @@
</button> </button>
</div> </div>
<div id="app-settings-content"> <div id="app-settings-content">
<label for="webdavurl"><?php p($l->t('WebDAV'));?></label> <div id="files-setting-showhidden">
<input id="webdavurl" type="text" readonly="readonly" value="<?php p(\OCP\Util::linkToRemote('webdav')); ?>" /> <input class="checkbox" id="showhiddenfilesToggle" checked="checked" type="checkbox">
<em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank" rel="noreferrer">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em> <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(\OCP\Util::linkToRemote('webdav')); ?>" />
<em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank" rel="noreferrer">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em>
</div> </div>
</div> </div>
</div> </div>

View File

@ -20,4 +20,5 @@
<input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="<?php p($_['allowShareWithLink']) ?>" /> <input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="<?php p($_['allowShareWithLink']) ?>" />
<input type="hidden" name="defaultFileSorting" id="defaultFileSorting" value="<?php p($_['defaultFileSorting']) ?>" /> <input type="hidden" name="defaultFileSorting" id="defaultFileSorting" value="<?php p($_['defaultFileSorting']) ?>" />
<input type="hidden" name="defaultFileSortingDirection" id="defaultFileSortingDirection" value="<?php p($_['defaultFileSortingDirection']) ?>" /> <input type="hidden" name="defaultFileSortingDirection" id="defaultFileSortingDirection" value="<?php p($_['defaultFileSortingDirection']) ?>" />
<input type="hidden" name="showHiddenFiles" id="showHiddenFiles" value="<?php p($_['showHiddenFiles']); ?>" />
<?php endif; <?php endif;

View File

@ -155,11 +155,12 @@ class ViewControllerTest extends TestCase {
'owner' => 'MyName', 'owner' => 'MyName',
'ownerDisplayName' => 'MyDisplayName', 'ownerDisplayName' => 'MyDisplayName',
])); ]));
$this->config->expects($this->exactly(2)) $this->config->expects($this->exactly(3))
->method('getUserValue') ->method('getUserValue')
->will($this->returnValueMap([ ->will($this->returnValueMap([
[$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'], [$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'],
[$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'] [$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'],
[$this->user->getUID(), 'files', 'show_hidden', false, false],
])); ]));
$this->config $this->config
@ -244,6 +245,7 @@ class ViewControllerTest extends TestCase {
'isPublic' => false, 'isPublic' => false,
'defaultFileSorting' => 'name', 'defaultFileSorting' => 'name',
'defaultFileSortingDirection' => 'asc', 'defaultFileSortingDirection' => 'asc',
'showHiddenFiles' => false,
'mailNotificationEnabled' => 'no', 'mailNotificationEnabled' => 'no',
'mailPublicNotificationEnabled' => 'no', 'mailPublicNotificationEnabled' => 'no',
'allowShareWithLink' => 'yes', 'allowShareWithLink' => 'yes',

View File

@ -1,4 +1,5 @@
<?php <?php
/** /**
* @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Lukas Reschke <lukas@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com>
@ -382,4 +383,17 @@ class ApiControllerTest extends TestCase {
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
public function testShowHiddenFiles() {
$show = false;
$this->config->expects($this->once())
->method('setUserValue')
->with($this->user->getUID(), 'files', 'show_hidden', $show);
$expected = new Http\Response();
$actual = $this->apiController->showHiddenFiles($show);
$this->assertEquals($expected, $actual);
}
} }

View File

@ -33,7 +33,8 @@ OCA.Sharing.App = {
id: 'shares.self', id: 'shares.self',
scrollContainer: $('#app-content'), scrollContainer: $('#app-content'),
sharedWithUser: true, sharedWithUser: true,
fileActions: this._createFileActions() fileActions: this._createFileActions(),
config: OCA.Files.App.getFilesConfig()
} }
); );
@ -55,7 +56,8 @@ OCA.Sharing.App = {
id: 'shares.others', id: 'shares.others',
scrollContainer: $('#app-content'), scrollContainer: $('#app-content'),
sharedWithUser: false, sharedWithUser: false,
fileActions: this._createFileActions() fileActions: this._createFileActions(),
config: OCA.Files.App.getFilesConfig()
} }
); );
@ -77,7 +79,8 @@ OCA.Sharing.App = {
id: 'shares.link', id: 'shares.link',
scrollContainer: $('#app-content'), scrollContainer: $('#app-content'),
linksOnly: true, linksOnly: true,
fileActions: this._createFileActions() fileActions: this._createFileActions(),
config: OCA.Files.App.getFilesConfig()
} }
); );

View File

@ -29,7 +29,8 @@ OCA.Trashbin.App = {
scrollContainer: $('#app-content'), scrollContainer: $('#app-content'),
fileActions: this._createFileActions(), fileActions: this._createFileActions(),
detailsViewEnabled: false, detailsViewEnabled: false,
scrollTo: urlParams.scrollto scrollTo: urlParams.scrollto,
config: OCA.Files.App.getFilesConfig()
} }
); );
}, },

View File

@ -28,7 +28,8 @@
{ {
id: 'systemtags', id: 'systemtags',
scrollContainer: $('#app-content'), scrollContainer: $('#app-content'),
fileActions: this._createFileActions() fileActions: this._createFileActions(),
config: OCA.Files.App.getFilesConfig()
} }
); );