diff --git a/r2/r2/lib/strings.py b/r2/r2/lib/strings.py index 9e3af2f9e..75a10ab54 100644 --- a/r2/r2/lib/strings.py +++ b/r2/r2/lib/strings.py @@ -216,6 +216,7 @@ Note: there are a couple of places outside of your subreddit where someone can c create_multi = _('create a new multi'), awesomeness_goes_here = _('awesomeness goes here'), add_multi_sr = _('add a subreddit to your multi.'), + multi_already_exists = _('that multi already exists'), ) class StringHandler(object): diff --git a/r2/r2/public/static/css/reddit.less b/r2/r2/public/static/css/reddit.less index 20db7586a..10d96d54d 100755 --- a/r2/r2/public/static/css/reddit.less +++ b/r2/r2/public/static/css/reddit.less @@ -5163,7 +5163,7 @@ table.calendar { display: none; margin-bottom: 10px; - .copy-name { + .multi-name { border: 1px solid #ccc; padding: 3px; } diff --git a/r2/r2/public/static/js/multi.js b/r2/r2/public/static/js/multi.js index 4a103f611..aa1532ff8 100644 --- a/r2/r2/public/static/js/multi.js +++ b/r2/r2/public/static/js/multi.js @@ -83,6 +83,14 @@ r.multi.MultiReddit = Backbone.Model.extend({ removeSubreddit: function(name, options) { this.subreddits.getByName(name).destroy(options) + }, + + copyTo: function(newMulti) { + var attrs = _.clone(this.attributes) + delete attrs.path + attrs.visibility = 'private' + newMulti.set(attrs) + return newMulti } }) @@ -95,7 +103,7 @@ r.multi.MyMultiCollection = Backbone.Collection.extend({ create: function(attributes, options) { if ('name' in attributes) { - attributes['path'] = '/user/' + r.config.logged + '/m/' + attributes['name'] + attributes['path'] = this.pathByName(attributes['name']) delete attributes['name'] } Backbone.Collection.prototype.create.call(this, attributes, options) @@ -105,6 +113,14 @@ r.multi.MyMultiCollection = Backbone.Collection.extend({ return _.map(data, function(multiData) { return r.multi.multis.reify(multiData) }) + }, + + pathByName: function(name) { + return '/user/' + r.config.logged + '/m/' + name + }, + + touchByName: function(name) { + return r.multi.multis.touch(this.pathByName(name)) } }) @@ -174,7 +190,6 @@ r.multi.MultiDetails = Backbone.View.extend({ 'submit .add-sr': 'addSubreddit', 'change [name="visibility"]': 'setVisibility', 'click .show-copy': 'showCopyMulti', - 'click .copy': 'copyMulti', 'confirm .delete': 'deleteMulti' }, @@ -281,39 +296,20 @@ r.multi.MultiDetails = Backbone.View.extend({ }, showCopyMulti: function() { - this.$('form.copy-multi') + var $copyForm = this.$('form.copy-multi') + + $copyForm .show() - .find('.copy-name').focus() - }, + .find('.multi-name').focus() - copyMulti: function(ev) { - ev.preventDefault() - - var nameEl = this.$('.copy-multi .copy-name'), - multiName = $.trim(nameEl.val()) - if (!multiName) { - return - } - - this.$('.copy-error').css('visibility', 'hidden') - - var attrs = _.clone(this.model.attributes) - delete attrs.path - attrs.name = multiName - attrs.visibility = 'private' - r.multi.mine.create(attrs, { - wait: true, - success: function(multi) { - window.location = multi.get('path') - }, - error: _.bind(function(multi, xhr) { - var resp = JSON.parse(xhr.responseText) - this.$('.copy-error') - .text(resp.explanation) - .css('visibility', 'visible') - .show() - }, this), - beforeSend: _.bind(r.ui.showWorkingDeferred, this, this.$el) + this.copyForm = new r.multi.MultiCreateForm({ + el: $copyForm, + navOnCreate: true, + createMulti: _.bind(function(name) { + var newMulti = r.multi.mine.touchByName(name) + this.model.copyTo(newMulti) + return newMulti + }, this) }) }, @@ -356,11 +352,10 @@ r.multi.MultiSubscribeBubble = r.ui.Bubble.extend({ className: 'multi-selector hover-bubble anchor-right', template: _.template('
<%- title %>/r/<%- srName %>
'), itemTemplate: _.template(''), - itemCreateTemplate: _.template(''), + itemCreateTemplate: _.template(''), events: { - 'click .add-to-multi': 'toggleSubscribed', - 'submit .create-multi': 'createMulti' + 'click .add-to-multi': 'toggleSubscribed' }, initialize: function() { @@ -397,6 +392,10 @@ r.multi.MultiSubscribeBubble = r.ui.Bubble.extend({ createMsg: r.strings('create_multi') })) this.$el.append(content) + + this.createForm = new r.multi.MultiCreateForm({ + el: this.$('form.create-multi') + }) }, toggleSubscribed: function(ev) { @@ -407,51 +406,80 @@ r.multi.MultiSubscribeBubble = r.ui.Bubble.extend({ } else { multi.removeSubreddit(this.options.srName) } + } +}) + +r.multi.MultiCreateForm = Backbone.View.extend({ + events: { + 'submit': 'createMulti' + }, + + initialize: function() { + this.showWorkingDeferred = _.bind(r.ui.showWorkingDeferred, this, this.$el) }, createMulti: function(ev) { ev.preventDefault() - var name = this.$('.create-multi input[type="text"]').val() + + var name = this.$('input.multi-name').val() name = $.trim(name) - if (name) { - r.multi.mine.create({name: name}, { - wait: true, - error: _.bind(function(multi, xhr) { - var resp = JSON.parse(xhr.responseText) - this.$('.create-multi-error').text(resp.explanation).show() - }, this), - beforeSend: _.bind(r.ui.showWorkingDeferred, this, this.$el) - }) + if (!name) { + return } + + var newMulti + if (this.options.createMulti) { + newMulti = this.options.createMulti(name) + } else { + newMulti = r.multi.mine.touchByName(name) + } + + // check if the multi already exists + newMulti.fetch({beforeSend: this.showWorkingDeferred}) + .done(_.bind(function() { + this.showError(r.strings('multi_already_exists')) + }, this)) + .fail(_.bind(function() { + r.multi.mine.create(newMulti, { + wait: true, + beforeSend: this.showWorkingDeferred, + success: _.bind(function(multi) { + this.trigger('create', multi) + if (this.options.navOnCreate) { + window.location = multi.get('path') + '#created' + } + }, this), + error: _.bind(function(multi, xhr) { + var resp = JSON.parse(xhr.responseText) + this.showError(resp.explanation) + }, this) + }) + }, this)) + }, + + showError: function(error) { + this.$('.error').text(error).show() + }, + + focus: function() { + this.$('.multi-name').focus() } }) r.multi.ListingChooser = Backbone.View.extend({ events: { - 'submit .create': 'createClick' + 'click .create button': 'createClick' }, createClick: function(ev) { - ev.preventDefault() if (!this.$('.create').is('.expanded')) { + ev.preventDefault() this.$('.create').addClass('expanded') - this.$('.create input[type="text"]').focus() - } else { - var name = this.$('.create input[type="text"]').val() - name = $.trim(name) - if (name) { - r.multi.mine.create({name: name}, { - wait: true, - success: function(multi) { - window.location = multi.get('path') + '#created' - }, - error: _.bind(function(multi, xhr) { - var resp = JSON.parse(xhr.responseText) - this.$('.error').text(resp.explanation).show() - }, this), - beforeSend: _.bind(r.ui.showWorkingDeferred, this, this.$el) - }) - } + this.createForm = new r.multi.MultiCreateForm({ + el: this.$('.create form'), + navOnCreate: true + }) + this.createForm.focus() } } }) diff --git a/r2/r2/templates/listingchooser.html b/r2/r2/templates/listingchooser.html index 58e0b9e33..fa808021a 100644 --- a/r2/r2/templates/listingchooser.html +++ b/r2/r2/templates/listingchooser.html @@ -56,7 +56,7 @@ ${section_items(thing.sections['multi'])}
  • - +
    diff --git a/r2/r2/templates/multiinfobar.html b/r2/r2/templates/multiinfobar.html index fdc8af15c..16b325938 100644 --- a/r2/r2/templates/multiinfobar.html +++ b/r2/r2/templates/multiinfobar.html @@ -52,7 +52,7 @@ %if thing.can_copy:
    - +
    %endif