Merge pull request #11778 from nextcloud/versions-webui-dav

move versions webui over to the dav api
This commit is contained in:
Roeland Jago Douma 2018-10-23 20:21:05 +02:00 committed by GitHub
commit 530e39b061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 118 additions and 529 deletions

View File

@ -1,56 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Bart Visscher <bartv@thisnet.nl>
* @author Björn Schießle <bjoern@schiessle.org>
* @author Frank Karlitschek <frank@karlitschek.de>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Sam Tuke <mail@samtuke.com>
* @author Vincent Petry <pvince81@owncloud.com>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
\OC_JSON::checkLoggedIn();
\OC_JSON::callCheck();
\OC_JSON::checkAppEnabled('files_versions');
$source = (string)$_GET['source'];
$start = (int)$_GET['start'];
list ($uid, $filename) = OCA\Files_Versions\Storage::getUidAndFilename($source);
$count = 5; //show the newest revisions
$versions = OCA\Files_Versions\Storage::getVersions($uid, $filename, $source);
if( $versions ) {
$endReached = false;
if (count($versions) <= $start+$count) {
$endReached = true;
}
$versions = array_slice($versions, $start, $count);
// remove owner path from request to not disclose it to the recipient
foreach ($versions as $version) {
unset($version['path']);
}
\OC_JSON::success(array('data' => array('versions' => $versions, 'endReached' => $endReached)));
} else {
\OC_JSON::success(array('data' => array('versions' => [], 'endReached' => true)));
}

View File

@ -1,41 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Bart Visscher <bartv@thisnet.nl>
* @author Björn Schießle <bjoern@schiessle.org>
* @author Frank Karlitschek <frank@karlitschek.de>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Robin Appelman <robin@icewind.nl>
* @author Sam Tuke <mail@samtuke.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Thomas Tanghus <thomas@tanghus.net>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
\OC_JSON::checkLoggedIn();
\OC_JSON::checkAppEnabled('files_versions');
\OC_JSON::callCheck();
$file = (string)$_GET['file'];
$revision=(int)$_GET['revision'];
if(OCA\Files_Versions\Storage::rollback( $file, $revision )) {
\OC_JSON::success(array("data" => array( "revision" => $revision, "file" => $file )));
}else{
$l = \OC::$server->getL10N('files_versions');
\OC_JSON::error(array("data" => array( "message" => $l->t("Could not revert: %s", array($file) ))));
}

View File

@ -1,59 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Andreas Fischer <bantu@owncloud.com>
* @author Björn Schießle <bjoern@schiessle.org>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Vincent Petry <pvince81@owncloud.com>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
\OC_JSON::checkAppEnabled('files_versions');
\OC_JSON::checkLoggedIn();
$file = $_GET['file'];
$revision=(int)$_GET['revision'];
try {
list($uid, $filename) = OCA\Files_Versions\Storage::getUidAndFilename($file);
} catch(\OCP\Files\NotFoundException $e) {
http_response_code(404);
$tmpl = new OCP\Template('', '404', 'guest');
$tmpl->assign('file', '');
$tmpl->printPage();
exit();
}
$versionName = '/'.$uid.'/files_versions/'.$filename.'.v'.$revision;
$view = new OC\Files\View('/');
$ftype = \OC::$server->getMimeTypeDetector()->getSecureMimeType($view->getMimeType('/'.$uid.'/files/'.$filename));
header('Content-Type:'.$ftype);
\OC_Response::setContentDispositionHeader(basename($filename), 'attachment');
header('Pragma: public');// enable caching in IE
header('Expires: 0');
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
\OC_Response::setContentLengthHeader($view->filesize($versionName));
OC_Util::obEnd();
$view->readfile($versionName);

View File

