Completed
Push — master ( e7fe3e...2b225b )
by Maxence
02:31
created

FullTextSearch._initFileActions   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 59
rs 9.597
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 3 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/*
2
 * Files_FullTextSearch - Index the content of your files
3
 *
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later. See the COPYING file.
6
 *
7
 * @author Maxence Lange <[email protected]>
8
 * @copyright 2018
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
27
/** global: OCA */
28
29
var fullTextSearch = OCA.FullTextSearch.api;
30
31
32
var elements = {
33
	old_files: null,
34
	search_result: null,
35
	current_dir: ''
36
};
37
38
39
var FullTextSearch = function () {
40
	this.init();
41
};
42
43
44
FullTextSearch.prototype = {
45
46
	/**
47
	 * File actions handler, defaults to OCA.Files.FileActions
48
	 * @type OCA.Files.FileActions
49
	 */
50
	fileActions: null,
51
52
53
	init: function () {
54
		var self = this;
55
56
		elements.old_files = $('#app-content-files');
57
58
		elements.search_result = $('<div>');
59
		elements.search_result.insertBefore(elements.old_files);
60
61
		fullTextSearch.setResultContainer(elements.search_result);
62
		fullTextSearch.setEntryTemplate(self.generateEntryTemplate());
63
		fullTextSearch.setResultHeader(self.generateResultHeader());
64
		// fullTextSearch.setResultFooter(self.generateResultFooter());
65
66
		fullTextSearch.initFullTextSearch('files', 'files', self);
67
68
		this._initFileActions();
69
	},
70
71
	_initFileActions: function () {
72
73
		this.fileActions = new OCA.Files.FileActions();
74
		this.fileActions.registerDefaultActions();
75
		this.fileActions.merge(window.FileActions);
76
		this.fileActions.merge(OCA.Files.fileActions)
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
77
78
		this._onActionsUpdated = _.bind(this._onActionsUpdated, this);
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
79
		OCA.Files.fileActions.on('setDefault.app-files', this._onActionsUpdated);
80
		OCA.Files.fileActions.on('registerAction.app-files', this._onActionsUpdated);
81
		window.FileActions.on('setDefault.app-files', this._onActionsUpdated);
82
		window.FileActions.on('registerAction.app-files', this._onActionsUpdated);
83
84
		this.fileActions.actions.all.Rename = undefined;
85
		this.fileActions.actions.all.MoveCopy = undefined;
86
		this.fileActions.actions.all.Copy = undefined;
87
		this.fileActions.actions.all.Delete = undefined;
88
89
		console.log(JSON.stringify(this.fileActions.actions));
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
90
91
		this.fileActions.registerAction({
92
			name: 'GoToFolder',
93
			displayName: t('files_fulltextsearch', 'Go to folder'),
94
			mime: 'file',
95
			order: -50,
96
			iconClass: 'icon-folder',
97
			permissions: OC.PERMISSION_NONE,
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
98
			actionHandler: function (filename, context) {
99
				window.open('/apps/files/?dir=' + context.dir + '&scrollto=' + context.filename);
100
			}
101
		});
102
103
		this.fileActions.registerAction({
104
			name: 'OpenFolder',
105
			displayName: t('files_fulltextsearch', 'Open folder'),
106
			mime: 'dir',
107
			order: -50,
108
			iconClass: 'icon-folder',
109
			permissions: OC.PERMISSION_NONE,
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
110
			actionHandler: function (filename, context) {
111
				console.log(JSON.stringify(context));
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
112
				window.open('/apps/files/?dir=' + context.dir + context.filename);
113
			}
114
		});
115
116
		// if (this._detailsView) {
117
		// 	this.fileActions.registerAction({
118
		// 		name: 'Details',
119
		// 		displayName: t('files', 'Details'),
120
		// 		mime: 'all',
121
		// 		order: -50,
122
		// 		iconClass: 'icon-details',
123
		// 		permissions: OC.PERMISSION_NONE,
124
		// 		actionHandler: function (fileName, context) {
125
		// 			self._updateDetailsView(fileName);
126
		// 		}
127
		// 	});
128
		// }
129
	},
130
131
132
	_onActionsUpdated: function (ev, newAction) {
0 ignored issues
show
Unused Code introduced by
The parameter newAction is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
133
		if (ev.action) {
134
			this.fileActions.registerAction(ev.action);
135
		} else if (ev.defaultAction) {
136
			this.fileActions.setDefault(
137
				ev.defaultAction.mime,
138
				ev.defaultAction.name
139
			);
140
		}
141
	},
142
143
144
	generateResultHeader: function () {
145
146
		var resultHeader = $('<div>', {class: 'files_header'});
147
		resultHeader.append($('<div>', {class: 'files_div_checkbox'}).html('&nbsp;'));
148
		resultHeader.append($('<div>', {class: 'files_div_thumb'}).html('&nbsp;'));
149
		resultHeader.append(
150
			$('<div>', {class: 'files_header_div files_div_name'}).text(_('Name')));
151
		resultHeader.append(
152
			$('<div>', {class: 'files_header_div files_div_modified'}).text(_('Modified')));
153
		resultHeader.append(
154
			$('<div>', {class: 'files_header_div files_div_size'}).text(_('Size')));
155
156
		return resultHeader;
157
	},
158
159
160
	generateResultFooter: function () {
161
		var resultFooter = $('<div>', {class: 'files_footer'});
162
163
		return resultFooter;
164
	},
165
166
167
	/**
168
	 *
169
	 * !!! use this in the fulltextsearch app
170
	 * !!! use this in the fulltextsearch app
171
	 * !!! use this in the fulltextsearch app
172
	 */
173
	generateEntryTemplate: function () {
174
175
		var resultName = $('<div>', {class: 'files_result_file'});
176
		resultName.append($('<div>', {
177
			id: 'title',
178
			class: 'files_result_title'
179
		}));
180
		resultName.append($('<div>', {
181
			id: 'extract',
182
			class: 'files_result_extract'
183
		}));
184
185
		var resultEntry = $('<div>', {class: 'files_result'});
186
		resultEntry.append($('<div>', {class: 'files_div_checkbox'}));
187
		resultEntry.append($('<div>', {class: 'files_div_thumb files_result_div'}));
188
189
		resultEntry.append($('<div>', {class: 'files_result_div files_div_name'}).append(resultName));
190
191
		var resultMore = $('<a>', {
192
			class: 'action action-menu permanent',
193
			href: '#',
194
			'data-action': 'menu',
195
			'data-original-title': ''
196
		}).append($('<span>', {
197
			id: 'more',
198
			class: 'icon icon-more'
199
		}).html('&nbsp;'));
200
201
		// <a class="action action-menu permanent" href="#" data-action="menu" data-original-title=""
202
		// title=""> <span class="icon icon-more"></span><span
203
		// class="hidden-visually">Actions</span></a>
204
		resultEntry.append(
205
			$('<div>', {
206
				class: 'files_result_div files_result_item files_div_more'
207
			}).append(resultMore));
208
209
		resultEntry.append(
210
			$('<div>', {class: 'files_result_div files_result_item files_div_size'}));
211
212
		var resultModified = $('<div>',
213
			{class: 'files_result_div files_result_item files_div_modified'});
214
		resultModified.append($('<div>', {id: 'modified'}));
215
		resultModified.append($('<div>', {id: 'info'}));
216
		resultEntry.append(resultModified);
217
218
		return $('<div>').append(resultEntry);
219
	},
220
221
222
	onEntryGenerated: function (divEntry, entry) {
223
224
		var divFile = divEntry.find('.files_result');
225
		divFile.attr({
226
			'data-id': entry.id,
227
			'data-type': entry.info.type,
228
			'data-size': entry.info.size,
229
			'data-file': entry.info.file,
230
			'data-mime': entry.info.mime,
231
			'data-mtime': entry.info.mtime,
232
			'data-etag': entry.info.etag,
233
			'data-permissions': entry.info.permissions,
234
			'data-path': entry.info.path
235
		});
236
237
		var mtime = parseInt(entry.info.mtime, 10) * 1000;
238
		var size = OC.Util.humanFileSize(parseInt(entry.info.size, 10), true);
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
239
		var thumb = '/index.php/apps/theming/img/core/filetypes/folder.svg?v=3';
240
		if (entry.info.type !== 'dir') {
241
			thumb = '/index.php/core/preview?fileId=' + entry.id + '&x=32&y=32&forceIcon=0&c=' +
242
				entry.info.etag;
243
		}
244
		divEntry.find('.files_div_size').text(size);
245
		divEntry.find('#modified').text(OC.Util.relativeModifiedDate(mtime));
246
		divEntry.find('.files_div_thumb').css('background-image', 'url("' + thumb + '")');
247
	},
248
249
250
	onEntrySelected: function (divEntry, event) {
251
252
		var resultEntry = divEntry.find('.files_result');
253
		this.fileActions.currentFile = resultEntry.children('.files_div_more');
254
255
		var path = resultEntry.attr('data-path');
256
		var filename = resultEntry.attr('data-file');
257
		var mime = resultEntry.attr('data-mime');
258
		var type = resultEntry.attr('data-type');
259
		var permissions = resultEntry.attr('data-permissions');
260
261
		// if (type !== 'file') {
262
		// 	return false;
263
		// }
264
265
		if (event.target.id === 'more') {
266
267
			this.hackFileActions(resultEntry);
268
			// this.fileActions._showMenu(filename, this.hackFileActions(divEntry));
269
			return true;
270
		}
271
272
		if (event && (event.ctrlKey || event.which === 2 || event.button === 4)) {
273
			return false;
274
		}
275
276
		var action = this.fileActions.getDefault(mime, type, permissions);
277
		if (action) {
278
			event.preventDefault();
279
			window.FileActions.currentFile = this.fileActions.currentFile;
280
			action(filename, {
281
				$file: resultEntry,
282
				fileName: filename,
283
				fileList: this,
284
				fileActions: this.fileActions,
285
				dir: path
286
			});
287
288
			return true;
289
		}
290
291
		return false;
292
		// if (event && (event.ctrlKey || event.which === 2 || event.button === 4)) {
293
		// 	window.open('/remote.php/webdav' + path + '/' + filename);
294
		// } else {
295
		// 	window.open('/remote.php/webdav' + path + '/' + filename, '_self');
296
		// }
297
298
299
	},
300
301
302
	getModelForFile: function () {
303
		return null;
304
	},
305
306
	getCurrentDirectory: function () {
307
		return this.fileActions.currentFile.parent('.files_result').attr('data-path');
308
	},
309
310
	getDownloadUrl: function (files, dir, isDir) {
311
		var file = this.fileActions.currentFile.parent('.files_result').attr('data-file');
312
		var path = this.fileActions.currentFile.parent('.files_result').attr('data-path');
313
		return OCA.Files.Files.getDownloadUrl(file, path, isDir);
314
	},
315
316
	showFileBusyState: function (files, state) {
0 ignored issues
show
Unused Code introduced by
The parameter state is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter files is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
317
	},
318
319
320
	/**
321
	 * Copies a file to a given target folder.
322
	 *
323
	 * @param fileNames array of file names to copy
324
	 * @param targetPath absolute target path
325
	 * @param callback to call when copy is finished with success
326
	 * @param dir the dir path where fileNames are located (optionnal, will take current folder if
327
	 *     undefined)
328
	 */
329
	copy: function (fileNames, targetPath, callback, dir) {
330
		var self = this;
331
		var filesToNotify = [];
332
		var count = 0;
333
334
		dir = typeof dir === 'string' ? dir : this.getCurrentDirectory();
335
		if (dir.charAt(dir.length - 1) !== '/') {
336
			dir += '/';
337
		}
338
		var target = OC.basename(targetPath);
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
339
		if (!_.isArray(fileNames)) {
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
340
			fileNames = [fileNames];
341
		}
342
		_.each(fileNames, function (fileName) {
343
			var $tr = self.findFileEl(fileName);
344
			self.showFileBusyState($tr, true);
345
			if (targetPath.charAt(targetPath.length - 1) !== '/') {
346
				// make sure we move the files into the target dir,
347
				// not overwrite it
348
				targetPath = targetPath + '/';
349
			}
350
			self.filesClient.copy(dir + fileName, targetPath + fileName)
351
				.done(function () {
352
					filesToNotify.push(fileName);
353
354
					// if still viewing the same directory
355
					if (OC.joinPaths(self.getCurrentDirectory(), '/') === dir) {
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
356
						// recalculate folder size
357
						var oldFile = self.findFileEl(target);
358
						var newFile = self.findFileEl(fileName);
359
						var oldSize = oldFile.data('size');
360
						var newSize = oldSize + newFile.data('size');
361
						oldFile.data('size', newSize);
362
						oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize));
363
					}
364
				})
365
				.fail(function (status) {
366
					if (status === 412) {
367
						// TODO: some day here we should invoke the conflict dialog
368
						OC.Notification.show(t('files', 'Could not copy "{file}", target exists',
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
369
							{file: fileName}), {type: 'error'}
370
						);
371
					} else {
372
						OC.Notification.show(t('files', 'Could not copy "{file}"',
373
							{file: fileName}), {type: 'error'}
374
						);
375
					}
376
				})
377
				.always(function () {
378
					self.showFileBusyState($tr, false);
379
					count++;
380
381
					/**
382
					 * We only show the notifications once the last file has been copied
383
					 */
384
					if (count === fileNames.length) {
385
						// Remove leading and ending /
386
						if (targetPath.slice(0, 1) === '/') {
387
							targetPath = targetPath.slice(1, targetPath.length);
388
						}
389
						if (targetPath.slice(-1) === '/') {
390
							targetPath = targetPath.slice(0, -1);
391
						}
392
393
						if (filesToNotify.length > 0) {
394
							// Since there's no visual indication that the files were copied, let's send
395
							// some notifications !
396
							if (filesToNotify.length === 1) {
397
								OC.Notification.show(t('files', 'Copied {origin} inside {destination}',
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
398
									{
399
										origin: filesToNotify[0],
400
										destination: targetPath
401
									}
402
								), {timeout: 10});
403
							} else if (filesToNotify.length > 0 && filesToNotify.length < 3) {
404
								OC.Notification.show(t('files', 'Copied {origin} inside {destination}',
405
									{
406
										origin: filesToNotify.join(', '),
407
										destination: targetPath
408
									}
409
								), {timeout: 10});
410
							} else {
411
								OC.Notification.show(t('files',
412
									'Copied {origin} and {nbfiles} other files inside {destination}',
413
									{
414
										origin: filesToNotify[0],
415
										nbfiles: filesToNotify.length - 1,
416
										destination: targetPath
417
									}
418
								), {timeout: 10});
419
							}
420
						}
421
					}
422
				});
423
		});
