Browse Source
			
			
			Merge pull request #8417 from owncloud/share-overview
			
				
		Merge pull request #8417 from owncloud/share-overview
	
		
	
			
				Sharing overview pageremotes/origin/ldap_group_count
				 27 changed files with 1494 additions and 162 deletions
			
			
		- 
					8apps/files/css/files.css
- 
					5apps/files/index.php
- 
					35apps/files/js/app.js
- 
					101apps/files/js/fileactions.js
- 
					60apps/files/js/filelist.js
- 
					53apps/files/tests/js/appSpec.js
- 
					80apps/files/tests/js/fileactionsSpec.js
- 
					47apps/files/tests/js/filelistSpec.js
- 
					20apps/files_sharing/appinfo/app.php
- 
					3apps/files_sharing/css/sharedfilelist.css
- 
					106apps/files_sharing/js/app.js
- 
					23apps/files_sharing/js/public.js
- 
					50apps/files_sharing/js/share.js
- 
					235apps/files_sharing/js/sharedfilelist.js
- 
					38apps/files_sharing/lib/api.php
- 
					11apps/files_sharing/list.php
- 
					28apps/files_sharing/templates/list.php
- 
					143apps/files_sharing/tests/js/appSpec.js
- 
					412apps/files_sharing/tests/js/sharedfilelistSpec.js
- 
					2apps/files_trashbin/appinfo/app.php
- 
					24apps/files_trashbin/js/app.js
- 
					4apps/files_trashbin/js/filelist.js
- 
					11apps/files_trashbin/tests/js/filelistSpec.js
- 
					37apps/files_versions/js/versions.js
- 
					13core/js/js.js
- 
					64core/js/share.js
- 
					43tests/karma.config.js
| @ -0,0 +1,3 @@ | |||
| #filestable.shareList .summary .filesize { | |||
| 	display: none; | |||
| } | |||
| @ -0,0 +1,106 @@ | |||
| /* | |||
|  * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> | |||
|  * | |||
|  * This file is licensed under the Affero General Public License version 3 | |||
|  * or later. | |||
|  * | |||
|  * See the COPYING-README file. | |||
|  * | |||
|  */ | |||
| 
 | |||
| OCA.Sharing = {}; | |||
| OCA.Sharing.App = { | |||
| 
 | |||
| 	_inFileList: null, | |||
| 	_outFileList: null, | |||
| 
 | |||
| 	initSharingIn: function($el) { | |||
| 		if (this._inFileList) { | |||
| 			return this._inFileList; | |||
| 		} | |||
| 
 | |||
| 		this._inFileList = new OCA.Sharing.FileList( | |||
| 			$el, | |||
| 			{ | |||
| 				scrollContainer: $('#app-content'), | |||
| 				sharedWithUser: true, | |||
| 				fileActions: this._createFileActions() | |||
| 			} | |||
| 		); | |||
| 
 | |||
| 		this._extendFileList(this._inFileList); | |||
| 		this._inFileList.appName = t('files_sharing', 'Shared with you'); | |||
| 		this._inFileList.$el.find('#emptycontent').text(t('files_sharing', 'No files have been shared with you yet.')); | |||
| 		return this._inFileList; | |||
| 	}, | |||
| 
 | |||
| 	initSharingOut: function($el) { | |||
| 		if (this._outFileList) { | |||
| 			return this._outFileList; | |||
| 		} | |||
| 		this._outFileList = new OCA.Sharing.FileList( | |||
| 			$el, | |||
| 			{ | |||
| 				scrollContainer: $('#app-content'), | |||
| 				sharedWithUser: false, | |||
| 				fileActions: this._createFileActions() | |||
| 			} | |||
| 		); | |||
| 
 | |||
| 		this._extendFileList(this._outFileList); | |||
| 		this._outFileList.appName = t('files_sharing', 'Shared with others'); | |||
| 		this._outFileList.$el.find('#emptycontent').text(t('files_sharing', 'You haven\'t shared any files yet.')); | |||
| 		return this._outFileList; | |||
| 	}, | |||
| 
 | |||
| 	removeSharingIn: function() { | |||
| 		if (this._inFileList) { | |||
| 			this._inFileList.$fileList.empty(); | |||
| 		} | |||
| 	}, | |||
| 
 | |||
| 	removeSharingOut: function() { | |||
| 		if (this._outFileList) { | |||
| 			this._outFileList.$fileList.empty(); | |||
| 		} | |||
| 	}, | |||
| 
 | |||
| 	_createFileActions: function() { | |||
| 		// inherit file actions from the files app
 | |||
| 		var fileActions = new OCA.Files.FileActions(); | |||
| 		// note: not merging the legacy actions because legacy apps are not
 | |||
| 		// compatible with the sharing overview and need to be adapted first
 | |||
| 		fileActions.registerDefaultActions(); | |||
| 		fileActions.merge(OCA.Files.fileActions); | |||
| 
 | |||
| 		// when the user clicks on a folder, redirect to the corresponding
 | |||
| 		// folder in the files app instead of opening it directly
 | |||
| 		fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) { | |||
| 			OCA.Files.App.setActiveView('files', {silent: true}); | |||
| 			OCA.Files.App.fileList.changeDirectory(context.$file.attr('data-path') + '/' + filename, true, true); | |||
| 		}); | |||
| 		fileActions.setDefault('dir', 'Open'); | |||
| 		return fileActions; | |||
| 	}, | |||
| 
 | |||
