summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2015-09-14 12:48:01 +0200
committerVincent Petry <pvince81@owncloud.com>2015-09-16 07:23:28 +0200
commit8194d092e71b1c44a441dddc64b7e7533adbbfb9 (patch)
treed108baa62acb8a08e2b95fadd28ff8ebc82066b8
parentc2ff2ca9825af347d0247687322d3d12eb311185 (diff)
downloadnextcloud-server-8194d092e71b1c44a441dddc64b7e7533adbbfb9.tar.gz
nextcloud-server-8194d092e71b1c44a441dddc64b7e7533adbbfb9.zip
Add expiration date handling in share tab
-rw-r--r--core/css/share.css8
-rw-r--r--core/js/sharedialogexpirationview.js49
-rw-r--r--core/js/sharedialoglinkshareview.js11
-rw-r--r--core/js/shareitemmodel.js104
4 files changed, 147 insertions, 25 deletions
diff --git a/core/css/share.css b/core/css/share.css
index bdf34e9a863..73bad5c500d 100644
--- a/core/css/share.css
+++ b/core/css/share.css
@@ -126,6 +126,14 @@ a.unshare {
margin-right: 0;
}
+.shareTabView .error {
+ color: #e9322d;
+ border-color: #e9322d;
+ -webkit-box-shadow: 0 0 6px #f8b9b7;
+ -moz-box-shadow: 0 0 6px #f8b9b7;
+ box-shadow: 0 0 6px #f8b9b7;
+}
+
#link #showPassword img {
padding-left:5px;
width:12px;
diff --git a/core/js/sharedialogexpirationview.js b/core/js/sharedialogexpirationview.js
index f244fe56548..c5d8c829657 100644
--- a/core/js/sharedialogexpirationview.js
+++ b/core/js/sharedialogexpirationview.js
@@ -19,13 +19,13 @@
// 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" id="expirationCheckbox" value="1" ' +
+ '<input type="checkbox" name="expirationCheckbox" class="expirationCheckbox" id="expirationCheckbox" value="1" ' +
'{{#if isExpirationSet}}checked="checked"{{/if}} {{#if disableCheckbox}}disabled="disabled"{{/if}} />' +
'<label for="expirationCheckbox">{{setExpirationLabel}}</label>' +
- ' {{#if isExpirationSet}}' +
- '<label for="expirationDate" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' +
- '<input id="expirationDate" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{expirationValue}}" />' +
- ' {{/if}}' +
+ '<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>' +
@@ -58,6 +58,11 @@
className: 'hidden',
+ events: {
+ 'change .expirationCheckbox': '_onToggleExpiration',
+ 'change .datepicker': '_onChangeExpirationDate'
+ },
+
initialize: function(options) {
if(!_.isUndefined(options.configModel)) {
this.configModel = options.configModel;
@@ -79,6 +84,38 @@
});
},
+ _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.setExpirationDate('');
+ this.model.saveLinkShare();
+ }
+ },
+
+ _onChangeExpirationDate: function(event) {
+ var $target = $(event.target);
+ $target.tooltip('hide');
+ $target.removeClass('error');
+
+ this.model.setExpirationDate($target.val());
+ this.model.saveLinkShare(null, {
+ 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');
@@ -136,6 +173,8 @@
this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'});
+ this.delegateEvents();
+
return this;
},
diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js
index f49a73f291b..cadec3071d3 100644
--- a/core/js/sharedialoglinkshareview.js
+++ b/core/js/sharedialoglinkshareview.js
@@ -108,7 +108,8 @@
if($checkBox.is(':checked')) {
if(this.configModel.get('enforcePasswordForPublicLink') === false) {
$loading.removeClass('hidden');
- this.model.addLinkShare();
+ // this will create it
+ this.model.saveLinkShare();
} else {
this.$el.find('#linkPass').slideToggle(OC.menuSpeed);
// TODO drop with IE8 drop
@@ -131,7 +132,8 @@
onShowPasswordClick: function() {
this.$el.find('#linkPass').slideToggle(OC.menuSpeed);
if(!this.$el.find('#showPassword').is(':checked')) {
- this.model.addLinkShare({password: ''});
+ this.model.setPassword('');
+ this.model.saveLinkShare();
} else {
this.$el.find('#linkPassText').focus();
}
@@ -147,13 +149,15 @@
.removeClass('hidden')
.addClass('inlineblock');
- this.model.addLinkShare({password: password});
+ this.model.setPassword(password);
+ this.model.saveLinkShare();
},
onAllowPublicUploadChange: function() {
this.$el.find('#sharingDialogAllowPublicUpload')
.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock');
this.model.setPublicUpload(this.$el.find('#sharingDialogAllowPublicUpload').is(':checked'));
+ this.model.saveLinkShare();
},
render: function() {
@@ -205,6 +209,7 @@
mailButtonText: t('core', 'Send')
}));
+ // TODO: move this to delegate events instead
this.$el.find('#linkCheckbox').change(this.onLinkCheckBoxChange);
this.$el.find('#sharingDialogAllowPublicUpload').change(this.onAllowPublicUploadChange);
this.$el.find('#linkText').click(this.onLinkTextClick);
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
index eb44b735737..2a97bc8abd5 100644
--- a/core/js/shareitemmodel.js
+++ b/core/js/shareitemmodel.js
@@ -70,6 +70,9 @@
* Represents the GUI of the share dialogue
*
* // FIXME: use OC Share API once #17143 is done
+ *
+ * // TODO: this really should be a collection of share item models instead,
+ * where the link share is one of them
*/
var ShareItemModel = OC.Backbone.Model.extend({
initialize: function(attributes, options) {
@@ -90,47 +93,114 @@
linkShare: {}
},
- addLinkShare: function(options) {
+ /**
+ * Saves the current link share information.
+ *
+ * This will trigger an ajax call and refetch the model afterwards.
+ *
+ * TODO: this should be a separate model
+ */
+ saveLinkShare: function(attributes, options) {
var model = this;
- var expiration = this.configModel.getDefaultExpirationDateString();
var itemType = this.get('itemType');
var itemSource = this.get('itemSource');
- var options = options || {};
- var requiredOptions = [
+ // TODO: use backbone's default value mechanism once this is a separate model
+ var requiredAttributes = [
{ name: 'password', defaultValue: '' },
- { name: 'permissions', defaultValue: OC.PERMISSION_READ }
+ { name: 'permissions', defaultValue: OC.PERMISSION_READ },
+ { name: 'expiration', defaultValue: this.configModel.getDefaultExpirationDateString() }
];
- _.each(requiredOptions, function(option) {
+
+ attributes = attributes || {};
+
+ // get attributes from the model and fill in with default values
+ _.each(requiredAttributes, function(attribute) {
// a provided options overrides a present value of the link
// share. If neither is given, the default value is used.
- if(_.isUndefined(options[option.name])) {
- options[option.name] = option.defaultValue;
- var currentValue = model.get('linkShare')[option.name];
+ if(_.isUndefined(attribute[attribute.name])) {
+ attributes[attribute.name] = attribute.defaultValue;
+ var currentValue = model.get('linkShare')[attribute.name];
if(!_.isUndefined(currentValue)) {
- options[option.name] = currentValue;
+ attributes[attribute.name] = currentValue;
}
}
});
- OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, options.password, options.permissions, this.fileInfoModel.get('name'), expiration, function(data) {
- model.fetch();
- //FIXME: updateIcon belongs to view
- OC.Share.updateIcon(itemType, itemSource);
- });
+ OC.Share.share(
+ itemType,
+ itemSource,
+ OC.Share.SHARE_TYPE_LINK,
+ attributes.password,
+ attributes.permissions,
+ this.fileInfoModel.get('name'),
+ attributes.expiration,
+ function(result) {
+ if (!result || result.status !== 'success') {
+ model.fetch({
+ success: function() {
+ if (options && _.isFunction(options.success)) {
+ options.success(model);
+ }
+ }
+ });
+ } else {
+ if (options && _.isFunction(options.error)) {
+ options.error(model);
+ }
+ }
+ //FIXME: updateIcon belongs to view
+ OC.Share.updateIcon(itemType, itemSource);
+ },
+ function(result) {
+ var msg = t('core', 'Error');
+ if (result.data && result.data.message) {
+ msg = result.data.message;
+ }
+
+ if (options && _.isFunction(options.error)) {
+ options.error(model, msg);
+ } else {
+ OC.dialogs.alert(msg, t('core', 'Error while sharing'));
+ }
+ }
+ );
},
removeLinkShare: function() {
this.removeShare(OC.Share.SHARE_TYPE_LINK, '');
},
+ /**
+ * Sets the public upload flag
+ *
+ * @param {bool} allow whether public upload is allowed
+ */
setPublicUpload: function(allow) {
var permissions = OC.PERMISSION_READ;
if(allow) {
- permissions = OC.PERMISSION_UPDATE + OC.PERMISSION_CREATE + OC.PERMISSION_READ;
+ permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ;
}
- this.addLinkShare({permissions: permissions});
+ this.get('linkShare').permissions = permissions;
+ },
+
+ /**
+ * Sets the expiration date of the public link
+ *
+ * @param {string} expiration expiration date
+ */
+ setExpirationDate: function(expiration) {
+ this.get('linkShare').expiration = expiration;
+ },
+
+ /**
+ * Set password of the public link share
+ *
+ * @param {string} password
+ */
+ setPassword: function(password) {
+ this.get('linkShare').password = password;
},
addShare: function(event, selected, options) {