diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/css/apps.scss | 4 | ||||
-rw-r--r-- | core/css/share.scss | 14 | ||||
-rw-r--r-- | core/js/sharedialogshareelistview.js | 230 | ||||
-rw-r--r-- | core/js/shareitemmodel.js | 20 |
4 files changed, 256 insertions, 12 deletions
diff --git a/core/css/apps.scss b/core/css/apps.scss index 0c31e5bae44..da1c5162051 100644 --- a/core/css/apps.scss +++ b/core/css/apps.scss @@ -477,7 +477,7 @@ kbd { border-radius: 0; text-align: left; padding-left: 42px; - font-weight: normal; + font-weight: 300; &:hover, &:focus { background-color: $color-main-background; @@ -667,7 +667,7 @@ kbd { width: auto; height: auto; margin: 0; - font-weight: inherit; + font-weight: 300; box-shadow: none; /* prevent .action class to break the design */ &.action { diff --git a/core/css/share.scss b/core/css/share.scss index 0e6eb3ccf8b..de545955aa9 100644 --- a/core/css/share.scss +++ b/core/css/share.scss @@ -106,6 +106,7 @@ .shareOption { white-space: nowrap; display: inline-block; + opacity: 1 !important; } .unshare img, .showCruds img { @@ -184,3 +185,16 @@ a { padding-top: 12px; color: rgba($color-main-text, .4); } + +.popovermenu .datepicker { + margin-left: 35px; +} + +.popovermenu .passwordField { + margin-left: 35px; + width: inherit !important; +} + +.ui-datepicker { + z-index: 1111 !important; +} diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index e46a761db6c..a9945b594e1 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -13,6 +13,10 @@ /* globals Handlebars */ (function() { + + var PASSWORD_PLACEHOLDER = '**********'; + var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the mail share'); + if (!OC.Share) { OC.Share = {}; } @@ -25,12 +29,10 @@ '<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' + '<span class="sharingOptionsGroup">' + '{{#if editPermissionPossible}}' + - '{{#unless isFileSharedByMail}}' + '<span class="shareOption">' + '<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' + '<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' + '</span>' + - '{{/unless}}' + '{{/if}}' + '<a href="#"><span class="icon icon-more"></span></a>' + '{{{popoverMenu}}}' + @@ -87,6 +89,37 @@ '</li>' + '{{/unless}}{{/if}}' + '{{/if}}' + + '{{#if isMailShare}}' + + '{{#if hasCreatePermission}}' + + '<li>' + + '<span class="shareOption menuitem">' + + '<input id="secureDrop-{{cid}}-{{shareId}}" type="checkbox" name="secureDrop" class="checkbox secureDrop" {{#if secureDropMode}}checked="checked"{{/if}} data-permissions="{{readPermission}}"/>' + + '<label for="secureDrop-{{cid}}-{{shareId}}">{{secureDropLabel}}</label>' + + '</span>' + + '</li>' + + '{{/if}}' + + '<li>' + + '<span class="shareOption menuitem">' + + '<input id="password-{{cid}}-{{shareId}}" type="checkbox" name="password" class="password checkbox" {{#if isPasswordSet}}checked="checked"{{/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}}" />' + + ' <span class="icon-loading-small hidden"></span>' + + '</div>' + + '</span>' + + '</li>' + + '{{/if}}' + + '<li>' + + '<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="{{expireDate}}" />' + + '</div>' + + '</span>' + + '</li>' + '<li>' + '<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' + '</li>' + @@ -125,6 +158,13 @@ 'click .unshare': 'onUnshare', 'click .icon-more': 'onToggleMenu', 'click .permissions': 'onPermissionChange', + 'click .expireDate' : 'onExpireDateChange', + 'click .password' : 'onMailSharePasswordProtectChange', + 'click .secureDrop' : 'onSecureDropChange', + 'keyup input.passwordField': 'onMailSharePasswordKeyUp', + 'focusout input.passwordField': 'onMailSharePasswordEntered', + 'change .datepicker': 'onChangeExpirationDate', + 'click .datepicker' : 'showDatePicker' }, initialize: function(options) { @@ -171,6 +211,11 @@ shareWithTitle = shareWith; } + var share = this.model.get('shares')[shareIndex]; + var password = share.password; + var hasPassword = password !== null && password !== ''; + + return _.extend(hasPermissionOverride, { cid: this.cid, hasSharePermission: this.model.hasSharePermission(shareIndex), @@ -187,19 +232,27 @@ isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE, isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL, isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE, - isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder() + isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(), + isPasswordSet: hasPassword, + secureDropMode: !this.model.hasReadPermission(shareIndex), + hasExpireDate: this.model.getExpireDate(shareIndex) !== null, + expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'), + passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, }); }, getShareProperties: function() { return { unshareLabel: t('core', 'Unshare'), - canShareLabel: t('core', 'can reshare'), - canEditLabel: t('core', 'can edit'), - createPermissionLabel: t('core', 'can create'), - updatePermissionLabel: t('core', 'can change'), - deletePermissionLabel: t('core', 'can delete'), - crudsLabel: t('core', 'access control'), + canShareLabel: t('core', 'Can reshare'), + canEditLabel: t('core', 'Can edit'), + createPermissionLabel: t('core', 'Can create'), + updatePermissionLabel: t('core', 'Can change'), + deletePermissionLabel: t('core', 'Can delete'), + secureDropLabel: t('core', 'Secure drop (upload only)'), + expireDateLabel: t('core', 'Set expiration date'), + passwordLabel: t('core', 'Password protect'), + crudsLabel: t('core', 'Access control'), triangleSImage: OC.imagePath('core', 'actions/triangle-s'), isResharingAllowed: this.configModel.get('isResharingAllowed'), sharePermissionPossible: this.model.sharePermissionPossible(), @@ -211,6 +264,7 @@ createPermission: OC.PERMISSION_CREATE, updatePermission: OC.PERMISSION_UPDATE, deletePermission: OC.PERMISSION_DELETE, + readPermission: OC.PERMISSION_READ, isFolder: this.model.isFolder() }; }, @@ -313,6 +367,19 @@ this.$('.popovermenu').on('afterHide', function() { _this._menuOpen = false; }); + this.$('.popovermenu').on('beforeHide', function() { + var shareId = parseInt(_this._menuOpen, 10); + if(!_.isNaN(shareId)) { + var datePickerClass = '.expirationDateContainer-' + _this.cid + '-' + shareId; + var datePickerInput = '#expirationDatePicker-' + _this.cid + '-' + shareId; + var expireDateCheckbox = '#expireDate-' + _this.cid + '-' + shareId; + if ($(expireDateCheckbox).prop('checked')) { + $(datePickerInput).removeClass('hidden-visually'); + $(datePickerClass).removeClass('hasDatepicker'); + $(datePickerClass + ' .ui-datepicker').hide(); + } + } + }); if (this._menuOpen != false) { // Open menu again if it was opened before var shareId = parseInt(this._menuOpen, 10); @@ -401,6 +468,123 @@ this._menuOpen = $li.data('share-id'); }, + onExpireDateChange: function(event) { + 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'); + datePicker.toggleClass('hidden', !state); + if (!state) { + this.setExpirationDate(shareId, ''); + } else { + 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-' + this.cid + '-' + shareId; + var view = this; + $(expirationDatePicker).closest('div').datepicker({ + dateFormat : 'dd-mm-yy', + onSelect: + function (expireDate) { + view.setExpirationDate(shareId, expireDate); + }, + onClose: + function () { + $(expirationDatePicker).removeClass('hidden-visually'); + } + }); + + $(expirationDatePicker).addClass('hidden-visually'); + }, + + setExpirationDate: function(shareId, expireDate) { + this.model.updateShare(shareId, {expireDate: expireDate}, {}); + }, + + onMailSharePasswordProtectChange: function(event) { + 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 passwordContainer = $(passwordContainerClass); + var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); + var inputClass = '#passwordField-' + this.cid + '-' + shareId; + var passwordField = $(inputClass); + var state = element.prop('checked'); + if (!state) { + this.model.updateShare(shareId, {password: ''}); + passwordField.attr('value', ''); + passwordField.removeClass('error'); + passwordField.tooltip('hide'); + loading.addClass('hidden'); + passwordField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE); + // We first need to reset the password field before we hide it + passwordContainer.toggleClass('hidden', !state); + } else { + passwordContainer.toggleClass('hidden', !state); + passwordField = '#passwordField-' + this.cid + '-' + shareId; + this.$(passwordField).focus(); + } + }, + + onMailSharePasswordKeyUp: function(event) { + if(event.keyCode === 13) { + this.onMailSharePasswordEntered(event); + } + }, + + onMailSharePasswordEntered: function(event) { + var passwordField = $(event.target); + var li = passwordField.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId; + var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); + if (!loading.hasClass('hidden')) { + // still in process + return; + } + + passwordField.removeClass('error'); + var password = passwordField.val(); + // in IE9 the password might be the placeholder due to bugs in the placeholders polyfill + if(password === '' || password === PASSWORD_PLACEHOLDER || password === PASSWORD_PLACEHOLDER_MESSAGE) { + return; + } + + loading + .removeClass('hidden') + .addClass('inlineblock'); + + + this.model.updateShare(shareId, { + password: password + }, { + error: function(model, msg) { + // destroy old tooltips + passwordField.tooltip('destroy'); + loading.removeClass('inlineblock').addClass('hidden'); + passwordField.addClass('error'); + passwordField.attr('title', msg); + passwordField.tooltip({placement: 'bottom', trigger: 'manual'}); + passwordField.tooltip('show'); + }, + success: function(model, msg) { + passwordField.blur(); + passwordField.attr('value', ''); + passwordField.attr('placeholder', PASSWORD_PLACEHOLDER); + loading.removeClass('inlineblock').addClass('hidden'); + } + }); + }, + onPermissionChange: function(event) { event.preventDefault(); event.stopPropagation(); @@ -451,6 +635,34 @@ this._renderPermissionChange = shareId; }, + + onSecureDropChange: function(event) { + event.preventDefault(); + event.stopPropagation(); + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + + var permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE | OC.PERMISSION_READ; + if ($element.is(':checked')) { + permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE; + } + + /** disable checkboxes during save operation to avoid race conditions **/ + $li.find('input[type=checkbox]').prop('disabled', true); + var enableCb = function() { + $li.find('input[type=checkbox]').prop('disabled', false); + }; + var errorCb = function(elem, msg) { + OC.dialogs.alert(msg, t('core', 'Error while sharing')); + enableCb(); + }; + + this.model.updateShare(shareId, {permissions: permissions}, {error: errorCb, success: enableCb}); + + this._renderPermissionChange = shareId; + } + }); OC.Share.ShareDialogShareeListView = ShareDialogShareeListView; diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index ae4c07e3f4e..6bb8d75b91f 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -363,6 +363,10 @@ return this.get('reshare').share_type; }, + getExpireDate: function(shareIndex) { + return this._shareExpireDate(shareIndex); + }, + /** * Returns all share entries that only apply to the current item * (file/folder) @@ -449,6 +453,16 @@ return (share.permissions & permission) === permission; }, + + _shareExpireDate: function(shareIndex) { + var share = this.get('shares')[shareIndex]; + if(!_.isObject(share)) { + throw "Unknown Share"; + } + var date2 = share.expiration; + return date2; + }, + /** * @returns {boolean} */ @@ -509,6 +523,10 @@ return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE); }, + hasReadPermission: function(shareIndex) { + return this._shareHasPermission(shareIndex, OC.PERMISSION_READ); + }, + /** * @returns {boolean} */ @@ -757,7 +775,7 @@ isLinkShare: true, id: share.id, token: share.token, - password: share.share_with, + password: share.password, link: link, permissions: share.permissions, // currently expiration is only effective for link shares. |