aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@owncloud.com>2015-07-31 00:07:41 +0200
committerVincent Petry <pvince81@owncloud.com>2015-09-16 07:23:25 +0200
commitedd163a6113664921a2fda730037dcf68bfe08ae (patch)
tree2e5b7b0911e121c5e2b019259d3a0247c31ee1c9
parent2fc19635f6a98c0acbd223b3f9d0028ff2755585 (diff)
downloadnextcloud-server-edd163a6113664921a2fda730037dcf68bfe08ae.tar.gz
nextcloud-server-edd163a6113664921a2fda730037dcf68bfe08ae.zip
refactor share dialog for multi-purpose use (dropdown, sidebar) and better maintainability
-rw-r--r--apps/files_sharing/appinfo/app.php3
-rw-r--r--apps/files_sharing/css/sharetabview.css69
-rw-r--r--core/js/share.js25
-rw-r--r--core/js/sharedialogview.js253
-rw-r--r--core/js/shareitemmodel.js113
-rw-r--r--lib/private/share/share.php2
6 files changed, 462 insertions, 3 deletions
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index 20f1b046d35..3049dc6a263 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -55,8 +55,9 @@ $application->setupPropagation();
\OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
\OCP\Util::addScript('files_sharing', 'share');
+\OCP\Util::addScript('files_sharing', 'sharetabview');
\OCP\Util::addScript('files_sharing', 'external');
-\OCP\Util::addStyle('files_sharing', 'sharetabview');
+// \OCP\Util::addStyle('files_sharing', 'sharetabview');
\OC::$server->getActivityManager()->registerExtension(function() {
return new \OCA\Files_Sharing\Activity(
diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css
index 42c9bee7173..8b9af852531 100644
--- a/apps/files_sharing/css/sharetabview.css
+++ b/apps/files_sharing/css/sharetabview.css
@@ -1,3 +1,72 @@
.app-files .shareTabView {
min-height: 100px;
}
+
+.shareTabView .oneline { white-space: nowrap; }
+
+.shareTabView .shareWithLoading {
+ display: inline-block !important;
+ padding-left: 10px;
+ position: relative;
+ right: 30px;
+ top: 2px;
+}
+
+.shareTabView .shareWithRemoteInfo {
+ padding: 11px 0 11px 10px
+}
+
+.shareTabView label {
+ font-weight:400;
+ white-space: nowrap;
+}
+
+.shareTabView input[type="checkbox"] {
+ margin:0 3px 0 8px;
+ vertical-align: middle;
+}
+
+.shareTabView input[type="text"], .shareTabView input[type="password"] {
+ width: 91%;
+ margin-left: 7px;
+}
+
+.shareTabView form {
+ font-size: 100%;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+#shareWithList {
+ list-style-type:none;
+ padding:8px;
+}
+
+#shareWithList li {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ font-weight: bold;
+ line-height: 21px;
+ white-space: normal;
+}
+
+#shareWithList .unshare img, #shareWithList .showCruds img {
+ vertical-align:text-bottom; /* properly align icons */
+}
+
+#shareWithList label input[type=checkbox]{
+ margin-left: 0;
+ position: relative;
+}
+#shareWithList .username{
+ padding-right: 8px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ max-width: 254px;
+ display: inline-block;
+ overflow: hidden;
+ vertical-align: middle;
+}
+#shareWithList li label{
+ margin-right: 8px;
+}
diff --git a/core/js/share.js b/core/js/share.js
index cd4a614e9d1..5d3253e6d5c 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -3,7 +3,7 @@
/**
* @namespace
*/
-OC.Share={
+OC.Share = _.extend(OC.Share, {
SHARE_TYPE_USER:0,
SHARE_TYPE_GROUP:1,
SHARE_TYPE_LINK:3,
@@ -289,6 +289,12 @@ OC.Share={
}
img.attr('src', image);
},
+ /**
+ *
+ * @param itemType
+ * @param itemSource
+ * @returns {OC.Share.Types.ShareInfo}
+ */
loadItem:function(itemType, itemSource) {
var data = '';
var checkReshare = true;
@@ -371,6 +377,21 @@ OC.Share={
});
},
showDropDown:function(itemType, itemSource, appendTo, link, possiblePermissions, filename) {
+ var itemModel = new OC.Share.ShareItemModel(itemType, itemSource);
+ var dialogView = new OC.Share.ShareDialogView('dropdown');
+ dialogView.setContainerClasses('drop shareDropDown');
+ dialogView.setShowLink(link);
+ dialogView.setPossiblePermissions(possiblePermissions);
+ dialogView.setItemModel(itemModel);
+ var $dialog = dialogView.render();
+ $dialog.appendTo(appendTo);
+ $dialog.attr('data-item-source-name', filename);
+ $dialog.slideDown(OC.menuSpeed, function() {
+ OC.Share.droppedDown = true;
+ });
+ return;
+
+
var data = OC.Share.loadItem(itemType, itemSource);
var dropDownEl;
var html = '<div id="dropdown" class="drop shareDropDown" data-item-type="'+itemType+'" data-item-source="'+itemSource+'">';
@@ -897,7 +918,7 @@ OC.Share={
}
return expireDateString;
}
-};
+});
$(document).ready(function() {
diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js
new file mode 100644
index 00000000000..cbab9694afe
--- /dev/null
+++ b/core/js/sharedialogview.js
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+ if(!OC.Share) {
+ OC.Share = {};
+ }
+
+ var TEMPLATE_BASE =
+ '<div id="{{containerID}}" {{{containerClasses}}}>' +
+ ' {{{resharerInfo}}}' +
+ ' <label for="shareWith" class="hidden-visually">{{shareLabel}}</label>' +
+ ' <div class="oneline">' +
+ ' <input id="shareWith" type="text" placeholder="{{sharePlaceholder}}" />' +
+ ' <span class="shareWithLoading icon-loading-small hidden"></span>'+
+ ' </div>' +
+ // FIXME: find a good position for remoteShareInfo
+ ' {{{remoteShareInfo}}}' +
+ ' <ul id="shareWithList">' +
+ ' </ul>' +
+ ' {{{linkShare}}}' +
+ '</div>';
+
+ var TEMPLATE_RESHARER_INFO =
+ '<span class="reshare">' +
+ ' {{#if avatarEnabled}}' +
+ ' <div class="avatar"></div>' +
+ ' {{/if}}' +
+ ' {{sharedByText}}' +
+ '</span><br />';
+
+ var TEMPLATE_REMOTE_SHARE_INFO =
+ '<a target="_blank" class="icon-info svg shareWithRemoteInfo" href="{{docLink}}" ' +
+ 'title="{{tooltip}}"></a>';
+
+ var TEMPLATE_LINK_SHARE =
+ '<div id="link" class="linkShare">' +
+ ' <span class="icon-loading-small hidden"></span>' +
+ ' <input type="checkbox" name="linkCheckbox" id="linkCheckbox" value="1" /><label for="linkCheckbox">{{linkShareLabel}}</label>' +
+ ' <br />' +
+ ' <label for="linkText" class="hidden-visually">{{urlLabel}}</label>' +
+ ' <input id="linkText" type="text" readonly="readonly" />' +
+ ' <input type="checkbox" name="showPassword" id="showPassword" value="1" class="hidden" /><label for="showPassword" class="hidden-visually">{{enablePasswordLabel}}</label>' +
+ ' <div id="linkPass">' +
+ ' <label for="linkPassText" class="hidden-visually">{{passwordLabel}}</label>' +
+ ' <input id="linkPassText" type="password" placeholder="passwordPlaceholder" />' +
+ ' <span class="icon-loading-small hidden"></span>' +
+ ' </div>'
+ ;
+
+ /**
+ * @class OCA.Share.ShareDialogView
+ * @classdesc
+ *
+ * Represents the GUI of the share dialogue
+ *
+ */
+ var ShareDialogView = function(id) {
+ this.initialize(id);
+ };
+
+ /**
+ * @memberof OCA.Sharing
+ */
+ ShareDialogView.prototype = {
+ /** @member {OC.Share.ShareItemModel} **/
+ _itemModel: null,
+
+ /** @var {string} **/
+ _id: null,
+
+ /** @var {Object} **/
+ _templates: {},
+
+ /** @var {string} **/
+ _containerClasses: '',
+
+ /** @var {boolean} **/
+ _showLink: true,
+
+ /** @var {unknown} **/
+ _possiblePermissions: null,
+
+ initialize: function (id) {
+ this._id = id;
+ },
+
+ render: function() {
+ var baseTemplate = this._getTemplate('base', TEMPLATE_BASE);
+
+ var $dialog = $(baseTemplate({
+ containerID: this._id,
+ containerClasses: this._renderContainerClasses(),
+ shareLabel: t('core', 'Share'),
+ resharerInfo: this._renderResharerInfo(),
+ sharePlaceholder: this._renderSharePlaceholderPart(),
+ remoteShareInfo: this._renderRemoteShareInfoPart(),
+ linkShare: this._renderLinkSharePart()
+ }));
+
+ return $dialog;
+ },
+
+ setItemModel: function(model) {
+ if(model instanceof OC.Share.ShareItemModel) {
+ this._itemModel = model;
+ } else {
+ console.warn('model is not an instance of OC.Share.ShareItemModel');
+ }
+ },
+
+ /**
+ * sets the classes the main container should get additionally
+ * TODO:: figure out whether this is really necessary
+ *
+ * @param {string} classes whitespace seperated
+ */
+ setContainerClasses: function(classes) {
+ this._containerClasses = classes;
+ },
+
+ /**
+ * sets whether share by link should be displayed or not. Default is
+ * true.
+ *
+ * @param {bool} showLink
+ */
+ setShowLink: function(showLink) {
+ this._showLink = (typeof showLink === 'boolean') ? showLink : true;
+ },
+
+ setPossiblePermissions: function(permissions) {
+ //TODO: maybe move to model? Whatever this is.
+ this._possiblePermissions = permissions;
+ },
+
+ _renderResharerInfo: function() {
+ var resharerInfo = '';
+ if ( this._itemModel.hasReshare()
+ && this._itemModel.getReshareOwner() !== OC.currentUser)
+ {
+ var reshareTemplate = this._getReshareTemplate();
+ var sharedByText = '';
+ if (this._itemModel.getReshareType() === OC.Share.SHARE_TYPE_GROUP) {
+ sharedByText = t(
+ 'core',
+ 'Shared with you and the group {group} by {owner}',
+ {
+ group: this._itemModel.getReshareWith(),
+ owner: this._itemModel.getReshareOwnerDisplayname()
+ }
+ );
+ } else {
+ sharedByText = t(
+ 'core',
+ 'Shared with you by {owner}',
+ { owner: this._itemModel.getReshareOwnerDisplayname() }
+ );
+ }
+
+
+ resharerInfo = reshareTemplate({
+ avatarEnabled: oc_config.enable_avatars === true,
+ sharedByText: sharedByText
+ });
+ }
+ },
+
+ _renderContainerClasses: function() {
+ var classes = '';
+ if(this._containerClasses) {
+ classes = 'class="' + this._containerClasses + '"';
+ }
+ return classes;
+ },
+
+ _renderRemoteShareInfoPart: function() {
+ var remoteShareInfo = '';
+ if(oc_appconfig.core.remoteShareAllowed) {
+ var infoTemplate = this._getRemoteShareInfoTemplate();
+ remoteShareInfo = infoTemplate({
+ docLink: oc_appconfig.core.federatedCloudShareDoc,
+ tooltip: t('core', 'Share with people on other ownClouds using the syntax username@example.com/owncloud')
+ });
+ }
+ return remoteShareInfo;
+ },
+
+ _renderLinkSharePart: function() {
+ var linkShare = '';
+ if(this._showLink && $('#allowShareWithLink').val() === 'yes') {
+ var linkShareTemplate = this._getLinkShareTemplate();
+ linkShare = linkShareTemplate({
+ linkShareLabel: t('core', 'Share link'),
+ urlLabel: t('core', 'Link'),
+ enablePasswordLabel: t('core', 'Password protect'),
+ passwordLabel: t('core', 'Password'),
+ passwordPlaceholder: t('core', 'Choose a password for the public link')
+ });
+ }
+ return linkShare;
+ },
+
+ _renderSharePlaceholderPart: function () {
+ var sharePlaceholder = t('core', 'Share with users or groups …');
+ if (oc_appconfig.core.remoteShareAllowed) {
+ sharePlaceholder = t('core', 'Share with users, groups or remote users …');
+ }
+ return sharePlaceholder;
+ },
+
+ _getTemplate: function (key, template) {
+ if (!this._templates[key]) {
+ this._templates[key] = Handlebars.compile(template);
+ }
+ return this._templates[key];
+ },
+
+ /**
+ * returns the info template for remote sharing
+ *
+ * @returns {Handlebars}
+ * @private
+ */
+ _getRemoteShareInfoTemplate: function() {
+ return this._getTemplate('remoteShareInfo', TEMPLATE_REMOTE_SHARE_INFO);
+ },
+
+ /**
+ * returns the info template for link sharing
+ *
+ * @returns {Handlebars}
+ * @private
+ */
+ _getLinkShareTemplate: function() {
+ return this._getTemplate('linkShare', TEMPLATE_LINK_SHARE);
+ },
+
+ _getReshareTemplate: function() {
+ return this._getTemplate('reshare', TEMPLATE_RESHARER_INFO);
+ },
+ };
+
+ OC.Share.ShareDialogView = ShareDialogView;
+
+})();
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
new file mode 100644
index 00000000000..1db49536db5
--- /dev/null
+++ b/core/js/shareitemmodel.js
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+ if(!OC.Share) {
+ OC.Share = {};
+ OC.Share.Types = {};
+ }
+
+ /**
+ * @typedef {object} OC.Share.Types.Reshare
+ * @property {string} uid_owner
+ * @property {number} share_type
+ * @property {string} share_with
+ * @property {string} displayname_owner
+ * @property {number} permissions
+ */
+
+ /**
+ * @typedef {object} OC.Share.Types.ShareInfo
+ * @property {number} share_type
+ * @property {number} permissions
+ * @property {number} file_source optional
+ * @property {number} item_source
+ * @property {string} token
+ * @property {string} share_with
+ * @property {string} share_with_displayname
+ * @property {string} share_mail_send
+ * @property {bool} collection //TODO: verify
+ * @property {Date} expiration optional?
+ * @property {number} stime optional?
+ */
+
+ /**
+ * @typedef {object} OC.Share.Types.ShareItemInfo
+ * @property {OC.Share.Types.Reshare} reshare
+ * @property {OC.Share.Types.ShareInfo[]} shares
+ */
+
+ /**
+ * @class OCA.Share.ShareItemModel
+ * @classdesc
+ *
+ * Represents the GUI of the share dialogue
+ *
+ */
+ var ShareItemModel = function(itemType, itemSource) {
+ this.initialize(itemType, itemSource);
+ };
+
+ /**
+ * @memberof OCA.Sharing
+ */
+ ShareItemModel.prototype = {
+ /** @var {string} **/
+ _itemType: null,
+ /** @var {mixed} **/ //TODO: what type?
+ _itemSource: null,
+
+ /** @var {OC.Share.Types.Reshare} **/
+ _reshare: null,
+
+ /** @var {OC.Share.Types.ShareInfo[]} **/
+ _shares: null,
+
+ initialize: function(itemType, itemSource) {
+ this._itemType = itemType;
+ this._itemSource = itemSource;
+ this._retrieveData();
+ },
+
+ hasReshare: function() {
+ return _.isObject(this._reshare) && !_.isUndefined(this._reshare.uid_owner);
+ },
+
+ getReshareOwner: function() {
+ return this._reshare.uid_owner;
+ },
+
+ getReshareOwnerDisplayname: function() {
+ return this._reshare.displayname_owner;
+ },
+
+ getReshareWith: function() {
+ return this._reshare.share_with;
+ },
+
+ getReshareType: function() {
+ return this._reshare.share_type;
+ },
+
+ _retrieveData: function() {
+ /** var {OC.Share.Types.ShareItemInfo} **/
+ var data = OC.Share.loadItem(this._itemType, this._itemSource);
+ if(data === false) {
+ console.warn('no data was returned');
+ return;
+ }
+ this._reshare = data.reshare;
+ this._shares = data.shares;
+
+ }
+ };
+
+ OC.Share.ShareItemModel = ShareItemModel;
+})();
diff --git a/lib/private/share/share.php b/lib/private/share/share.php
index 6ad36d60fe8..65968f581f5 100644
--- a/lib/private/share/share.php
+++ b/lib/private/share/share.php
@@ -83,6 +83,8 @@ class Share extends Constants {
'supportedFileExtensions' => $supportedFileExtensions
);
if(count(self::$backendTypes) === 1) {
+ \OC_Util::addScript('core', 'shareitemmodel');
+ \OC_Util::addScript('core', 'sharedialogview');
\OC_Util::addScript('core', 'share');
\OC_Util::addStyle('core', 'share');
}