424
425
		if (callback) {
426
			callback();
427
		}
428
	},
429
430
431
	changeDirectory: function (targetDir, changeUrl, force, fileId) {
432
		var self = this;
433
		var currentDir = '/';
434
		targetDir = targetDir || '/';
435
		if (!force && currentDir === targetDir) {
436
			return;
437
		}
438
		this._setCurrentDir(targetDir, changeUrl, fileId);
439
440
		// discard finished uploads list, we'll get it through a regular reload
441
		this._uploads = {};
442
		this.reload().then(function (success) {
443
			if (!success) {
444
				self.changeDirectory(currentDir, true);
445
			}
446
		});
447
	},
448
449
450
	_setCurrentDir: function (targetDir, changeUrl, fileId) {
0 ignored issues
show
Unused Code introduced by
The parameter changeUrl is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter fileId is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
451
		window.open('/index.php/apps/files?dir=' + targetDir, '_self');
452
	},
453
454
455
	onSearchRequest: function (data) {
456
		if (data.options.files_within_dir === '1') {
457
			var url = new URL(window.location.href);
0 ignored issues
show
Bug introduced by
The variable URL seems to be never declared. If this is a global, consider adding a /** global: URL */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
458
			data.options.files_within_dir = url.searchParams.get("dir");
459
		}
460
	},