| 	_extendFileList: function(fileList) { | |||
| 		// remove size column from summary
 | |||
| 		fileList.fileSummary.$el.find('.filesize').remove(); | |||
| 	} | |||
| }; | |||
| 
 | |||
| $(document).ready(function() { | |||
| 	$('#app-content-sharingin').on('show', function(e) { | |||
| 		OCA.Sharing.App.initSharingIn($(e.target)); | |||
| 	}); | |||
| 	$('#app-content-sharingin').on('hide', function() { | |||
| 		OCA.Sharing.App.removeSharingIn(); | |||
| 	}); | |||
| 	$('#app-content-sharingout').on('show', function(e) { | |||
| 		OCA.Sharing.App.initSharingOut($(e.target)); | |||
| 	}); | |||
| 	$('#app-content-sharingout').on('hide', function() { | |||
| 		OCA.Sharing.App.removeSharingOut(); | |||
| 	}); | |||
| }); | |||
| 
 | |||
| @ -0,0 +1,235 @@ | |||
| /* | |||
|  * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> | |||
|  * | |||
|  * This file is licensed under the Affero General Public License version 3 | |||
|  * or later. | |||
|  * | |||
|  * See the COPYING-README file. | |||
|  * | |||
|  */ | |||
| (function() { | |||
| 
 | |||
| 	/** | |||
| 	 * Sharing file list | |||
| 	 * | |||
| 	 * Contains both "shared with others" and "shared with you" modes. | |||
| 	 */ | |||
| 	var FileList = function($el, options) { | |||
| 		this.initialize($el, options); | |||
| 	}; | |||
| 
 | |||
| 	FileList.prototype = _.extend({}, OCA.Files.FileList.prototype, { | |||
| 		appName: 'Shares', | |||
| 
 | |||
| 		/** | |||
| 		 * Whether the list shows the files shared with the user (true) or | |||
| 		 * the files that the user shared with others (false). | |||
| 		 */ | |||
| 		_sharedWithUser: false, | |||
| 
 | |||
| 		initialize: function($el, options) { | |||
| 			OCA.Files.FileList.prototype.initialize.apply(this, arguments); | |||
| 			if (this.initialized) { | |||
| 				return; | |||
| 			} | |||
| 
 | |||
| 			if (options && options.sharedWithUser) { | |||
| 				this._sharedWithUser = true; | |||
| 			} | |||
| 		}, | |||
| 
 | |||
| 		_createRow: function(fileData) { | |||
| 			// TODO: hook earlier and render the whole row here
 | |||
| 			var $tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments); | |||
| 			$tr.find('.filesize').remove(); | |||
| 			$tr.find('td.date').before($tr.children('td:first')); | |||
| 			$tr.find('td.filename input:checkbox').remove(); | |||
| 			$tr.attr('data-share-id', _.pluck(fileData.shares, 'id').join(',')); | |||
| 			if (this._sharedWithUser) { | |||
| 				$tr.attr('data-share-owner', fileData.shares[0].ownerDisplayName); | |||
| 			} | |||
| 			return $tr; | |||
| 		}, | |||
| 
 | |||
| 		/** | |||
| 		 * Set whether the list should contain outgoing shares | |||
| 		 * or incoming shares. | |||
| 		 * | |||
| 		 * @param state true for incoming shares, false otherwise | |||
| 		 */ | |||
| 		setSharedWithUser: function(state) { | |||
| 			this._sharedWithUser = !!state; | |||
| 		}, | |||
| 
 | |||
| 		updateEmptyContent: function() { | |||
| 			var dir = this.getCurrentDirectory(); | |||
| 			if (dir === '/') { | |||
| 				// root has special permissions
 | |||
| 				this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); | |||
| 				this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); | |||
| 			} | |||
| 			else { | |||
| 				OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments); | |||
| 			} | |||
| 		}, | |||
| 
 | |||
| 		getDirectoryPermissions: function() { | |||
| 			return OC.PERMISSION_READ | OC.PERMISSION_DELETE; | |||
| 		}, | |||
| 
 | |||
| 		updateStorageStatistics: function() { | |||
| 			// no op because it doesn't have
 | |||
| 			// storage info like free space / used space
 | |||
| 		}, | |||
| 
 | |||
| 		reload: function() { | |||
| 			var self = this; | |||
| 			this.showMask(); | |||
| 			if (this._reloadCall) { | |||
| 				this._reloadCall.abort(); | |||
| 			} | |||
| 			this._reloadCall = $.ajax({ | |||
| 				url: OC.linkToOCS('apps/files_sharing/api/v1') + 'shares', | |||
| 				/* jshint camelcase: false */ | |||
| 				data: { | |||
| 					format: 'json', | |||
| 					shared_with_me: !!this._sharedWithUser | |||
| 				}, | |||
| 				type: 'GET', | |||
| 				beforeSend: function(xhr) { | |||
| 					xhr.setRequestHeader('OCS-APIREQUEST', 'true'); | |||
| 				}, | |||
| 				error: function(result) { | |||
| 					self.reloadCallback(result); | |||
| 				}, | |||
| 				success: function(result) { | |||
| 					self.reloadCallback(result); | |||
| 				} | |||
| 			}); | |||
| 		}, | |||
| 
 | |||
