[Pkg-owncloud-commits] [owncloud] 12/172: Add sorting to files list, trashbin and public files

David Prévot taffit at moszumanska.debian.org
Sun May 18 20:09:34 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository owncloud.

commit 688f6162daeec724c537f9c283092f45b29b05f2
Author: Vincent Petry <pvince81 at owncloud.com>
Date:   Thu Apr 3 20:57:06 2014 +0200

    Add sorting to files list, trashbin and public files
---
 apps/files/ajax/list.php                |   5 +-
 apps/files/css/files.css                |  36 ++++++--
 apps/files/js/filelist.js               | 139 ++++++++++++++++++++++++----
 apps/files/lib/helper.php               |  55 ++++++++++-
 apps/files/templates/index.php          |  12 ++-
 apps/files/tests/js/filelistSpec.js     | 157 ++++++++++++++++++++++++++++++--
 apps/files_sharing/ajax/list.php        |   5 +-
 apps/files_trashbin/ajax/list.php       |   4 +-
 apps/files_trashbin/lib/helper.php      |  10 +-
 apps/files_trashbin/templates/index.php |  16 ++--
 10 files changed, 382 insertions(+), 57 deletions(-)

diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php
index 2d76b68..bae3628 100644
--- a/apps/files/ajax/list.php
+++ b/apps/files/ajax/list.php
@@ -17,8 +17,11 @@ $baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir=';
 
 $permissions = $dirInfo->getPermissions();
 
+$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
+$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;
+
 // make filelist