461
462
463
	onResultDisplayed: function () {
464
		elements.old_files.fadeOut(150, function () {
465
			elements.search_result.fadeIn(150);
466
		});
467
	},
468
469
470
	onResultClose: function () {
471
		elements.search_result.fadeOut(150, function () {
472
			elements.old_files.fadeIn(150);
473
		});
474
	},
475
476
477
	onSearchReset: function () {
478
		elements.search_result.fadeOut(150, function () {
479
			elements.old_files.fadeIn(150);
480
		});
481
	},
482
483
484
	// Hacky way.
485
	// fit the FileActionMenu to the div.
486
	hackFileActions: function (div) {
487
		var menu = new OCA.Files.FileActionsMenu();
488
489
		div.append(menu.$el);
490
		menu.$el.on('afterHide', function () {
491
			// context.$file.removeClass('mouseOver');
492
			// $trigger.removeClass('open');
493
			// menu.remove();
494
		});
495
496
		console.log('???' + div.attr('data-path'));
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
497
		var fileInfoModel = new OCA.Files.FileInfoModel(this.elementToFile(div));
498
		menu.show({
499
			fileActions: this.fileActions,
500
			fileList: this,
501
			fileInfoModel: fileInfoModel,
502
			$file: div,
503
			filename: div.attr('data-file'),
504
			dir: div.attr('data-path')
505
		});
506
507
		div.find('.fileActionsMenu').addClass('files_force_action_menu');
508
	},
