diff options
Diffstat (limited to 'core/js')
-rw-r--r-- | core/js/apps.js | 12 | ||||
-rw-r--r-- | core/js/core.json | 1 | ||||
-rw-r--r-- | core/js/merged-share-backend.json | 17 | ||||
-rw-r--r-- | core/js/sharedialogexpirationview.js | 209 | ||||
-rw-r--r-- | core/js/sharedialoglinkshareview.js | 408 | ||||
-rw-r--r-- | core/js/sharedialogresharerinfoview.js | 12 | ||||
-rw-r--r-- | core/js/sharedialogshareelistview.js | 148 | ||||
-rw-r--r-- | core/js/sharedialogview.js | 8 | ||||
-rw-r--r-- | core/js/shareitemmodel.js | 20 | ||||
-rw-r--r-- | core/js/tests/specs/sharedialoglinkshareview.js | 2 | ||||
-rw-r--r-- | core/js/tests/specs/sharedialogviewSpec.js | 186 |
11 files changed, 481 insertions, 542 deletions
diff --git a/core/js/apps.js b/core/js/apps.js index b40883e88cf..473fec313a1 100644 --- a/core/js/apps.js +++ b/core/js/apps.js @@ -27,8 +27,9 @@ */ exports.Apps.showAppSidebar = function($el) { var $appSidebar = $el || $('#app-sidebar'); - $appSidebar.removeClass('disappear'); - $('#content').addClass('with-app-sidebar').trigger(new $.Event('appresized')); + $appSidebar.removeClass('disappear') + .show('slide', { direction: 'right' }, 300); + $('#app-content').trigger(new $.Event('appresized')); }; /** @@ -39,8 +40,11 @@ */ exports.Apps.hideAppSidebar = function($el) { var $appSidebar = $el || $('#app-sidebar'); - $appSidebar.addClass('disappear'); - $('#content').removeClass('with-app-sidebar').trigger(new $.Event('appresized')); + $appSidebar.hide('slide', { direction: 'right' }, 300, + function() { + $appSidebar.addClass('disappear'); + }); + $('#app-content').trigger(new $.Event('appresized')); }; /** diff --git a/core/js/core.json b/core/js/core.json index 502e3a57976..2ebc2e710ed 100644 --- a/core/js/core.json +++ b/core/js/core.json @@ -37,7 +37,6 @@ "shareconfigmodel.js", "shareitemmodel.js", "sharedialogview.js", - "sharedialogexpirationview.js", "sharedialoglinkshareview.js", "sharedialogresharerinfoview.js", "sharedialogshareelistview.js", diff --git a/core/js/merged-share-backend.json b/core/js/merged-share-backend.json index d39945b8f79..63c3575a666 100644 --- a/core/js/merged-share-backend.json +++ b/core/js/merged-share-backend.json @@ -1,11 +1,10 @@ [ - "shareconfigmodel.js", - "shareitemmodel.js", - "sharesocialmanager.js", - "sharedialogresharerinfoview.js", - "sharedialoglinkshareview.js", - "sharedialogexpirationview.js", - "sharedialogshareelistview.js", - "sharedialogview.js", - "share.js" + "shareconfigmodel.js", + "shareitemmodel.js", + "sharesocialmanager.js", + "sharedialogresharerinfoview.js", + "sharedialoglinkshareview.js", + "sharedialogshareelistview.js", + "sharedialogview.js", + "share.js" ] diff --git a/core/js/sharedialogexpirationview.js b/core/js/sharedialogexpirationview.js deleted file mode 100644 index a9849ef9161..00000000000 --- a/core/js/sharedialogexpirationview.js +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2015 - * - * This file is licensed under the Affero General Public License version 3 - * or later. - * - * See the COPYING-README file. - * - */ - -/* global moment, Handlebars */ - -(function() { - if (!OC.Share) { - OC.Share = {}; - } - - var TEMPLATE = - // currently expiration is only effective for link share. - // this is about to change in future. Therefore this is not included - // in the LinkShareView to ease reusing it in future. Then, - // modifications (getting rid of IDs) are still necessary. - '{{#if isLinkShare}}' + - '<input type="checkbox" name="expirationCheckbox" class="expirationCheckbox checkbox" id="expirationCheckbox-{{cid}}" value="1" ' + - '{{#if isExpirationSet}}checked="checked"{{/if}} {{#if disableCheckbox}}disabled="disabled"{{/if}} />' + - '<label for="expirationCheckbox-{{cid}}">{{setExpirationLabel}}</label>' + - '<div class="expirationDateContainer {{#unless isExpirationSet}}hidden{{/unless}}">' + - ' <label for="expirationDate" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' + - ' <input id="expirationDate" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{expirationValue}}" />' + - '</div>' + - ' {{#if isExpirationEnforced}}' + - // originally the expire message was shown when a default date was set, however it never had text - '<em id="defaultExpireMessage">{{defaultExpireMessage}}</em>' + - ' {{/if}}' + - '{{/if}}' - ; - - /** - * @class OCA.Share.ShareDialogExpirationView - * @member {OC.Share.ShareItemModel} model - * @member {jQuery} $el - * @memberof OCA.Sharing - * @classdesc - * - * Represents the expiration part in the GUI of the share dialogue - * - */ - var ShareDialogExpirationView = OC.Backbone.View.extend({ - /** @type {string} **/ - id: 'shareDialogLinkShare', - - /** @type {OC.Share.ShareConfigModel} **/ - configModel: undefined, - - /** @type {Function} **/ - _template: undefined, - - /** @type {boolean} **/ - showLink: true, - - className: 'hidden', - - events: { - 'change .expirationCheckbox': '_onToggleExpiration', - 'change .datepicker': '_onChangeExpirationDate' - }, - - initialize: function(options) { - if(!_.isUndefined(options.configModel)) { - this.configModel = options.configModel; - } else { - throw 'missing OC.Share.ShareConfigModel'; - } - - var view = this; - this.configModel.on('change:isDefaultExpireDateEnforced', function() { - view.render(); - }); - - this.model.on('change:itemType', function() { - view.render(); - }); - - this.model.on('change:linkShare', function() { - view.render(); - }); - }, - - _onToggleExpiration: function(event) { - var $checkbox = $(event.target); - var state = $checkbox.prop('checked'); - // TODO: slide animation - this.$el.find('.expirationDateContainer').toggleClass('hidden', !state); - if (!state) { - // discard expiration date - this.model.get('linkShare').expiration = ''; - this.model.saveLinkShare({ - expireDate: '' - }); - } else { - this.$el.find('#expirationDate').focus(); - } - }, - - _onChangeExpirationDate: function(event) { - var $target = $(event.target); - $target.tooltip('hide'); - $target.removeClass('error'); - - var expiration = moment($target.val(), 'DD-MM-YYYY').format('YYYY-MM-DD'); - this.model.get('linkShare').expiration = expiration; - this.model.saveLinkShare({ - expiration: expiration - }, { - error: function(model, message) { - if (!message) { - $target.attr('title', t('core', 'Error setting expiration date')); - } else { - $target.attr('title', message); - } - $target.tooltip({gravity: 'n'}); - $target.tooltip('show'); - $target.addClass('error'); - } - }); - }, - - render: function() { - var defaultExpireMessage = ''; - var defaultExpireDays = this.configModel.get('defaultExpireDate'); - var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); - - if( (this.model.isFolder() || this.model.isFile()) - && isExpirationEnforced) { - defaultExpireMessage = t( - 'core', - 'The public link will expire no later than {days} days after it is created', - {'days': defaultExpireDays } - ); - } - - var isExpirationSet = !!this.model.get('linkShare').expiration || isExpirationEnforced; - - var expiration; - if (isExpirationSet) { - expiration = moment(this.model.get('linkShare').expiration, 'YYYY-MM-DD').format('DD-MM-YYYY'); - } - - this.$el.html(this.template({ - cid: this.cid, - setExpirationLabel: t('core', 'Set expiration date'), - expirationLabel: t('core', 'Expiration'), - expirationDatePlaceholder: t('core', 'Expiration date'), - defaultExpireMessage: defaultExpireMessage, - isLinkShare: this.model.get('linkShare').isLinkShare, - isExpirationSet: isExpirationSet, - isExpirationEnforced: isExpirationEnforced, - disableCheckbox: isExpirationEnforced && isExpirationSet, - expirationValue: expiration - })); - - // what if there is another date picker on that page? - var minDate = new Date(); - var maxDate = null; - // min date should always be the next day - minDate.setDate(minDate.getDate()+1); - - if(isExpirationSet) { - if(isExpirationEnforced) { - // TODO: hack: backend returns string instead of integer - var shareTime = this.model.get('linkShare').stime; - if (_.isNumber(shareTime)) { - shareTime = new Date(shareTime * 1000); - } - if (!shareTime) { - shareTime = new Date(); // now - } - shareTime = OC.Util.stripTime(shareTime).getTime(); - maxDate = new Date(shareTime + defaultExpireDays * 24 * 3600 * 1000); - } - } - $.datepicker.setDefaults({ - minDate: minDate, - maxDate: maxDate - }); - - this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'}); - - this.delegateEvents(); - - return this; - }, - - /** - * @returns {Function} from Handlebars - * @private - */ - template: function (data) { - if (!this._template) { - this._template = Handlebars.compile(TEMPLATE); - } - return this._template(data); - } - - }); - - OC.Share.ShareDialogExpirationView = ShareDialogExpirationView; - -})(); diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 5a78276a491..925d8ed918e 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -21,71 +21,101 @@ var TEMPLATE = '{{#if shareAllowed}}' + - '<span class="icon-loading-small hidden"></span>' + - '<input type="checkbox" name="linkCheckbox" id="linkCheckbox-{{cid}}" class="checkbox linkCheckbox" value="1" {{#if isLinkShare}}checked="checked"{{/if}} />' + - '<label for="linkCheckbox-{{cid}}">{{linkShareLabel}}</label>' + - '<br />' + - '<div class="oneline">' + - '<label for="linkText-{{cid}}" class="hidden-visually">{{urlLabel}}</label>' + - '<input id="linkText-{{cid}}" class="linkText {{#unless isLinkShare}}hidden{{/unless}}" type="text" readonly="readonly" value="{{shareLinkURL}}" />' + - '{{#if singleAction}}' + - '<a class="{{#unless isLinkShare}}hidden-visually{{/unless}} clipboardButton icon icon-clippy" data-clipboard-target="#linkText-{{cid}}"></a>' + - '{{else}}' + - '<a class="{{#unless isLinkShare}}hidden-visually{{/unless}}" href="#"><span class="linkMore icon icon-more"></span></a>' + - '{{{popoverMenu}}}' + - '{{/if}}' + - '</div>' + - '{{#if publicUpload}}' + - '<div>' + - '<span class="icon-loading-small hidden"></span>' + - '<input type="radio" name="publicUpload" value="{{publicUploadRValue}}" id="sharingDialogAllowPublicUpload-r-{{cid}}" class="radio publicUploadRadio" {{{publicUploadRChecked}}} />' + - '<label for="sharingDialogAllowPublicUpload-r-{{cid}}">{{publicUploadRLabel}}</label>' + - '</div>' + - '<div>' + - '<span class="icon-loading-small hidden"></span>' + - '<input type="radio" name="publicUpload" value="{{publicUploadRWValue}}" id="sharingDialogAllowPublicUpload-rw-{{cid}}" class="radio publicUploadRadio" {{{publicUploadRWChecked}}} />' + - '<label for="sharingDialogAllowPublicUpload-rw-{{cid}}">{{publicUploadRWLabel}}</label>' + - '</div>' + - '<div>' + - '<span class="icon-loading-small hidden"></span>' + - '<input type="radio" name="publicUpload" value="{{publicUploadWValue}}" id="sharingDialogAllowPublicUpload-w-{{cid}}" class="radio publicUploadRadio" {{{publicUploadWChecked}}} />' + - '<label for="sharingDialogAllowPublicUpload-w-{{cid}}">{{publicUploadWLabel}}</label>' + - '</div>' + - '{{/if}}' + - ' {{#if publicEditing}}' + - '<div id="allowPublicEditingWrapper">' + - ' <span class="icon-loading-small hidden"></span>' + - ' <input type="checkbox" value="1" name="allowPublicEditing" id="sharingDialogAllowPublicEditing-{{cid}}" class="checkbox publicEditingCheckbox" {{{publicEditingChecked}}} />' + - '<label for="sharingDialogAllowPublicEditing-{{cid}}">{{publicEditingLabel}}</label>' + - '</div>' + - ' {{/if}}' + - ' {{#if showPasswordCheckBox}}' + - '<input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} value="1" />' + - '<label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label>' + - ' {{/if}}' + - '<div id="linkPass" class="oneline linkPass {{#unless isPasswordSet}}hidden{{/unless}}">' + - ' <label for="linkPassText-{{cid}}" class="hidden-visually">{{passwordLabel}}</label>' + - ' {{#if showPasswordCheckBox}}' + - ' <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" autocomplete="new-password" />' + - ' {{else}}' + - ' <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholderInitial}}" autocomplete="new-password" />' + - ' {{/if}}' + - ' <span class="icon icon-loading-small hidden"></span>' + - '</div>' + + '<ul id="shareLink" class="shareWithList">' + + ' <li data-share-id="{{cid}}">' + + ' <div class="avatar icon-public-white"></div><span class="username" title="{{linkShareLabel}}">{{linkShareLabel}}</span>' + + ' <span class="sharingOptionsGroup">' + + ' <span class="shareOption"> ' + + ' <span class="icon-loading-small hidden"></span>' + + ' <input id="linkCheckbox-{{cid}}" {{#if isLinkShare}}checked="checked"{{/if}} type="checkbox" name="linkCheckbox" class="linkCheckbox permissions checkbox">' + + ' <label for="linkCheckbox-{{cid}}">{{linkShareEnableLabel}}</label>' + + ' </span>' + + ' {{#if isLinkShare}}' + + ' <div class="share-menu" tabindex="0"><span class="icon icon-more"></span>' + + ' {{{popoverMenu}}}' + + ' </div>' + + ' {{/if}}' + + ' </span>' + + ' </li>' + + '</ul>' + '{{else}}' + // FIXME: this doesn't belong in this view '{{#if noSharingPlaceholder}}<input id="shareWith-{{cid}}" class="shareWithField" type="text" placeholder="{{noSharingPlaceholder}}" disabled="disabled"/>{{/if}}' + '{{/if}}' ; var TEMPLATE_POPOVER_MENU = - '<div class="popovermenu bubble hidden menu socialSharingMenu">' + + '<div class="popovermenu menu">' + '<ul>' + '<li>' + - '<a href="#" class="shareOption menuitem clipboardButton" data-clipboard-target="#linkText-{{cid}}">' + + '<a href="#" class="menuitem clipboardButton" data-clipboard-text="{{shareLinkURL}}">' + '<span class="icon icon-clippy" ></span>' + '<span>{{copyLabel}}</span>' + '</a>' + '</li>' + + '<li class="hidden linkTextMenu">' + + '<span class="menuitem icon-link-text">' + + '<input id="linkText-{{cid}}" class="linkText" type="text" readonly="readonly" value="{{shareLinkURL}}" />' + + '</span>' + + '</li>' + + '{{#if publicUpload}}' + + '<li><span class="shareOption menuitem">' + + '<span class="icon-loading-small hidden"></span>' + + '<input type="radio" name="publicUpload" value="{{publicUploadRValue}}" id="sharingDialogAllowPublicUpload-r-{{cid}}" class="radio publicUploadRadio" {{{publicUploadRChecked}}} />' + + '<label for="sharingDialogAllowPublicUpload-r-{{cid}}">{{publicUploadRLabel}}</label>' + + '</span></li>' + + '<li><span class="shareOption menuitem">' + + '<span class="icon-loading-small hidden"></span>' + + '<input type="radio" name="publicUpload" value="{{publicUploadRWValue}}" id="sharingDialogAllowPublicUpload-rw-{{cid}}" class="radio publicUploadRadio" {{{publicUploadRWChecked}}} />' + + '<label for="sharingDialogAllowPublicUpload-rw-{{cid}}">{{publicUploadRWLabel}}</label>' + + '</span></li>' + + '<li><span class="shareOption menuitem">' + + '<span class="icon-loading-small hidden"></span>' + + '<input type="radio" name="publicUpload" value="{{publicUploadWValue}}" id="sharingDialogAllowPublicUpload-w-{{cid}}" class="radio publicUploadRadio" {{{publicUploadWChecked}}} />' + + '<label for="sharingDialogAllowPublicUpload-w-{{cid}}">{{publicUploadWLabel}}</label>' + + '</span></li>' + + '{{/if}}' + + '{{#if publicEditing}}' + + ' <li id="allowPublicEditingWrapper"><span class="shareOption menuitem">' + + ' <span class="icon-loading-small hidden"></span>' + + ' <input type="checkbox" name="allowPublicEditing" id="sharingDialogAllowPublicEditing-{{cid}}" class="checkbox publicEditingCheckbox" {{{publicEditingChecked}}} />' + + ' <label for="sharingDialogAllowPublicEditing-{{cid}}">{{publicEditingLabel}}</label>' + + ' </span></li>' + + '{{/if}}' + + '{{#if showPasswordCheckBox}}' + + ' <li><span class="shareOption menuitem">' + + ' <input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} value="1" />' + + ' <label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label>' + + ' </span></li>' + + ' <li class="{{#unless isPasswordSet}}hidden{{/unless}} linkPassMenu"><span class="shareOption menuitem icon-share-pass">' + + ' <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" autocomplete="new-password" />' + + ' <span class="icon icon-loading-small hidden"></span>' + + ' </span></li>' + + '{{/if}}' + + '<li>' + + '<span class="shareOption menuitem">' + + '<input id="expireDate-{{cid}}" type="checkbox" name="expirationDate" class="expireDate checkbox" {{#if hasExpireDate}}checked="checked"{{/if}}" />' + + '<label for="expireDate-{{cid}}">{{expireDateLabel}}</label>' + + '</li>' + + '<li class="{{#unless hasExpireDate}}hidden{{/unless}}">' + + '<span class="menuitem icon-expiredate expirationDateContainer-{{cid}}">' + + ' <label for="expirationDatePicker-{{cid}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' + + ' <input id="expirationDatePicker-{{cid}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" />' + + '</span>' + + '</span>' + + '</li>' + + '<li>' + + '<a href="#" class="share-add"><span class="icon-loading-small hidden"></span>' + + ' <span class="icon icon-edit"></span>' + + ' <span>{{addNoteLabel}}</span>' + + ' <input type="button" class="share-note-delete icon-delete">' + + '</a>' + + '</li>' + + '<li class="share-note-form share-note-link hidden">' + + '<span class="menuitem icon-note">' + + ' <textarea class="share-note">{{shareNote}}</textarea>' + + ' <input type="submit" class="icon-confirm share-note-submit" value="" id="add-note-{{shareId}}" />' + + '</span>' + + '</li>' + '{{#each social}}' + '<li>' + '<a href="#" class="shareOption menuitem pop-up" data-url="{{url}}" data-window="{{newWindow}}">' + @@ -131,9 +161,15 @@ 'click .linkText': 'onLinkTextClick', 'change .publicEditingCheckbox': 'onAllowPublicEditingChange', 'click .showPasswordCheckbox': 'onShowPasswordClick', - 'click .icon-more': 'onToggleMenu', + 'click .share-menu .icon-more': 'onToggleMenu', 'click .pop-up': 'onPopUpClick', - 'change .publicUploadRadio': 'onPublicUploadChange' + 'change .publicUploadRadio': 'onPublicUploadChange', + 'click .expireDate' : 'onExpireDateChange', + 'change .datepicker': 'onChangeExpirationDate', + 'click .datepicker' : 'showDatePicker', + 'click .share-add': 'showNoteForm', + 'click .share-note-delete': 'deleteNote', + 'click .share-note-submit': 'updateNote' }, initialize: function(options) { @@ -165,37 +201,26 @@ throw 'missing OC.Share.ShareConfigModel'; } - _.bindAll( - this, - 'onLinkCheckBoxChange', - 'onPasswordEntered', - 'onPasswordKeyUp', - 'onLinkTextClick', - 'onShowPasswordClick', - 'onAllowPublicEditingChange', - 'onPublicUploadChange' - ); - var clipboard = new Clipboard('.clipboardButton'); clipboard.on('success', function(e) { - var $input = $(e.trigger); - $input.tooltip('hide') + var $menu = $(e.trigger); + var $linkTextMenu = $menu.parent().next('li.linkTextMenu') + + $menu.tooltip('hide') .attr('data-original-title', t('core', 'Copied!')) .tooltip('fixTitle') .tooltip({placement: 'bottom', trigger: 'manual'}) .tooltip('show'); _.delay(function() { - $input.tooltip('hide'); - if (OC.Share.Social.Collection.size() == 0) { - $input.attr('data-original-title', t('core', 'Copy')) - .tooltip('fixTitle'); - } else { - $input.tooltip("destroy"); - } + $menu.tooltip('hide'); + $menu.tooltip('destroy'); }, 3000); }); clipboard.on('error', function (e) { - var $input = $(e.trigger); + var $menu = $(e.trigger); + var $linkTextMenu = $menu.parent().next('li.linkTextMenu') + var $input = $linkTextMenu.find('.linkText'); + var actionMsg = ''; if (/iPhone|iPad/i.test(navigator.userAgent)) { actionMsg = t('core', 'Not supported!'); @@ -205,6 +230,8 @@ actionMsg = t('core', 'Press Ctrl-C to copy.'); } + $linkTextMenu.removeClass('hidden'); + $input.select(); $input.tooltip('hide') .attr('data-original-title', actionMsg) .tooltip('fixTitle') @@ -212,15 +239,10 @@ .tooltip('show'); _.delay(function () { $input.tooltip('hide'); - if (OC.Share.Social.Collection.size() == 0) { - $input.attr('data-original-title', t('core', 'Copy')) - .tooltip('fixTitle'); - } else { - $input.tooltip("destroy"); - } + $input.attr('data-original-title', t('core', 'Copy')) + .tooltip('fixTitle'); }, 3000); }); - }, onLinkCheckBoxChange: function() { @@ -257,6 +279,7 @@ onShowPasswordClick: function() { this.$el.find('.linkPass').slideToggle(OC.menuSpeed); + this.$el.find('.linkPassMenu').toggleClass('hidden'); if(!this.$el.find('.showPasswordCheckbox').is(':checked')) { this.model.saveLinkShare({ password: '' @@ -275,7 +298,7 @@ }, onPasswordEntered: function() { - var $loading = this.$el.find('.linkPass .icon-loading-small'); + var $loading = this.$el.find('.linkPassMenu .icon-loading-small'); if (!$loading.hasClass('hidden')) { // still in process return; @@ -334,12 +357,95 @@ }, - onPublicUploadChange: function(e) { + onPublicUploadChange: function(e) { var permissions = e.currentTarget.value; this.model.saveLinkShare({ permissions: permissions }); }, + + showNoteForm: function(event) { + event.preventDefault(); + event.stopPropagation(); + var self = this; + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var $menu = $element.closest('li'); + var $form = $menu.next('li.share-note-form'); + + // show elements + $menu.find('.share-note-delete').toggle(); + $form.toggleClass('hidden'); + $form.find('textarea').focus(); + }, + + deleteNote: function(event) { + event.preventDefault(); + event.stopPropagation(); + var self = this; + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $menu = $element.closest('li'); + var $form = $menu.next('li.share-note-form'); + + console.log($form.find('.share-note')); + $form.find('.share-note').val(''); + + $form.addClass('hidden'); + $menu.find('.share-note-delete').hide(); + + self.sendNote('', shareId, $menu); + }, + + updateNote: function(event) { + event.preventDefault(); + event.stopPropagation(); + var self = this; + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $form = $element.closest('li.share-note-form'); + var $menu = $form.prev('li'); + var message = $form.find('.share-note').val().trim(); + + if (message.length < 1) { + return; + } + + self.sendNote(message, shareId, $menu); + }, + + sendNote: function(note, shareId, $menu) { + var $form = $menu.next('li.share-note-form'); + var $submit = $form.find('input.share-note-submit'); + var $error = $form.find('input.share-note-error'); + + $submit.prop('disabled', true); + $menu.find('.icon-loading-small').removeClass('hidden'); + $menu.find('.icon-edit').hide(); + + var complete = function() { + $submit.prop('disabled', false); + $menu.find('.icon-loading-small').addClass('hidden'); + $menu.find('.icon-edit').show(); + }; + var error = function() { + $error.show(); + setTimeout(function() { + $error.hide(); + }, 3000); + }; + + // send data + $.ajax({ + method: 'PUT', + url: OC.linkToOCS('apps/files_sharing/api/v1/shares',2) + shareId + '?' + OC.buildQueryString({format: 'json'}), + data: { note: note }, + complete : complete, + error: error + }); + }, render: function() { var linkShareTemplate = this.template(); @@ -412,18 +518,48 @@ }); }); - var popover = this.popoverMenuTemplate({ - cid: this.cid, - copyLabel: t('core', 'Copy'), - social: social + var defaultExpireDays = this.configModel.get('defaultExpireDate'); + var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); + var hasExpireDate = !!this.model.get('linkShare').expiration || isExpirationEnforced; + + var expireDate; + if (hasExpireDate) { + expireDate = moment(this.model.get('linkShare').expiration, 'YYYY-MM-DD').format('DD-MM-YYYY'); + } + + // what if there is another date picker on that page? + var minDate = new Date(); + var maxDate = null; + // min date should always be the next day + minDate.setDate(minDate.getDate()+1); + + if(hasExpireDate) { + if(isExpirationEnforced) { + // TODO: hack: backend returns string instead of integer + var shareTime = this.model.get('linkShare').stime; + if (_.isNumber(shareTime)) { + shareTime = new Date(shareTime * 1000); + } + if (!shareTime) { + shareTime = new Date(); // now + } + shareTime = OC.Util.stripTime(shareTime).getTime(); + maxDate = new Date(shareTime + defaultExpireDays * 24 * 3600 * 1000); + } + } + $.datepicker.setDefaults({ + minDate: minDate, + maxDate: maxDate }); - this.$el.html(linkShareTemplate({ - cid: this.cid, - shareAllowed: true, - isLinkShare: isLinkShare, + this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'}); + + var popover = this.popoverMenuTemplate({ + cid: this.model.get('linkShare').id, + copyLabel: t('core', 'Copy URL'), + social: social, + shareLinkURL: this.model.get('linkShare').link, - linkShareLabel: t('core', 'Share link'), urlLabel: t('core', 'Link'), enablePasswordLabel: t('core', 'Password protect'), passwordLabel: t('core', 'Password'), @@ -437,8 +573,6 @@ publicEditingLabel: t('core', 'Allow editing'), mailPrivatePlaceholder: t('core', 'Email link to person'), mailButtonText: t('core', 'Send'), - singleAction: OC.Share.Social.Collection.size() == 0, - popoverMenu: popover, publicUploadRWLabel: t('core', 'Allow upload and editing'), publicUploadRLabel: t('core', 'Read only'), publicUploadWLabel: t('core', 'File drop (upload only)'), @@ -447,19 +581,32 @@ publicUploadWValue: OC.PERMISSION_CREATE, publicUploadRWChecked: publicUploadRWChecked, publicUploadRChecked: publicUploadRChecked, - publicUploadWChecked: publicUploadWChecked - })); + publicUploadWChecked: publicUploadWChecked, + expireDateLabel: t('core', 'Set expiration date'), + expirationLabel: t('core', 'Expiration'), + expirationDatePlaceholder: t('core', 'Expiration date'), + hasExpireDate: hasExpireDate, + isExpirationEnforced: isExpirationEnforced, + expireDate: expireDate, + defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today + shareNote: this.model.get('linkShare').note, + addNoteLabel: t('core', 'Set share note'), + }); - if (OC.Share.Social.Collection.size() == 0) { - this.$el.find('.clipboardButton').tooltip({ - placement: 'bottom', - title: t('core', 'Copy'), - trigger: 'hover' - }); - } + this.$el.html(linkShareTemplate({ + cid: this.model.get('linkShare').id, + shareAllowed: true, + isLinkShare: isLinkShare, + linkShareLabel: t('core', 'Share link'), + linkShareEnableLabel: t('core', 'Enable'), + popoverMenu: popover, + })); this.delegateEvents(); + // new note autosize + autosize(this.$el.find('.share-note-form .share-note')); + return this; }, @@ -467,8 +614,8 @@ event.preventDefault(); event.stopPropagation(); var $element = $(event.target); - var $li = $element.closest('.oneline'); - var $menu = $li.find('.popovermenu'); + var $li = $element.closest('li[data-share-id]'); + var $menu = $li.find('.sharingOptionsGroup .popovermenu'); OC.showMenu(null, $menu); this._menuOpen = $li.data('share-id'); @@ -517,7 +664,52 @@ window.location.href = url; } } - } + }, + + onExpireDateChange: function(event) { + var $element = $(event.target); + var li = $element.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var expirationDatePicker = '#expirationDateContainer-' + shareId; + var datePicker = $(expirationDatePicker); + var state = $element.prop('checked'); + datePicker.toggleClass('hidden', !state); + + if (!state) { + // disabled, let's hide the input and + // set the expireDate to nothing + $element.closest('li').next('li').addClass('hidden'); + this.setExpirationDate(''); + } else { + // enabled, show the input and the datepicker + $element.closest('li').next('li').removeClass('hidden'); + this.showDatePicker(event); + + } + }, + + showDatePicker: function(event) { + var $element = $(event.target); + var li = $element.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var expirationDatePicker = '#expirationDatePicker-' + shareId; + var self = this; + + $(expirationDatePicker).datepicker({ + dateFormat : 'dd-mm-yy', + onSelect: function (expireDate) { + self.setExpirationDate(expireDate); + } + }); + console.log(event, $(expirationDatePicker)); + $(expirationDatePicker).datepicker('show'); + $(expirationDatePicker).focus(); + + }, + + setExpirationDate: function(expireDate) { + this.model.saveLinkShare({expireDate: expireDate}); + }, }); diff --git a/core/js/sharedialogresharerinfoview.js b/core/js/sharedialogresharerinfoview.js index f4bf9afa0b2..fadd0a41f7b 100644 --- a/core/js/sharedialogresharerinfoview.js +++ b/core/js/sharedialogresharerinfoview.js @@ -19,7 +19,8 @@ '<span class="reshare">' + ' <div class="avatar" data-userName="{{reshareOwner}}"></div>' + ' {{sharedByText}}' + - '</span><br/>' + '</span>' + + '{{#if hasShareNote}}<div class="share-note">{{shareNote}}</div>{{/if}}' ; /** @@ -72,7 +73,10 @@ var reshareTemplate = this.template(); var ownerDisplayName = this.model.getReshareOwnerDisplayname(); + var shareNote = this.model.getReshareNote(); + var sharedByText = ''; + if (this.model.getReshareType() === OC.Share.SHARE_TYPE_GROUP) { sharedByText = t( 'core', @@ -105,9 +109,13 @@ ); } + + this.$el.html(reshareTemplate({ reshareOwner: this.model.getReshareOwner(), - sharedByText: sharedByText + sharedByText: sharedByText, + shareNote: shareNote, + hasShareNote: shareNote !== '' })); this.$el.find('.avatar').each(function() { diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index 53a65fcdf7a..574d47b4aac 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -34,8 +34,9 @@ '<label for="canEdit-{{cid}}-{{shareId}}">{{canEditLabel}}</label>' + '</span>' + '{{/if}}' + - '<a href="#"><span class="icon icon-more"></span></a>' + - '{{{popoverMenu}}}' + + '<div tabindex="0" class="share-menu"><span class="icon icon-more"></span>' + + '{{{popoverMenu}}}' + + '</div>' + '</span>' + '</li>' + '{{/each}}' + @@ -102,11 +103,13 @@ '<span class="shareOption menuitem">' + '<input id="password-{{cid}}-{{shareId}}" type="checkbox" name="password" class="password checkbox" {{#if isPasswordSet}}checked="checked"{{/if}}{{#if isPasswordSet}}{{#if isPasswordForMailSharesRequired}}disabled=""{{/if}}{{/if}}" />' + '<label for="password-{{cid}}-{{shareId}}">{{passwordLabel}}</label>' + - '<div class="passwordContainer-{{cid}}-{{shareId}} {{#unless isPasswordSet}}hidden{{/unless}}">' + - ' <label for="passwordField-{{cid}}-{{shareId}}" class="hidden-visually" value="{{password}}">{{passwordLabel}}</label>' + - ' <input id="passwordField-{{cid}}-{{shareId}}" class="passwordField" type="password" placeholder="{{passwordPlaceholder}}" value="{{passwordValue}}" autocomplete="new-password" />' + - ' <span class="icon-loading-small hidden"></span>' + - '</div>' + + '</span>' + + '</li>' + + '<li class="passwordMenu-{{cid}}-{{shareId}} {{#unless isPasswordSet}}hidden{{/unless}}">' + + '<span class="passwordContainer-{{cid}}-{{shareId}} icon-passwordmail menuitem">' + + ' <label for="passwordField-{{cid}}-{{shareId}}" class="hidden-visually" value="{{password}}">{{passwordLabel}}</label>' + + ' <input id="passwordField-{{cid}}-{{shareId}}" class="passwordField" type="password" placeholder="{{passwordPlaceholder}}" value="{{passwordValue}}" autocomplete="new-password" />' + + ' <span class="icon-loading-small hidden"></span>' + '</span>' + '</li>' + '{{/if}}' + @@ -114,12 +117,29 @@ '<span class="shareOption menuitem">' + '<input id="expireDate-{{cid}}-{{shareId}}" type="checkbox" name="expirationDate" class="expireDate checkbox" {{#if hasExpireDate}}checked="checked"{{/if}}" />' + '<label for="expireDate-{{cid}}-{{shareId}}">{{expireDateLabel}}</label>' + - '<div class="expirationDateContainer-{{cid}}-{{shareId}} {{#unless hasExpireDate}}hidden{{/unless}}">' + - ' <label for="expirationDatePicker-{{cid}}-{{shareId}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' + - ' <input id="expirationDatePicker-{{cid}}-{{shareId}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" />' + - '</div>' + '</span>' + '</li>' + + '<li class="expirationDateMenu-{{cid}}-{{shareId}} {{#unless hasExpireDate}}hidden{{/unless}}">' + + '<span class="expirationDateContainer-{{cid}}-{{shareId}} icon-expiredate menuitem">' + + ' <label for="expirationDatePicker-{{cid}}-{{shareId}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' + + ' <input id="expirationDatePicker-{{cid}}-{{shareId}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" />' + + '</span>' + + '</li>' + + '{{#if isNoteAvailable}}' + + '<li>' + + '<a href="#" class="share-add"><span class="icon-loading-small hidden"></span>' + + ' <span class="icon icon-edit"></span>' + + ' <span>{{addNoteLabel}}</span>' + + ' <input type="button" class="share-note-delete icon-delete">' + + '</a>' + + '</li>' + + '<li class="share-note-form hidden">' + + '<span class="menuitem icon-note">' + + ' <textarea class="share-note">{{shareNote}}</textarea>' + + ' <input type="submit" class="icon-confirm share-note-submit" value="" id="add-note-{{shareId}}" />' + + '</span>' + + '</li>' + + '{{/if}}' + '<li>' + '<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' + '</li>' + @@ -156,7 +176,10 @@ events: { 'click .unshare': 'onUnshare', - 'click .icon-more': 'onToggleMenu', + 'click .share-add': 'showNoteForm', + 'click .share-note-delete': 'deleteNote', + 'click .share-note-submit': 'updateNote', + 'click .share-menu .icon-more': 'onToggleMenu', 'click .permissions': 'onPermissionChange', 'click .expireDate' : 'onExpireDateChange', 'click .password' : 'onMailSharePasswordProtectChange', @@ -255,12 +278,14 @@ modSeed: shareType !== OC.Share.SHARE_TYPE_USER && (shareType !== OC.Share.SHARE_TYPE_CIRCLE || shareWithAvatar), isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE, isRemoteGroupShare: shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP, + isNoteAvailable: shareType !== OC.Share.SHARE_TYPE_REMOTE && shareType !== OC.Share.SHARE_TYPE_REMOTE_GROUP, isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL, isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE, isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(), isPasswordSet: hasPassword, secureDropMode: !this.model.hasReadPermission(shareIndex), hasExpireDate: this.model.getExpireDate(shareIndex) !== null, + shareNote: this.model.getNote(shareIndex), expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'), passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, }); @@ -269,6 +294,7 @@ getShareProperties: function() { return { unshareLabel: t('core', 'Unshare'), + addNoteLabel: t('core', 'Set share note'), canShareLabel: t('core', 'Can reshare'), canEditLabel: t('core', 'Can edit'), createPermissionLabel: t('core', 'Can create'), @@ -435,6 +461,9 @@ this._renderPermissionChange = false; + // new note autosize + autosize(this.$el.find('.share-note-form .share-note')); + this.delegateEvents(); return this; @@ -470,6 +499,88 @@ return this._popoverMenuTemplate(data); }, + showNoteForm: function(event) { + event.preventDefault(); + event.stopPropagation(); + var $element = $(event.target); + var $menu = $element.closest('li'); + var $form = $menu.next('li.share-note-form'); + + // show elements + $menu.find('.share-note-delete').toggle(); + $form.toggleClass('hidden'); + $form.find('textarea').focus(); + }, + + deleteNote: function(event) { + event.preventDefault(); + event.stopPropagation(); + var self = this; + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $menu = $element.closest('li'); + var $form = $menu.next('li.share-note-form'); + + console.log($form.find('.share-note')); + $form.find('.share-note').val(''); + + $form.addClass('hidden'); + $menu.find('.share-note-delete').hide(); + + self.sendNote('', shareId, $menu); + }, + + updateNote: function(event) { + event.preventDefault(); + event.stopPropagation(); + var self = this; + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + var $form = $element.closest('li.share-note-form'); + var $menu = $form.prev('li'); + var message = $form.find('.share-note').val().trim(); + + if (message.length < 1) { + return; + } + + self.sendNote(message, shareId, $menu); + + }, + + sendNote: function(note, shareId, $menu) { + var $form = $menu.next('li.share-note-form'); + var $submit = $form.find('input.share-note-submit'); + var $error = $form.find('input.share-note-error'); + + $submit.prop('disabled', true); + $menu.find('.icon-loading-small').removeClass('hidden'); + $menu.find('.icon-edit').hide(); + + var complete = function() { + $submit.prop('disabled', false); + $menu.find('.icon-loading-small').addClass('hidden'); + $menu.find('.icon-edit').show(); + }; + var error = function() { + $error.show(); + setTimeout(function() { + $error.hide(); + }, 3000); + }; + + // send data + $.ajax({ + method: 'PUT', + url: OC.linkToOCS('apps/files_sharing/api/v1/shares',2) + shareId + '?' + OC.buildQueryString({format: 'json'}), + data: { note: note }, + complete : complete, + error: error + }); + }, + onUnshare: function(event) { event.preventDefault(); event.stopPropagation(); @@ -513,16 +624,21 @@ }, onExpireDateChange: function(event) { - var element = $(event.target); - var li = element.closest('li[data-share-id]'); + var $element = $(event.target); + var li = $element.closest('li[data-share-id]'); var shareId = li.data('share-id'); var datePickerClass = '.expirationDateContainer-' + this.cid + '-' + shareId; var datePicker = $(datePickerClass); - var state = element.prop('checked'); + var state = $element.prop('checked'); datePicker.toggleClass('hidden', !state); if (!state) { + // disabled, let's hide the input and + // set the expireDate to nothing + $element.closest('li').next('li').addClass('hidden'); this.setExpirationDate(shareId, ''); } else { + // enabled, show the input and the datepicker + $element.closest('li').next('li').removeClass('hidden'); this.showDatePicker(event); } @@ -552,7 +668,7 @@ var element = $(event.target); var li = element.closest('li[data-share-id]'); var shareId = li.data('share-id'); - var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId; + var passwordContainerClass = '.passwordMenu-' + this.cid + '-' + shareId; var passwordContainer = $(passwordContainerClass); var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); var inputClass = '#passwordField-' + this.cid + '-' + shareId; diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index d886e45856f..9fa1847d3d5 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -27,7 +27,6 @@ '{{/if}}' + '<div class="shareeListView subView"></div>' + '<div class="linkShareView subView"></div>' + - '<div class="expirationView subView"></div>' + '<div class="loading hidden" style="height: 50px"></div>'; /** @@ -60,9 +59,6 @@ linkShareView: undefined, /** @type {object} **/ - expirationView: undefined, - - /** @type {object} **/ shareeListView: undefined, /** @type {object} **/ @@ -111,7 +107,6 @@ var subViews = { resharerInfoView: 'ShareDialogResharerInfoView', linkShareView: 'ShareDialogLinkShareView', - expirationView: 'ShareDialogExpirationView', shareeListView: 'ShareDialogShareeListView' }; @@ -671,9 +666,6 @@ this.linkShareView.$el = this.$el.find('.linkShareView'); this.linkShareView.render(); - this.expirationView.$el = this.$el.find('.expirationView'); - this.expirationView.render(); - this.shareeListView.$el = this.$el.find('.shareeListView'); this.shareeListView.render(); diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index 93feba9c889..241b9c19c0d 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -343,6 +343,13 @@ /** * @returns {string} */ + getReshareNote: function() { + return this.get('reshare').note; + }, + + /** + * @returns {string} + */ getReshareWith: function() { return this.get('reshare').share_with; }, @@ -366,6 +373,10 @@ return this._shareExpireDate(shareIndex); }, + getNote: function(shareIndex) { + return this._shareNote(shareIndex); + }, + /** * Returns all share entries that only apply to the current item * (file/folder) @@ -502,6 +513,15 @@ return date2; }, + + _shareNote: function(shareIndex) { + var share = this.get('shares')[shareIndex]; + if(!_.isObject(share)) { + throw "Unknown Share"; + } + return share.note; + }, + /** * @return {int} */ diff --git a/core/js/tests/specs/sharedialoglinkshareview.js b/core/js/tests/specs/sharedialoglinkshareview.js index 12f5e762cee..9d07dcb479d 100644 --- a/core/js/tests/specs/sharedialoglinkshareview.js +++ b/core/js/tests/specs/sharedialoglinkshareview.js @@ -92,7 +92,7 @@ describe('OC.Share.ShareDialogLinkShareView', function () { var $passwordDiv = view.$el.find('#linkPass'); $passwordText = view.$el.find('.linkPassText'); - $workingIcon = view.$el.find('.linkPass .icon-loading-small'); + $workingIcon = view.$el.find('.linkPassMenu .icon-loading-small'); sinon.stub(shareModel, 'saveLinkShare'); diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js index 5fd920a758c..33d3be51440 100644 --- a/core/js/tests/specs/sharedialogviewSpec.js +++ b/core/js/tests/specs/sharedialogviewSpec.js @@ -214,188 +214,6 @@ describe('OC.Share.ShareDialogView', function() { focusStub.restore(); selectStub.restore(); }); - describe('password', function() { - var slideToggleStub; - - beforeEach(function() { - $('#allowShareWithLink').val('yes'); - configModel.set({ - enforcePasswordForPublicLink: false - }); - - slideToggleStub = sinon.stub($.fn, 'slideToggle'); - }); - afterEach(function() { - slideToggleStub.restore(); - }); - - it('enforced but toggled does not fire request', function() { - configModel.set('enforcePasswordForPublicLink', true); - dialog.render(); - - dialog.$el.find('.linkCheckbox').click(); - - // The password linkPass field is shown (slideToggle is called). - // No request is made yet - expect(slideToggleStub.callCount).toEqual(1); - expect(slideToggleStub.getCall(0).thisValue.eq(0).attr('id')).toEqual('linkPass'); - expect(fakeServer.requests.length).toEqual(0); - - // Now untoggle share by link - dialog.$el.find('.linkCheckbox').click(); - dialog.render(); - - // Password field disappears and no ajax requests have been made - expect(fakeServer.requests.length).toEqual(0); - expect(slideToggleStub.callCount).toEqual(2); - expect(slideToggleStub.getCall(1).thisValue.eq(0).attr('id')).toEqual('linkPass'); - }); - }); - describe('expiration date', function() { - var shareData; - var shareItem; - var clock; - var expectedMinDate; - - beforeEach(function() { - // pick a fake date - clock = sinon.useFakeTimers(new Date(2014, 0, 20, 14, 0, 0).getTime()); - expectedMinDate = new Date(2014, 0, 21, 14, 0, 0); - - configModel.set({ - enforcePasswordForPublicLink: false, - isDefaultExpireDateEnabled: false, - isDefaultExpireDateEnforced: false, - defaultExpireDate: 7 - }); - - shareModel.set('linkShare', { - isLinkShare: true, - token: 'tehtoken', - permissions: OC.PERMISSION_READ, - expiration: null - }); - }); - afterEach(function() { - clock.restore(); - }); - - it('does not check expiration date checkbox when no date was set', function() { - shareModel.get('linkShare').expiration = null; - dialog.render(); - - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); - expect(dialog.$el.find('.datepicker').val()).toEqual(''); - }); - it('does not check expiration date checkbox for new share', function() { - dialog.render(); - - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); - expect(dialog.$el.find('.datepicker').val()).toEqual(''); - }); - it('checks expiration date checkbox and populates field when expiration date was set', function() { - shareModel.get('linkShare').expiration = '2014-02-01 00:00:00'; - dialog.render(); - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); - expect(dialog.$el.find('.datepicker').val()).toEqual('01-02-2014'); - }); - it('sets default date when default date setting is enabled', function() { - configModel.set('isDefaultExpireDateEnabled', true); - dialog.render(); - dialog.$el.find('.linkCheckbox').click(); - // here fetch would be called and the server returns the expiration date - shareModel.get('linkShare').expiration = '2014-1-27 00:00:00'; - dialog.render(); - - // enabled by default - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); - expect(dialog.$el.find('.datepicker').val()).toEqual('27-01-2014'); - - // disabling is allowed - dialog.$el.find('[name=expirationCheckbox]').click(); - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); - }); - it('enforces default date when enforced date setting is enabled', function() { - configModel.set({ - isDefaultExpireDateEnabled: true, - isDefaultExpireDateEnforced: true - }); - dialog.render(); - dialog.$el.find('.linkCheckbox').click(); - // here fetch would be called and the server returns the expiration date - shareModel.get('linkShare').expiration = '2014-1-27 00:00:00'; - dialog.render(); - - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); - expect(dialog.$el.find('.datepicker').val()).toEqual('27-01-2014'); - - // disabling is not allowed - expect(dialog.$el.find('[name=expirationCheckbox]').prop('disabled')).toEqual(true); - dialog.$el.find('[name=expirationCheckbox]').click(); - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); - }); - it('enforces default date when enforced date setting is enabled and password is enforced', function() { - configModel.set({ - enforcePasswordForPublicLink: true, - isDefaultExpireDateEnabled: true, - isDefaultExpireDateEnforced: true - }); - dialog.render(); - dialog.$el.find('.linkCheckbox').click(); - // here fetch would be called and the server returns the expiration date - shareModel.get('linkShare').expiration = '2014-1-27 00:00:00'; - dialog.render(); - - //Enter password - dialog.$el.find('.linkPassText').val('foo'); - dialog.$el.find('.linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); - expect(dialog.$el.find('.datepicker').val()).toEqual('27-01-2014'); - - // disabling is not allowed - expect(dialog.$el.find('[name=expirationCheckbox]').prop('disabled')).toEqual(true); - dialog.$el.find('[name=expirationCheckbox]').click(); - expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); - }); - it('sets picker minDate to today and no maxDate by default', function() { - dialog.render(); - dialog.$el.find('.linkCheckbox').click(); - dialog.$el.find('[name=expirationCheckbox]').click(); - expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); - expect($.datepicker._defaults.maxDate).toEqual(null); - }); - it('limits the date range to X days after share time when enforced', function() { - configModel.set({ - isDefaultExpireDateEnabled: true, - isDefaultExpireDateEnforced: true - }); - dialog.render(); - dialog.$el.find('.linkCheckbox').click(); - expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); - expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); - }); - it('limits the date range to X days after share time when enforced, even when redisplayed the next days', function() { - // item exists, was created two days ago - var shareItem = shareModel.get('linkShare'); - shareItem.expiration = '2014-1-27'; - // share time has time component but must be stripped later - shareItem.stime = new Date(2014, 0, 20, 11, 0, 25).getTime() / 1000; - configModel.set({ - isDefaultExpireDateEnabled: true, - isDefaultExpireDateEnforced: true - }); - dialog.render(); - expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); - expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); - }); - }); - }); describe('check for avatar', function() { beforeEach(function() { @@ -455,8 +273,8 @@ describe('OC.Share.ShareDialogView', function() { it('test correct function calls', function() { expect(avatarStub.calledThrice).toEqual(true); expect(placeholderStub.callCount).toEqual(4); - expect(dialog.$('.shareWithList').children().length).toEqual(5); - expect(dialog.$('.avatar').length).toEqual(6); + expect(dialog.$('.shareWithList').children().length).toEqual(6); + expect(dialog.$('.avatar').length).toEqual(7); }); it('test avatar owner', function() { |