summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2014-06-06 18:59:37 +0200
committerVincent Petry <pvince81@owncloud.com>2014-06-06 18:59:37 +0200
commit506f7adb12d2da0916fadb22b6f2ddd2c52ba708 (patch)
treed174d7f5648aeff2647eada49fefc0467d687093
parentdc77910758d83fff14359996a79ba29afd183a0a (diff)
parente39e6a5584e04d998f75e987aef398dd572b8538 (diff)
downloadnextcloud-server-506f7adb12d2da0916fadb22b6f2ddd2c52ba708.tar.gz
nextcloud-server-506f7adb12d2da0916fadb22b6f2ddd2c52ba708.zip
Merge pull request #8925 from owncloud/extstorage-sidebar
Added external storage list in files app
-rw-r--r--apps/files/css/files.css11
-rw-r--r--apps/files_external/appinfo/app.php12
-rw-r--r--apps/files_external/appinfo/routes.php27
-rw-r--r--apps/files_external/js/app.js71
-rw-r--r--apps/files_external/js/mountsfilelist.js122
-rw-r--r--apps/files_external/lib/api.php83
-rw-r--r--apps/files_external/list.php11
-rw-r--r--apps/files_external/templates/list.php31
8 files changed, 363 insertions, 5 deletions
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 55f3d17ac2b..4dac2b66a59 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -186,7 +186,8 @@ table th#headerSize, table td.filesize {
table table td.filesize {
padding: 0 16px;
}
-table th#headerDate, table td.date {
+table th#headerDate, table td.date,
+table th.column-last, table td.column-last {
-moz-box-sizing: border-box;
box-sizing: border-box;
position: relative;
@@ -237,9 +238,9 @@ table td.filename input.filename {
cursor: text;
}
table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
-table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; }
+table td.filename .nametext, .uploadtext, .modified, .column-last>span:first-child { float:left; padding:14px 0; }
-.modified {
+.modified, .column-last>span:first-child {
position: relative;
padding-left: 15px;
overflow: hidden;
@@ -247,8 +248,8 @@ table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0
width: 90%;
}
/* ellipsize long modified dates to make room for showing delete button */
-#fileList tr:hover .modified,
-#fileList tr:focus .modified {
+#fileList tr:hover .modified, #fileList tr:hover .column-last>span:first-child,
+#fileList tr:focus .modified, #fileList tr:focus .column-last>span:first-child {
width: 75%;
}
diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php
index ca164784fb0..e88880fe516 100644
--- a/apps/files_external/appinfo/app.php
+++ b/apps/files_external/appinfo/app.php
@@ -20,12 +20,23 @@ OC::$CLASSPATH['OC\Files\Storage\AmazonS3'] = 'files_external/lib/amazons3.php';
OC::$CLASSPATH['OC\Files\Storage\Dropbox'] = 'files_external/lib/dropbox.php';
OC::$CLASSPATH['OC\Files\Storage\SFTP'] = 'files_external/lib/sftp.php';
OC::$CLASSPATH['OC_Mount_Config'] = 'files_external/lib/config.php';
+OC::$CLASSPATH['OCA\Files\External\Api'] = 'files_external/lib/api.php';
OCP\App::registerAdmin('files_external', 'settings');
if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == 'yes') {
OCP\App::registerPersonal('files_external', 'personal');
}
+\OCA\Files\App::getNavigationManager()->add(
+ array(
+ "id" => 'extstoragemounts',
+ "appname" => 'files_external',
+ "script" => 'list.php',
+ "order" => 30,
+ "name" => $l->t('External storage')
+ )
+);
+
// connecting hooks
OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OC_Mount_Config', 'initMountPointsHook');
OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\SMB_OC', 'login');
@@ -164,3 +175,4 @@ OC_Mount_Config::registerBackend('\OC\Files\Storage\SFTP', array(
'user' => (string)$l->t('Username'),
'password' => '*'.$l->t('Password'),
'root' => '&'.$l->t('Root'))));
+
diff --git a/apps/files_external/appinfo/routes.php b/apps/files_external/appinfo/routes.php
new file mode 100644
index 00000000000..cb950364e5d
--- /dev/null
+++ b/apps/files_external/appinfo/routes.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * ownCloud - External Storage Routes
+ *
+ * @author Vincent Petry
+ * @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+OC_API::register('get',
+ '/apps/files_external/api/v1/mounts',
+ array('\OCA\Files\External\Api', 'getUserMounts'),
+ 'files_external');
+
diff --git a/apps/files_external/js/app.js b/apps/files_external/js/app.js
new file mode 100644
index 00000000000..58ad1a0f6ef
--- /dev/null
+++ b/apps/files_external/js/app.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+if (!OCA.External) {
+ OCA.External = {};
+}
+OCA.External.App = {
+
+ fileList: null,
+
+ initList: function($el) {
+ if (this.fileList) {
+ return this.fileList;
+ }
+
+ this.fileList = new OCA.External.FileList(
+ $el,
+ {
+ scrollContainer: $('#app-content'),
+ fileActions: this._createFileActions()
+ }
+ );
+
+ this._extendFileList(this.fileList);
+ this.fileList.appName = t('files_external', 'External storage');
+ return this.fileList;
+ },
+
+ removeList: function() {
+ if (this.fileList) {
+ this.fileList.$fileList.empty();
+ }
+ },
+
+ _createFileActions: function() {
+ // inherit file actions from the files app
+ var fileActions = new OCA.Files.FileActions();
+ fileActions.registerDefaultActions();
+
+ // when the user clicks on a folder, redirect to the corresponding
+ // folder in the files app instead of opening it directly
+ fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
+ OCA.Files.App.setActiveView('files', {silent: true});
+ OCA.Files.App.fileList.changeDirectory(context.$file.attr('data-path') + '/' + filename, true, true);
+ });
+ fileActions.setDefault('dir', 'Open');
+ return fileActions;
+ },
+
+ _extendFileList: function(fileList) {
+ // remove size column from summary
+ fileList.fileSummary.$el.find('.filesize').remove();
+ }
+};
+
+$(document).ready(function() {
+ $('#app-content-extstoragemounts').on('show', function(e) {
+ OCA.External.App.initList($(e.target));
+ });
+ $('#app-content-extstoragemounts').on('hide', function() {
+ OCA.External.App.removeList();
+ });
+});
+
diff --git a/apps/files_external/js/mountsfilelist.js b/apps/files_external/js/mountsfilelist.js
new file mode 100644
index 00000000000..70b5b81e65b
--- /dev/null
+++ b/apps/files_external/js/mountsfilelist.js
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+(function() {
+
+ /**
+ * External storage file list
+ */
+ var FileList = function($el, options) {
+ this.initialize($el, options);
+ };
+
+ FileList.prototype = _.extend({}, OCA.Files.FileList.prototype, {
+ appName: 'External storage',
+
+ initialize: function($el, options) {
+ OCA.Files.FileList.prototype.initialize.apply(this, arguments);
+ if (this.initialized) {
+ return;
+ }
+ },
+
+ _createRow: function(fileData) {
+ // TODO: hook earlier and render the whole row here
+ var $tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments);
+ var $scopeColumn = $('<td class="column-scope column-last"><span></span></td>');
+ var $backendColumn = $('<td class="column-backend"></td>');
+ var scopeText = t('files_external', 'Personal');
+ if (fileData.scope === 'system') {
+ scopeText = t('files_external', 'System');
+ }
+ $tr.find('.filesize,.date').remove();
+ $scopeColumn.find('span').text(scopeText);
+ $backendColumn.text(fileData.backend);
+ $tr.find('td.filename').after($scopeColumn).after($backendColumn);
+ $tr.find('td.filename input:checkbox').remove();
+ return $tr;
+ },
+
+ updateEmptyContent: function() {
+ var dir = this.getCurrentDirectory();
+ if (dir === '/') {
+ // root has special permissions
+ this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty);
+ this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty);
+ }
+ else {
+ OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments);
+ }
+ },
+
+ getDirectoryPermissions: function() {
+ return OC.PERMISSION_READ | OC.PERMISSION_DELETE;
+ },
+
+ updateStorageStatistics: function() {
+ // no op because it doesn't have
+ // storage info like free space / used space
+ },
+
+ reload: function() {
+ var self = this;
+ this.showMask();
+ if (this._reloadCall) {
+ this._reloadCall.abort();
+ }
+ this._reloadCall = $.ajax({
+ url: OC.linkToOCS('apps/files_external/api/v1') + 'mounts',
+ data: {
+ format: 'json'
+ },
+ type: 'GET',
+ beforeSend: function(xhr) {
+ xhr.setRequestHeader('OCS-APIREQUEST', 'true');
+ },
+ error: function(result) {
+ self.reloadCallback(result);
+ },
+ success: function(result) {
+ self.reloadCallback(result);
+ }
+ });
+ },
+
+ reloadCallback: function(result) {
+ delete this._reloadCall;
+ this.hideMask();
+
+ if (result.ocs && result.ocs.data) {
+ this.setFiles(this._makeFiles(result.ocs.data));
+ }
+ else {
+ // TODO: error handling
+ }
+ },
+
+ /**
+ * Converts the OCS API response data to a file info
+ * list
+ * @param OCS API mounts array
+ * @return array of file info maps
+ */
+ _makeFiles: function(data) {
+ var files = _.map(data, function(fileData) {
+ fileData.icon = OC.imagePath('core', 'filetypes/folder-external');
+ return fileData;
+ });
+
+ files.sort(this._sortComparator);
+
+ return files;
+ }
+ });
+
+ OCA.External.FileList = FileList;
+})();
diff --git a/apps/files_external/lib/api.php b/apps/files_external/lib/api.php
new file mode 100644
index 00000000000..51c48427aa3
--- /dev/null
+++ b/apps/files_external/lib/api.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Vincent Petry
+ * @copyright 2014 Vincent Petry pvince81@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files\External;
+
+class Api {
+
+ /**
+ * Formats the given mount config to a mount entry.
+ *
+ * @param bool $isSystemMount true for system mount, false
+ * for personal mount
+ *
+ * @return array entry
+ */
+ private static function formatMount($mountConfig, $isSystemMount = false) {
+ // split user name from mount point
+ $path = dirname($mountConfig['mountpoint']);
+ if ($path === '.') {
+ $path = '';
+ }
+
+ $permissions = \OCP\PERMISSION_READ;
+ // personal mounts can be deleted
+ if (!$isSystemMount) {
+ $permissions |= \OCP\PERMISSION_DELETE;
+ }
+
+ // TODO: add storageType, might need to use another OC_Mount_Config method
+ $entry = array(
+ 'name' => basename($mountConfig['mountpoint']),
+ 'path' => $path,
+ 'type' => 'dir',
+ 'backend' => $mountConfig['backend'],
+ 'scope' => ( $isSystemMount ? 'system' : 'personal' ),
+ 'permissions' => $permissions
+ );
+ return $entry;
+ }
+
+ /**
+ * Returns the mount points visible for this user.
+ *
+ * @param array $params
+ * @return \OC_OCS_Result share information
+ */
+ public static function getUserMounts($params) {
+ $entries = array();
+ $user = \OC_User::getUser();
+
+ $personalMounts = \OC_Mount_Config::getPersonalMountPoints();
+ $systemMounts = \OC_Mount_Config::getSystemMountPoints();
+
+ foreach ($systemMounts as $mountConfig) {
+ $entries[] = self::formatMount($mountConfig, true);
+ }
+
+ foreach ($personalMounts as $mountConfig) {
+ $entries[] = self::formatMount($mountConfig, false);
+ }
+
+ return new \OC_OCS_Result($entries);
+ }
+}
diff --git a/apps/files_external/list.php b/apps/files_external/list.php
new file mode 100644
index 00000000000..e9517724f2f
--- /dev/null
+++ b/apps/files_external/list.php
@@ -0,0 +1,11 @@
+<?php
+
+// Check if we are a user
+OCP\User::checkLoggedIn();
+
+$tmpl = new OCP\Template('files_external', 'list', '');
+
+OCP\Util::addScript('files_external', 'app');
+OCP\Util::addScript('files_external', 'mountsfilelist');
+
+$tmpl->printPage();
diff --git a/apps/files_external/templates/list.php b/apps/files_external/templates/list.php
new file mode 100644
index 00000000000..4e06bc7024c
--- /dev/null
+++ b/apps/files_external/templates/list.php
@@ -0,0 +1,31 @@
+<?php /** @var $l OC_L10N */ ?>
+<div id="controls">
+ <div id="file_action_panel"></div>
+</div>
+<div id='notification'></div>
+
+<div id="emptycontent" class="hidden"><?php p($l->t( 'You don\'t have any external storages' )); ?></div>
+
+<input type="hidden" name="dir" value="" id="dir">
+
+<table id="filestable">
+ <thead>
+ <tr>
+ <th id='headerName' class="hidden column-name">
+ <div id="headerName-container">
+ <a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a>
+ </div>
+ </th>
+ <th id="headerBackend" class="hidden column-backend">
+ <a class="backend sort columntitle" data-sort="backend"><span><?php p($l->t('Storage type')); ?></span><span class="sort-indicator"></span></a>
+ </th>
+ <th id="headerScope" class="hidden column-scope column-last">
+ <a class="scope sort columntitle" data-sort="scope"><span><?php p($l->t('Scope')); ?></span><span class="sort-indicator"></span></a>
+ </th>
+ </tr>
+ </thead>
+ <tbody id="fileList">
+ </tbody>
+ <tfoot>
+ </tfoot>
+</table>