summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2016-05-10 09:44:50 +0200
committerLukas Reschke <lukas@statuscode.ch>2016-05-10 09:44:50 +0200
commite8e72aa9101b1c4b7e321dd3f17dcc9462f34a8f (patch)
tree0eec63cb17f7ad60130474a0bbdcbfaaa281d884 /apps
parent1fb7be42e55236c2663b52f89a85b54d81ae08ba (diff)
parent254576e1f7f5ec610ddbd9de81005397191cf52f (diff)
downloadnextcloud-server-e8e72aa9101b1c4b7e321dd3f17dcc9462f34a8f.tar.gz
nextcloud-server-e8e72aa9101b1c4b7e321dd3f17dcc9462f34a8f.zip
Merge pull request #24434 from owncloud/permalinks
Permalinks
Diffstat (limited to 'apps')
-rw-r--r--apps/files/appinfo/application.php15
-rw-r--r--apps/files/controller/viewcontroller.php48
-rw-r--r--apps/files/css/detailsView.css13
-rw-r--r--apps/files/js/app.js37
-rw-r--r--apps/files/js/fileactions.js2
-rw-r--r--apps/files/js/filelist.js36
-rw-r--r--apps/files/js/mainfileinfodetailview.js38
-rw-r--r--apps/files/tests/controller/ViewControllerTest.php103
-rw-r--r--apps/files/tests/js/appSpec.js36
-rw-r--r--apps/files/tests/js/filelistSpec.js9
-rw-r--r--apps/files/tests/js/mainfileinfodetailviewSpec.js5
11 files changed, 317 insertions, 25 deletions
diff --git a/apps/files/appinfo/application.php b/apps/files/appinfo/application.php
index 2d2decf6288..3dd73037871 100644
--- a/apps/files/appinfo/application.php
+++ b/apps/files/appinfo/application.php
@@ -26,6 +26,7 @@ use OCA\Files\Controller\ApiController;
use OCP\AppFramework\App;
use \OCA\Files\Service\TagService;
use \OCP\IContainer;
+use OCA\Files\Controller\ViewController;
class Application extends App {
public function __construct(array $urlParams=array()) {
@@ -48,6 +49,20 @@ class Application extends App {
);
});
+ $container->registerService('ViewController', function (IContainer $c) use ($server) {
+ return new ViewController(
+ $c->query('AppName'),
+ $c->query('Request'),
+ $server->getURLGenerator(),
+ $server->getNavigationManager(),
+ $c->query('L10N'),
+ $server->getConfig(),
+ $server->getEventDispatcher(),
+ $server->getUserSession(),
+ $server->getUserFolder()
+ );
+ });
+
/**
* Core
*/
diff --git a/apps/files/controller/viewcontroller.php b/apps/files/controller/viewcontroller.php
index ded6fd555df..6ee924e2f0b 100644
--- a/apps/files/controller/viewcontroller.php
+++ b/apps/files/controller/viewcontroller.php
@@ -3,6 +3,7 @@
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Lukas Reschke <lukas@owncloud.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Vincent Petry <pvince81@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
@@ -26,6 +27,7 @@ namespace OCA\Files\Controller;
use OC\AppFramework\Http\Request;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\ContentSecurityPolicy;
+use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
@@ -35,6 +37,8 @@ use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserSession;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use OCP\AppFramework\Http\NotFoundResponse;
+use OCP\Files\Folder;
/**
* Class ViewController
@@ -58,6 +62,8 @@ class ViewController extends Controller {
protected $eventDispatcher;
/** @var IUserSession */
protected $userSession;
+ /** @var \OCP\Files\Folder */
+ protected $userFolder;
/**
* @param string $appName
@@ -68,6 +74,7 @@ class ViewController extends Controller {
* @param IConfig $config
* @param EventDispatcherInterface $eventDispatcherInterface
* @param IUserSession $userSession
+ * @param Folder $userFolder
*/
public function __construct($appName,
IRequest $request,
@@ -76,7 +83,9 @@ class ViewController extends Controller {
IL10N $l10n,
IConfig $config,
EventDispatcherInterface $eventDispatcherInterface,
- IUserSession $userSession) {
+ IUserSession $userSession,
+ Folder $userFolder
+ ) {
parent::__construct($appName, $request);
$this->appName = $appName;
$this->request = $request;
@@ -86,6 +95,7 @@ class ViewController extends Controller {
$this->config = $config;
$this->eventDispatcher = $eventDispatcherInterface;
$this->userSession = $userSession;
+ $this->userFolder = $userFolder;
}
/**
@@ -124,10 +134,15 @@ class ViewController extends Controller {
*
* @param string $dir
* @param string $view
+ * @param string $fileid
* @return TemplateResponse
* @throws \OCP\Files\NotFoundException
*/
- public function index($dir = '', $view = '') {
+ public function index($dir = '', $view = '', $fileid = null) {
+ if ($fileid !== null) {
+ return $this->showFile($fileid);
+ }
+
$nav = new \OCP\Template('files', 'appnavigation', '');
// Load the files we need
@@ -239,4 +254,33 @@ class ViewController extends Controller {
return $response;
}
+
+ /**
+ * Redirects to the file list and highlight the given file id
+ *
+ * @param string $fileId file id to show
+ * @return Response redirect response or not found response
+ *
+ * @NoCSRFRequired
+ * @NoAdminRequired
+ */
+ public function showFile($fileId) {
+ $files = $this->userFolder->getById($fileId);
+ $params = [];
+
+ if (!empty($files)) {
+ $file = current($files);
+ if ($file instanceof Folder) {
+ // set the full path to enter the folder
+ $params['dir'] = $this->userFolder->getRelativePath($file->getPath());
+ } else {
+ // set parent path as dir
+ $params['dir'] = $this->userFolder->getRelativePath($file->getParent()->getPath());
+ // and scroll to the entry
+ $params['scrollto'] = $file->getName();
+ }
+ return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params));
+ }
+ return new NotFoundResponse();
+ }
}
diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
index c77bb28c774..669a15c4e38 100644
--- a/apps/files/css/detailsView.css
+++ b/apps/files/css/detailsView.css
@@ -14,6 +14,19 @@
width: 100%;
}
+#app-sidebar .mainFileInfoView .icon {
+ display: inline-block;
+}
+
+#app-sidebar .mainFileInfoView .permalink {
+ margin-left: 10px;
+ opacity: .5;
+}
+#app-sidebar .mainFileInfoView .permalink-field>input {
+ clear: both;
+ width: 90%;
+}
+
#app-sidebar .file-details-container {
display: inline-block;
float: left;
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index eac080a009d..7a3d78f9663 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -174,6 +174,7 @@
// detect when app changed their current directory
$('#app-content').delegate('>div', 'changeDirectory', _.bind(this._onDirectoryChanged, this));
+ $('#app-content').delegate('>div', 'afterChangeDirectory', _.bind(this._onAfterDirectoryChanged, this));
$('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this));
$('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this));
@@ -224,7 +225,16 @@
*/
_onDirectoryChanged: function(e) {
if (e.dir) {
- this._changeUrl(this.navigation.getActiveItem(), e.dir);
+ this._changeUrl(this.navigation.getActiveItem(), e.dir, e.fileId);
+ }
+ },
+
+ /**
+ * Event handler for when an app notified that its directory changed
+ */
+ _onAfterDirectoryChanged: function(e) {
+ if (e.dir && e.fileId) {
+ this._changeUrl(this.navigation.getActiveItem(), e.dir, e.fileId);
}
},
@@ -261,14 +271,35 @@
},
/**
+ * Encode URL params into a string, except for the "dir" attribute
+ * that gets encoded as path where "/" is not encoded
+ *
+ * @param {Object.<string>} params
+ * @return {string} encoded params
+ */
+ _makeUrlParams: function(params) {
+ var dir = params.dir;
+ delete params.dir;
+ return 'dir=' + OC.encodePath(dir) + '&' + OC.buildQueryString(params);
+ },
+
+ /**
* Change the URL to point to the given dir and view
*/
- _changeUrl: function(view, dir) {
+ _changeUrl: function(view, dir, fileId) {
var params = {dir: dir};
if (view !== 'files') {
params.view = view;
+ } else if (fileId) {
+ params.fileid = fileId;
+ }
+ var currentParams = OC.Util.History.parseUrlQuery();
+ if (currentParams.dir === params.dir && currentParams.view === params.view && currentParams.fileid !== params.fileid) {
+ // if only fileid changed or was added, replace instead of push
+ OC.Util.History.replaceState(this._makeUrlParams(params));
+ } else {
+ OC.Util.History.pushState(this._makeUrlParams(params));
}
- OC.Util.History.pushState(params);
}
};
})();
diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index 69e32d500c4..c3d4fba9ef5 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -619,7 +619,7 @@
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));
+ context.fileList.changeDirectory(OC.joinPaths(dir, filename), true, false, parseInt(context.$file.attr('data-id'), 10));
});
this.registerAction({
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 16ca5e91ed2..9395112bce3 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -1362,19 +1362,20 @@
return parseInt(this.$el.find('#permissions').val(), 10);
},
/**
- * @brief Changes the current directory and reload the file list.
- * @param targetDir target directory (non URL encoded)
- * @param changeUrl false if the URL must not be changed (defaults to true)
- * @param {boolean} force set to true to force changing directory
+ * Changes the current directory and reload the file list.
+ * @param {string} targetDir target directory (non URL encoded)
+ * @param {boolean} [changeUrl=true] if the URL must not be changed (defaults to true)
+ * @param {boolean} [force=false] set to true to force changing directory
+ * @param {string} [fileId] optional file id, if known, to be appended in the URL
*/
- changeDirectory: function(targetDir, changeUrl, force) {
+ changeDirectory: function(targetDir, changeUrl, force, fileId) {
var self = this;
var currentDir = this.getCurrentDirectory();
targetDir = targetDir || '/';
if (!force && currentDir === targetDir) {
return;
}
- this._setCurrentDir(targetDir, changeUrl);
+ this._setCurrentDir(targetDir, changeUrl, fileId);
this.reload().then(function(success){
if (!success) {
self.changeDirectory(currentDir, true);
@@ -1389,8 +1390,9 @@
* Sets the current directory name and updates the breadcrumb.
* @param targetDir directory to display
* @param changeUrl true to also update the URL, false otherwise (default)
+ * @param {string} [fileId] file id
*/
- _setCurrentDir: function(targetDir, changeUrl) {
+ _setCurrentDir: function(targetDir, changeUrl, fileId) {
targetDir = targetDir.replace(/\\/g, '/');
var previousDir = this.getCurrentDirectory(),
baseDir = OC.basename(targetDir);
@@ -1408,10 +1410,14 @@
this.$el.find('#dir').val(targetDir);
if (changeUrl !== false) {
- this.$el.trigger(jQuery.Event('changeDirectory', {
+ var params = {
dir: targetDir,
previousDir: previousDir
- }));
+ };
+ if (fileId) {
+ params.fileId = fileId;
+ }
+ this.$el.trigger(jQuery.Event('changeDirectory', params));
}
this.breadcrumb.setDirectory(this.getCurrentDirectory());
},
@@ -1557,6 +1563,18 @@
result.sort(this._sortComparator);
this.setFiles(result);
+
+ if (this.dirInfo) {
+ var newFileId = this.dirInfo.id;
+ // update fileid in URL
+ var params = {
+ dir: this.getCurrentDirectory()
+ };
+ if (newFileId) {
+ params.fileId = newFileId;
+ }
+ this.$el.trigger(jQuery.Event('afterChangeDirectory', params));
+ }
return true;
},
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
index 1bcb4873c53..c586135b9c7 100644
--- a/apps/files/js/mainfileinfodetailview.js
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -12,7 +12,13 @@
var TEMPLATE =
'<div class="thumbnailContainer"><a href="#" class="thumbnail action-default"><div class="stretcher"/></a></div>' +
'<div class="file-details-container">' +
- '<div class="fileName"><h3 title="{{name}}" class="ellipsis">{{name}}</h3></div>' +
+ '<div class="fileName">' +
+ '<h3 title="{{name}}" class="ellipsis">{{name}}</h3>' +
+ '<a class="permalink" href="{{permalink}}" title="{{permalinkTitle}}">' +
+ '<span class="icon icon-public"></span>' +
+ '<span class="hidden-visually">{{permalinkTitle}}</span>' +
+ '</a>' +
+ '</div>' +
' <div class="file-details ellipsis">' +
' <a href="#" ' +
' class="action action-favorite favorite">' +
@@ -20,6 +26,9 @@
' </a>' +
' {{#if hasSize}}<span class="size" title="{{altSize}}">{{size}}</span>, {{/if}}<span class="date" title="{{altDate}}">{{date}}</span>' +
' </div>' +
+ '</div>' +
+ '<div class="hidden permalink-field">' +
+ '<input type="text" value="{{permalink}}" placeholder="{{permalinkTitle}}" readonly="readonly"/>' +
'</div>';
/**
@@ -50,7 +59,9 @@
events: {
'click a.action-favorite': '_onClickFavorite',
- 'click a.action-default': '_onClickDefaultAction'
+ 'click a.action-default': '_onClickDefaultAction',
+ 'click a.permalink': '_onClickPermalink',
+ 'focus .permalink-field>input': '_onFocusPermalink'
},
template: function(data) {
@@ -72,6 +83,20 @@
}
},
+ _onClickPermalink: function() {
+ var $row = this.$('.permalink-field');
+ $row.toggleClass('hidden');
+ if (!$row.hasClass('hidden')) {
+ $row.find('>input').focus();
+ }
+ // cancel click, user must right-click + copy or middle click
+ return false;
+ },
+
+ _onFocusPermalink: function() {
+ this.$('.permalink-field>input').select();
+ },
+
_onClickFavorite: function(event) {
event.preventDefault();
this._fileActions.triggerAction('Favorite', this.model, this._fileList);
@@ -87,6 +112,11 @@
this.render();
},
+ _makePermalink: function(fileId) {
+ var baseUrl = OC.getProtocol() + '://' + OC.getHost();
+ return baseUrl + OC.generateUrl('/f/{fileId}', {fileId: fileId});
+ },
+
setFileInfo: function(fileInfo) {
if (this.model) {
this.model.off('change', this._onModelChanged, this);
@@ -118,7 +148,9 @@
altDate: OC.Util.formatDate(this.model.get('mtime')),
date: OC.Util.relativeModifiedDate(this.model.get('mtime')),
starAltText: isFavorite ? t('files', 'Favorited') : t('files', 'Favorite'),
- starIcon: OC.imagePath('core', isFavorite ? 'actions/starred' : 'actions/star')
+ starIcon: OC.imagePath('core', isFavorite ? 'actions/starred' : 'actions/star'),
+ permalink: this._makePermalink(this.model.get('id')),
+ permalinkTitle: t('files', 'Local link')
}));
// TODO: we really need OC.Previews
diff --git a/apps/files/tests/controller/ViewControllerTest.php b/apps/files/tests/controller/ViewControllerTest.php
index 420e635b4b9..797702def6b 100644
--- a/apps/files/tests/controller/ViewControllerTest.php
+++ b/apps/files/tests/controller/ViewControllerTest.php
@@ -36,6 +36,7 @@ use OCP\IL10N;
use OCP\IConfig;
use OCP\IUserSession;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use OCP\Files\Folder;
/**
* Class ViewControllerTest
@@ -61,6 +62,8 @@ class ViewControllerTest extends TestCase {
private $user;
/** @var IUserSession */
private $userSession;
+ /** @var Folder */
+ private $userFolder;
public function setUp() {
parent::setUp();
@@ -75,6 +78,7 @@ class ViewControllerTest extends TestCase {
$this->userSession->expects($this->any())
->method('getUser')
->will($this->returnValue($this->user));
+ $this->userFolder = $this->getMock('\OCP\Files\Folder');
$this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController')
->setConstructorArgs([
'files',
@@ -84,7 +88,8 @@ class ViewControllerTest extends TestCase {
$this->l10n,
$this->config,
$this->eventDispatcher,
- $this->userSession
+ $this->userSession,
+ $this->userFolder
])
->setMethods([
'getStorageInfo',
@@ -287,4 +292,100 @@ class ViewControllerTest extends TestCase {
$expected->setContentSecurityPolicy($policy);
$this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView'));
}
+
+ public function showFileMethodProvider() {
+ return [
+ [true],
+ [false],
+ ];
+ }
+
+ /**
+ * @dataProvider showFileMethodProvider
+ */
+ public function testShowFileRouteWithFolder($useShowFile) {
+ $node = $this->getMock('\OCP\Files\Folder');
+ $node->expects($this->once())
+ ->method('getPath')
+ ->will($this->returnValue('/user/files/test/sub'));
+
+ $this->userFolder->expects($this->at(0))
+ ->method('getById')
+ ->with(123)
+ ->will($this->returnValue([$node]));
+ $this->userFolder->expects($this->at(1))
+ ->method('getRelativePath')
+ ->with('/user/files/test/sub')
+ ->will($this->returnValue('/test/sub'));
+
+ $this->urlGenerator
+ ->expects($this->once())
+ ->method('linkToRoute')
+ ->with('files.view.index', ['dir' => '/test/sub'])
+ ->will($this->returnValue('/apps/files/?dir=/test/sub'));
+
+ $expected = new Http\RedirectResponse('/apps/files/?dir=/test/sub');
+ if ($useShowFile) {
+ $this->assertEquals($expected, $this->viewController->showFile(123));
+ } else {
+ $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123'));
+ }
+ }
+
+ /**
+ * @dataProvider showFileMethodProvider
+ */
+ public function testShowFileRouteWithFile($useShowFile) {
+ $parentNode = $this->getMock('\OCP\Files\Folder');
+ $parentNode->expects($this->once())
+ ->method('getPath')
+ ->will($this->returnValue('/user/files/test'));
+
+ $node = $this->getMock('\OCP\Files\File');
+ $node->expects($this->once())
+ ->method('getParent')
+ ->will($this->returnValue($parentNode));
+ $node->expects($this->once())
+ ->method('getName')
+ ->will($this->returnValue('somefile.txt'));
+
+ $this->userFolder->expects($this->at(0))
+ ->method('getById')
+ ->with(123)
+ ->will($this->returnValue([$node]));
+ $this->userFolder->expects($this->at(1))
+ ->method('getRelativePath')
+ ->with('/user/files/test')
+ ->will($this->returnValue('/test'));
+
+ $this->urlGenerator
+ ->expects($this->once())
+ ->method('linkToRoute')
+ ->with('files.view.index', ['dir' => '/test', 'scrollto' => 'somefile.txt'])
+ ->will($this->returnValue('/apps/files/?dir=/test/sub&scrollto=somefile.txt'));
+
+ $expected = new Http\RedirectResponse('/apps/files/?dir=/test/sub&scrollto=somefile.txt');
+ if ($useShowFile) {
+ $this->assertEquals($expected, $this->viewController->showFile(123));
+ } else {
+ $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123'));
+ }
+ }
+
+ /**
+ * @dataProvider showFileMethodProvider
+ */
+ public function testShowFileRouteWithInvalidFileId($useShowFile) {
+ $this->userFolder->expects($this->at(0))
+ ->method('getById')
+ ->with(123)
+ ->will($this->returnValue([]));
+
+ $expected = new Http\NotFoundResponse();
+ if ($useShowFile) {
+ $this->assertEquals($expected, $this->viewController->showFile(123));
+ } else {
+ $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123'));
+ }
+ }
}
diff --git a/apps/files/tests/js/appSpec.js b/apps/files/tests/js/appSpec.js
index dce513339f0..b9c323e7c12 100644
--- a/apps/files/tests/js/appSpec.js
+++ b/apps/files/tests/js/appSpec.js
@@ -22,6 +22,7 @@
describe('OCA.Files.App tests', function() {
var App = OCA.Files.App;
var pushStateStub;
+ var replaceStateStub;
var parseUrlQueryStub;
var oldLegacyFileActions;
@@ -48,6 +49,7 @@ describe('OCA.Files.App tests', function() {
OCA.Files.fileActions = new OCA.Files.FileActions();
pushStateStub = sinon.stub(OC.Util.History, 'pushState');
+ replaceStateStub = sinon.stub(OC.Util.History, 'replaceState');
parseUrlQueryStub = sinon.stub(OC.Util.History, 'parseUrlQuery');
parseUrlQueryStub.returns({});
@@ -59,6 +61,7 @@ describe('OCA.Files.App tests', function() {
window.FileActions = oldLegacyFileActions;
pushStateStub.restore();
+ replaceStateStub.restore();
parseUrlQueryStub.restore();
});
@@ -119,18 +122,39 @@ describe('OCA.Files.App tests', function() {
describe('URL handling', function() {
it('pushes the state to the URL when current app changed directory', function() {
- $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'subdir'}));
+ $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'sub dir'}));
expect(pushStateStub.calledOnce).toEqual(true);
- expect(pushStateStub.getCall(0).args[0].dir).toEqual('subdir');
- expect(pushStateStub.getCall(0).args[0].view).not.toBeDefined();
+ var params = OC.parseQueryString(pushStateStub.getCall(0).args[0]);
+ expect(params.dir).toEqual('sub dir');
+ expect(params.view).not.toBeDefined();
$('li[data-id=other]>a').click();
pushStateStub.reset();
- $('#app-content-other').trigger(new $.Event('changeDirectory', {dir: 'subdir'}));
+ $('#app-content-other').trigger(new $.Event('changeDirectory', {dir: 'sub dir'}));
expect(pushStateStub.calledOnce).toEqual(true);
- expect(pushStateStub.getCall(0).args[0].dir).toEqual('subdir');
- expect(pushStateStub.getCall(0).args[0].view).toEqual('other');
+ params = OC.parseQueryString(pushStateStub.getCall(0).args[0]);
+ expect(params.dir).toEqual('sub dir');
+ expect(params.view).toEqual('other');
+ });
+ it('replaces the state to the URL when fileid is known', function() {
+ $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'sub dir'}));
+ expect(pushStateStub.calledOnce).toEqual(true);
+ var params = OC.parseQueryString(pushStateStub.getCall(0).args[0]);
+ expect(params.dir).toEqual('sub dir');
+ expect(params.view).not.toBeDefined();
+ expect(replaceStateStub.notCalled).toEqual(true);
+
+ parseUrlQueryStub.returns({dir: 'sub dir'});
+
+ $('#app-content-files').trigger(new $.Event('afterChangeDirectory', {dir: 'sub dir', fileId: 123}));
+
+ expect(pushStateStub.calledOnce).toEqual(true);
+ expect(replaceStateStub.calledOnce).toEqual(true);
+ params = OC.parseQueryString(replaceStateStub.getCall(0).args[0]);
+ expect(params.dir).toEqual('sub dir');
+ expect(params.view).not.toBeDefined();
+ expect(params.fileid).toEqual('123');
});
describe('onpopstate', function() {
it('sends "urlChanged" event to current app', function() {
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index cc3bcd74b46..7e6408128bb 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -1358,6 +1358,15 @@ describe('OCA.Files.FileList tests', function() {
expect(handler.calledOnce).toEqual(true);
expect(handler.getCall(0).args[0].dir).toEqual('/somedir');
});
+ it('triggers "afterChangeDirectory" event with fileid after changing directory', function() {
+ var handler = sinon.stub();
+ $('#app-content-files').on('afterChangeDirectory', handler);
+ fileList.changeDirectory('/somedir');
+ deferredList.resolve(200, [testRoot].concat(testFiles));
+ expect(handler.calledOnce).toEqual(true);
+ expect(handler.getCall(0).args[0].dir).toEqual('/somedir');
+ expect(handler.getCall(0).args[0].fileId).toEqual(99);
+ });
it('changes the directory when receiving "urlChanged" event', function() {
$('#app-content-files').trigger(new $.Event('urlChanged', {view: 'files', dir: '/somedir'}));
expect(fileList.getCurrentDirectory()).toEqual('/somedir');
diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js
index 460629806c8..e81adbcf7ac 100644
--- a/apps/files/tests/js/mainfileinfodetailviewSpec.js
+++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js
@@ -62,6 +62,11 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
expect(view.$el.find('.date').attr('title')).toEqual(dateExpected);
clock.restore();
});
+ it('displays permalink', function() {
+ view.setFileInfo(testFileInfo);
+ expect(view.$el.find('.permalink').attr('href'))
+ .toEqual(OC.getProtocol() + '://' + OC.getHost() + OC.generateUrl('/f/5'));
+ });
it('displays favorite icon', function() {
testFileInfo.set('tags', [OC.TAG_FAVORITE]);
view.setFileInfo(testFileInfo);