You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sharedialoglinkshareview.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright (c) 2015
  3. *
  4. * This file is licensed under the Affero General Public License version 3
  5. * or later.
  6. *
  7. * See the COPYING-README file.
  8. *
  9. */
  10. (function() {
  11. if (!OC.Share) {
  12. OC.Share = {};
  13. }
  14. var PASSWORD_PLACEHOLDER = '**********';
  15. var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the public link');
  16. var TEMPLATE =
  17. '{{#if shareAllowed}}' +
  18. '<span class="icon-loading-small hidden"></span>' +
  19. '<input type="checkbox" name="linkCheckbox" id="linkCheckbox-{{cid}}" class="checkbox linkCheckbox" value="1" {{#if isLinkShare}}checked="checked"{{/if}} />' +
  20. '<label for="linkCheckbox-{{cid}}">{{linkShareLabel}}</label>' +
  21. '<br />' +
  22. '<label for="linkText-{{cid}}" class="hidden-visually">{{urlLabel}}</label>' +
  23. '<input id="linkText-{{cid}}" class="linkText {{#unless isLinkShare}}hidden{{/unless}}" type="text" readonly="readonly" value="{{shareLinkURL}}" />' +
  24. ' {{#if showPasswordCheckBox}}' +
  25. '<input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} value="1" />' +
  26. '<label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label>' +
  27. ' {{/if}}' +
  28. '<div id="linkPass" class="linkPass {{#unless isPasswordSet}}hidden{{/unless}}">' +
  29. ' <label for="linkPassText-{{cid}}" class="hidden-visually">{{passwordLabel}}</label>' +
  30. ' <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" />' +
  31. ' <span class="icon-loading-small hidden"></span>' +
  32. '</div>' +
  33. ' {{#if publicUpload}}' +
  34. '<div id="allowPublicUploadWrapper">' +
  35. ' <span class="icon-loading-small hidden"></span>' +
  36. ' <input type="checkbox" value="1" name="allowPublicUpload" id="sharingDialogAllowPublicUpload-{{cid}}" class="checkbox publicUploadCheckbox" {{{publicUploadChecked}}} />' +
  37. '<label for="sharingDialogAllowPublicUpload-{{cid}}">{{publicUploadLabel}}</label>' +
  38. '</div>' +
  39. ' {{/if}}' +
  40. ' {{#if mailPublicNotificationEnabled}}' +
  41. '<form id="emailPrivateLink" class="emailPrivateLinkForm">' +
  42. ' <input id="email" class="emailField" value="" placeholder="{{mailPrivatePlaceholder}}" type="text" />' +
  43. ' <input id="emailButton" class="emailButton" type="submit" value="{{mailButtonText}}" />' +
  44. '</form>' +
  45. ' {{/if}}' +
  46. '{{else}}' +
  47. // FIXME: this doesn't belong in this view
  48. '<input id="shareWith-{{cid}}" class="shareWithField" type="text" placeholder="{{noSharingPlaceholder}}" disabled="disabled"/>' +
  49. '{{/if}}'
  50. ;
  51. /**
  52. * @class OCA.Share.ShareDialogLinkShareView
  53. * @member {OC.Share.ShareItemModel} model
  54. * @member {jQuery} $el
  55. * @memberof OCA.Sharing
  56. * @classdesc
  57. *
  58. * Represents the GUI of the share dialogue
  59. *
  60. */
  61. var ShareDialogLinkShareView = OC.Backbone.View.extend({
  62. /** @type {string} **/
  63. id: 'shareDialogLinkShare',
  64. /** @type {OC.Share.ShareConfigModel} **/
  65. configModel: undefined,
  66. /** @type {Function} **/
  67. _template: undefined,
  68. /** @type {boolean} **/
  69. showLink: true,
  70. events: {
  71. 'submit .emailPrivateLinkForm': '_onEmailPrivateLink',
  72. 'focusout input.linkPassText': 'onPasswordEntered',
  73. 'keyup input.linkPassText': 'onPasswordKeyUp',
  74. 'click .linkCheckbox': 'onLinkCheckBoxChange',
  75. 'click .linkText': 'onLinkTextClick',
  76. 'change .publicUploadCheckbox': 'onAllowPublicUploadChange',
  77. 'click .showPasswordCheckbox': 'onShowPasswordClick'
  78. },
  79. initialize: function(options) {
  80. var view = this;
  81. this.model.on('change:permissions', function() {
  82. view.render();
  83. });
  84. this.model.on('change:itemType', function() {
  85. view.render();
  86. });
  87. this.model.on('change:allowPublicUploadStatus', function() {
  88. view.render();
  89. });
  90. this.model.on('change:linkShare', function() {
  91. view.render();
  92. });
  93. if(!_.isUndefined(options.configModel)) {
  94. this.configModel = options.configModel;
  95. } else {
  96. throw 'missing OC.Share.ShareConfigModel';
  97. }
  98. _.bindAll(
  99. this,
  100. '_onEmailPrivateLink',
  101. 'onLinkCheckBoxChange',
  102. 'onPasswordEntered',
  103. 'onPasswordKeyUp',
  104. 'onLinkTextClick',
  105. 'onShowPasswordClick',
  106. 'onAllowPublicUploadChange'
  107. );
  108. },
  109. onLinkCheckBoxChange: function() {
  110. var $checkBox = this.$el.find('.linkCheckbox');
  111. var $loading = $checkBox.siblings('.icon-loading-small');
  112. if(!$loading.hasClass('hidden')) {
  113. return false;
  114. }
  115. if($checkBox.is(':checked')) {
  116. if(this.configModel.get('enforcePasswordForPublicLink') === false) {
  117. $loading.removeClass('hidden');
  118. // this will create it
  119. this.model.saveLinkShare();
  120. } else {
  121. this.$el.find('.linkPass').slideToggle(OC.menuSpeed);
  122. this.$el.find('.linkPassText').focus();
  123. }
  124. } else {
  125. $loading.removeClass('hidden');
  126. if (this.model.get('linkShare').isLinkShare) {
  127. this.model.removeLinkShare();
  128. } else {
  129. this.$el.find('.linkPass').slideToggle(OC.menuSpeed);
  130. }
  131. }
  132. },
  133. onLinkTextClick: function() {
  134. var $el = this.$el.find('.linkText');
  135. $el.focus();
  136. $el.select();
  137. },
  138. onShowPasswordClick: function() {
  139. this.$el.find('.linkPass').slideToggle(OC.menuSpeed);
  140. if(!this.$el.find('.showPasswordCheckbox').is(':checked')) {
  141. this.model.setPassword('');
  142. this.model.saveLinkShare();
  143. } else {
  144. this.$el.find('.linkPassText').focus();
  145. }
  146. },
  147. onPasswordKeyUp: function(event) {
  148. if(event.keyCode == 13) {
  149. this.onPasswordEntered();
  150. }
  151. },
  152. onPasswordEntered: function() {
  153. var self = this;
  154. var $loading = this.$el.find('.linkPass .icon-loading-small');
  155. if (!$loading.hasClass('hidden')) {
  156. // still in process
  157. return;
  158. }
  159. var $input = this.$el.find('.linkPassText');
  160. $input.removeClass('error');
  161. var password = $input.val();
  162. // in IE9 the password might be the placeholder due to bugs in the placeholders polyfill
  163. if(password === '' || password === PASSWORD_PLACEHOLDER || password === PASSWORD_PLACEHOLDER_MESSAGE) {
  164. return;
  165. }
  166. $loading
  167. .removeClass('hidden')
  168. .addClass('inlineblock');
  169. this.model.setPassword(password);
  170. this.model.saveLinkShare({}, {
  171. error: function(model, msg) {
  172. $loading.removeClass('inlineblock').addClass('hidden');
  173. $input.addClass('error');
  174. $input.attr('title', msg);
  175. $input.tooltip({placement: 'bottom', trigger: 'manual'});
  176. $input.tooltip('show');
  177. }
  178. });
  179. },
  180. onAllowPublicUploadChange: function() {
  181. var $checkbox = this.$('.publicUploadCheckbox');
  182. $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock');
  183. this.model.setPublicUpload($checkbox.is(':checked'));
  184. this.model.saveLinkShare();
  185. },
  186. _onEmailPrivateLink: function(event) {
  187. event.preventDefault();
  188. var $emailField = this.$el.find('.emailField');
  189. var $emailButton = this.$el.find('.emailButton');
  190. var email = $emailField.val();
  191. if (email !== '') {
  192. $emailField.prop('disabled', true);
  193. $emailButton.prop('disabled', true);
  194. $emailField.val(t('core', 'Sending ...'));
  195. this.model.sendEmailPrivateLink(email).done(function() {
  196. $emailField.css('font-weight', 'bold').val(t('core','Email sent'));
  197. setTimeout(function() {
  198. $emailField.val('');
  199. $emailField.css('font-weight', 'normal');
  200. $emailField.prop('disabled', false);
  201. $emailButton.prop('disabled', false);
  202. }, 2000);
  203. }).fail(function() {
  204. $emailField.val(email);
  205. $emailField.css('font-weight', 'normal');
  206. $emailField.prop('disabled', false);
  207. $emailButton.prop('disabled', false);
  208. });
  209. }
  210. return false;
  211. },
  212. render: function() {
  213. var linkShareTemplate = this.template();
  214. if( !this.model.sharePermissionPossible()
  215. || !this.showLink
  216. || !this.configModel.isShareWithLinkAllowed())
  217. {
  218. this.$el.html(linkShareTemplate({
  219. shareAllowed: false,
  220. noSharingPlaceholder: t('core', 'Resharing is not allowed')
  221. }));
  222. return this;
  223. }
  224. var publicUpload =
  225. this.model.isFolder()
  226. && this.model.createPermissionPossible()
  227. && this.configModel.isPublicUploadEnabled();
  228. var publicUploadChecked = '';
  229. if(this.model.isPublicUploadAllowed()) {
  230. publicUploadChecked = 'checked="checked"';
  231. }
  232. var isLinkShare = this.model.get('linkShare').isLinkShare;
  233. var isPasswordSet = !!this.model.get('linkShare').password;
  234. var showPasswordCheckBox = isLinkShare
  235. && ( !this.configModel.get('enforcePasswordForPublicLink')
  236. || !this.model.get('linkShare').password);
  237. this.$el.html(linkShareTemplate({
  238. cid: this.cid,
  239. shareAllowed: true,
  240. isLinkShare: isLinkShare,
  241. shareLinkURL: this.model.get('linkShare').link,
  242. linkShareLabel: t('core', 'Share link'),
  243. urlLabel: t('core', 'Link'),
  244. enablePasswordLabel: t('core', 'Password protect'),
  245. passwordLabel: t('core', 'Password'),
  246. passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE,
  247. isPasswordSet: isPasswordSet,
  248. showPasswordCheckBox: showPasswordCheckBox,
  249. publicUpload: publicUpload && isLinkShare,
  250. publicUploadChecked: publicUploadChecked,
  251. publicUploadLabel: t('core', 'Allow editing'),
  252. mailPublicNotificationEnabled: isLinkShare && this.configModel.isMailPublicNotificationEnabled(),
  253. mailPrivatePlaceholder: t('core', 'Email link to person'),
  254. mailButtonText: t('core', 'Send')
  255. }));
  256. var $emailField = this.$el.find('.emailField');
  257. if (isLinkShare && $emailField.length !== 0) {
  258. $emailField.autocomplete({
  259. minLength: 1,
  260. source: function (search, response) {
  261. $.get(
  262. OC.generateUrl('core/ajax/share.php'), {
  263. fetch: 'getShareWithEmail',
  264. search: search.term
  265. }, function(result) {
  266. if (result.status == 'success' && result.data.length > 0) {
  267. response(result.data);
  268. }
  269. });
  270. },
  271. select: function( event, item ) {
  272. $emailField.val(item.item.email);
  273. return false;
  274. }
  275. })
  276. .data("ui-autocomplete")._renderItem = function( ul, item ) {
  277. return $('<li>')
  278. .append('<a>' + escapeHTML(item.displayname) + "<br>" + escapeHTML(item.email) + '</a>' )
  279. .appendTo( ul );
  280. };
  281. }
  282. // TODO drop with IE8 drop
  283. if($('html').hasClass('ie8')) {
  284. this.$el.find('#linkPassText').removeAttr('placeholder');
  285. this.$el.find('#linkPassText').val('');
  286. }
  287. this.delegateEvents();
  288. return this;
  289. },
  290. /**
  291. * @returns {Function} from Handlebars
  292. * @private
  293. */
  294. template: function () {
  295. if (!this._template) {
  296. this._template = Handlebars.compile(TEMPLATE);
  297. }
  298. return this._template;
  299. }
  300. });
  301. OC.Share.ShareDialogLinkShareView = ShareDialogLinkShareView;
  302. })();