summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2016-04-12 17:10:09 +0200
committerChristoph Wurst <christoph@owncloud.com>2016-04-19 16:08:56 +0200
commit6c5696d3a84ff71fc5ddb53b490bbc77f5c119f5 (patch)
tree03aec364e0e7f342ab822b2896c8dde6c40ea480
parentf8c55beaae9dc0e5fefb4aa8f78d3d71ea580d59 (diff)
downloadnextcloud-server-6c5696d3a84ff71fc5ddb53b490bbc77f5c119f5.tar.gz
nextcloud-server-6c5696d3a84ff71fc5ddb53b490bbc77f5c119f5.zip
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
-rw-r--r--apps/files/appinfo/routes.php5
-rw-r--r--apps/files/controller/apicontroller.php12
-rw-r--r--apps/files/controller/viewcontroller.php3
-rw-r--r--apps/files/css/files.css5
-rw-r--r--apps/files/js/app.js51
-rw-r--r--apps/files/js/filelist.js46
-rw-r--r--apps/files/templates/appnavigation.php10
-rw-r--r--apps/files/templates/index.php1
-rw-r--r--apps/files/tests/controller/ViewControllerTest.php6
-rw-r--r--apps/files/tests/controller/apicontrollertest.php14
-rw-r--r--apps/files_sharing/js/app.js9
-rw-r--r--apps/files_trashbin/js/app.js3
-rw-r--r--apps/systemtags/js/app.js3
13 files changed, 155 insertions, 13 deletions
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index 6ad938101a2..2291b48e3c5 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -54,6 +54,11 @@ $application->registerRoutes(
'url' => '/api/v1/sorting',
'verb' => 'POST'
),
+ array(
+ 'name' => 'API#showHiddenFiles',
+ 'url' => '/api/v1/showhidden',
+ 'verb' => 'POST'
+ ),
[
'name' => 'view#index',
'url' => '/',
diff --git a/apps/files/controller/apicontroller.php b/apps/files/controller/apicontroller.php
index 43d426476fe..072498c7b5f 100644
--- a/apps/files/controller/apicontroller.php
+++ b/apps/files/controller/apicontroller.php
@@ -224,4 +224,16 @@ class ApiController extends Controller {
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();
+ }
+
}
diff --git a/apps/files/controller/viewcontroller.php b/apps/files/controller/viewcontroller.php
index 6c5f4c6d2a0..9fe34521332 100644
--- a/apps/files/controller/viewcontroller.php
+++ b/apps/files/controller/viewcontroller.php
@@ -67,6 +67,7 @@ class ViewController extends Controller {
* @param IL10N $l10n
* @param IConfig $config
* @param EventDispatcherInterface $eventDispatcherInterface
+ * @param IUserSession $userSession
*/
public function __construct($appName,
IRequest $request,
@@ -222,6 +223,8 @@ class ViewController extends Controller {
$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);
+ $params['showHiddenFiles'] = $showHidden ? 1 : 0;
$params['appNavigation'] = $nav;
$params['appContents'] = $contentItems;
$this->navigationManager->setActiveEntry('files_index');
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index d20ab102ba5..373739071e9 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -2,6 +2,11 @@
This file is licensed under the Affero General Public License version 3 or later.
See the COPYING-README file. */
+/* SETTINGS */
+#files-setting-showhidden {
+ padding-bottom: 8px;
+}
+
/* FILE MENU */
.actions { padding:5px; height:32px; display: inline-block; float: left; }
.actions input, .actions button, .actions .button { margin:0; float:left; }
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index 4ed805d2681..eac080a009d 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -11,7 +11,7 @@
*
*/
-/* global dragOptions, folderDropOptions */
+/* global dragOptions, folderDropOptions, OC */
(function() {
if (!OCA.Files) {
@@ -41,10 +41,22 @@
fileList: null,
/**
+ * Backbone model for storing files preferences
+ */
+ _filesConfig: null,
+
+ /**
* Initializes the files app
*/
initialize: function() {
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 fileActions = new OCA.Files.FileActions();
@@ -76,7 +88,8 @@
sorting: {
mode: $('#defaultFileSorting').val(),
direction: $('#defaultFileSortingDirection').val()
- }
+ },
+ config: this._filesConfig,
}
);
this.files.initialize();
@@ -90,6 +103,8 @@
this._setupEvents();
// trigger URL change event handlers
this._onPopState(urlParams);
+
+ this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200);
},
/**
@@ -144,6 +159,14 @@
},
/**
+ *
+ * @returns {Backbone.Model}
+ */
+ getFilesConfig: function() {
+ return this._filesConfig;
+ },
+
+ /**
* Setup events based on URL changes
*/
_setupEvents: function() {
@@ -154,6 +177,30 @@
$('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, 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
+ });
},
/**
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 7de64f8ade3..79dc42da8f1 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -145,6 +145,11 @@
_filter: '',
/**
+ * @type Backbone.Model
+ */
+ _filesConfig: null,
+
+ /**
* Sort attribute
* @type String
*/
@@ -198,6 +203,15 @@
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) {
this._dragOptions = options.dragOptions;
}
@@ -847,6 +861,10 @@
* @return array of DOM elements of the newly added files
*/
_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,
count = this.pageSize(),
hidden,
@@ -893,6 +911,10 @@
}
}, 0);
}
+
+ // Restore full files list after rendering
+ this.files = allFiles;
+
return newTrs;
},
@@ -930,18 +952,25 @@
// clear "Select all" checkbox
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._nextPage();
this.updateEmptyContent();
- this.fileSummary.calculate(filesArray);
+ this.fileSummary.calculate(this.files);
this._selectedFiles = {};
this._selectionSummary.clear();
this.updateSelectionSummary();
$(window).scrollTop(0);
+ // Restore full files list after rendering
+ this.files = allFiles;
+
this.$fileList.trigger(jQuery.Event('updated'));
_.defer(function() {
self.$el.closest('#app-content').trigger(jQuery.Event('apprendered'));
@@ -949,6 +978,21 @@
},
/**
+ * 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
*
* @param {OC.Files.FileInfo} fileInfo file info
diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php
index 39a5875f3d0..9c79f806713 100644
--- a/apps/files/templates/appnavigation.php
+++ b/apps/files/templates/appnavigation.php
@@ -16,9 +16,13 @@
</button>
</div>
<div id="app-settings-content">
- <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 id="files-setting-showhidden">
+ <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(\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>
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index db464ad2eca..7281edd3aec 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -20,4 +20,5 @@
<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="defaultFileSortingDirection" id="defaultFileSortingDirection" value="<?php p($_['defaultFileSortingDirection']) ?>" />
+<input type="hidden" name="showHiddenFiles" id="showHiddenFiles" value="<?php p($_['showHiddenFiles']); ?>" />
<?php endif;
diff --git a/apps/files/tests/controller/ViewControllerTest.php b/apps/files/tests/controller/ViewControllerTest.php
index 0446cc8982c..420e635b4b9 100644
--- a/apps/files/tests/controller/ViewControllerTest.php
+++ b/apps/files/tests/controller/ViewControllerTest.php
@@ -155,11 +155,12 @@ class ViewControllerTest extends TestCase {
'owner' => 'MyName',
'ownerDisplayName' => 'MyDisplayName',
]));
- $this->config->expects($this->exactly(2))
+ $this->config->expects($this->exactly(3))
->method('getUserValue')
->will($this->returnValueMap([
[$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
@@ -244,6 +245,7 @@ class ViewControllerTest extends TestCase {
'isPublic' => false,
'defaultFileSorting' => 'name',
'defaultFileSortingDirection' => 'asc',
+ 'showHiddenFiles' => false,
'mailNotificationEnabled' => 'no',
'mailPublicNotificationEnabled' => 'no',
'allowShareWithLink' => 'yes',
diff --git a/apps/files/tests/controller/apicontrollertest.php b/apps/files/tests/controller/apicontrollertest.php
index 59f53e8ee81..2eba7d62feb 100644
--- a/apps/files/tests/controller/apicontrollertest.php
+++ b/apps/files/tests/controller/apicontrollertest.php
@@ -1,4 +1,5 @@
<?php
+
/**
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Lukas Reschke <lukas@owncloud.com>
@@ -382,4 +383,17 @@ class ApiControllerTest extends TestCase {
$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);
+ }
+
}
diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js
index af198208de2..6f12b3d4456 100644
--- a/apps/files_sharing/js/app.js
+++ b/apps/files_sharing/js/app.js
@@ -33,7 +33,8 @@ OCA.Sharing.App = {
id: 'shares.self',
scrollContainer: $('#app-content'),
sharedWithUser: true,
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);
@@ -55,7 +56,8 @@ OCA.Sharing.App = {
id: 'shares.others',
scrollContainer: $('#app-content'),
sharedWithUser: false,
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);
@@ -77,7 +79,8 @@ OCA.Sharing.App = {
id: 'shares.link',
scrollContainer: $('#app-content'),
linksOnly: true,
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);
diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js
index 771ea90bc16..fd3d5db32ff 100644
--- a/apps/files_trashbin/js/app.js
+++ b/apps/files_trashbin/js/app.js
@@ -29,7 +29,8 @@ OCA.Trashbin.App = {
scrollContainer: $('#app-content'),
fileActions: this._createFileActions(),
detailsViewEnabled: false,
- scrollTo: urlParams.scrollto
+ scrollTo: urlParams.scrollto,
+ config: OCA.Files.App.getFilesConfig()
}
);
},
diff --git a/apps/systemtags/js/app.js b/apps/systemtags/js/app.js
index d28514358c1..e027c0be123 100644
--- a/apps/systemtags/js/app.js
+++ b/apps/systemtags/js/app.js
@@ -28,7 +28,8 @@
{
id: 'systemtags',
scrollContainer: $('#app-content'),
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);