Completed
Push — stable9 ( 485cb1...e094cf )
by Lukas
26:41 queued 26:23
created

apps/files_sharing/js/sharedfilelist.js (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
/*
2
 * Copyright (c) 2014 Vincent Petry <[email protected]>
3
 *
4
 * This file is licensed under the Affero General Public License version 3
5
 * or later.
6
 *
7
 * See the COPYING-README file.
8
 *
9
 */
10
(function() {
11
12
	/**
13
	 * @class OCA.Sharing.FileList
14
	 * @augments OCA.Files.FileList
15
	 *
16
	 * @classdesc Sharing file list.
17
	 * Contains both "shared with others" and "shared with you" modes.
18
	 *
19
	 * @param $el container element with existing markup for the #controls
20
	 * and a table
21
	 * @param [options] map of options, see other parameters
22
	 * @param {boolean} [options.sharedWithUser] true to return files shared with
23
	 * the current user, false to return files that the user shared with others.
24
	 * Defaults to false.
25
	 * @param {boolean} [options.linksOnly] true to return only link shares
26
	 */
27
	var FileList = function($el, options) {
28
		this.initialize($el, options);
29
	};
30
	FileList.prototype = _.extend({}, OCA.Files.FileList.prototype,
31
		/** @lends OCA.Sharing.FileList.prototype */ {
32
		appName: 'Shares',
33
34
		/**
35
		 * Whether the list shows the files shared with the user (true) or
36
		 * the files that the user shared with others (false).
37
		 */
38
		_sharedWithUser: false,
39
		_linksOnly: false,
40
		_clientSideSort: true,
41
		_allowSelection: false,
42
43
		/**
44
		 * @private
45
		 */
46
		initialize: function($el, options) {
47
			OCA.Files.FileList.prototype.initialize.apply(this, arguments);
48
			if (this.initialized) {
49
				return;
50
			}
51
52
			// TODO: consolidate both options
53
			if (options && options.sharedWithUser) {
54
				this._sharedWithUser = true;
55
			}
56
			if (options && options.linksOnly) {
57
				this._linksOnly = true;
58
			}
59
			OC.Plugins.attach('OCA.Sharing.FileList', this);
60
		},
61
62
		_renderRow: function() {
63
			// HACK: needed to call the overridden _renderRow
64
			// this is because at the time this class is created
65
			// the overriding hasn't been done yet...
66
			return OCA.Files.FileList.prototype._renderRow.apply(this, arguments);
67
		},
68
69
		_createRow: function(fileData) {
70
			// TODO: hook earlier and render the whole row here
71
			var $tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments);
72
			$tr.find('.filesize').remove();
73
			$tr.find('td.date').before($tr.children('td:first'));
74
			$tr.find('td.filename input:checkbox').remove();
75
			$tr.attr('data-share-id', _.pluck(fileData.shares, 'id').join(','));
76
			if (this._sharedWithUser) {
77
				$tr.attr('data-share-owner', fileData.shareOwner);
78
				$tr.attr('data-mounttype', 'shared-root');
79
				var permission = parseInt($tr.attr('data-permissions')) | OC.PERMISSION_DELETE;
80
				$tr.attr('data-permissions', permission);
81
			}
82
			return $tr;
83
		},
84
85
		/**
86
		 * Set whether the list should contain outgoing shares
87
		 * or incoming shares.
88
		 *
89
		 * @param state true for incoming shares, false otherwise
90
		 */
91
		setSharedWithUser: function(state) {
92
			this._sharedWithUser = !!state;
93
		},
94
95
		updateEmptyContent: function() {
96
			var dir = this.getCurrentDirectory();
97
			if (dir === '/') {
98
				// root has special permissions
99
				this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty);
100
				this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty);
101
			}
102
			else {
103
				OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments);
104
			}
105
		},
106
107
		getDirectoryPermissions: function() {
108
			return OC.PERMISSION_READ | OC.PERMISSION_DELETE;
109
		},
110
111
		updateStorageStatistics: function() {
112
			// no op because it doesn't have
113
			// storage info like free space / used space
114
		},
115
116
		reload: function() {
117
			this.showMask();
118
			if (this._reloadCall) {
119
				this._reloadCall.abort();
120
			}
121
122
			// there is only root
123
			this._setCurrentDir('/', false);
124
125
			var promises = [];
126
			var shares = $.ajax({
127
				url: OC.linkToOCS('apps/files_sharing/api/v1') + 'shares',
128
				/* jshint camelcase: false */
129
				data: {
130
					format: 'json',
131
					shared_with_me: !!this._sharedWithUser
132
				},
133
				type: 'GET',
134
				beforeSend: function(xhr) {
135
					xhr.setRequestHeader('OCS-APIREQUEST', 'true');
136
				},
137
			});
138
			promises.push(shares);
139
140
			if (!!this._sharedWithUser) {
141
				var remoteShares = $.ajax({
142
					url: OC.linkToOCS('apps/files_sharing/api/v1') + 'remote_shares',
143
					/* jshint camelcase: false */
144
					data: {
145
						format: 'json'
146
					},
147
					type: 'GET',
148
					beforeSend: function(xhr) {
149
						xhr.setRequestHeader('OCS-APIREQUEST', 'true');
150
					},
151
				});
152
				promises.push(remoteShares);
153
			} else {
154
				//Push empty promise so callback gets called the same way
155
				promises.push($.Deferred().resolve());
156
			}
157
158
			this._reloadCall = $.when.apply($, promises);
159
			var callBack = this.reloadCallback.bind(this);
160
			return this._reloadCall.then(callBack, callBack);
161
		},
162
163
		reloadCallback: function(shares, remoteShares) {
164
			delete this._reloadCall;
165
			this.hideMask();
166
167
			this.$el.find('#headerSharedWith').text(
168
				t('files_sharing', this._sharedWithUser ? 'Shared by' : 'Shared with')
169
			);
170
171
			var files = [];
172
173
			if (shares[0].ocs && shares[0].ocs.data) {
174
				files = files.concat(this._makeFilesFromShares(shares[0].ocs.data));
175
			}
176
177
			if (remoteShares && remoteShares[0].ocs && remoteShares[0].ocs.data) {
178
				files = files.concat(this._makeFilesFromRemoteShares(remoteShares[0].ocs.data));
179
			}
180
181
			this.setFiles(files);
182
			return true;
183
		},
184
185
		_makeFilesFromRemoteShares: function(data) {
186
			var self = this;
187
			var files = data;
188
189
			files = _.chain(files)
190
				// convert share data to file data
191
				.map(function(share) {
192
					var file = {
193
						shareOwner: share.owner + '@' + share.remote.replace(/.*?:\/\//g, ""),
194
						name: OC.basename(share.mountpoint),
195
						mtime: share.mtime * 1000,
196
						mimetype: share.mimetype,
197
						type: share.type,
198
						id: share.file_id,
0 ignored issues
show
Identifier 'file_id' is not in camel case.
Loading history...
199
						path: OC.dirname(share.mountpoint),
200
						permissions: share.permissions
201
					};
202
203
					file.shares = [{
204
						id: share.id,
205
						type: OC.Share.SHARE_TYPE_REMOTE
206
					}];
207
					return file;
208
				})
209
				.value();
210
			return files;
211
		},
212
213
		/**
214
		 * Converts the OCS API share response data to a file info
215
		 * list
216
		 * @param {Array} data OCS API share array
217
		 * @return {Array.<OCA.Sharing.SharedFileInfo>} array of shared file info
218
		 */
219
		_makeFilesFromShares: function(data) {
220
			/* jshint camelcase: false */
221
			var self = this;
222
			var files = data;
223
224
			if (this._linksOnly) {
225
				files = _.filter(data, function(share) {
226
					return share.share_type === OC.Share.SHARE_TYPE_LINK;
227
				});
228
			}
229
230
			// OCS API uses non-camelcased names
231
			files = _.chain(files)
232
				// convert share data to file data
233
				.map(function(share) {
234
					// TODO: use OC.Files.FileInfo
235
					var file = {
236
						id: share.file_source,
237
						icon: OC.MimeType.getIconUrl(share.mimetype),
238
						mimetype: share.mimetype
239
					};
240
					if (share.item_type === 'folder') {
241
						file.type = 'dir';
242
						file.mimetype = 'httpd/unix-directory';
243
					}
244
					else {
245
						file.type = 'file';
246
					}
247
					file.share = {
248
						id: share.id,
249
						type: share.share_type,
250
						target: share.share_with,
251
						stime: share.stime * 1000,
252
					};
253
					if (self._sharedWithUser) {
254
						file.shareOwner = share.displayname_owner;
255
						file.name = OC.basename(share.file_target);
256
						file.path = OC.dirname(share.file_target);
257
						file.permissions = share.permissions;
258
						if (file.path) {
259
							file.extraData = share.file_target;
260
						}
261
					}
262
					else {
263
						if (share.share_type !== OC.Share.SHARE_TYPE_LINK) {
264
							file.share.targetDisplayName = share.share_with_displayname;
265
						}
266
						file.name = OC.basename(share.path);
267
						file.path = OC.dirname(share.path);
268
						file.permissions = OC.PERMISSION_ALL;
269
						if (file.path) {
270
							file.extraData = share.path;
271
						}
272
					}
273
					return file;
274
				})
275
				// Group all files and have a "shares" array with
276
				// the share info for each file.
277
				//
278
				// This uses a hash memo to cumulate share information
279
				// inside the same file object (by file id).
280
				.reduce(function(memo, file) {
281
					var data = memo[file.id];
282
					var recipient = file.share.targetDisplayName;
283
					if (!data) {
284
						data = memo[file.id] = file;
285
						data.shares = [file.share];
286
						// using a hash to make them unique,
287
						// this is only a list to be displayed
288
						data.recipients = {};
289
						// share types
290
						data.shareTypes = {};
291
						// counter is cheaper than calling _.keys().length
292
						data.recipientsCount = 0;
293
						data.mtime = file.share.stime;
294
					}
295
					else {
296
						// always take the most recent stime
297
						if (file.share.stime > data.mtime) {
298
							data.mtime = file.share.stime;
299
						}
300
						data.shares.push(file.share);
301
					}
302
303
					if (recipient) {
304
						// limit counterparts for output
305
						if (data.recipientsCount < 4) {
306
							// only store the first ones, they will be the only ones
307
							// displayed
308
							data.recipients[recipient] = true;
309
						}
310
						data.recipientsCount++;
311
					}
312
313
					data.shareTypes[file.share.type] = true;
314
315
					delete file.share;
316
					return memo;
317
				}, {})
318
				// Retrieve only the values of the returned hash
319
				.values()
320
				// Clean up
321
				.each(function(data) {
322
					// convert the recipients map to a flat
323
					// array of sorted names
324
					data.mountType = 'shared';
325
					data.recipients = _.keys(data.recipients);
326
					data.recipientsDisplayName = OCA.Sharing.Util.formatRecipients(
327
						data.recipients,
328
						data.recipientsCount
329
					);
330
					delete data.recipientsCount;
331
					if (self._sharedWithUser) {
332
						// only for outgoing shres
333
						delete data.shareTypes;
334
					} else {
335
						data.shareTypes = _.keys(data.shareTypes);
336
					}
337
				})
338
				// Finish the chain by getting the result
339
				.value();
340
341
			// Sort by expected sort comparator
342
			return files.sort(this._sortComparator);
343
		}
344
	});
345
346
	/**
347
	 * Share info attributes.
348
	 *
349
	 * @typedef {Object} OCA.Sharing.ShareInfo
350
	 *
351
	 * @property {int} id share ID
352
	 * @property {int} type share type
353
	 * @property {String} target share target, either user name or group name
354
	 * @property {int} stime share timestamp in milliseconds
355
	 * @property {String} [targetDisplayName] display name of the recipient
356
	 * (only when shared with others)
357
	 *
358
	 */
359
360
	/**
361
	 * Shared file info attributes.
362
	 *
363
	 * @typedef {OCA.Files.FileInfo} OCA.Sharing.SharedFileInfo
364
	 *
365
	 * @property {Array.<OCA.Sharing.ShareInfo>} shares array of shares for
366
	 * this file
367
	 * @property {int} mtime most recent share time (if multiple shares)
368
	 * @property {String} shareOwner name of the share owner
369
	 * @property {Array.<String>} recipients name of the first 4 recipients
370
	 * (this is mostly for display purposes)
371
	 * @property {String} recipientsDisplayName display name
372
	 */
373
374
	OCA.Sharing.FileList = FileList;
375
})();
376