-$files = \OCA\Files\Helper::getFiles($dir);
+$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection);
 
 $data['directory'] = $dir;
 $data['files'] = \OCA\Files\Helper::formatFileInfos($files);
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 5330506..2aae73f 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -116,10 +116,29 @@ tr:hover span.extension {
 
 table tr.mouseOver td { background-color:#eee; }
 table th { height:24px; padding:0 8px; color:#999; }
-table th .name {
-	position: absolute;
-	left: 55px;
-	top: 15px;
+table th .columntitle {
+	display: inline-block;
+	padding: 15px;
+	width: 100%;
+	height: 50px;
+	box-sizing: border-box;
+	-moz-box-sizing: border-box;
+	vertical-align: middle;
+}
+table th .columntitle.name {
+	padding-left: 5px;
+	margin-left: 50px;
+	max-width: 300px;
+}
+/* hover effect on sortable column */
+table th a.columntitle:hover {
+	background-color: #F0F0F0;
+}
+table th .sort-indicator {
+	width: 10px;
+	height: 8px;
+	margin-left: 10px;
+	display: inline-block;
 }
 table th, table td { border-bottom:1px solid #ddd; text-align:left; font-weight:normal; }
 table td {
@@ -139,8 +158,11 @@ table th#headerName {
 }
 table th#headerSize, table td.filesize {
 	min-width: 48px;
-	padding: 0 16px;
 	text-align: right;
+	padding: 0;
+}
+table table td.filesize {
+	padding: 0 16px;
 }
 table th#headerDate, table td.date {
 	-moz-box-sizing: border-box;
@@ -197,10 +219,6 @@ table td.filename input.filename {
 table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
 table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; }
 
-#modified {
-	position: absolute;
-	top: 15px;
-}
 .modified {
 	position: relative;
 	padding-left: 8px;
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 40ec898..1c24ca4 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -11,6 +11,9 @@
 /* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */
 /* global dragOptions, folderDropOptions */
 window.FileList = {
+	SORT_INDICATOR_ASC_CLASS: 'icon-triangle-s',
+	SORT_INDICATOR_DESC_CLASS: 'icon-triangle-n',
+
 	appName: t('files', 'Files'),
 	isEmpty: true,
 	useUndo:true,
@@ -45,18 +48,19 @@ window.FileList = {
 	_selectionSummary: null,
 
 	/**
-	 * Compare two file info objects, sorting by
-	 * folders first, then by name.
+	 * Sort attribute
 	 */
-	_fileInfoCompare: function(fileInfo1, fileInfo2) {
-		if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
-			return -1;
-		}
-		if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
-			return 1;
-		}
-		return fileInfo1.name.localeCompare(fileInfo2.name);
-	},
+	_sort: 'name',
+
+	/**
+	 * Sort direction: 'asc' or 'desc'
+	 */
+	_sortDirection: 'asc',
+
+	/**
+	 * Sort comparator function for the current sort
+	 */
+	_sortComparator: null,
 
 	/**
 	 * Initialize the file list and its components
@@ -76,6 +80,10 @@ window.FileList = {
 
 		this.fileSummary = this._createSummary();
 
+		this._sort = 'name';
+		this._sortDirection = 'asc';
+		this._sortComparator = this.Comparators.name;
+
 		this.breadcrumb = new BreadCrumb({
 			onClick: this._onClickBreadCrumb,
 			onDrop: _.bind(this._onDropOnBreadCrumb, this),
@@ -86,6 +94,8 @@ window.FileList = {
 
 		$('#controls').prepend(this.breadcrumb.$el);
 
+		this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this));
+
 		$(window).resize(function() {
 			// TODO: debounce this ?
 			var width = $(this).width();
@@ -237,6 +247,27 @@ window.FileList = {
 	},
 
 	/**
+	 * Event handler when clicking on a table header
+	 */
+	_onClickHeader: function(e) {
+		var $target = $(e.target);
+		var sort;
+		if (!$target.is('a')) {
+			$target = $target.closest('a');
+		}
+		sort = $target.attr('data-sort');
+		if (sort) {
+			if (this._sort === sort) {
+				this.setSort(sort, (this._sortDirection === 'desc')?'asc':'desc');
+			}
+			else {
+				this.setSort(sort, 'asc');
+			}
+			this.reload();
+		}
+	},
+
+	/**
 	 * Event handler when clicking on a bread crumb
 	 */
 	_onClickBreadCrumb: function(e) {
@@ -723,6 +754,27 @@ window.FileList = {
 		this.breadcrumb.setDirectory(this.getCurrentDirectory());
 	},
 	/**
+	 * Sets the current sorting and refreshes the list
+	 *
+	 * @param sort sort attribute name
+	 * @param direction sort direction, one of "asc" or "desc"
+	 */
+	setSort: function(sort, direction) {
+		var comparator = this.Comparators[sort] || this.Comparators.name;
+		this._sort = sort;
+		this._sortDirection = (direction === 'desc')?'desc':'asc';
+		this._sortComparator = comparator;
+		if (direction === 'desc') {
+			this._sortComparator = function(fileInfo1, fileInfo2) {
+				return -comparator(fileInfo1, fileInfo2);
+			};
+		}
+		this.$el.find('thead th .sort-indicator')
+			.removeClass(this.SORT_INDICATOR_ASC_CLASS + ' ' + this.SORT_INDICATOR_DESC_CLASS);
+		this.$el.find('thead th.column-' + sort + ' .sort-indicator')
+			.addClass(direction === 'desc' ? this.SORT_INDICATOR_DESC_CLASS : this.SORT_INDICATOR_ASC_CLASS);
+	},
+	/**
 	 * @brief Reloads the file list using ajax call
 	 */
 	reload: function() {
@@ -733,7 +785,9 @@ window.FileList = {
 		FileList._reloadCall = $.ajax({
 			url: Files.getAjaxUrl('list'),
 			data: {
-				dir : $('#dir').val()
+				dir: $('#dir').val(),
+				sort: FileList._sort,
+				sortdirection: FileList._sortDirection
 			},
 			error: function(result) {
 				FileList.reloadCallback(result);
@@ -859,7 +913,7 @@ window.FileList = {
 	 */
 	_findInsertionIndex: function(fileData) {
 		var index = 0;
-		while (index < this.files.length && this._fileInfoCompare(fileData, this.files[index]) > 0) {
+		while (index < this.files.length && this._sortComparator(fileData, this.files[index]) > 0) {
 			index++;
 		}
 		return index;
@@ -1218,15 +1272,15 @@ window.FileList = {
 	updateSelectionSummary: function() {
 		var summary = this._selectionSummary.summary;
 		if (summary.totalFiles === 0 && summary.totalDirs === 0) {
-			$('#headerName span.name').text(t('files','Name'));
-			$('#headerSize').text(t('files','Size'));
-			$('#modified').text(t('files','Modified'));
+			$('#headerName a.name>span:first').text(t('files','Name'));
+			$('#headerSize a>span:first').text(t('files','Size'));
+			$('#modified a>span:first').text(t('files','Modified'));
 			$('table').removeClass('multiselect');
 			$('.selectedActions').addClass('hidden');
 		}
 		else {
 			$('.selectedActions').removeClass('hidden');
-			$('#headerSize').text(OC.Util.humanFileSize(summary.totalSize));
+			$('#headerSize a>span:first').text(OC.Util.humanFileSize(summary.totalSize));
 			var selection = '';
 			if (summary.totalDirs > 0) {
 				selection += n('files', '%n folder', '%n folders', summary.totalDirs);
@@ -1237,8 +1291,8 @@ window.FileList = {
 			if (summary.totalFiles > 0) {
 				selection += n('files', '%n file', '%n files', summary.totalFiles);
 			}
-			$('#headerName span.name').text(selection);
-			$('#modified').text('');
+			$('#headerName a.name>span:first').text(selection);
+			$('#modified a>span:first').text('');
 			$('table').addClass('multiselect');
 		}
 	},
@@ -1529,6 +1583,7 @@ $(document).ready(function() {
 			targetDir = parseCurrentDirFromUrl();
 		}
 		if (targetDir) {
+			FileList.setSort('name', 'asc');
 			FileList.changeDirectory(targetDir, false);
 		}
 	};
@@ -1542,3 +1597,49 @@ $(document).ready(function() {
 	}, 0);
 });
 
+/**
+ * Sort comparators.
+ */
+FileList.Comparators = {
+	/**
+	 * Compares two file infos by name, making directories appear
+	 * first.
+	 *
+	 * @param fileInfo1 file info
+	 * @param fileInfo2 file info
+	 * @return -1 if the first file must appear before the second one,
+	 * 0 if they are identify, 1 otherwise.
+	 */
+	name: function(fileInfo1, fileInfo2) {
+		if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
+			return -1;
+		}
+		if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
+			return 1;
+		}
+		return fileInfo1.name.localeCompare(fileInfo2.name);
+	},
+	/**
+	 * Compares two file infos by size.
+	 *
+	 * @param fileInfo1 file info
+	 * @param fileInfo2 file info
+	 * @return -1 if the first file must appear before the second one,
+	 * 0 if they are identify, 1 otherwise.
+	 */
+	size: function(fileInfo1, fileInfo2) {
+		return fileInfo1.size - fileInfo2.size;
+	},
+	/**
+	 * Compares two file infos by timestamp.
+	 *
+	 * @param fileInfo1 file info
+	 * @param fileInfo2 file info
+	 * @return -1 if the first file must appear before the second one,
+	 * 0 if they are identify, 1 otherwise.
+	 */
+	mtime: function(fileInfo1, fileInfo2) {
+		return fileInfo1.mtime - fileInfo2.mtime;
+	}
+};
+
diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php
index 0ae87d1..94c7658 100644
--- a/apps/files/lib/helper.php
+++ b/apps/files/lib/helper.php
@@ -70,6 +70,32 @@ class Helper
 	}
 
 	/**
+	 * Comparator function to sort files by date
+	 *
+	 * @param \OCP\Files\FileInfo $a file
+	 * @param \OCP\Files\FileInfo $b file
+	 * @return int -1 if $a must come before $b, 1 otherwise
+	 */
+	public static function mtimeCmp($a, $b) {
+		$aTime = $a->getMTime();
+		$bTime = $b->getMTime();
+		return $aTime - $bTime;
+	}
+
+	/**
+	 * Comparator function to sort files by size
+	 *
+	 * @param \OCP\Files\FileInfo $a file
+	 * @param \OCP\Files\FileInfo $b file
+	 * @return int -1 if $a must come before $b, 1 otherwise
+	 */
+	public static function sizeCmp($a, $b) {
+		$aSize = $a->getSize();
+		$bSize = $b->getSize();
+		return $aSize - $bSize;
+	}
+
+	/**
 	 * Formats the file info to be returned as JSON to the client.
 	 *
 	 * @param \OCP\Files\FileInfo $i
@@ -120,12 +146,35 @@ class Helper
 	 * returns it as a sorted array of FileInfo.
 	 *
 	 * @param string $dir path to the directory
+	 * @param string $sortAttribute attribute to sort on
+	 * @param bool $sortDescending true for descending sort, false otherwise
 	 * @return \OCP\Files\FileInfo[] files
 	 */
-	public static function getFiles($dir) {
+	public static function getFiles($dir, $sortAttribute = 'name', $sortDescending = false) {
 		$content = \OC\Files\Filesystem::getDirectoryContent($dir);
 
-		usort($content, array('\OCA\Files\Helper', 'fileCmp'));
-		return $content;
+		return self::sortFiles($content, $sortAttribute, $sortDescending);
+	}
+
+	/**
+	 * Sort the given file info array
+	 *
+	 * @param \OCP\Files\FileInfo[] files to sort
+	 * @param string $sortAttribute attribute to sort on
+	 * @param bool $sortDescending true for descending sort, false otherwise
+	 * @return \OCP\Files\FileInfo[] sorted files
+	 */
+	public static function sortFiles($files, $sortAttribute = 'name', $sortDescending = false) {
+		$sortFunc = 'fileCmp';
+		if ($sortAttribute === 'mtime') {
+			$sortFunc = 'mtimeCmp';
+		} else if ($sortAttribute === 'size') {
+			$sortFunc = 'sizeCmp';
+		}
+		usort($files, array('\OCA\Files\Helper', $sortFunc));
+		if ($sortDescending) {
+			$files = array_reverse($files);
+		}
+		return $files;
 	}
 }
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index 42263c8..822aee0 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -60,11 +60,11 @@
 <table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="36" data-preview-y="36">
 	<thead>
 		<tr>
-			<th class="hidden" id='headerName'>
+			<th id='headerName' class="hidden column-name">
 				<div id="headerName-container">
 					<input type="checkbox" id="select_all" />
 					<label for="select_all"></label>
-					<span class="name"><?php p($l->t( 'Name' )); ?></span>
+					<a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a>
 					<span id="selectedActionsList" class="selectedActions">
 						<?php if($_['allowZipDownload']) : ?>
 							<a href="" class="download">
@@ -76,9 +76,11 @@
 					</span>
 				</div>
 			</th>
-			<th class="hidden" id="headerSize"><?php p($l->t('Size')); ?></th>
-			<th class="hidden" id="headerDate">
-				<span id="modified"><?php p($l->t( 'Modified' )); ?></span>
+			<th id="headerSize" class="hidden column-size">
+				<a class="size sort columntitle" data-sort="size"><span><?php p($l->t('Size')); ?></span><span class="sort-indicator"></span></a>
+			</th>
+			<th id="headerDate" class="hidden column-mtime">
+				<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Modified' )); ?></span><span class="sort-indicator"></span></a>
 				<?php if ($_['permissions'] & OCP\PERMISSION_DELETE): ?>
 					<span class="selectedActions"><a href="" class="delete-selected">
 						<?php p($l->t('Delete'))?>
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index eab3646..0c56e79 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -77,13 +77,17 @@ describe('FileList tests', function() {
 			// dummy table
 			// TODO: at some point this will be rendered by the FileList class itself!
 			'<table id="filestable">' +
-			'<thead><tr><th id="headerName" class="hidden">' +
+			'<thead><tr>' +
+			'<th id="headerName" class="hidden column-name">' +
 			'<input type="checkbox" id="select_all">' +
-			'<span class="name">Name</span>' +
+			'<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' +
 			'<span class="selectedActions hidden">' +
 			'<a href class="download">Download</a>' +
 			'<a href class="delete-selected">Delete</a></span>' +
-			'</th></tr></thead>' +
+			'</th>' +
+			'<th class="hidden column-size"><a class="columntitle" data-sort="size"><span class="sort-indicator"></span></a></th>' +
+			'<th class="hidden column-mtime"><a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a></th>' +
+			'</tr></thead>' +
 		   	'<tbody id="fileList"></tbody>' +
 			'<tfoot></tfoot>' +
 			'</table>' +
@@ -926,7 +930,7 @@ describe('FileList tests', function() {
 			expect(fakeServer.requests.length).toEqual(1);
 			var url = fakeServer.requests[0].url;
 			var query = url.substr(url.indexOf('?') + 1);
-			expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir'});
+			expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir', sort: 'name', sortdirection: 'asc'});
 			fakeServer.respond();
 			expect($('#fileList tr').length).toEqual(4);
 			expect(FileList.findFileEl('One.txt').length).toEqual(1);
@@ -937,7 +941,7 @@ describe('FileList tests', function() {
 			expect(fakeServer.requests.length).toEqual(1);
 			var url = fakeServer.requests[0].url;
 			var query = url.substr(url.indexOf('?') + 1);
-			expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir'});
+			expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir', sort: 'name', sortdirection: 'asc'});
 			fakeServer.respond();
 		});
 		it('switches to root dir when current directory does not exist', function() {
@@ -1246,7 +1250,7 @@ describe('FileList tests', function() {
 			expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(42);
 		});
 		it('Selecting files updates selection summary', function() {
-			var $summary = $('#headerName span.name');
+			var $summary = $('#headerName a.name>span:first');
 			expect($summary.text()).toEqual('Name');
 			FileList.findFileEl('One.txt').find('input:checkbox').click();
 			FileList.findFileEl('Three.pdf').find('input:checkbox').click();
@@ -1254,7 +1258,7 @@ describe('FileList tests', function() {
 			expect($summary.text()).toEqual('1 folder & 2 files');
 		});
 		it('Unselecting files hides selection summary', function() {
-			var $summary = $('#headerName span.name');
+			var $summary = $('#headerName a.name>span:first');
 			FileList.findFileEl('One.txt').find('input:checkbox').click().click();
 			expect($summary.text()).toEqual('Name');
 		});
@@ -1418,4 +1422,143 @@ describe('FileList tests', function() {
 			});
 		});
 	});
+	describe('Sorting files', function() {
+		it('Sorts by name by default', function() {
+			FileList.reload();
+			expect(fakeServer.requests.length).toEqual(1);
+			var url = fakeServer.requests[0].url;
+			var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1));
+			expect(query.sort).toEqual('name');
+			expect(query.sortdirection).toEqual('asc');
+		});
+		it('Reloads file list with a different sort when clicking on column header of unsorted column', function() {
+			FileList.$el.find('.column-size .columntitle').click();
+			expect(fakeServer.requests.length).toEqual(1);
+			var url = fakeServer.requests[0].url;
+			var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1));
+			expect(query.sort).toEqual('size');
+			expect(query.sortdirection).toEqual('asc');
+		});
+		it('Toggles sort direction when clicking on already sorted column', function() {
+			FileList.$el.find('.column-name .columntitle').click();
+			expect(fakeServer.requests.length).toEqual(1);
+			var url = fakeServer.requests[0].url;
+			var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1));
+			expect(query.sort).toEqual('name');
+			expect(query.sortdirection).toEqual('desc');
+		});
+		it('Toggles the sort indicator when clicking on a column header', function() {
+			var ASC_CLASS = FileList.SORT_INDICATOR_ASC_CLASS;
+			var DESC_CLASS = FileList.SORT_INDICATOR_DESC_CLASS;
+			FileList.$el.find('.column-size .columntitle').click();
+			// moves triangle to size column
+			expect(
+				FileList.$el.find('.column-name .sort-indicator').hasClass(ASC_CLASS + ' ' + DESC_CLASS)
+			).toEqual(false);
+			expect(
+				FileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS)
+			).toEqual(true);
+
+			// click again on size column, reverses direction
+			FileList.$el.find('.column-size .columntitle').click();
+			expect(
+				FileList.$el.find('.column-size .sort-indicator').hasClass(DESC_CLASS)
+			).toEqual(true);
+
+			// click again on size column, reverses direction
+			FileList.$el.find('.column-size .columntitle').click();
+			expect(
+				FileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS)
+			).toEqual(true);
+
+			// click on mtime column, moves indicator there
+			FileList.$el.find('.column-mtime .columntitle').click();
+			expect(
+				FileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS + ' ' + DESC_CLASS)
+			).toEqual(false);
+			expect(
+				FileList.$el.find('.column-mtime .sort-indicator').hasClass(ASC_CLASS)
+			).toEqual(true);
+		});
+		it('Uses correct sort comparator when inserting files', function() {
+			testFiles.sort(FileList.Comparators.size);
+			// this will make it reload the testFiles with the correct sorting
+			FileList.$el.find('.column-size .columntitle').click();
+			expect(fakeServer.requests.length).toEqual(1);
+			fakeServer.requests[0].respond(
+				200,
+				{ 'Content-Type': 'application/json' },
+				JSON.stringify({
+					status: 'success',
+					data: {
+						files: testFiles,
+						permissions: 31
+					}
+				})
+			);
+			var newFileData = {
+				id: 999,
+				type: 'file',
+				name: 'new file.txt',
+				mimetype: 'text/plain',
+				size: 40001,
+				etag: '999'
+			};
+			FileList.add(newFileData);
+			expect(FileList.files.length).toEqual(5);
+			expect(FileList.$fileList.find('tr').length).toEqual(5);
+			expect(FileList.findFileEl('One.txt').index()).toEqual(0);
+			expect(FileList.findFileEl('somedir').index()).toEqual(1);
+			expect(FileList.findFileEl('Two.jpg').index()).toEqual(2);
+			expect(FileList.findFileEl('new file.txt').index()).toEqual(3);
+			expect(FileList.findFileEl('Three.pdf').index()).toEqual(4);
+		});
+		it('Uses correct reversed sort comparator when inserting files', function() {
+			testFiles.sort(FileList.Comparators.size);
+			testFiles.reverse();
+			// this will make it reload the testFiles with the correct sorting
+			FileList.$el.find('.column-size .columntitle').click();
+			expect(fakeServer.requests.length).toEqual(1);
+			fakeServer.requests[0].respond(
+				200,
+				{ 'Content-Type': 'application/json' },
+				JSON.stringify({
+					status: 'success',
+					data: {
+						files: testFiles,
+						permissions: 31
+					}
+				})
+			);
+			// reverse sort
+			FileList.$el.find('.column-size .columntitle').click();
+			fakeServer.requests[1].respond(
+				200,
+				{ 'Content-Type': 'application/json' },
+				JSON.stringify({
+					status: 'success',
+					data: {
+						files: testFiles,
+						permissions: 31
+					}
+				})
+			);
+			var newFileData = {
+				id: 999,
+				type: 'file',
+				name: 'new file.txt',
+				mimetype: 'text/plain',
+				size: 40001,
+				etag: '999'
+			};
+			FileList.add(newFileData);
+			expect(FileList.files.length).toEqual(5);
+			expect(FileList.$fileList.find('tr').length).toEqual(5);
+			expect(FileList.findFileEl('One.txt').index()).toEqual(4);
+			expect(FileList.findFileEl('somedir').index()).toEqual(3);
+			expect(FileList.findFileEl('Two.jpg').index()).toEqual(2);
+			expect(FileList.findFileEl('new file.txt').index()).toEqual(1);
+			expect(FileList.findFileEl('Three.pdf').index()).toEqual(0);
+		});
+	});
 });
diff --git a/apps/files_sharing/ajax/list.php b/apps/files_sharing/ajax/list.php
index 4b64549..36deb58 100644
--- a/apps/files_sharing/ajax/list.php
+++ b/apps/files_sharing/ajax/list.php
@@ -47,6 +47,9 @@ if (isset($_GET['dir'])) {
 	$relativePath = $_GET['dir'];
 }
 
+$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
+$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;
+
 $data = \OCA\Files_Sharing\Helper::setupFromToken($token, $relativePath, $password);
 
 $linkItem = $data['linkItem'];
@@ -64,7 +67,7 @@ $data = array();
 $baseUrl = OCP\Util::linkTo('files_sharing', 'index.php') . '?t=' . urlencode($token) . '&dir=';
 
 // make filelist
-$files = \OCA\Files\Helper::getFiles($dir);
+$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection);
 
 $formattedFiles = array();
 foreach ($files as $file) {
diff --git a/apps/files_trashbin/ajax/list.php b/apps/files_trashbin/ajax/list.php
index 89a5511..e1f52e8 100644
--- a/apps/files_trashbin/ajax/list.php
+++ b/apps/files_trashbin/ajax/list.php
@@ -4,11 +4,13 @@ OCP\JSON::checkLoggedIn();
 
 // Load the files
 $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
+$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
+$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;
 $data = array();
 
 // make filelist
 try {
-	$files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir);
+	$files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir, $sortAttribute, $sortDirection);
 } catch (Exception $e) {
 	header("HTTP/1.0 404 Not Found");
 	exit();
diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php
index e6ca735..c98d575 100644
--- a/apps/files_trashbin/lib/helper.php
+++ b/apps/files_trashbin/lib/helper.php
@@ -8,11 +8,14 @@ class Helper
 {
 	/**
 	 * Retrieves the contents of a trash bin directory.
+	 *
 	 * @param string $dir path to the directory inside the trashbin
 	 * or empty to retrieve the root of the trashbin
+	 * @param string $sortAttribute attribute to sort on or empty to disable sorting
+	 * @param bool $sortDescending true for descending sort, false otherwise
 	 * @return \OCP\Files\FileInfo[]
 	 */
-	public static function getTrashFiles($dir){
+	public static function getTrashFiles($dir, $sortAttribute = '', $sortDescending = false){
 		$result = array();
 		$timestamp = null;
 		$user = \OCP\User::getUser();
@@ -57,8 +60,9 @@ class Helper
 			closedir($dirContent);
 		}
 
-		usort($result, array('\OCA\Files\Helper', 'fileCmp'));
-
+		if ($sortAttribute !== '') {
+			return \OCA\Files\Helper::sortFiles($result, $sortAttribute, $sortDescending);
+		}
 		return $result;
 	}
 
diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php
index 323e749..ccfcab6 100644
--- a/apps/files_trashbin/templates/index.php
+++ b/apps/files_trashbin/templates/index.php
@@ -12,22 +12,22 @@
 <table id="filestable">
 	<thead>
 		<tr>
-			<th id='headerName'>
+			<th id='headerName' class="hidden column-name">
 				<div id="headerName-container">
-				<input type="checkbox" id="select_all" />
-				<label for="select_all"></label>
-				<span class='name'><?php p($l->t( 'Name' )); ?></span>
-				<span class='selectedActions'>
+					<input type="checkbox" id="select_all" />
+					<label for="select_all"></label>
+					<a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a>
+					<span id="selectedActionsList" class='selectedActions'>
 						<a href="" class="undelete">
 							<img class="svg" alt="<?php p($l->t( 'Restore' )); ?>"
 								 src="<?php print_unescaped(OCP\image_path("core", "actions/history.svg")); ?>" />
 							<?php p($l->t('Restore'))?>
 						</a>
-				</span>
+					</span>
 				</div>
 			</th>
-			<th id="headerDate">
-				<span id="modified"><?php p($l->t( 'Deleted' )); ?></span>
+			<th id="headerDate" class="hidden column-mtime">
+				<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Deleted' )); ?></span><span class="sort-indicator"></span></a>
 				<span class="selectedActions">
 					<a href="" class="delete-selected">
 						<?php p($l->t('Delete'))?>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git



More information about the Pkg-owncloud-commits mailing list