| 		reloadCallback: function(result) { | |||
| 			delete this._reloadCall; | |||
| 			this.hideMask(); | |||
| 
 | |||
| 			this.$el.find('#headerSharedWith').text( | |||
| 				t('files_sharing', this._sharedWithUser ? 'Shared by' : 'Shared with') | |||
| 			); | |||
| 			if (result.ocs && result.ocs.data) { | |||
| 				this.setFiles(this._makeFilesFromShares(result.ocs.data)); | |||
| 			} | |||
| 			else { | |||
| 				// TODO: error handling
 | |||
| 			} | |||
| 		}, | |||
| 
 | |||
| 		/** | |||
| 		 * Converts the OCS API share response data to a file info | |||
| 		 * list | |||
| 		 * @param OCS API share array | |||
| 		 * @return array of file info maps | |||
| 		 */ | |||
| 		_makeFilesFromShares: function(data) { | |||
| 			var self = this; | |||
| 			// OCS API uses non-camelcased names
 | |||
| 			var files = _.chain(data) | |||
| 				// convert share data to file data
 | |||
| 				.map(function(share) { | |||
| 					/* jshint camelcase: false */ | |||
| 					var file = { | |||
| 						id: share.file_source, | |||
| 						mimetype: share.mimetype | |||
| 					}; | |||
| 					if (share.item_type === 'folder') { | |||
| 						file.type = 'dir'; | |||
| 						file.mimetype = 'httpd/unix-directory'; | |||
| 					} | |||
| 					else { | |||
| 						file.type = 'file'; | |||
| 						// force preview retrieval as we don't have mime types,
 | |||
| 						// the preview endpoint will fall back to the mime type
 | |||
| 						// icon if no preview exists
 | |||
| 						file.isPreviewAvailable = true; | |||
| 						file.icon = true; | |||
| 					} | |||
| 					file.share = { | |||
| 						id: share.id, | |||
| 						type: share.share_type, | |||
| 						target: share.share_with, | |||
| 						stime: share.stime * 1000, | |||
| 					}; | |||
| 					if (self._sharedWithUser) { | |||
| 						file.share.ownerDisplayName = share.displayname_owner; | |||
| 						file.name = OC.basename(share.file_target); | |||
| 						file.path = OC.dirname(share.file_target); | |||
| 						file.permissions = share.permissions; | |||
| 					} | |||
| 					else { | |||
| 						file.share.targetDisplayName = share.share_with_displayname; | |||
| 						file.name = OC.basename(share.path); | |||
| 						file.path = OC.dirname(share.path); | |||
| 						file.permissions = OC.PERMISSION_ALL; | |||
| 					} | |||
| 					return file; | |||
| 				}) | |||
| 				// Group all files and have a "shares" array with
 | |||
| 				// the share info for each file.
 | |||
| 				//
 | |||
| 				// This uses a hash memo to cumulate share information
 | |||
| 				// inside the same file object (by file id).
 | |||
| 				.reduce(function(memo, file) { | |||
| 					var data = memo[file.id]; | |||
| 					var counterPart = file.share.ownerDisplayName || file.share.targetDisplayName; | |||
| 					if (!data) { | |||
| 						data = memo[file.id] = file; | |||
| 						data.shares = [file.share]; | |||
| 						// using a hash to make them unique,
 | |||
| 						// this is only a list to be displayed
 | |||
| 						data.counterParts = {}; | |||
| 						// counter is cheaper than calling _.keys().length
 | |||
| 						data.counterPartsCount = 0; | |||
| 						data.mtime = file.share.stime; | |||
| 					} | |||
| 					else { | |||
| 						// always take the most recent stime
 | |||
| 						if (file.share.stime > data.mtime) { | |||
| 							data.mtime = file.share.stime; | |||
| 						} | |||
| 						data.shares.push(file.share); | |||
| 					} | |||
| 
 | |||
| 					if (file.share.type === OC.Share.SHARE_TYPE_LINK) { | |||
| 						data.hasLinkShare = true; | |||
| 					} else if (counterPart && data.counterPartsCount < 10) { | |||
| 						// limit counterparts for output
 | |||
| 						data.counterParts[counterPart] = true; | |||
| 						data.counterPartsCount++; | |||
| 					} | |||
| 
 | |||
| 					delete file.share; | |||
| 					return memo; | |||
| 				}, {}) | |||
| 				// Retrieve only the values of the returned hash
 | |||
| 				.values() | |||
| 				// Clean up
 | |||
| 				.each(function(data) { | |||
| 					// convert the counterParts map to a flat
 | |||
| 					// array of sorted names
 | |||
| 					data.counterParts = _.chain(data.counterParts).keys().sort().value(); | |||
| 					if (data.hasLinkShare) { | |||
| 						data.counterParts.unshift(t('files_sharing', 'link')); | |||
| 						delete data.hasLinkShare; | |||
| 					} | |||
| 					delete data.counterPartsCount; | |||
| 				}) | |||
| 				// Sort by expected sort comparator
 | |||
| 				.sortBy(this._sortComparator) | |||
| 				// Finish the chain by getting the result
 | |||
| 				.value(); | |||
| 
 | |||
| 			return files; | |||
| 		} | |||
| 	}); | |||
| 
 | |||
