Skip to content

Commit

Permalink
Allow files to be copied through action menu & multiple files actions
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
  • Loading branch information
tcitworld committed Aug 27, 2017
1 parent a17aba4 commit b6b9244
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
14 changes: 14 additions & 0 deletions apps/files/js/fileactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,20 @@
}
});

this.registerAction({
name: 'Copy',
displayName: t('files', 'Copy'),
mime: 'all',
order: -25,
permissions: OC.PERMISSION_READ,
iconClass: 'icon-external',
actionHandler: function (filename, context) {
OC.dialogs.filepicker(t('files', 'Target folder'), function(targetPath) {
context.fileList.copy(filename, targetPath);
}, false, "httpd/unix-directory", true);
}
});

this.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
var dir = context.$file.attr('data-path') || context.fileList.getCurrentDirectory();
context.fileList.changeDirectory(OC.joinPaths(dir, filename), true, false, parseInt(context.$file.attr('data-id'), 10));
Expand Down
116 changes: 116 additions & 0 deletions apps/files/js/filelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@
this.$el.on('urlChanged', _.bind(this._onUrlChanged, this));
this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this));
this.$el.find('.download').click(_.bind(this._onClickDownloadSelected, this));
this.$el.find('.copy').click(_.bind(this._onClickCopySelected, this));
this.$el.find('.delete-selected').click(_.bind(this._onClickDeleteSelected, this));

this.$el.find('.selectedActions a').tooltip({placement:'top'});
Expand Down Expand Up @@ -757,6 +758,40 @@
return false;
},

/**
* Event handler for when clicking on "Copy" for the selected files
*/
_onClickCopySelected: function(event) {
var files;
var self = this;
var dir = this.getCurrentDirectory();
if (this.isAllSelected() && this.getSelectedFiles().length > 1) {
files = OC.basename(dir);
dir = OC.dirname(dir) || '/';
}
else {
files = _.pluck(this.getSelectedFiles(), 'name');
}

var copyFileAction = $('#selectedActionsList').find('.copy');

// don't allow a second click on the download action
if(copyFileAction.hasClass('disabled')) {
event.preventDefault();
return;
}

var disableLoadingState = function(){
OCA.Files.FileActions.updateFileActionSpinner(copyFileAction, false);
};

OCA.Files.FileActions.updateFileActionSpinner(copyFileAction, true);
OC.dialogs.filepicker(t('files', 'Target folder'), function(targetPath) {
self.copy(files, targetPath, disableLoadingState);
}, false, "httpd/unix-directory", true);
return false;
},

/**
* Event handler for when clicking on "Delete" for the selected files
*/
Expand Down Expand Up @@ -1944,6 +1979,7 @@
}
return index;
},

/**
* Moves a file to a given target folder.
*
Expand Down Expand Up @@ -2003,6 +2039,86 @@

},

/**
* Copies a file to a given target folder.
*
* @param fileNames array of file names to copy
* @param targetPath absolute target path
* @param callback to call when copy is finished with success
*/
copy: function(fileNames, targetPath, callback) {
var self = this;
var dir = this.getCurrentDirectory();
if (dir.charAt(dir.length - 1) !== '/') {
dir += '/';
}
if (!_.isArray(fileNames)) {
fileNames = [fileNames];
}
_.each(fileNames, function(fileName) {
var $tr = self.findFileEl(fileName);
self.showFileBusyState($tr, true);
if (targetPath.charAt(targetPath.length - 1) !== '/') {
// make sure we move the files into the target dir,
// not overwrite it
targetPath = targetPath + '/';
}
self.filesClient.copy(dir + fileName, targetPath + fileName)
.fail(function(status) {
if (status === 412) {
// TODO: some day here we should invoke the conflict dialog
OC.Notification.show(t('files', 'Could not copy "{file}", target exists',
{file: fileName}), {type: 'error'}
);
} else {
OC.Notification.show(t('files', 'Could not copy "{file}"',
{file: fileName}), {type: 'error'}
);
}
})
.always(function() {
self.showFileBusyState($tr, false);
});
});

// Remove leading and ending /
if (targetPath.slice(0, 1) === '/') {
targetPath = targetPath.slice(1, targetPath.length);
}
if (targetPath.slice(-1) === '/') {
targetPath = targetPath.slice(0, -1);
}

// Since there's no visual indication that the files were copied, let's send some notifications !
if (fileNames.length === 1) {
OC.Notification.show(t('files', 'Copied {origin} inside {destination}',
{
origin: fileNames[0],
destination: targetPath
}
), {timeout: 10});
} else if (fileNames.length < 4) {
OC.Notification.show(t('files', 'Copied {origin} inside {destination}',
{
origin: fileNames.join(', '),
destination: targetPath
}
), {timeout: 10});
} else {
OC.Notification.show(t('files', 'Copied {origin} and {nbfiles} other files inside {destination}',
{
origin: fileNames[0],
nbfiles: fileNames.length,
destination: targetPath,
}
), {timeout: 10});
}

if (callback) {
callback();
}
},

/**
* Updates the given row with the given file info
*
Expand Down
4 changes: 4 additions & 0 deletions apps/files/templates/list.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
</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="copy">
<span class="icon icon-external"></span>
<span><?php p($l->t('Copy'))?></span>
</a>
<a href="" class="download">
<span class="icon icon-download"></span>
<span><?php p($l->t('Download'))?></span>
Expand Down
45 changes: 45 additions & 0 deletions core/js/files/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,51 @@
return promise;
},

/**
* Copies path to another path
*
* @param {String} path path to copy
* @param {String} destinationPath destination path
* @param {boolean} [allowOverwrite=false] true to allow overwriting,
* false otherwise
*
* @return {Promise} promise
*/
copy: function (path, destinationPath, allowOverwrite) {
if (!path) {
throw 'Missing argument "path"';
}
if (!destinationPath) {
throw 'Missing argument "destinationPath"';
}

var self = this;
var deferred = $.Deferred();
var promise = deferred.promise();
var headers = {
'Destination' : this._buildUrl(destinationPath)
};

if (!allowOverwrite) {
headers.Overwrite = 'F';
}

this._client.request(
'COPY',
this._buildUrl(path),
headers
).then(
function(response) {
if (self._isSuccessStatus(response.status)) {
deferred.resolve(response.status);
} else {
deferred.reject(response.status);
}
}
);
return promise;
},

/**
* Add a file info parser function
*
Expand Down

0 comments on commit b6b9244

Please sign in to comment.