From a85327fe87ce471b04a14839e7b7b7dae4298753 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Thu, 2 Mar 2017 14:12:13 +0100 Subject: [PATCH 1/5] Add social sharing * Add socialshare manager * Add social share field under link share Signed-off-by: Roeland Jago Douma --- core/js/sharedialoglinksocialview.js | 132 +++++++++++++++++++++++++++ core/js/sharedialogview.js | 10 +- core/js/sharesocialmanager.js | 53 +++++++++++ lib/private/Share/Share.php | 2 + 4 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 core/js/sharedialoglinksocialview.js create mode 100644 core/js/sharesocialmanager.js diff --git a/core/js/sharedialoglinksocialview.js b/core/js/sharedialoglinksocialview.js new file mode 100644 index 0000000000000..1cd8d91bc7aeb --- /dev/null +++ b/core/js/sharedialoglinksocialview.js @@ -0,0 +1,132 @@ +/** + * @copyright 2017, Roeland Jago Douma + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * 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 . + * + */ + +(function() { + if (!OC.Share) { + OC.Share = {}; + } + + var TEMPLATE = + '' + ; + + /** + * @class OCA.Share.ShareDialogLinkSocialView + * @member {OC.Share.ShareItemModel} model + * @member {jQuery} $el + * @memberof OCA.Sharing + * @classdesc + * + * Represents the GUI of the share dialogue + * + */ + var ShareDialogLinkSocialView = OC.Backbone.View.extend({ + /** @type {string} **/ + id: 'shareDialogLinkSocialView', + + /** @type {OC.Share.ShareConfigModel} **/ + configModel: undefined, + + /** @type {Function} **/ + _template: undefined, + + /** @type {boolean} **/ + showLink: true, + + events: { + 'click .pop-up': 'onPopUpClick' + }, + + initialize: function(options) { + var view = this; + + this.model.on('change:linkShare', function() { + view.render(); + }); + + if(!_.isUndefined(options.configModel)) { + this.configModel = options.configModel; + } else { + throw 'missing OC.Share.ShareConfigModel'; + } + }, + + onPopUpClick: function(event) { + var url = $(event.target).data('url'); + $(event.target).tooltip('hide'); + if (url) { + var width = 600; + var height = 400; + var left = (screen.width/2)-(width/2); + var top = (screen.height/2)-(height/2); + + window.open(url, 'name', 'width=' + width + ', height=' + height + ', top=' + top + ', left=' + left); + } + }, + + render: function() { + var isLinkShare = this.model.get('linkShare').isLinkShare; + if (isLinkShare && OC.Share.Social.Collection.size() > 0) { + var linkShareTemplate = this.template(); + var link = this.model.get('linkShare').link; + + var html = ''; + + OC.Share.Social.Collection.each(function(model) { + var url = model.get('url'); + url = url.replace('{{reference}}', link); + + html += linkShareTemplate({ + url: url, + shareToolTip: t('core', 'Share to {name}', {name: model.get('name')}), + iconClass: model.get('iconClass') + }); + }); + + this.$el.html(html); + this.$el.show(); + } else { + this.$el.hide(); + } + + this.delegateEvents(); + + return this; + }, + + /** + * @returns {Function} from Handlebars + * @private + */ + template: function () { + if (!this._template) { + this._template = Handlebars.compile(TEMPLATE); + } + return this._template; + } + + }); + + OC.Share.ShareDialogLinkSocialView = ShareDialogLinkSocialView; +})(); diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index a63960da2b8bd..ed887dfb7164a 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -28,6 +28,7 @@ '
' + '
' + '
' + + '
' + ''; var TEMPLATE_REMOTE_SHARE_INFO = @@ -69,6 +70,9 @@ /** @type {object} **/ shareeListView: undefined, + /** @type OC.Share.ShareDialogLinkSocialView **/ + socalView: undefined, + events: { 'input .shareWithField': 'onShareWithFieldChanged' }, @@ -105,7 +109,8 @@ resharerInfoView: 'ShareDialogResharerInfoView', linkShareView: 'ShareDialogLinkShareView', expirationView: 'ShareDialogExpirationView', - shareeListView: 'ShareDialogShareeListView' + shareeListView: 'ShareDialogShareeListView', + socialView: 'ShareDialogLinkSocialView' }; for(var name in subViews) { @@ -421,6 +426,9 @@ this.shareeListView.$el = this.$el.find('.shareeListView'); this.shareeListView.render(); + this.socialView.$el = this.$('.socialView'); + this.socialView.render(); + this.$el.find('.hasTooltip').tooltip(); return this; diff --git a/core/js/sharesocialmanager.js b/core/js/sharesocialmanager.js new file mode 100644 index 0000000000000..c1db48dda6237 --- /dev/null +++ b/core/js/sharesocialmanager.js @@ -0,0 +1,53 @@ +/** + * @copyright 2017, Roeland Jago Douma + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * 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 . + * + */ + +(function() { + if (!OC.Share) { + OC.Share = {}; + } + + OC.Share.Social = {}; + + var SocialModel = OC.Backbone.Model.extend({ + defaults: { + /** used for sorting social buttons */ + key: null, + /** url to open, {{reference}} will be replaced with the link */ + url: null, + /** Name to show in the tooltip */ + name: null, + /** Icon class to display */ + iconClass: null + } + }); + + OC.Share.Social.Model = SocialModel; + + var SocialCollection = OC.Backbone.Collection.extend({ + model: OC.Share.Social.Model, + + comparator: 'key' + }); + + + OC.Share.Social.Collection = new SocialCollection; +})(); diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index 6abaa7dd41377..c693af02a5046 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -94,8 +94,10 @@ public static function registerBackend($itemType, $class, $collectionOf = null, if(count(self::$backendTypes) === 1) { \OC_Util::addScript('core', 'shareconfigmodel'); \OC_Util::addScript('core', 'shareitemmodel'); + \OC_Util::addScript('core', 'sharesocialmanager'); \OC_Util::addScript('core', 'sharedialogresharerinfoview'); \OC_Util::addScript('core', 'sharedialoglinkshareview'); + \OC_Util::addScript('core', 'sharedialoglinksocialview'); \OC_Util::addScript('core', 'sharedialogexpirationview'); \OC_Util::addScript('core', 'sharedialogshareelistview'); \OC_Util::addScript('core', 'sharedialogview'); From fd71b8bde8fc003b0f160075825402c4fab1d54c Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 3 Mar 2017 13:27:06 +0100 Subject: [PATCH 2/5] Move social buttons to menu * If there are social sharing buttons move them and the copy action to a menu * If there are no social sharing buttons just leave the copy action where it is directly Signed-off-by: Roeland Jago Douma --- apps/files_sharing/css/sharetabview.css | 11 ++ core/js/sharedialoglinkshareview.js | 103 ++++++++++++++++-- core/js/sharedialoglinksocialview.js | 132 ------------------------ core/js/sharedialogview.js | 10 +- lib/private/Share/Share.php | 1 - 5 files changed, 107 insertions(+), 150 deletions(-) delete mode 100644 core/js/sharedialoglinksocialview.js diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css index 4738f8b780237..5896e18abada9 100644 --- a/apps/files_sharing/css/sharetabview.css +++ b/apps/files_sharing/css/sharetabview.css @@ -21,6 +21,17 @@ padding: 14px; } +.shareTabView .linkMore { + position: absolute; + right: -7px; + top: -4px; + padding: 14px; +} + +.shareTabView .popovermenu .clipboardButton { + position: relative; +} + .shareTabView label { white-space: nowrap; } diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 84a3d18942f84..014819d510359 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -27,7 +27,12 @@ '
' + '' + '' + - '' + + '{{#if singleAction}}' + + '' + + '{{else}}' + + '' + + '{{{popoverMenu}}}' + + '{{/if}}' + '
' + ' {{#if publicUpload}}' + '
' + @@ -64,6 +69,27 @@ '{{#if noSharingPlaceholder}}{{/if}}' + '{{/if}}' ; + var TEMPLATE_POPOVER_MENU = + ''; /** * @class OCA.Share.ShareDialogLinkShareView @@ -85,6 +111,9 @@ /** @type {Function} **/ _template: undefined, + /** @type {Function} **/ + _popoverMenuTemplate: undefined, + /** @type {boolean} **/ showLink: true, @@ -96,7 +125,9 @@ 'change .publicUploadCheckbox': 'onAllowPublicUploadChange', 'change .publicEditingCheckbox': 'onAllowPublicEditingChange', 'change .hideFileListCheckbox': 'onHideFileListChange', - 'click .showPasswordCheckbox': 'onShowPasswordClick' + 'click .showPasswordCheckbox': 'onShowPasswordClick', + 'click .icon-more': 'onToggleMenu', + 'click .pop-up': 'onPopUpClick' }, initialize: function(options) { @@ -150,8 +181,7 @@ .tooltip('show'); _.delay(function() { $input.tooltip('hide') - .attr('data-original-title', t('core', 'Copy')) - .tooltip('fixTitle'); + .tooltip("destroy"); }, 3000); }); clipboard.on('error', function (e) { @@ -173,7 +203,7 @@ _.delay(function () { $input.tooltip('hide') .attr('data-original-title', t('core', 'Copy')) - .tooltip('fixTitle'); + .tooltip("destroy"); }, 3000); }); @@ -354,6 +384,26 @@ && isLinkShare && this.model.updatePermissionPossible(); + var link = this.model.get('linkShare').link; + var social = []; + OC.Share.Social.Collection.each(function(model) { + var url = model.get('url'); + url = url.replace('{{reference}}', link); + + social.push({ + url: url, + label: t('core', 'Share to {name}', {name: model.get('name')}), + name: model.get('name'), + iconClass: model.get('iconClass') + }); + }); + + var popover = this.popoverMenuTemplate({ + cid: this.cid, + copyLabel: t('core', 'Copy'), + social: social + }); + this.$el.html(linkShareTemplate({ cid: this.cid, shareAllowed: true, @@ -376,16 +426,27 @@ publicEditingLabel: t('core', 'Allow editing'), hideFileListLabel: t('core', 'File drop (upload only)'), mailPrivatePlaceholder: t('core', 'Email link to person'), - mailButtonText: t('core', 'Send') + mailButtonText: t('core', 'Send'), + singleAction: OC.Share.Social.Collection.size() == 0, + popoverMenu: popover })); - this.$el.find('.clipboardButton').tooltip({placement: 'bottom', title: t('core', 'Copy'), trigger: 'hover'}); - this.delegateEvents(); return this; }, + onToggleMenu: function(event) { + event.preventDefault(); + event.stopPropagation(); + var $element = $(event.target); + var $li = $element.closest('.oneline'); + var $menu = $li.find('.popovermenu'); + + OC.showMenu(null, $menu); + this._menuOpen = $li.data('share-id'); + }, + /** * @returns {Function} from Handlebars * @private @@ -395,6 +456,32 @@ this._template = Handlebars.compile(TEMPLATE); } return this._template; + }, + + /** + * renders the popover template and returns the resulting HTML + * + * @param {Object} data + * @returns {string} + */ + popoverMenuTemplate: function(data) { + if(!this._popoverMenuTemplate) { + this._popoverMenuTemplate = Handlebars.compile(TEMPLATE_POPOVER_MENU); + } + return this._popoverMenuTemplate(data); + }, + + onPopUpClick: function(event) { + var url = $(event.target).data('url'); + $(event.target).tooltip('hide'); + if (url) { + var width = 600; + var height = 400; + var left = (screen.width/2)-(width/2); + var top = (screen.height/2)-(height/2); + + window.open(url, 'name', 'width=' + width + ', height=' + height + ', top=' + top + ', left=' + left); + } } }); diff --git a/core/js/sharedialoglinksocialview.js b/core/js/sharedialoglinksocialview.js deleted file mode 100644 index 1cd8d91bc7aeb..0000000000000 --- a/core/js/sharedialoglinksocialview.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @copyright 2017, Roeland Jago Douma - * - * @author Roeland Jago Douma - * - * @license GNU AGPL version 3 or any later version - * - * 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 . - * - */ - -(function() { - if (!OC.Share) { - OC.Share = {}; - } - - var TEMPLATE = - '' - ; - - /** - * @class OCA.Share.ShareDialogLinkSocialView - * @member {OC.Share.ShareItemModel} model - * @member {jQuery} $el - * @memberof OCA.Sharing - * @classdesc - * - * Represents the GUI of the share dialogue - * - */ - var ShareDialogLinkSocialView = OC.Backbone.View.extend({ - /** @type {string} **/ - id: 'shareDialogLinkSocialView', - - /** @type {OC.Share.ShareConfigModel} **/ - configModel: undefined, - - /** @type {Function} **/ - _template: undefined, - - /** @type {boolean} **/ - showLink: true, - - events: { - 'click .pop-up': 'onPopUpClick' - }, - - initialize: function(options) { - var view = this; - - this.model.on('change:linkShare', function() { - view.render(); - }); - - if(!_.isUndefined(options.configModel)) { - this.configModel = options.configModel; - } else { - throw 'missing OC.Share.ShareConfigModel'; - } - }, - - onPopUpClick: function(event) { - var url = $(event.target).data('url'); - $(event.target).tooltip('hide'); - if (url) { - var width = 600; - var height = 400; - var left = (screen.width/2)-(width/2); - var top = (screen.height/2)-(height/2); - - window.open(url, 'name', 'width=' + width + ', height=' + height + ', top=' + top + ', left=' + left); - } - }, - - render: function() { - var isLinkShare = this.model.get('linkShare').isLinkShare; - if (isLinkShare && OC.Share.Social.Collection.size() > 0) { - var linkShareTemplate = this.template(); - var link = this.model.get('linkShare').link; - - var html = ''; - - OC.Share.Social.Collection.each(function(model) { - var url = model.get('url'); - url = url.replace('{{reference}}', link); - - html += linkShareTemplate({ - url: url, - shareToolTip: t('core', 'Share to {name}', {name: model.get('name')}), - iconClass: model.get('iconClass') - }); - }); - - this.$el.html(html); - this.$el.show(); - } else { - this.$el.hide(); - } - - this.delegateEvents(); - - return this; - }, - - /** - * @returns {Function} from Handlebars - * @private - */ - template: function () { - if (!this._template) { - this._template = Handlebars.compile(TEMPLATE); - } - return this._template; - } - - }); - - OC.Share.ShareDialogLinkSocialView = ShareDialogLinkSocialView; -})(); diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index ed887dfb7164a..a63960da2b8bd 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -28,7 +28,6 @@ '
' + '
' + '
' + - '
' + ''; var TEMPLATE_REMOTE_SHARE_INFO = @@ -70,9 +69,6 @@ /** @type {object} **/ shareeListView: undefined, - /** @type OC.Share.ShareDialogLinkSocialView **/ - socalView: undefined, - events: { 'input .shareWithField': 'onShareWithFieldChanged' }, @@ -109,8 +105,7 @@ resharerInfoView: 'ShareDialogResharerInfoView', linkShareView: 'ShareDialogLinkShareView', expirationView: 'ShareDialogExpirationView', - shareeListView: 'ShareDialogShareeListView', - socialView: 'ShareDialogLinkSocialView' + shareeListView: 'ShareDialogShareeListView' }; for(var name in subViews) { @@ -426,9 +421,6 @@ this.shareeListView.$el = this.$el.find('.shareeListView'); this.shareeListView.render(); - this.socialView.$el = this.$('.socialView'); - this.socialView.render(); - this.$el.find('.hasTooltip').tooltip(); return this; diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index c693af02a5046..38b12a57ccfbc 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -97,7 +97,6 @@ public static function registerBackend($itemType, $class, $collectionOf = null, \OC_Util::addScript('core', 'sharesocialmanager'); \OC_Util::addScript('core', 'sharedialogresharerinfoview'); \OC_Util::addScript('core', 'sharedialoglinkshareview'); - \OC_Util::addScript('core', 'sharedialoglinksocialview'); \OC_Util::addScript('core', 'sharedialogexpirationview'); \OC_Util::addScript('core', 'sharedialogshareelistview'); \OC_Util::addScript('core', 'sharedialogview'); From 835b49d941009842f3d37fd62970feddde38d512 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 3 Mar 2017 13:36:20 +0100 Subject: [PATCH 3/5] Make sure copy tooltip remains when we have no social providers Signed-off-by: Roeland Jago Douma --- core/js/sharedialoglinkshareview.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 014819d510359..dc8644ab4cd7d 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -180,8 +180,13 @@ .tooltip({placement: 'bottom', trigger: 'manual'}) .tooltip('show'); _.delay(function() { - $input.tooltip('hide') - .tooltip("destroy"); + $input.tooltip('hide'); + if (OC.Share.Social.Collection.size() == 0) { + $input.attr('data-original-title', t('core', 'Copy')) + .tooltip('fixTitle'); + } else { + $input.tooltip("destroy"); + } }, 3000); }); clipboard.on('error', function (e) { @@ -201,9 +206,13 @@ .tooltip({placement: 'bottom', trigger: 'manual'}) .tooltip('show'); _.delay(function () { - $input.tooltip('hide') - .attr('data-original-title', t('core', 'Copy')) - .tooltip("destroy"); + $input.tooltip('hide'); + if (OC.Share.Social.Collection.size() == 0) { + $input.attr('data-original-title', t('core', 'Copy')) + .tooltip('fixTitle'); + } else { + $input.tooltip("destroy"); + } }, 3000); }); @@ -431,6 +440,14 @@ popoverMenu: popover })); + if (OC.Share.Social.Collection.size() == 0) { + this.$el.find('.clipboardButton').tooltip({ + placement: 'bottom', + title: t('core', 'Copy'), + trigger: 'hover' + }); + } + this.delegateEvents(); return this; From be45d6aac9e02890fd162bd2fca4239c4e39bd06 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 6 Mar 2017 21:26:04 +0100 Subject: [PATCH 4/5] Fix tests Signed-off-by: Roeland Jago Douma --- core/js/core.json | 1 + 1 file changed, 1 insertion(+) diff --git a/core/js/core.json b/core/js/core.json index d589208c82846..52d81b352d42f 100644 --- a/core/js/core.json +++ b/core/js/core.json @@ -28,6 +28,7 @@ "l10n.js", "apps.js", "share.js", + "sharesocialmanager.js", "shareconfigmodel.js", "shareitemmodel.js", "sharedialogview.js", From 13aae43d89389d19b750ff036294e5c2e61f9d8d Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Tue, 14 Mar 2017 22:50:32 -0600 Subject: [PATCH 5/5] Fix layout of sharing buttons Signed-off-by: Morris Jobke --- apps/files_sharing/css/sharetabview.css | 8 +++++++ core/js/sharedialoglinkshareview.js | 31 ++++++++++++++----------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css index 5896e18abada9..6fd2b9b316509 100644 --- a/apps/files_sharing/css/sharetabview.css +++ b/apps/files_sharing/css/sharetabview.css @@ -28,8 +28,16 @@ padding: 14px; } +/* fix the popup menu because the button is shifted and then the menu is not aligned */ +.shareTabView .popovermenu.socialSharingMenu { + right: -7px; +} + .shareTabView .popovermenu .clipboardButton { position: relative; + top: initial; + right: initial; + padding: 18px 0 18px 36px; } .shareTabView label { diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index dc8644ab4cd7d..e7bea516be03d 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -70,22 +70,21 @@ '{{/if}}' ; var TEMPLATE_POPOVER_MENU = - '