509
510
511
	/**
512
	 * Returns the file data from a given file element.
513
	 * @param $el file tr element
0 ignored issues
show
Documentation introduced by
The parameter $el does not exist. Did you maybe forget to remove this comment?
Loading history...
514
	 * @return file data
515
	 */
516
	elementToFile: function (div) {
517
		var data = {
518
			id: parseInt(div.attr('data-id'), 10),
519
			name: div.attr('data-file'),
520
			mimetype: div.attr('data-mime'),
521
			mtime: parseInt(div.attr('data-mtime'), 10),
522
			type: div.attr('data-type'),
523
			etag: div.attr('data-etag'),
524
			permissions: parseInt(div.attr('data-permissions'), 10),
525
			hasPreview: div.attr('data-has-preview') === 'true',
526
			isEncrypted: div.attr('data-e2eencrypted') === 'true'
527
		};
528
		var size = div.attr('data-size');
529
		if (size) {
530
			data.size = parseInt(size, 10);
531
		}
532
		var icon = div.attr('data-icon');
533
		if (icon) {
534
			data.icon = icon;
535
		}
536
		var mountType = div.attr('data-mounttype');
537
		if (mountType) {
538
			data.mountType = mountType;
539
		}
540
		var path = div.attr('data-path');
541
		if (path) {
542
			data.path = path;
543
		}
544
		return data;
545
	}
546
547
};
548
549
550
OCA.Files.FullTextSearch = FullTextSearch;
551
552
$(document).ready(function () {
553
	OCA.Files.FullTextSearch = new FullTextSearch();
554
});
555
556
557
558