summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2016-01-27 15:09:59 +0100
committerVincent Petry <pvince81@owncloud.com>2016-01-27 15:09:59 +0100
commit714d8c2424323a449f3d4fa9ea81a76260f0014c (patch)
tree3aacddc1bcad25b46ad3ca07e3364cc040a6a7bb /core
parent308396b770f3b1b41ba31ff0ee889d485b14d14a (diff)
downloadnextcloud-server-714d8c2424323a449f3d4fa9ea81a76260f0014c.tar.gz
nextcloud-server-714d8c2424323a449f3d4fa9ea81a76260f0014c.zip
Fix system tags conflict situations
Does not disrupt the UX whenever a tag or association was created concurrently. The input field will adjust itself as if the tag was already there in the first place.
Diffstat (limited to 'core')
-rw-r--r--core/js/systemtags/systemtagsinputfield.js29
-rw-r--r--core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js59
2 files changed, 85 insertions, 3 deletions
diff --git a/core/js/systemtags/systemtagsinputfield.js b/core/js/systemtags/systemtagsinputfield.js
index b90ecbe4265..ae9f93ca671 100644
--- a/core/js/systemtags/systemtagsinputfield.js
+++ b/core/js/systemtags/systemtagsinputfield.js
@@ -186,6 +186,12 @@
return false;
},
+ _addToSelect2Selection: function(selection) {
+ var data = this.$tagsField.select2('data');
+ data.push(selection);
+ this.$tagsField.select2('data', data);
+ },
+
/**
* Event handler whenever a tag is selected.
* Also called whenever tag creation is requested through the dummy tag object.
@@ -204,10 +210,27 @@
userAssignable: true
}, {
success: function(model) {
- var data = self.$tagsField.select2('data');
- data.push(model.toJSON());
- self.$tagsField.select2('data', data);
+ self._addToSelect2Selection(model.toJSON());
self.trigger('select', model);
+ },
+ error: function(model, xhr) {
+ if (xhr.status === 409) {
+ // re-fetch collection to get the missing tag
+ self.collection.reset();
+ self.collection.fetch({
+ success: function(collection) {
+ // find the tag in the collection
+ var model = collection.where({name: e.object.name, userVisible: true, userAssignable: true});
+ if (model.length) {
+ model = model[0];
+ // the tag already exists or was already assigned,
+ // add it to the list anyway
+ self._addToSelect2Selection(model.toJSON());
+ self.trigger('select', model);
+ }
+ }
+ });
+ }
}
});
this.$tagsField.select2('close');
diff --git a/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js b/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js
index 07e926cd2a9..0ad383860bc 100644
--- a/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js
+++ b/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js
@@ -158,6 +158,65 @@ describe('OC.SystemTags.SystemTagsInputField tests', function() {
expect(selectHandler.calledOnce).toEqual(true);
expect(selectHandler.getCall(0).args[0]).toEqual('2');
});
+ it('triggers select event and still adds to list even in case of conflict', function() {
+ var selectHandler = sinon.stub();
+ view.on('select', selectHandler);
+ var fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
+ var createStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'create');
+ view.$el.find('input').trigger(new $.Event('select2-selecting', {
+ object: {
+ id: -1,
+ name: 'newname',
+ isNew: true
+ }
+ }));
+
+ expect(createStub.calledOnce).toEqual(true);
+ expect(createStub.getCall(0).args[0]).toEqual({
+ name: 'newname',
+ userVisible: true,
+ userAssignable: true
+ });
+
+ var newModel = new OC.SystemTags.SystemTagModel({
+ id: '123',
+ name: 'newname',
+ userVisible: true,
+ userAssignable: true
+ });
+
+ // not called yet
+ expect(selectHandler.notCalled).toEqual(true);
+
+ select2Stub.withArgs('data').returns([{
+ id: '1',
+ name: 'abc'
+ }]);
+
+ // simulate conflict response for tag creation
+ createStub.yieldTo('error', view.collection, {status: 409});
+
+ // at this point it fetches from the server
+ expect(fetchStub.calledOnce).toEqual(true);
+ // simulate fetch result by adding model to the collection
+ view.collection.add(newModel);
+ fetchStub.yieldTo('success', view.collection);
+
+ expect(select2Stub.lastCall.args[0]).toEqual('data');
+ expect(select2Stub.lastCall.args[1]).toEqual([{
+ id: '1',
+ name: 'abc'
+ },
+ newModel.toJSON()
+ ]);
+
+ // select event still called
+ expect(selectHandler.calledOnce).toEqual(true);
+ expect(selectHandler.getCall(0).args[0]).toEqual(newModel);
+
+ createStub.restore();
+ fetchStub.restore();
+ });
});
describe('tag actions', function() {
var opts;