@ -24,7 +24,9 @@ templates['item'] = template({"1":function(container,depth0,helpers,partials,dat
+ alias4(((helper = (helper = helpers.previewUrl || (depth0 != null ? depth0.previewUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"previewUrl","hash":{},"data":data}) : helper))) + alias4(((helper = (helper = helpers.previewUrl || (depth0 != null ? depth0.previewUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"previewUrl","hash":{},"data":data}) : helper)))
+ "\" width=\"44\" height=\"44\"/>\n </div>\n <div class=\"version-container\">\n <div>\n <a href=\"" + "\" width=\"44\" height=\"44\"/>\n </div>\n <div class=\"version-container\">\n <div>\n <a href=\""
+ alias4(((helper = (helper = helpers.downloadUrl || (depth0 != null ? depth0.downloadUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"downloadUrl","hash":{},"data":data}) : helper))) + alias4(((helper = (helper = helpers.downloadUrl || (depth0 != null ? depth0.downloadUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"downloadUrl","hash":{},"data":data}) : helper)))
+ "\" class=\"downloadVersion\"><img src=\"" + "\" class=\"downloadVersion\" download=\""
+ alias4(((helper = (helper = helpers.downloadName || (depth0 != null ? depth0.downloadName : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"downloadName","hash":{},"data":data}) : helper)))
+ "\"><img src=\""
+ alias4(((helper = (helper = helpers.downloadIconUrl || (depth0 != null ? depth0.downloadIconUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"downloadIconUrl","hash":{},"data":data}) : helper))) + alias4(((helper = (helper = helpers.downloadIconUrl || (depth0 != null ? depth0.downloadIconUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"downloadIconUrl","hash":{},"data":data}) : helper)))
+ "\" />\n <span class=\"versiondate has-tooltip live-relative-timestamp\" data-timestamp=\"" + "\" />\n <span class=\"versiondate has-tooltip live-relative-timestamp\" data-timestamp=\""
+ alias4(((helper = (helper = helpers.millisecondsTimestamp || (depth0 != null ? depth0.millisecondsTimestamp : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"millisecondsTimestamp","hash":{},"data":data}) : helper))) + alias4(((helper = (helper = helpers.millisecondsTimestamp || (depth0 != null ? depth0.millisecondsTimestamp : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"millisecondsTimestamp","hash":{},"data":data}) : helper)))

View File

@ -5,7 +5,7 @@
</div> </div>
<div class="version-container"> <div class="version-container">
<div> <div>
<a href="{{downloadUrl}}" class="downloadVersion"><img src="{{downloadIconUrl}}" /> <a href="{{downloadUrl}}" class="downloadVersion" download="{{downloadName}}"><img src="{{downloadIconUrl}}" />
<span class="versiondate has-tooltip live-relative-timestamp" data-timestamp="{{millisecondsTimestamp}}" title="{{formattedTimestamp}}">{{relativeTimestamp}}</span> <span class="versiondate has-tooltip live-relative-timestamp" data-timestamp="{{millisecondsTimestamp}}" title="{{formattedTimestamp}}">{{relativeTimestamp}}</span>
</a> </a>
</div> </div>

View File

@ -8,86 +8,72 @@
* *
*/ */
(function() { (function () {
/** /**
* @memberof OCA.Versions * @memberof OCA.Versions
*/ */
var VersionCollection = OC.Backbone.Collection.extend({ var VersionCollection = OC.Backbone.Collection.extend({
model: OCA.Versions.VersionModel, model: OCA.Versions.VersionModel,
sync: OC.Backbone.davSync,
/** /**
* @var OCA.Files.FileInfoModel * @var OCA.Files.FileInfoModel
*/ */
_fileInfo: null, _fileInfo: null,
_endReached: false, _currentUser: null,
_currentIndex: 0,
url: function() { _client: null,
var url = OC.generateUrl('/apps/files_versions/ajax/getVersions.php');
var query = {
source: this._fileInfo.getFullPath(),
start: this._currentIndex
};
return url + '?' + OC.buildQueryString(query);
},
setFileInfo: function(fileInfo) { setFileInfo: function (fileInfo) {
this._fileInfo = fileInfo; this._fileInfo = fileInfo;
// reset
this._endReached = false;
this._currentIndex = 0;
}, },
getFileInfo: function() { getFileInfo: function () {
return this._fileInfo; return this._fileInfo;
}, },
hasMoreResults: function() { setCurrentUser: function(user) {
return !this._endReached; this._currentUser = user;
}, },
fetch: function(options) { getCurrentUser: function() {
if (!options || options.remove) { return this._currentUser || OC.getCurrentUser().uid;
this._currentIndex = 0;
}
return OC.Backbone.Collection.prototype.fetch.apply(this, arguments);
}, },
/** setClient: function(client) {
* Fetch the next set of results this._client = client;
*/
fetchNext: function() {
if (!this.hasMoreResults()) {
return null;
}
if (this._currentIndex === 0) {
return this.fetch();
}
return this.fetch({remove: false});
}, },
reset: function() { getClient: function() {
this._currentIndex = 0; return this._client || new OC.Files.Client({
OC.Backbone.Collection.prototype.reset.apply(this, arguments); host: OC.getHost(),
root: OC.linkToRemoteBase('dav') + '/versions/' + this.getCurrentUser(),
useHTTPS: OC.getProtocol() === 'https'
});
},
url: function () {
return OC.linkToRemoteBase('dav') + '/versions/' + this.getCurrentUser() + '/versions/' + this._fileInfo.get('id');
}, },
parse: function(result) { parse: function(result) {
var fullPath = this._fileInfo.getFullPath(); var fullPath = this._fileInfo.getFullPath();
var results = _.map(result.data.versions, function(version) { var fileId = this._fileInfo.get('id');
var revision = parseInt(version.version, 10); var name = this._fileInfo.get('name');
return { var user = this.getCurrentUser();
id: revision, var client = this.getClient();
name: version.name, return _.map(result, function(version) {
fullPath: fullPath, version.fullPath = fullPath;
timestamp: revision, version.fileId = fileId;
size: version.size, version.name = name;
mimetype: version.mimetype version.timestamp = parseInt(moment(new Date(version.timestamp)).format('X'), 10);
}; version.id = parseInt(OC.basename(version.href), 10);
version.size = parseInt(version.size, 10);
version.user = user;
version.client = client;
return version;
}); });
this._endReached = result.data.endReached;
this._currentIndex += results.length;
return results;
} }
}); });

View File

@ -8,50 +8,50 @@
* *
*/ */
(function() { /* global moment */
(function () {
/** /**
* @memberof OCA.Versions * @memberof OCA.Versions
*/ */
var VersionModel = OC.Backbone.Model.extend({ var VersionModel = OC.Backbone.Model.extend({
sync: OC.Backbone.davSync,
davProperties: {
'size': '{DAV:}getcontentlength',
'mimetype': '{DAV:}getcontenttype',
'timestamp': '{DAV:}getlastmodified',
},
/** /**
* Restores the original file to this revision * Restores the original file to this revision
*/ */
revert: function(options) { revert: function (options) {
options = options ? _.clone(options) : {}; options = options ? _.clone(options) : {};
var model = this; var model = this;
var file = this.getFullPath();
var revision = this.get('timestamp');
$.ajax({ var client = this.get('client');
type: 'GET',
url: OC.generateUrl('/apps/files_versions/ajax/rollbackVersion.php'), return client.move('/versions/' + this.get('fileId') + '/' + this.get('id'), '/restore/target', true)
dataType: 'json', .done(function () {
data: { if (options.success) {
file: file, options.success.call(options.context, model, {}, options);
revision: revision
},
success: function(response) {
if (response.status === 'error') {
if (options.error) {
options.error.call(options.context, model, response, options);
}
model.trigger('error', model, response, options);
} else {
if (options.success) {
options.success.call(options.context, model, response, options);
}
model.trigger('revert', model, response, options);
} }
} model.trigger('revert', model, options);
}); })
.fail(function () {
if (options.error) {
options.error.call(options.context, model, {}, options);
}
model.trigger('error', model, {}, options);
});
}, },
getFullPath: function() { getFullPath: function () {
return this.get('fullPath'); return this.get('fullPath');
}, },
getPreviewUrl: function() { getPreviewUrl: function () {
var url = OC.generateUrl('/apps/files_versions/preview'); var url = OC.generateUrl('/apps/files_versions/preview');
var params = { var params = {
file: this.get('fullPath'), file: this.get('fullPath'),
@ -60,13 +60,8 @@
return url + '?' + OC.buildQueryString(params); return url + '?' + OC.buildQueryString(params);
}, },
getDownloadUrl: function() { getDownloadUrl: function () {
var url = OC.generateUrl('/apps/files_versions/download.php'); return OC.linkToRemoteBase('dav') + '/versions/' + this.get('user') + '/versions/' + this.get('fileId') + '/' + this.get('id');
var params = {
file: this.get('fullPath'),
revision: this.get('timestamp')
};
return url + '?' + OC.buildQueryString(params);
} }
}); });

View File

@ -8,14 +8,11 @@
* *
*/ */
/* @global Handlebars */
(function() { (function() {
/** /**
* @memberof OCA.Versions * @memberof OCA.Versions
*/ */
var VersionsTabView = OCA.Files.DetailTabView.extend( var VersionsTabView = OCA.Files.DetailTabView.extend(/** @lends OCA.Versions.VersionsTabView.prototype */{
/** @lends OCA.Versions.VersionsTabView.prototype */ {
id: 'versionsTabView', id: 'versionsTabView',
className: 'tab versionsTabView', className: 'tab versionsTabView',
@ -24,8 +21,7 @@
$versionsContainer: null, $versionsContainer: null,
events: { events: {
'click .revertVersion': '_onClickRevertVersion', 'click .revertVersion': '_onClickRevertVersion'
'click .showMoreVersions': '_onClickShowMoreVersions'
}, },
initialize: function() { initialize: function() {
@ -43,19 +39,14 @@
}, },
nextPage: function() { nextPage: function() {
if (this._loading || !this.collection.hasMoreResults()) { if (this._loading) {
return; return;
} }
if (this.collection.getFileInfo() && this.collection.getFileInfo().isDirectory()) { if (this.collection.getFileInfo() && this.collection.getFileInfo().isDirectory()) {
return; return;
} }
this.collection.fetchNext(); this.collection.fetch();
},
_onClickShowMoreVersions: function(ev) {
ev.preventDefault();
this.nextPage();
}, },
_onClickRevertVersion: function(ev) { _onClickRevertVersion: function(ev) {
@ -70,8 +61,6 @@
ev.preventDefault(); ev.preventDefault();
revision = $target.attr('data-revision'); revision = $target.attr('data-revision');
this.$el.find('.versions, .showMoreVersions').addClass('hidden');
var versionModel = this.collection.get(revision); var versionModel = this.collection.get(revision);
versionModel.revert({ versionModel.revert({
success: function() { success: function() {
@ -79,7 +68,7 @@
self.$versionsContainer.empty(); self.$versionsContainer.empty();
self.collection.setFileInfo(fileInfoModel); self.collection.setFileInfo(fileInfoModel);
self.collection.reset([], {silent: true}); self.collection.reset([], {silent: true});
self.collection.fetchNext(); self.collection.fetch();
self.$el.find('.versions').removeClass('hidden'); self.$el.find('.versions').removeClass('hidden');
@ -97,7 +86,7 @@
fileInfoModel.trigger('busy', fileInfoModel, false); fileInfoModel.trigger('busy', fileInfoModel, false);
self.$el.find('.versions').removeClass('hidden'); self.$el.find('.versions').removeClass('hidden');
self._toggleLoading(false); self._toggleLoading(false);
OC.Notification.show(t('files_version', 'Failed to revert {file} to revision {timestamp}.', OC.Notification.show(t('files_version', 'Failed to revert {file} to revision {timestamp}.',
{ {
file: versionModel.getFullPath(), file: versionModel.getFullPath(),
timestamp: OC.Util.formatDate(versionModel.get('timestamp') * 1000) timestamp: OC.Util.formatDate(versionModel.get('timestamp') * 1000)
@ -121,27 +110,16 @@
_onRequest: function() { _onRequest: function() {
this._toggleLoading(true); this._toggleLoading(true);
this.$el.find('.showMoreVersions').addClass('hidden');
}, },
_onEndRequest: function() { _onEndRequest: function() {
this._toggleLoading(false); this._toggleLoading(false);
this.$el.find('.empty').toggleClass('hidden', !!this.collection.length); this.$el.find('.empty').toggleClass('hidden', !!this.collection.length);
this.$el.find('.showMoreVersions').toggleClass('hidden', !this.collection.hasMoreResults());
}, },
_onAddModel: function(model) { _onAddModel: function(model) {
var $el = $(this.itemTemplate(this._formatItem(model))); var $el = $(this.itemTemplate(this._formatItem(model)));
this.$versionsContainer.append($el); this.$versionsContainer.append($el);
var preview = $el.find('.preview')[0];
this._lazyLoadPreview({
url: model.getPreviewUrl(),
mime: model.get('mimetype'),
callback: function(url) {
preview.src = url;
}
});
$el.find('.has-tooltip').tooltip(); $el.find('.has-tooltip').tooltip();
}, },
@ -168,8 +146,9 @@
_formatItem: function(version) { _formatItem: function(version) {
var timestamp = version.get('timestamp') * 1000; var timestamp = version.get('timestamp') * 1000;
var size = version.has('size') ? version.get('size') : 0; var size = version.has('size') ? version.get('size') : 0;
return _.extend({ return _.extend({
millisecondsTimestamp: timestamp, versionId: version.get('id'),
formattedTimestamp: OC.Util.formatDate(timestamp), formattedTimestamp: OC.Util.formatDate(timestamp),
relativeTimestamp: OC.Util.relativeModifiedDate(timestamp), relativeTimestamp: OC.Util.relativeModifiedDate(timestamp),
humanReadableSize: OC.Util.humanFileSize(size, true), humanReadableSize: OC.Util.humanFileSize(size, true),
@ -177,7 +156,9 @@
hasDetails: version.has('size'), hasDetails: version.has('size'),
downloadUrl: version.getDownloadUrl(), downloadUrl: version.getDownloadUrl(),
downloadIconUrl: OC.imagePath('core', 'actions/download'), downloadIconUrl: OC.imagePath('core', 'actions/download'),
downloadName: version.get('name'),
revertIconUrl: OC.imagePath('core', 'actions/history'), revertIconUrl: OC.imagePath('core', 'actions/history'),
previewUrl: version.getPreviewUrl(),
revertLabel: t('files_versions', 'Restore'), revertLabel: t('files_versions', 'Restore'),
canRevert: (this.collection.getFileInfo().get('permissions') & OC.PERMISSION_UPDATE) !== 0 canRevert: (this.collection.getFileInfo().get('permissions') & OC.PERMISSION_UPDATE) !== 0
}, version.attributes); }, version.attributes);
@ -188,8 +169,7 @@
*/ */
render: function() { render: function() {
this.$el.html(this.template({ this.$el.html(this.template({
emptyResultLabel: t('files_versions', 'No earlier versions available'), emptyResultLabel: t('files_versions', 'No other versions available'),
moreVersionsLabel: t('files_versions', 'More versions …')
})); }));
this.$el.find('.has-tooltip').tooltip(); this.$el.find('.has-tooltip').tooltip();
this.$versionsContainer = this.$el.find('ul.versions'); this.$versionsContainer = this.$el.find('ul.versions');
@ -206,38 +186,6 @@
return false; return false;
} }
return !fileInfo.isDirectory(); return !fileInfo.isDirectory();
},
/**
* Lazy load a file's preview.
*
* @param path path of the file
* @param mime mime type
* @param callback callback function to call when the image was loaded
* @param etag file etag (for caching)
*/
_lazyLoadPreview : function(options) {
var url = options.url;
var mime = options.mime;
var ready = options.callback;
// get mime icon url
var iconURL = OC.MimeType.getIconUrl(mime);
ready(iconURL); // set mimeicon URL
var img = new Image();
img.onload = function(){
// if loading the preview image failed (no preview for the mimetype) then img.width will < 5
if (img.width > 5) {
ready(url, img);
} else if (options.error) {
options.error();
}
};
if (options.error) {
img.onerror = options.error;
}
img.src = url;
} }
}); });

View File

@ -14,148 +14,21 @@ describe('OCA.Versions.VersionCollection', function() {
beforeEach(function() { beforeEach(function() {
fileInfoModel = new OCA.Files.FileInfoModel({ fileInfoModel = new OCA.Files.FileInfoModel({
path: '/subdir', path: '/subdir',
name: 'some file.txt' name: 'some file.txt',
id: 10,
}); });
collection = new VersionCollection(); collection = new VersionCollection();
collection.setFileInfo(fileInfoModel); collection.setFileInfo(fileInfoModel);
collection.setCurrentUser('user');
}); });
it('fetches the next page', function() { it('fetches the versions', function() {
collection.fetchNext(); collection.fetch();
expect(fakeServer.requests.length).toEqual(1); expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].url).toEqual( expect(fakeServer.requests[0].url).toEqual(
OC.generateUrl('apps/files_versions/ajax/getVersions.php') + OC.linkToRemoteBase('dav') + '/versions/user/versions/10'
'?source=%2Fsubdir%2Fsome%20file.txt&start=0'
); );
fakeServer.requests[0].respond( fakeServer.requests[0].respond(200);
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
endReached: false,
versions: [{
version: 10000000,
size: 123,
name: 'some file.txt',
fullPath: '/subdir/some file.txt'
},{
version: 15000000,
size: 150,
name: 'some file.txt',
path: '/subdir/some file.txt'
}]
}
})
);
expect(collection.length).toEqual(2);
expect(collection.hasMoreResults()).toEqual(true);
collection.fetchNext();
expect(fakeServer.requests.length).toEqual(2);
expect(fakeServer.requests[1].url).toEqual(
OC.generateUrl('apps/files_versions/ajax/getVersions.php') +
'?source=%2Fsubdir%2Fsome%20file.txt&start=2'
);
fakeServer.requests[1].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
endReached: true,
versions: [{
version: 18000000,
size: 123,
name: 'some file.txt',
path: '/subdir/some file.txt'
}]
}
})
);
expect(collection.length).toEqual(3);
expect(collection.hasMoreResults()).toEqual(false);
collection.fetchNext();
// no further requests
expect(fakeServer.requests.length).toEqual(2);
});
it('properly parses the results', function() {
collection.fetchNext();
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].url).toEqual(
OC.generateUrl('apps/files_versions/ajax/getVersions.php') +
'?source=%2Fsubdir%2Fsome%20file.txt&start=0'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
endReached: false,
versions: [{
version: 10000000,
size: 123,
name: 'some file.txt',
path: '/subdir/some file.txt'
},{
version: 15000000,
size: 150,
name: 'some file.txt',
path: '/subdir/some file.txt'
}]
}
})
);
expect(collection.length).toEqual(2);
var model = collection.at(0);
expect(model.get('id')).toEqual(10000000);
expect(model.get('timestamp')).toEqual(10000000);
expect(model.get('name')).toEqual('some file.txt');
expect(model.get('fullPath')).toEqual('/subdir/some file.txt');
expect(model.get('size')).toEqual(123);
model = collection.at(1);
expect(model.get('id')).toEqual(15000000);
expect(model.get('timestamp')).toEqual(15000000);
expect(model.get('name')).toEqual('some file.txt');
expect(model.get('fullPath')).toEqual('/subdir/some file.txt');
expect(model.get('size')).toEqual(150);
});
it('resets page counted when setting a new file info model', function() {
collection.fetchNext();
expect(fakeServer.requests.length).toEqual(1);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
endReached: true,
versions: [{
version: 18000000,
size: 123,
name: 'some file.txt',
path: '/subdir/some file.txt'
}]
}
})
);
expect(collection.hasMoreResults()).toEqual(false);
collection.setFileInfo(fileInfoModel);
expect(collection.hasMoreResults()).toEqual(true);
}); });
}); });

View File

@ -10,14 +10,23 @@
describe('OCA.Versions.VersionModel', function() { describe('OCA.Versions.VersionModel', function() {
var VersionModel = OCA.Versions.VersionModel; var VersionModel = OCA.Versions.VersionModel;
var model; var model;
var uid = OC.currentUser = 'user';
beforeEach(function() { beforeEach(function() {
model = new VersionModel({ model = new VersionModel({
id: 10000000, id: 10000000,
fileId: 10,
timestamp: 10000000, timestamp: 10000000,
fullPath: '/subdir/some file.txt', fullPath: '/subdir/some file.txt',
name: 'some file.txt', name: 'some file.txt',
size: 150 size: 150,
user: 'user',
client: new OC.Files.Client({
host: 'localhost',
port: 80,
root: '/remote.php/dav/versions/user',
useHTTPS: OC.getProtocol() === 'https'
})
}); });
}); });
@ -32,8 +41,8 @@ describe('OCA.Versions.VersionModel', function() {
}); });
it('returns the download url', function() { it('returns the download url', function() {
expect(model.getDownloadUrl()) expect(model.getDownloadUrl())
.toEqual(OC.generateUrl('/apps/files_versions/download.php') + .toEqual(OC.linkToRemoteBase('dav') + '/versions/' + uid +
'?file=%2Fsubdir%2Fsome%20file.txt&revision=10000000' '/versions/10/10000000'
); );
}); });
describe('reverting', function() { describe('reverting', function() {
@ -50,46 +59,40 @@ describe('OCA.Versions.VersionModel', function() {
model.on('error', errorStub); model.on('error', errorStub);
}); });
it('tells the server to revert when calling the revert method', function() { it('tells the server to revert when calling the revert method', function() {
model.revert({ var promise = model.revert({
success: successStub success: successStub
}); });
expect(fakeServer.requests.length).toEqual(1); expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].url) var request = fakeServer.requests[0];
expect(request.url)
.toEqual( .toEqual(
OC.generateUrl('/apps/files_versions/ajax/rollbackVersion.php') + OC.linkToRemoteBase('dav') + '/versions/user/versions/10/10000000'
'?file=%2Fsubdir%2Fsome+file.txt&revision=10000000'
); );
expect(request.requestHeaders.Destination).toEqual(OC.getRootPath() + '/remote.php/dav/versions/user/restore/target');
request.respond(201);
fakeServer.requests[0].respond( promise.then(function() {
200, expect(revertEventStub.calledOnce).toEqual(true);
{ 'Content-Type': 'application/json' }, expect(successStub.calledOnce).toEqual(true);
JSON.stringify({ expect(errorStub.notCalled).toEqual(true);
status: 'success', });
})
);
expect(revertEventStub.calledOnce).toEqual(true); return promise;
expect(successStub.calledOnce).toEqual(true);
expect(errorStub.notCalled).toEqual(true);
}); });
it('triggers error event when server returns a failure', function() { it('triggers error event when server returns a failure', function() {
model.revert({ var promise = model.revert({
success: successStub success: successStub
}); });
expect(fakeServer.requests.length).toEqual(1); expect(fakeServer.requests.length).toEqual(1);
fakeServer.requests[0].respond( fakeServer.requests[0].respond(404);
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'error',
})
);
expect(revertEventStub.notCalled).toEqual(true); promise.then(function() {
expect(successStub.notCalled).toEqual(true); expect(revertEventStub.notCalled).toEqual(true);
expect(errorStub.calledOnce).toEqual(true); expect(successStub.notCalled).toEqual(true);
expect(errorStub.calledOnce).toEqual(true);
});
}); });
}); });
}); });

View File

@ -82,14 +82,12 @@ describe('OCA.Versions.VersionsTabView', function() {
expect($item.find('.versiondate').text()).toEqual('seconds ago'); expect($item.find('.versiondate').text()).toEqual('seconds ago');
expect($item.find('.size').text()).toEqual('< 1 KB'); expect($item.find('.size').text()).toEqual('< 1 KB');
expect($item.find('.revertVersion').length).toEqual(1); expect($item.find('.revertVersion').length).toEqual(1);
expect($item.find('.preview').attr('src')).toEqual('http://localhost/core/img/filetypes/text.svg');
$item = $versions.eq(1); $item = $versions.eq(1);
expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl()); expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl());
expect($item.find('.versiondate').text()).toEqual('2 days ago'); expect($item.find('.versiondate').text()).toEqual('2 days ago');
expect($item.find('.size').text()).toEqual('< 1 KB'); expect($item.find('.size').text()).toEqual('< 1 KB');
expect($item.find('.revertVersion').length).toEqual(1); expect($item.find('.revertVersion').length).toEqual(1);
expect($item.find('.preview').attr('src')).toEqual('http://localhost/core/img/filetypes/text.svg');
}); });
it('does not render revert button when no update permissions', function() { it('does not render revert button when no update permissions', function() {
@ -106,71 +104,11 @@ describe('OCA.Versions.VersionsTabView', function() {
expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl()); expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl());
expect($item.find('.versiondate').text()).toEqual('seconds ago'); expect($item.find('.versiondate').text()).toEqual('seconds ago');
expect($item.find('.revertVersion').length).toEqual(0); expect($item.find('.revertVersion').length).toEqual(0);
expect($item.find('.preview').attr('src')).toEqual('http://localhost/core/img/filetypes/text.svg');
$item = $versions.eq(1); $item = $versions.eq(1);
expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl()); expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl());
expect($item.find('.versiondate').text()).toEqual('2 days ago'); expect($item.find('.versiondate').text()).toEqual('2 days ago');
expect($item.find('.revertVersion').length).toEqual(0); expect($item.find('.revertVersion').length).toEqual(0);
expect($item.find('.preview').attr('src')).toEqual('http://localhost/core/img/filetypes/text.svg');
});
});
describe('More versions', function() {
var hasMoreResultsStub;
beforeEach(function() {
tabView.setFileInfo(fileInfoModel);
fetchStub.reset();
tabView.collection.set(testVersions);
hasMoreResultsStub = sinon.stub(VersionCollection.prototype, 'hasMoreResults');
});
afterEach(function() {
hasMoreResultsStub.restore();
});
it('shows "More versions" button when more versions are available', function() {
hasMoreResultsStub.returns(true);
tabView.collection.trigger('sync');
expect(tabView.$el.find('.showMoreVersions').hasClass('hidden')).toEqual(false);
});
it('does not show "More versions" button when more versions are available', function() {
hasMoreResultsStub.returns(false);
tabView.collection.trigger('sync');
expect(tabView.$el.find('.showMoreVersions').hasClass('hidden')).toEqual(true);
});
it('fetches and appends the next page when clicking the "More" button', function() {
hasMoreResultsStub.returns(true);
expect(fetchStub.notCalled).toEqual(true);
tabView.$el.find('.showMoreVersions').click();
expect(fetchStub.calledOnce).toEqual(true);
});
it('appends version to the list when added to collection', function() {
var time3 = Date.UTC(2015, 6, 10, 1, 0, 0, 0) / 1000;
var version3 = new VersionModel({
id: time3,
timestamp: time3,
name: 'some file.txt',
size: 54,
fullPath: '/subdir/some file.txt',
mimetype: 'text/plain'
});
tabView.collection.add(version3);
expect(tabView.$el.find('.versions>li').length).toEqual(3);
var $item = tabView.$el.find('.versions>li').eq(2);
expect($item.find('.downloadVersion').attr('href')).toEqual(version3.getDownloadUrl());
expect($item.find('.versiondate').text()).toEqual('7 days ago');
expect($item.find('.revertVersion').length).toEqual(1);
expect($item.find('.preview').attr('src')).toEqual('http://localhost/core/img/filetypes/text.svg');
}); });
}); });