| 	OCA.Sharing.FileList = FileList; | |||
| })(); | |||
| @ -0,0 +1,11 @@ | |||
| <?php | |||
| 
 | |||
| // Check if we are a user
 | |||
| OCP\User::checkLoggedIn(); | |||
| 
 | |||
| $tmpl = new OCP\Template('files_sharing', 'list', ''); | |||
| 
 | |||
| OCP\Util::addScript('files_sharing', 'app'); | |||
| OCP\Util::addScript('files_sharing', 'sharedfilelist'); | |||
| 
 | |||
| $tmpl->printPage(); | |||
| @ -0,0 +1,28 @@ | |||
| <?php /** @var $l OC_L10N */ ?>
 | |||
| <div id="controls"> | |||
| 	<div id="file_action_panel"></div> | |||
| </div> | |||
| <div id='notification'></div> | |||
| 
 | |||
| <div id="emptycontent" class="hidden"></div> | |||
| 
 | |||
| <input type="hidden" name="dir" value="" id="dir"> | |||
| 
 | |||
| <table id="filestable"> | |||
| 	<thead> | |||
| 		<tr> | |||
| 			<th id='headerName' class="hidden column-name"> | |||
| 				<div id="headerName-container"> | |||
| 					<a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a>
 | |||
| 				</div> | |||
| 			</th> | |||
| 			<th id="headerDate" class="hidden column-mtime"> | |||
| 				<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Share time' )); ?></span><span class="sort-indicator"></span></a>
 | |||
| 			</th> | |||
| 		</tr> | |||
| 	</thead> | |||
| 	<tbody id="fileList"> | |||
| 	</tbody> | |||
| 	<tfoot> | |||
| 	</tfoot> | |||
| </table> | |||
| @ -0,0 +1,143 @@ | |||
| /** | |||
| * ownCloud | |||
| * | |||
| * @author Vincent Petry | |||
| * @copyright 2014 Vincent Petry <pvince81@owncloud.com> | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE | |||
| * License as published by the Free Software Foundation; either | |||
| * version 3 of the License, or any later version. | |||
| * | |||
| * This library is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |||
| * GNU AFFERO GENERAL PUBLIC LICENSE for more details. | |||
| * | |||
| * You should have received a copy of the GNU Affero General Public | |||
| * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 | |||
| * | |||
| */ | |||
| 
 | |||
