Signed-off-by: Louis Chemineau <louis@chmn.me>tags/v26.0.0beta1
@@ -20,6 +20,7 @@ | |||
* | |||
*/ | |||
// eslint-disable-next-line node/no-missing-import, import/no-unresolved | |||
import MessageReplyText from '@mdi/svg/svg/message-reply-text.svg?raw' | |||
// Init Comments tab component | |||
@@ -53,7 +54,7 @@ const commentTab = new OCA.Files.Sidebar.Tab({ | |||
}, | |||
}) | |||
window.addEventListener('DOMContentLoaded', function () { | |||
window.addEventListener('DOMContentLoaded', function() { | |||
if (OCA.Files && OCA.Files.Sidebar) { | |||
OCA.Files.Sidebar.registerTab(commentTab) | |||
} |
@@ -84,7 +84,6 @@ export default class Tab { | |||
this._id = id | |||
this._name = name | |||
this._icon = icon | |||
this._iconSvg = iconSvg | |||
this._mount = mount | |||
this._update = update | |||
this._destroy = destroy |
@@ -518,7 +518,7 @@ export default { | |||
::v-deep svg { | |||
width: 20px; | |||
height: 20px; | |||
fill: var(--color-main-text); | |||
fill: currentColor; | |||
} | |||
} | |||
} |
@@ -31,6 +31,7 @@ import ExternalLinkActions from './services/ExternalLinkActions.js' | |||
import ExternalShareActions from './services/ExternalShareActions.js' | |||
import TabSections from './services/TabSections.js' | |||
// eslint-disable-next-line node/no-missing-import, import/no-unresolved | |||
import ShareVariant from '@mdi/svg/svg/share-variant.svg?raw' | |||
// Init Sharing Tab Service | |||
@@ -50,7 +51,7 @@ Vue.use(VueClipboard) | |||
const View = Vue.extend(SharingTab) | |||
let TabInstance = null | |||
window.addEventListener('DOMContentLoaded', function () { | |||
window.addEventListener('DOMContentLoaded', function() { | |||
if (OCA.Files && OCA.Files.Sidebar) { | |||
OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab({ | |||
id: 'sharing', |
@@ -22,6 +22,7 @@ import { translate as t, translatePlural as n } from '@nextcloud/l10n' | |||
import VersionTab from './views/VersionTab.vue' | |||
import VTooltip from 'v-tooltip' | |||
// eslint-disable-next-line node/no-missing-import, import/no-unresolved | |||
import BackupRestore from '@mdi/svg/svg/backup-restore.svg?raw' | |||
Vue.prototype.t = t | |||
@@ -33,7 +34,7 @@ Vue.use(VTooltip) | |||
const View = Vue.extend(VersionTab) | |||
let TabInstance = null | |||
window.addEventListener('DOMContentLoaded', function () { | |||
window.addEventListener('DOMContentLoaded', function() { | |||
if (OCA.Files?.Sidebar === undefined) { | |||
return | |||
} |
@@ -29,7 +29,7 @@ import { translate } from '@nextcloud/l10n' | |||
import moment from '@nextcloud/moment' | |||
/** | |||
* @typedef {Object} Version | |||
* @typedef {object} Version | |||
* @property {string} title - 'Current version' or '' | |||
* @property {string} fileName - File name relative to the version DAV endpoint | |||
* @property {string} mimeType - Empty for the current version, else the actual mime type of the version |
@@ -1,48 +0,0 @@ | |||
/** | |||
* Copyright (c) 2015 | |||
* | |||
* @author Robin Appelman <robin@icewind.nl> | |||
* @author Vincent Petry <vincent@nextcloud.com> | |||
* | |||
* @license AGPL-3.0-or-later | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* 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 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
describe('OCA.Versions.VersionCollection', function() { | |||
var VersionCollection = OCA.Versions.VersionCollection; | |||
var collection, fileInfoModel; | |||
beforeEach(function() { | |||
fileInfoModel = new OCA.Files.FileInfoModel({ | |||
path: '/subdir', | |||
name: 'some file.txt', | |||
id: 10, | |||
}); | |||
collection = new VersionCollection(); | |||
collection.setFileInfo(fileInfoModel); | |||
collection.setCurrentUser('user'); | |||
}); | |||
it('fetches the versions', function() { | |||
collection.fetch(); | |||
expect(fakeServer.requests.length).toEqual(1); | |||
expect(fakeServer.requests[0].url).toEqual( | |||
OC.linkToRemoteBase('dav') + '/versions/user/versions/10' | |||
); | |||
fakeServer.requests[0].respond(200); | |||
}); | |||
}); | |||
@@ -1,124 +0,0 @@ | |||
/** | |||
* Copyright (c) 2015 | |||
* | |||
* @author Daniel Calviño Sánchez <danxuliu@gmail.com> | |||
* @author Robin Appelman <robin@icewind.nl> | |||
* @author Vincent Petry <vincent@nextcloud.com> | |||
* | |||
* @license AGPL-3.0-or-later | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* 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 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
describe('OCA.Versions.VersionModel', function() { | |||
var VersionModel = OCA.Versions.VersionModel; | |||
var model; | |||
var uid = OC.currentUser = 'user'; | |||
beforeEach(function() { | |||
model = new VersionModel({ | |||
id: 10000000, | |||
fileId: 10, | |||
timestamp: 10000000, | |||
fullPath: '/subdir/some file.txt', | |||
name: 'some file.txt', | |||
size: 150, | |||
user: 'user', | |||
client: new OC.Files.Client({ | |||
host: 'localhost', | |||
port: 80, | |||
root: '/remote.php/dav/versions/user', | |||
useHTTPS: OC.getProtocol() === 'https' | |||
}) | |||
}); | |||
}); | |||
it('returns the full path', function() { | |||
expect(model.getFullPath()).toEqual('/subdir/some file.txt'); | |||
}); | |||
it('returns the preview url', function() { | |||
expect(model.getPreviewUrl()) | |||
.toEqual(OC.generateUrl('/apps/files_versions/preview') + | |||
'?file=%2Fsubdir%2Fsome%20file.txt&version=10000000' | |||
); | |||
}); | |||
it('returns the download url', function() { | |||
expect(model.getDownloadUrl()) | |||
.toEqual(OC.linkToRemoteBase('dav') + '/versions/' + uid + | |||
'/versions/10/10000000' | |||
); | |||
}); | |||
describe('reverting', function() { | |||
var revertEventStub; | |||
var successStub; | |||
var errorStub; | |||
beforeEach(function() { | |||
revertEventStub = sinon.stub(); | |||
errorStub = sinon.stub(); | |||
successStub = sinon.stub(); | |||
model.on('revert', revertEventStub); | |||
model.on('error', errorStub); | |||
}); | |||
it('tells the server to revert when calling the revert method', function(done) { | |||
var promise = model.revert({ | |||
success: successStub | |||
}); | |||
expect(fakeServer.requests.length).toEqual(1); | |||
var request = fakeServer.requests[0]; | |||
expect(request.url) | |||
.toEqual( | |||
OC.linkToRemoteBase('dav') + '/versions/user/versions/10/10000000' | |||
); | |||
expect(request.requestHeaders.Destination).toEqual(OC.getRootPath() + '/remote.php/dav/versions/user/restore/target'); | |||
request.respond(201); | |||
promise.then(function() { | |||
expect(revertEventStub.calledOnce).toEqual(true); | |||
expect(successStub.calledOnce).toEqual(true); | |||
expect(errorStub.notCalled).toEqual(true); | |||
done(); | |||
}); | |||
}); | |||
it('triggers error event when server returns a failure', function(done) { | |||
var promise = model.revert({ | |||
success: successStub | |||
}); | |||
expect(fakeServer.requests.length).toEqual(1); | |||
var responseErrorHeaders = { | |||
"Content-Type": "application/xml" | |||
}; | |||
var responseErrorBody = | |||
'<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">' + | |||
' <s:exception>Sabre\\DAV\\Exception\\SomeException</s:exception>' + | |||
' <s:message>Some error message</s:message>' + | |||
'</d:error>'; | |||
fakeServer.requests[0].respond(404, responseErrorHeaders, responseErrorBody); | |||
promise.fail(function() { | |||
expect(revertEventStub.notCalled).toEqual(true); | |||
expect(successStub.notCalled).toEqual(true); | |||
expect(errorStub.calledOnce).toEqual(true); | |||
done(); | |||
}); | |||
}); | |||
}); | |||
}); | |||
@@ -1,193 +0,0 @@ | |||
/** | |||
* Copyright (c) 2015 | |||
* | |||
* @author Michael Jobst <mjobst+github@tecratech.de> | |||
* @author Morris Jobke <hey@morrisjobke.de> | |||
* @author noveens <noveen.sachdeva@research.iiit.ac.in> | |||
* @author Roeland Jago Douma <roeland@famdouma.nl> | |||
* @author Vincent Petry <vincent@nextcloud.com> | |||
* | |||
* @license AGPL-3.0-or-later | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* 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 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
describe('OCA.Versions.VersionsTabView', function() { | |||
var VersionCollection = OCA.Versions.VersionCollection; | |||
var VersionModel = OCA.Versions.VersionModel; | |||
var VersionsTabView = OCA.Versions.VersionsTabView; | |||
var fetchStub, fileInfoModel, tabView, testVersions, clock; | |||
beforeEach(function() { | |||
clock = sinon.useFakeTimers(Date.UTC(2015, 6, 17, 1, 2, 0, 3)); | |||
var time1 = Date.UTC(2015, 6, 17, 1, 2, 0, 3) / 1000; | |||
var time2 = Date.UTC(2015, 6, 15, 1, 2, 0, 3) / 1000; | |||
var version1 = new VersionModel({ | |||
id: time1, | |||
timestamp: time1, | |||
name: 'some file.txt', | |||
size: 140, | |||
fullPath: '/subdir/some file.txt', | |||
mimetype: 'text/plain' | |||
}); | |||
var version2 = new VersionModel({ | |||
id: time2, | |||
timestamp: time2, | |||
name: 'some file.txt', | |||
size: 150, | |||
fullPath: '/subdir/some file.txt', | |||
mimetype: 'text/plain' | |||
}); | |||
testVersions = [version1, version2]; | |||
fetchStub = sinon.stub(VersionCollection.prototype, 'fetch'); | |||
fileInfoModel = new OCA.Files.FileInfoModel({ | |||
id: 123, | |||
name: 'test.txt', | |||
permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE | |||
}); | |||
tabView = new VersionsTabView(); | |||
tabView.render(); | |||
}); | |||
afterEach(function() { | |||
fetchStub.restore(); | |||
tabView.remove(); | |||
clock.restore(); | |||
}); | |||
describe('rendering', function() { | |||
it('reloads matching versions when setting file info model', function() { | |||
tabView.setFileInfo(fileInfoModel); | |||
expect(fetchStub.calledOnce).toEqual(true); | |||
}); | |||
it('renders loading icon while fetching versions', function() { | |||
tabView.setFileInfo(fileInfoModel); | |||
tabView.collection.trigger('request'); | |||
expect(tabView.$el.find('.loading').length).toEqual(1); | |||
expect(tabView.$el.find('.versions li').length).toEqual(0); | |||
}); | |||
it('renders versions', function() { | |||
tabView.setFileInfo(fileInfoModel); | |||
tabView.collection.set(testVersions); | |||
var version1 = testVersions[0]; | |||
var version2 = testVersions[1]; | |||
var $versions = tabView.$el.find('.versions>li'); | |||
expect($versions.length).toEqual(2); | |||
var $item = $versions.eq(0); | |||
expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl()); | |||
expect($item.find('.versiondate').text()).toEqual('seconds ago'); | |||
expect($item.find('.size').text()).toEqual('< 1 KB'); | |||
expect($item.find('.revertVersion').length).toEqual(1); | |||
$item = $versions.eq(1); | |||
expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl()); | |||
expect($item.find('.versiondate').text()).toEqual('2 days ago'); | |||
expect($item.find('.size').text()).toEqual('< 1 KB'); | |||
expect($item.find('.revertVersion').length).toEqual(1); | |||
}); | |||
it('does not render revert button when no update permissions', function() { | |||
fileInfoModel.set('permissions', OC.PERMISSION_READ); | |||
tabView.setFileInfo(fileInfoModel); | |||
tabView.collection.set(testVersions); | |||
var version1 = testVersions[0]; | |||
var version2 = testVersions[1]; | |||
var $versions = tabView.$el.find('.versions>li'); | |||
expect($versions.length).toEqual(2); | |||
var $item = $versions.eq(0); | |||
expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl()); | |||
expect($item.find('.versiondate').text()).toEqual('seconds ago'); | |||
expect($item.find('.revertVersion').length).toEqual(0); | |||
$item = $versions.eq(1); | |||
expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl()); | |||
expect($item.find('.versiondate').text()).toEqual('2 days ago'); | |||
expect($item.find('.revertVersion').length).toEqual(0); | |||
}); | |||
}); | |||
describe('Reverting', function() { | |||
var revertStub; | |||
beforeEach(function() { | |||
revertStub = sinon.stub(VersionModel.prototype, 'revert'); | |||
tabView.setFileInfo(fileInfoModel); | |||
tabView.collection.set(testVersions); | |||
}); | |||
afterEach(function() { | |||
revertStub.restore(); | |||
}); | |||
it('tells the model to revert when clicking "Revert"', function() { | |||
tabView.$el.find('.revertVersion').eq(1).click(); | |||
expect(revertStub.calledOnce).toEqual(true); | |||
}); | |||
it('triggers busy state during revert', function() { | |||
var busyStub = sinon.stub(); | |||
fileInfoModel.on('busy', busyStub); | |||
tabView.$el.find('.revertVersion').eq(1).click(); | |||
expect(busyStub.calledOnce).toEqual(true); | |||
expect(busyStub.calledWith(fileInfoModel, true)).toEqual(true); | |||
busyStub.reset(); | |||
revertStub.getCall(0).args[0].success(); | |||
expect(busyStub.calledOnce).toEqual(true); | |||
expect(busyStub.calledWith(fileInfoModel, false)).toEqual(true); | |||
}); | |||
it('updates the file info model with the information from the reverted revision', function() { | |||
var changeStub = sinon.stub(); | |||
fileInfoModel.on('change', changeStub); | |||
tabView.$el.find('.revertVersion').eq(1).click(); | |||
expect(changeStub.notCalled).toEqual(true); | |||
revertStub.getCall(0).args[0].success(); | |||
expect(changeStub.calledOnce).toEqual(true); | |||
var changes = changeStub.getCall(0).args[0].changed; | |||
expect(changes.size).toEqual(150); | |||
expect(changes.mtime).toEqual(testVersions[1].get('timestamp') * 1000); | |||
expect(changes.etag).toBeDefined(); | |||
}); | |||
it('shows notification on revert error', function() { | |||
var notificationStub = sinon.stub(OC.Notification, 'show'); | |||
tabView.$el.find('.revertVersion').eq(1).click(); | |||
revertStub.getCall(0).args[0].error(); | |||
expect(notificationStub.calledOnce).toEqual(true); | |||
notificationStub.restore(); | |||
}); | |||
}); | |||
}); |