Add a share when clicking on the confirm button
Clicking on the confirm button now adds a share, but only if there is just a single exact match. If there are no exact matches or there is more than one exact match no share is added, and the autocomplete dropdown is shown again with all the suggestions. Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
parent
5e2a8cca1b
commit
9371b61c4d
|
@ -67,7 +67,8 @@
|
|||
|
||||
events: {
|
||||
'focus .shareWithField': 'onShareWithFieldFocus',
|
||||
'input .shareWithField': 'onShareWithFieldChanged'
|
||||
'input .shareWithField': 'onShareWithFieldChanged',
|
||||
'click .shareWithConfirm': '_confirmShare'
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
|
@ -438,6 +439,93 @@
|
|||
}});
|
||||
},
|
||||
|
||||
_confirmShare: function() {
|
||||
var self = this;
|
||||
var $shareWithField = $('.shareWithField');
|
||||
var $loading = this.$el.find('.shareWithLoading');
|
||||
var $confirm = this.$el.find('.shareWithConfirm');
|
||||
|
||||
$loading.removeClass('hidden');
|
||||
$loading.addClass('inlineblock');
|
||||
$confirm.addClass('hidden');
|
||||
|
||||
$shareWithField.prop('disabled', true);
|
||||
|
||||
var perPage = 200;
|
||||
var onlyExactMatches = true;
|
||||
this._getSuggestions(
|
||||
$shareWithField.val(),
|
||||
perPage,
|
||||
this.model,
|
||||
onlyExactMatches
|
||||
).done(function(suggestions, exactMatches) {
|
||||
if (suggestions.length === 0) {
|
||||
$loading.addClass('hidden');
|
||||
$loading.removeClass('inlineblock');
|
||||
$confirm.removeClass('hidden');
|
||||
|
||||
$shareWithField.prop('disabled', false);
|
||||
$shareWithField.focus();
|
||||
|
||||
// There is no need to show an error message here; it will
|
||||
// be automatically shown when the autocomplete is activated
|
||||
// again (due to the focus on the field) and it finds no
|
||||
// matches.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (exactMatches.length !== 1) {
|
||||
$loading.addClass('hidden');
|
||||
$loading.removeClass('inlineblock');
|
||||
$confirm.removeClass('hidden');
|
||||
|
||||
$shareWithField.prop('disabled', false);
|
||||
$shareWithField.focus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var actionSuccess = function() {
|
||||
$loading.addClass('hidden');
|
||||
$loading.removeClass('inlineblock');
|
||||
$confirm.removeClass('hidden');
|
||||
|
||||
$shareWithField.val('');
|
||||
$shareWithField.prop('disabled', false);
|
||||
$shareWithField.focus();
|
||||
};
|
||||
|
||||
var actionError = function(obj, msg) {
|
||||
$loading.addClass('hidden');
|
||||
$loading.removeClass('inlineblock');
|
||||
$confirm.removeClass('hidden');
|
||||
|
||||
$shareWithField.prop('disabled', false);
|
||||
$shareWithField.focus();
|
||||
|
||||
OC.Notification.showTemporary(msg);
|
||||
};
|
||||
|
||||
self.model.addShare(exactMatches[0].value, {
|
||||
success: actionSuccess,
|
||||
error: actionError
|
||||
});
|
||||
}).fail(function(message) {
|
||||
$loading.addClass('hidden');
|
||||
$loading.removeClass('inlineblock');
|
||||
$confirm.removeClass('hidden');
|
||||
|
||||
$shareWithField.prop('disabled', false);
|
||||
$shareWithField.focus();
|
||||
|
||||
// There is no need to show an error message here; it will be
|
||||
// automatically shown when the autocomplete is activated again
|
||||
// (due to the focus on the field) and getting the suggestions
|
||||
// fail.
|
||||
});
|
||||
},
|
||||
|
||||
_toggleLoading: function(state) {
|
||||
this._loading = state;
|
||||
this.$el.find('.subView').toggleClass('hidden', state);
|
||||
|
|
|
@ -1836,6 +1836,364 @@ describe('OC.Share.ShareDialogView', function() {
|
|||
addShareStub.restore();
|
||||
});
|
||||
});
|
||||
describe('confirm share', function() {
|
||||
var addShareStub;
|
||||
var tooltipStub;
|
||||
var showTemporaryNotificationStub;
|
||||
|
||||
beforeEach(function() {
|
||||
addShareStub = sinon.stub(shareModel, 'addShare');
|
||||
|
||||
tooltipStub = sinon.stub($.fn, 'tooltip').callsFake(function() {
|
||||
return $('<div></div>');
|
||||
});
|
||||
|
||||
showTemporaryNotificationStub = sinon.stub(OC.Notification, 'showTemporary');
|
||||
|
||||
dialog.render();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
addShareStub.restore();
|
||||
tooltipStub.restore();
|
||||
showTemporaryNotificationStub.restore();
|
||||
});
|
||||
|
||||
it('sets the appropriate UI state while waiting to get the suggestions', function() {
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(autocompleteStub.callCount).toEqual(1);
|
||||
expect(typeof autocompleteStub.firstCall.args[0]).toEqual('object');
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
});
|
||||
|
||||
it('calls addShare with the only suggestion', function() {
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs': {
|
||||
'meta': {
|
||||
'status': 'success',
|
||||
'statuscode': 100,
|
||||
'message': null
|
||||
},
|
||||
'data': {
|
||||
'exact': {
|
||||
'users': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'user1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'groups': [],
|
||||
'remotes': []
|
||||
},
|
||||
'users': [],
|
||||
'groups': [],
|
||||
'remotes': [],
|
||||
'lookup': []
|
||||
}
|
||||
}
|
||||
});
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
// Ensure that the UI is not restored before adding the share
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
|
||||
expect(addShareStub.calledOnce).toEqual(true);
|
||||
expect(addShareStub.firstCall.args[0]).toEqual({
|
||||
shareType: OC.Share.SHARE_TYPE_USER,
|
||||
shareWith: 'user1'
|
||||
});
|
||||
|
||||
// "yield" and "callArg" from SinonJS can not be used, as the
|
||||
// callback is a property not in the first argument.
|
||||
addShareStub.firstCall.args[1]['success'].apply(shareModel);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('');
|
||||
});
|
||||
|
||||
it('handles a failure to share', function() {
|
||||
expect(showTemporaryNotificationStub.called).toEqual(false);
|
||||
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs': {
|
||||
'meta': {
|
||||
'status': 'success',
|
||||
'statuscode': 100,
|
||||
'message': null
|
||||
},
|
||||
'data': {
|
||||
'exact': {
|
||||
'users': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'user1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'groups': [],
|
||||
'remotes': []
|
||||
},
|
||||
'users': [],
|
||||
'groups': [],
|
||||
'remotes': [],
|
||||
'lookup': []
|
||||
}
|
||||
}
|
||||
});
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
// Ensure that the UI is not restored before adding the share
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
|
||||
expect(addShareStub.calledOnce).toEqual(true);
|
||||
expect(addShareStub.firstCall.args[0]).toEqual({
|
||||
shareType: OC.Share.SHARE_TYPE_USER,
|
||||
shareWith: 'user1'
|
||||
});
|
||||
|
||||
// "yield" and "callArg" from SinonJS can not be used, as the
|
||||
// callback is a property not in the first argument.
|
||||
addShareStub.firstCall.args[1]['error'].apply(shareModel);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
|
||||
expect(showTemporaryNotificationStub.calledOnce).toEqual(true);
|
||||
});
|
||||
|
||||
it('restores UI if there are no matches at all', function() {
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs': {
|
||||
'meta': {
|
||||
'status': 'success',
|
||||
'statuscode': 100,
|
||||
'message': null
|
||||
},
|
||||
'data': {
|
||||
'exact': {
|
||||
'users': [],
|
||||
'groups': [],
|
||||
'remotes': []
|
||||
},
|
||||
'users': [],
|
||||
'groups': [],
|
||||
'remotes': [],
|
||||
'lookup': []
|
||||
}
|
||||
}
|
||||
});
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
expect(addShareStub.called).toEqual(false);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
|
||||
// No explicit tooltip is shown; it is automatically shown when the
|
||||
// autocomplete is activated again and it finds no matches.
|
||||
expect(tooltipStub.lastCall.args[0]).not.toEqual('show');
|
||||
});
|
||||
|
||||
it('shows tooltip if there are matches but no exact matches', function() {
|
||||
dialog.$el.find('.shareWithField').val('bo');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs': {
|
||||
'meta': {
|
||||
'status': 'success',
|
||||
'statuscode': 100,
|
||||
'message': null
|
||||
},
|
||||
'data': {
|
||||
'exact': {
|
||||
'users': [],
|
||||
'groups': [],
|
||||
'remotes': []
|
||||
},
|
||||
'users': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'user1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'groups': [],
|
||||
'remotes': [],
|
||||
'lookup': []
|
||||
}
|
||||
}
|
||||
});
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
expect(addShareStub.called).toEqual(false);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bo');
|
||||
});
|
||||
|
||||
it('shows tooltip if there is more than one exact match', function() {
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs': {
|
||||
'meta': {
|
||||
'status': 'success',
|
||||
'statuscode': 100,
|
||||
'message': null
|
||||
},
|
||||
'data': {
|
||||
'exact': {
|
||||
'users': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_USER,
|
||||
'shareWith': 'user1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'groups': [
|
||||
{
|
||||
'label': 'bob',
|
||||
'value': {
|
||||
'shareType': OC.Share.SHARE_TYPE_GROUP,
|
||||
'shareWith': 'group1'
|
||||
}
|
||||
}
|
||||
],
|
||||
'remotes': []
|
||||
},
|
||||
'users': [],
|
||||
'groups': [],
|
||||
'remotes': [],
|
||||
'lookup': []
|
||||
}
|
||||
}
|
||||
});
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
expect(addShareStub.called).toEqual(false);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
});
|
||||
|
||||
it('throws a notification for a successful ajax call with failure content', function () {
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
var jsonData = JSON.stringify({
|
||||
'ocs' : {
|
||||
'meta' : {
|
||||
'status': 'failure',
|
||||
'statuscode': 400,
|
||||
'message': 'error message'
|
||||
}
|
||||
}
|
||||
});
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{'Content-Type': 'application/json'},
|
||||
jsonData
|
||||
);
|
||||
|
||||
expect(addShareStub.called).toEqual(false);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
|
||||
expect(showTemporaryNotificationStub.called).toEqual(false);
|
||||
});
|
||||
|
||||
it('throws a notification when the ajax search lookup fails', function () {
|
||||
dialog.$el.find('.shareWithField').val('bob');
|
||||
|
||||
dialog._confirmShare();
|
||||
|
||||
fakeServer.requests[0].respond(500);
|
||||
|
||||
expect(addShareStub.called).toEqual(false);
|
||||
|
||||
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
|
||||
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
|
||||
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
|
||||
|
||||
expect(showTemporaryNotificationStub.called).toEqual(false);
|
||||
});
|
||||
});
|
||||
describe('reshare permissions', function() {
|
||||
it('does not show sharing options when sharing not allowed', function() {
|
||||
shareModel.set({
|
||||
|
|
Loading…
Reference in New Issue