| describe('OCA.Sharing.App tests', function() { | |||
| 	var App = OCA.Sharing.App; | |||
| 	var fileListIn; | |||
| 	var fileListOut; | |||
| 
 | |||
| 	beforeEach(function() { | |||
| 		$('#testArea').append( | |||
| 			'<div id="app-navigation">' + | |||
| 			'<ul><li data-id="files"><a>Files</a></li>' + | |||
| 			'<li data-id="sharingin"><a></a></li>' + | |||
| 			'<li data-id="sharingout"><a></a></li>' + | |||
| 			'</ul></div>' + | |||
| 			'<div id="app-content">' + | |||
| 			'<div id="app-content-files" class="hidden">' + | |||
| 			'</div>' + | |||
| 			'<div id="app-content-sharingin" class="hidden">' + | |||
| 			'</div>' + | |||
| 			'<div id="app-content-sharingout" class="hidden">' + | |||
| 			'</div>' + | |||
| 			'</div>' + | |||
| 			'</div>' | |||
| 		); | |||
| 		fileListIn = App.initSharingIn($('#app-content-sharingin')); | |||
| 		fileListOut = App.initSharingOut($('#app-content-sharingout')); | |||
| 	}); | |||
| 	afterEach(function() { | |||
| 		App._inFileList = null; | |||
| 		App._outFileList = null; | |||
| 		fileListIn = null; | |||
| 		fileListOut = null; | |||
| 	}); | |||
| 
 | |||
| 	describe('initialization', function() { | |||
| 		it('inits sharing-in list on show', function() { | |||
| 			expect(fileListIn._sharedWithUser).toEqual(true);		 | |||
| 		}); | |||
| 		it('inits sharing-out list on show', function() { | |||
| 			expect(fileListOut._sharedWithUser).toBeFalsy(); | |||
| 		}); | |||
| 	}); | |||
| 	describe('file actions', function() { | |||
| 		it('provides default file actions', function() { | |||
| 			_.each([fileListIn, fileListOut], function(fileList) { | |||
| 				var fileActions = fileList.fileActions; | |||
| 
 | |||
| 				expect(fileActions.actions.all).toBeDefined(); | |||
| 				expect(fileActions.actions.all.Delete).toBeDefined(); | |||
| 				expect(fileActions.actions.all.Rename).toBeDefined(); | |||
| 				expect(fileActions.actions.file.Download).toBeDefined(); | |||
| 
 | |||
| 				expect(fileActions.defaults.dir).toEqual('Open'); | |||
| 			}); | |||
| 		}); | |||
| 		it('provides custom file actions', function() { | |||
| 			var actionStub = sinon.stub(); | |||
| 			// regular file action
 | |||
| 			OCA.Files.fileActions.register( | |||
| 					'all', | |||
| 					'RegularTest', | |||
| 					OC.PERMISSION_READ, | |||
| 					OC.imagePath('core', 'actions/shared'), | |||
| 					actionStub | |||
| 			); | |||
| 
 | |||
| 			App._inFileList = null; | |||
| 			fileListIn = App.initSharingIn($('#app-content-sharingin')); | |||
| 
 | |||
| 			expect(fileListIn.fileActions.actions.all.RegularTest).toBeDefined(); | |||
| 		}); | |||
| 		it('does not provide legacy file actions', function() { | |||
| 			var actionStub = sinon.stub(); | |||
| 			// legacy file action
 | |||
| 			window.FileActions.register( | |||
| 					'all', | |||
| 					'LegacyTest', | |||
| 					OC.PERMISSION_READ, | |||
| 					OC.imagePath('core', 'actions/shared'), | |||
| 					actionStub | |||
| 			); | |||
| 
 | |||
| 			App._inFileList = null; | |||
| 			fileListIn = App.initSharingIn($('#app-content-sharingin')); | |||
| 
 | |||
| 			expect(fileListIn.fileActions.actions.all.LegacyTest).not.toBeDefined(); | |||
| 		}); | |||
| 		it('redirects to files app when opening a directory', function() { | |||
| 			var oldList = OCA.Files.App.fileList; | |||
| 			// dummy new list to make sure it exists
 | |||
| 			OCA.Files.App.fileList = new OCA.Files.FileList($('<table><thead></thead><tbody></tbody></table>')); | |||
| 
 | |||
| 			var setActiveViewStub = sinon.stub(OCA.Files.App, 'setActiveView'); | |||
| 			// create dummy table so we can click the dom
 | |||
| 			var $table = '<table><thead></thead><tbody id="fileList"></tbody></table>'; | |||
| 			$('#app-content-sharingin').append($table); | |||
| 
 | |||
| 			App._inFileList = null; | |||
| 			fileListIn = App.initSharingIn($('#app-content-sharingin')); | |||
| 
 | |||
| 			fileListIn.setFiles([{ | |||
| 				name: 'testdir', | |||
| 				type: 'dir', | |||
| 				path: '/somewhere/inside/subdir', | |||
| 				counterParts: ['user2'], | |||
| 				shares: [{ | |||
| 					ownerDisplayName: 'user2' | |||
| 				}] | |||
| 			}]); | |||
| 
 | |||
| 			fileListIn.findFileEl('testdir').find('td a.name').click(); | |||
| 
 | |||
| 			expect(OCA.Files.App.fileList.getCurrentDirectory()).toEqual('/somewhere/inside/subdir/testdir'); | |||
| 
 | |||
| 			expect(setActiveViewStub.calledOnce).toEqual(true); | |||
| 			expect(setActiveViewStub.calledWith('files')).toEqual(true); | |||
| 
 | |||
| 			setActiveViewStub.restore(); | |||
| 
 | |||
| 			// restore old list
 | |||
| 			OCA.Files.App.fileList = oldList; | |||
| 		}); | |||
| 	}); | |||
| }); | |||
| @ -0,0 +1,412 @@ | |||
| /* | |||
|  * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> | |||
|  * | |||
|  * This file is licensed under the Affero General Public License version 3 | |||
|  * or later. | |||
|  * | |||
|  * See the COPYING-README file. | |||
|  * | |||
|  */ | |||
| 
 | |||
