summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/css/apps.scss4
-rw-r--r--core/css/share.scss14
-rw-r--r--core/js/sharedialogshareelistview.js230
-rw-r--r--core/js/shareitemmodel.js20
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.