| describe('OCA.Sharing.FileList tests', function() { | |||
| 	var testFiles, alertStub, notificationStub, fileList; | |||
| 
 | |||
| 	beforeEach(function() { | |||
| 		alertStub = sinon.stub(OC.dialogs, 'alert'); | |||
| 		notificationStub = sinon.stub(OC.Notification, 'show'); | |||
| 
 | |||
| 		// init parameters and test table elements
 | |||
| 		$('#testArea').append( | |||
| 			'<div id="app-content-container">' + | |||
| 			// init horrible parameters
 | |||
| 			'<input type="hidden" id="dir" value="/"></input>' + | |||
| 			'<input type="hidden" id="permissions" value="31"></input>' + | |||
| 			// dummy controls
 | |||
| 			'<div id="controls">' + | |||
| 			'   <div class="actions creatable"></div>' + | |||
| 			'   <div class="notCreatable"></div>' + | |||
| 			'</div>' + | |||
| 			// 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 column-name">' + | |||
| 			'<input type="checkbox" id="select_all_files" class="select-all">' + | |||
| 			'<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' + | |||
| 			'<span class="selectedActions hidden">' + | |||
| 			'</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>' + | |||
| 			'<div id="emptycontent">Empty content message</div>' + | |||
| 			'</div>' | |||
| 		); | |||
| 	}); | |||
| 	afterEach(function() { | |||
| 		testFiles = undefined; | |||
| 		fileList = undefined; | |||
| 
 | |||
| 		notificationStub.restore(); | |||
| 		alertStub.restore(); | |||
| 	}); | |||
| 
 | |||
| 	describe('loading file list for incoming shares', function() { | |||
| 		var ocsResponse; | |||
| 
 | |||
| 		beforeEach(function() { | |||
| 			fileList = new OCA.Sharing.FileList( | |||
| 				$('#app-content-container'), { | |||
| 					sharedWithUser: true | |||
| 				} | |||
| 			); | |||
| 
 | |||
| 			fileList.reload(); | |||
| 
 | |||
| 			/* jshint camelcase: false */ | |||
| 			ocsResponse = { | |||
| 				ocs: { | |||
| 					meta: { | |||
| 						status: 'ok', | |||
| 						statuscode: 100, | |||
| 						message: null | |||
| 					}, | |||
| 					data: [{ | |||
| 						id: 7, | |||
| 						item_type: 'file', | |||
| 						item_source: 49, | |||
| 						item_target: '/49', | |||
| 						file_source: 49, | |||
| 						file_target: '/local path/local name.txt', | |||
| 						path: 'files/something shared.txt', | |||
| 						permissions: 31, | |||
| 						stime: 11111, | |||
| 						share_type: OC.Share.SHARE_TYPE_USER, | |||
| 						share_with: 'user1', | |||
| 						share_with_displayname: 'User One', | |||
| 						mimetype: 'text/plain', | |||
| 						uid_owner: 'user2', | |||
| 						displayname_owner: 'User Two' | |||
| 					}] | |||
| 				} | |||
| 			}; | |||
| 		}); | |||
| 		it('render file shares', function() { | |||
| 			var request; | |||
| 
 | |||
| 			expect(fakeServer.requests.length).toEqual(1); | |||
| 			request = fakeServer.requests[0]; | |||
| 			expect(request.url).toEqual( | |||
| 				OC.linkToOCS('apps/files_sharing/api/v1') + | |||
| 				'shares?format=json&shared_with_me=true' | |||
| 			); | |||
| 
 | |||
| 			fakeServer.requests[0].respond( | |||
| 				200, | |||
| 				{ 'Content-Type': 'application/json' }, | |||
| 				JSON.stringify(ocsResponse) | |||
| 			); | |||
| 
 | |||
| 			var $rows = fileList.$el.find('tbody tr'); | |||
| 			var $tr = $rows.eq(0); | |||
| 			expect($rows.length).toEqual(1); | |||
| 			expect($tr.attr('data-id')).toEqual('49'); | |||
| 			expect($tr.attr('data-type')).toEqual('file'); | |||
| 			expect($tr.attr('data-file')).toEqual('local name.txt'); | |||
| 			expect($tr.attr('data-path')).toEqual('/local path'); | |||
| 			expect($tr.attr('data-size')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
 | |||
| 			expect($tr.attr('data-mime')).toEqual('text/plain'); | |||
| 			expect($tr.attr('data-mtime')).toEqual('11111000'); | |||
| 			expect($tr.attr('data-share-owner')).toEqual('User Two'); | |||
| 			expect($tr.attr('data-share-id')).toEqual('7'); | |||
| 			expect($tr.find('a.name').attr('href')).toEqual( | |||
| 				OC.webroot + | |||
| 				'/index.php/apps/files/ajax/download.php' + | |||
| 				'?dir=%2Flocal%20path&files=local%20name.txt' | |||
| 			); | |||
| 			expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); | |||
| 		}); | |||
| 		it('render folder shares', function() { | |||
| 			/* jshint camelcase: false */ | |||
| 			var request; | |||
| 			ocsResponse.ocs.data[0] = _.extend(ocsResponse.ocs.data[0], { | |||
| 				item_type: 'folder', | |||
| 				file_target: '/local path/local name', | |||
| 				path: 'files/something shared', | |||
| 			}); | |||
| 
 | |||
| 			expect(fakeServer.requests.length).toEqual(1); | |||
| 			request = fakeServer.requests[0]; | |||
| 			expect(request.url).toEqual( | |||
| 				OC.linkToOCS('apps/files_sharing/api/v1') + | |||
| 				'shares?format=json&shared_with_me=true' | |||
| 			); | |||
| 
 | |||
| 			fakeServer.requests[0].respond( | |||
| 				200, | |||
| 				{ 'Content-Type': 'application/json' }, | |||
| 				JSON.stringify(ocsResponse) | |||
| 			); | |||
| 
 | |||
| 			var $rows = fileList.$el.find('tbody tr'); | |||
| 			var $tr = $rows.eq(0); | |||
| 			expect($rows.length).toEqual(1); | |||
| 			expect($tr.attr('data-id')).toEqual('49'); | |||
| 			expect($tr.attr('data-type')).toEqual('dir'); | |||
| 			expect($tr.attr('data-file')).toEqual('local name'); | |||
| 			expect($tr.attr('data-path')).toEqual('/local path'); | |||
| 			expect($tr.attr('data-size')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
 | |||
| 			expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); | |||
| 			expect($tr.attr('data-mtime')).toEqual('11111000'); | |||
| 			expect($tr.attr('data-share-owner')).toEqual('User Two'); | |||
| 			expect($tr.attr('data-share-id')).toEqual('7'); | |||
| 			expect($tr.find('a.name').attr('href')).toEqual( | |||
| 				OC.webroot + | |||
| 				'/index.php/apps/files' + | |||
| 				'?dir=/local%20path/local%20name' | |||
| 			); | |||
| 			expect($tr.find('.nametext').text().trim()).toEqual('local name'); | |||
| 		}); | |||
| 	}); | |||
| 	describe('loading file list for outgoing shares', function() { | |||
| 		var ocsResponse; | |||
| 
 | |||
| 		beforeEach(function() { | |||
| 			fileList = new OCA.Sharing.FileList( | |||
| 				$('#app-content-container'), { | |||
| 					sharedWithUser: false | |||
| 				} | |||
| 			); | |||
| 
 | |||
| 			fileList.reload(); | |||
| 
 | |||
| 			/* jshint camelcase: false */ | |||
| 			ocsResponse = { | |||
| 				ocs: { | |||
| 					meta: { | |||
| 						status: 'ok', | |||
| 						statuscode: 100, | |||
| 						message: null | |||
| 					}, | |||
| 					data: [{ | |||
| 						id: 7, | |||
| 						item_type: 'file', | |||
| 						item_source: 49, | |||
| 						file_source: 49, | |||
| 						path: '/local path/local name.txt', | |||
| 						permissions: 27, | |||
| 						stime: 11111, | |||
| 						share_type: OC.Share.SHARE_TYPE_USER, | |||
| 						share_with: 'user2', | |||
| 						share_with_displayname: 'User Two', | |||
| 						mimetype: 'text/plain', | |||
| 						uid_owner: 'user1', | |||
| 						displayname_owner: 'User One' | |||
| 					}] | |||
| 				} | |||
| 			}; | |||
| 		}); | |||
| 		it('render file shares', function() { | |||
| 			var request; | |||
| 
 | |||
| 			expect(fakeServer.requests.length).toEqual(1); | |||
| 			request = fakeServer.requests[0]; | |||
| 			expect(request.url).toEqual( | |||
| 				OC.linkToOCS('apps/files_sharing/api/v1') + | |||
| 				'shares?format=json&shared_with_me=false' | |||
| 			); | |||
| 
 | |||
| 			fakeServer.requests[0].respond( | |||
| 				200, | |||
| 				{ 'Content-Type': 'application/json' }, | |||
| 				JSON.stringify(ocsResponse) | |||
| 			); | |||
| 
 | |||
| 			var $rows = fileList.$el.find('tbody tr'); | |||
| 			var $tr = $rows.eq(0); | |||
| 			expect($rows.length).toEqual(1); | |||
| 			expect($tr.attr('data-id')).toEqual('49'); | |||
| 			expect($tr.attr('data-type')).toEqual('file'); | |||
| 			expect($tr.attr('data-file')).toEqual('local name.txt'); | |||
| 			expect($tr.attr('data-path')).toEqual('/local path'); | |||
| 			expect($tr.attr('data-size')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
 | |||
| 			expect($tr.attr('data-mime')).toEqual('text/plain'); | |||
| 			expect($tr.attr('data-mtime')).toEqual('11111000'); | |||
| 			expect($tr.attr('data-share-owner')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-share-id')).toEqual('7'); | |||
| 			expect($tr.find('a.name').attr('href')).toEqual( | |||
| 				OC.webroot + | |||
| 				'/index.php/apps/files/ajax/download.php' + | |||
| 				'?dir=%2Flocal%20path&files=local%20name.txt' | |||
| 			); | |||
| 			expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); | |||
| 		}); | |||
| 		it('render folder shares', function() { | |||
| 			var request; | |||
| 			/* jshint camelcase: false */ | |||
| 			ocsResponse.ocs.data[0] = _.extend(ocsResponse.ocs.data[0], { | |||
| 				item_type: 'folder', | |||
| 				path: '/local path/local name', | |||
| 			}); | |||
| 
 | |||
| 			expect(fakeServer.requests.length).toEqual(1); | |||
| 			request = fakeServer.requests[0]; | |||
| 			expect(request.url).toEqual( | |||
| 				OC.linkToOCS('apps/files_sharing/api/v1') + | |||
| 				'shares?format=json&shared_with_me=false' | |||
| 			); | |||
| 
 | |||
| 			fakeServer.requests[0].respond( | |||
| 				200, | |||
| 				{ 'Content-Type': 'application/json' }, | |||
| 				JSON.stringify(ocsResponse) | |||
| 			); | |||
| 
 | |||
| 			var $rows = fileList.$el.find('tbody tr'); | |||
| 			var $tr = $rows.eq(0); | |||
| 			expect($rows.length).toEqual(1); | |||
| 			expect($tr.attr('data-id')).toEqual('49'); | |||
| 			expect($tr.attr('data-type')).toEqual('dir'); | |||
| 			expect($tr.attr('data-file')).toEqual('local name'); | |||
| 			expect($tr.attr('data-path')).toEqual('/local path'); | |||
| 			expect($tr.attr('data-size')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
 | |||
| 			expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); | |||
| 			expect($tr.attr('data-mtime')).toEqual('11111000'); | |||
| 			expect($tr.attr('data-share-owner')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-share-id')).toEqual('7'); | |||
| 			expect($tr.find('a.name').attr('href')).toEqual( | |||
| 				OC.webroot + | |||
| 				'/index.php/apps/files' + | |||
| 				'?dir=/local%20path/local%20name' | |||
| 			); | |||
| 			expect($tr.find('.nametext').text().trim()).toEqual('local name'); | |||
| 		}); | |||
| 		it('render link shares', function() { | |||
| 			/* jshint camelcase: false */ | |||
| 			var request; | |||
| 			ocsResponse.ocs.data[0] = { | |||
| 				id: 7, | |||
| 				item_type: 'file', | |||
| 				item_source: 49, | |||
| 				file_source: 49, | |||
| 				path: '/local path/local name.txt', | |||
| 				permissions: 1, | |||
| 				stime: 11111, | |||
| 				share_type: OC.Share.SHARE_TYPE_LINK, | |||
| 				share_with: null, | |||
| 				token: 'abc', | |||
| 				mimetype: 'text/plain', | |||
| 				uid_owner: 'user1', | |||
| 				displayname_owner: 'User One' | |||
| 			}; | |||
| 			expect(fakeServer.requests.length).toEqual(1); | |||
| 			request = fakeServer.requests[0]; | |||
| 			expect(request.url).toEqual( | |||
| 				OC.linkToOCS('apps/files_sharing/api/v1') + | |||
| 				'shares?format=json&shared_with_me=false' | |||
| 			); | |||
| 
 | |||
| 			fakeServer.requests[0].respond( | |||
| 				200, | |||
| 				{ 'Content-Type': 'application/json' }, | |||
| 				JSON.stringify(ocsResponse) | |||
| 			); | |||
| 
 | |||
| 			var $rows = fileList.$el.find('tbody tr'); | |||
| 			var $tr = $rows.eq(0); | |||
| 			expect($rows.length).toEqual(1); | |||
| 			expect($tr.attr('data-id')).toEqual('49'); | |||
| 			expect($tr.attr('data-type')).toEqual('file'); | |||
| 			expect($tr.attr('data-file')).toEqual('local name.txt'); | |||
| 			expect($tr.attr('data-path')).toEqual('/local path'); | |||
| 			expect($tr.attr('data-size')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
 | |||
| 			expect($tr.attr('data-mime')).toEqual('text/plain'); | |||
| 			expect($tr.attr('data-mtime')).toEqual('11111000'); | |||
| 			expect($tr.attr('data-share-owner')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-share-id')).toEqual('7'); | |||
| 			expect($tr.find('a.name').attr('href')).toEqual( | |||
| 					OC.webroot + | |||
| 					'/index.php/apps/files/ajax/download.php' + | |||
| 					'?dir=%2Flocal%20path&files=local%20name.txt'); | |||
| 
 | |||
| 			expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); | |||
| 		}); | |||
| 		it('groups link shares with regular shares', function() { | |||
| 			/* jshint camelcase: false */ | |||
| 			var request; | |||
| 			// link share
 | |||
| 			ocsResponse.ocs.data.push({ | |||
| 				id: 8, | |||
| 				item_type: 'file', | |||
| 				item_source: 49, | |||
| 				file_source: 49, | |||
| 				path: '/local path/local name.txt', | |||
| 				permissions: 1, | |||
| 				stime: 11111, | |||
| 				share_type: OC.Share.SHARE_TYPE_LINK, | |||
| 				share_with: null, | |||
| 				token: 'abc', | |||
| 				mimetype: 'text/plain', | |||
| 				uid_owner: 'user1', | |||
| 				displayname_owner: 'User One' | |||
| 			}); | |||
| 			// another share of the same file
 | |||
| 			ocsResponse.ocs.data.push({ | |||
| 				id: 9, | |||
| 				item_type: 'file', | |||
| 				item_source: 49, | |||
| 				file_source: 49, | |||
| 				path: '/local path/local name.txt', | |||
| 				permissions: 27, | |||
| 				stime: 22222, | |||
| 				share_type: OC.Share.SHARE_TYPE_USER, | |||
| 				share_with: 'user3', | |||
| 				share_with_displayname: 'User Three', | |||
| 				mimetype: 'text/plain', | |||
| 				uid_owner: 'user1', | |||
| 				displayname_owner: 'User One' | |||
| 			}); | |||
| 			expect(fakeServer.requests.length).toEqual(1); | |||
| 			request = fakeServer.requests[0]; | |||
| 			expect(request.url).toEqual( | |||
| 				OC.linkToOCS('apps/files_sharing/api/v1') + | |||
| 				'shares?format=json&shared_with_me=false' | |||
| 			); | |||
| 
 | |||
| 			fakeServer.requests[0].respond( | |||
| 				200, | |||
| 				{ 'Content-Type': 'application/json' }, | |||
| 				JSON.stringify(ocsResponse) | |||
| 			); | |||
| 
 | |||
| 			var $rows = fileList.$el.find('tbody tr'); | |||
| 			var $tr = $rows.eq(0); | |||
| 			expect($rows.length).toEqual(1); | |||
| 			expect($tr.attr('data-id')).toEqual('49'); | |||
| 			expect($tr.attr('data-type')).toEqual('file'); | |||
| 			expect($tr.attr('data-file')).toEqual('local name.txt'); | |||
| 			expect($tr.attr('data-path')).toEqual('/local path'); | |||
| 			expect($tr.attr('data-size')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
 | |||
| 			expect($tr.attr('data-mime')).toEqual('text/plain'); | |||
| 			// always use the most recent stime
 | |||
| 			expect($tr.attr('data-mtime')).toEqual('22222000'); | |||
| 			expect($tr.attr('data-share-owner')).not.toBeDefined(); | |||
| 			expect($tr.attr('data-share-id')).toEqual('7,8,9'); | |||
| 			expect($tr.find('a.name').attr('href')).toEqual( | |||
| 				OC.webroot + | |||
| 				'/index.php/apps/files/ajax/download.php' + | |||
| 				'?dir=%2Flocal%20path&files=local%20name.txt' | |||
| 			); | |||
| 			expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); | |||
| 		}); | |||
| 	}); | |||
| }); | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue