mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-29 16:58:21 -05:00
Multi renaming.
Adds an api call for renaming a multi while preserving metadata. Abstracts MultiCreateForm to handle renaming.
This commit is contained in:
@@ -321,6 +321,7 @@ def make_map():
|
||||
mc('/api/:action', controller='api')
|
||||
|
||||
mc("/api/multi/mine", controller="multiapi", action="my_multis")
|
||||
mc("/api/multi/*multipath/rename", controller="multiapi", action="multi_rename")
|
||||
mc("/api/multi/*multipath/r/:srname", controller="multiapi", action="multi_subreddit")
|
||||
mc("/api/multi/*multipath", controller="multiapi", action="multi")
|
||||
|
||||
|
||||
@@ -190,6 +190,34 @@ class MultiApiController(RedditController, OAuth2ResourceController):
|
||||
"""Delete a multi."""
|
||||
multi.delete()
|
||||
|
||||
@require_oauth2_scope("subscribe")
|
||||
@api_doc(
|
||||
api_section.multis,
|
||||
uri="/api/multi/{multipath}/rename",
|
||||
)
|
||||
@validate(
|
||||
VUser(),
|
||||
VModhash(),
|
||||
from_multi=VMultiByPath("multipath", require_edit=True),
|
||||
to_path_info=VMultiPath("to",
|
||||
docs={"to": "destination multireddit url path"},
|
||||
),
|
||||
)
|
||||
def POST_multi_rename(self, multi, to_path_info):
|
||||
"""Rename a multi."""
|
||||
|
||||
self._check_new_multi_path(to_path_info)
|
||||
|
||||
try:
|
||||
LabeledMulti._byID(to_path_info['path'])
|
||||
except tdb_cassandra.NotFound:
|
||||
to_multi = LabeledMulti.copy(to_path_info['path'], multi)
|
||||
else:
|
||||
raise RedditError('MULTI_EXISTS', code=409, fields='multipath')
|
||||
|
||||
multi.delete()
|
||||
return self._format_multi(to_multi)
|
||||
|
||||
def _get_multi_subreddit(self, multi, sr):
|
||||
resp = LabeledMultiJsonTemplate.sr_props(multi, [sr])[0]
|
||||
return self.api_wrapper(resp)
|
||||
|
||||
@@ -1843,6 +1843,7 @@ class MultiInfoBar(Templated):
|
||||
self.multi = wrap_things(multi)[0]
|
||||
self.can_edit = multi.can_edit(user)
|
||||
self.can_copy = c.user_is_loggedin
|
||||
self.can_rename = c.user_is_loggedin and multi.owner == c.user
|
||||
srs.sort(key=lambda sr: sr.name.lower())
|
||||
self.srs = srs
|
||||
|
||||
|
||||
@@ -1422,6 +1422,13 @@ class LabeledMulti(tdb_cassandra.Thing, MultiReddit):
|
||||
obj._owner = owner
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def copy(cls, path, multi):
|
||||
obj = cls(_id=path, **multi._t)
|
||||
obj._commit()
|
||||
obj._owner = multi.owner
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def sr_props_to_columns(cls, sr_props):
|
||||
columns = {}
|
||||
|
||||
@@ -5148,7 +5148,7 @@ table.calendar {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label, .show-copy, .delete {
|
||||
label, & > button {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
@@ -5163,7 +5163,7 @@ table.calendar {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
form.copy-multi {
|
||||
form.copy-multi, form.rename-multi {
|
||||
display: none;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@@ -5175,7 +5175,22 @@ table.calendar {
|
||||
button {
|
||||
.light-button;
|
||||
padding: 3px 4px;
|
||||
background: #eeffdd;
|
||||
}
|
||||
}
|
||||
|
||||
form.copy-multi button {
|
||||
background: #eeffdd;
|
||||
}
|
||||
|
||||
form.rename-multi {
|
||||
button {
|
||||
background: #ffffdd;
|
||||
}
|
||||
|
||||
.warning {
|
||||
margin-top: .5em;
|
||||
font-weight: bold;
|
||||
color: #c2461f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,26 @@ r.multi.MultiReddit = Backbone.Model.extend({
|
||||
this.subreddits.getByName(name).destroy(options)
|
||||
},
|
||||
|
||||
rename: function(newPath) {
|
||||
var deferred = new $.Deferred
|
||||
Backbone.ajax({
|
||||
type: 'POST',
|
||||
url: this.url() + '/rename',
|
||||
data: {
|
||||
to: newPath
|
||||
},
|
||||
success: _.bind(function(resp) {
|
||||
var collection = this.collection
|
||||
this.trigger('destroy', this, this.collection)
|
||||
var multi = r.multi.multis.reify(resp)
|
||||
r.multi.mine.add(multi)
|
||||
deferred.resolve(multi)
|
||||
}, this),
|
||||
error: _.bind(deferred.reject, deferred)
|
||||
})
|
||||
return deferred
|
||||
},
|
||||
|
||||
copyTo: function(newMulti) {
|
||||
var attrs = _.clone(this.attributes)
|
||||
delete attrs.path
|
||||
@@ -216,6 +236,7 @@ r.multi.MultiDetails = Backbone.View.extend({
|
||||
'submit .add-sr': 'addSubreddit',
|
||||
'change [name="visibility"]': 'setVisibility',
|
||||
'click .show-copy': 'showCopyMulti',
|
||||
'click .show-rename': 'showRenameMulti',
|
||||
'confirm .delete': 'deleteMulti'
|
||||
},
|
||||
|
||||
@@ -318,6 +339,8 @@ r.multi.MultiDetails = Backbone.View.extend({
|
||||
},
|
||||
|
||||
showCopyMulti: function() {
|
||||
this.$('form.rename-multi').hide()
|
||||
|
||||
var $copyForm = this.$('form.copy-multi')
|
||||
|
||||
$copyForm
|
||||
@@ -328,16 +351,31 @@ r.multi.MultiDetails = Backbone.View.extend({
|
||||
.focus()
|
||||
|
||||
if (!this.copyForm) {
|
||||
this.copyForm = new r.multi.MultiCreateForm({
|
||||
this.copyForm = new r.multi.MultiCopyForm({
|
||||
el: $copyForm,
|
||||
navOnCreate: true,
|
||||
createMulti: _.bind(function(name) {
|
||||
var newMulti = new r.multi.MultiReddit({
|
||||
path: r.multi.mine.pathByName(name)
|
||||
}, {isNew: true})
|
||||
this.model.copyTo(newMulti)
|
||||
return newMulti
|
||||
}, this)
|
||||
sourceMulti: this.model
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
showRenameMulti: function() {
|
||||
this.$('form.copy-multi').hide()
|
||||
|
||||
var $renameForm = this.$('form.rename-multi')
|
||||
|
||||
$renameForm
|
||||
.show()
|
||||
.find('.multi-name')
|
||||
.val(this.model.name())
|
||||
.select()
|
||||
.focus()
|
||||
|
||||
if (!this.renameForm) {
|
||||
this.renameForm = new r.multi.MultiRenameForm({
|
||||
el: $renameForm,
|
||||
navOnCreate: true,
|
||||
sourceMulti: this.model
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -453,10 +491,6 @@ r.multi.MultiCreateForm = Backbone.View.extend({
|
||||
'submit': 'createMulti'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.showWorkingDeferred = _.bind(r.ui.showWorkingDeferred, this, this.$el)
|
||||
},
|
||||
|
||||
createMulti: function(ev) {
|
||||
ev.preventDefault()
|
||||
|
||||
@@ -466,29 +500,40 @@ r.multi.MultiCreateForm = Backbone.View.extend({
|
||||
return
|
||||
}
|
||||
|
||||
var newMulti
|
||||
if (this.options.createMulti) {
|
||||
newMulti = this.options.createMulti(name)
|
||||
} else {
|
||||
var newMulti = new r.multi.MultiReddit({
|
||||
path: r.multi.mine.pathByName(name)
|
||||
}, {isNew: true})
|
||||
}
|
||||
var deferred = this._createMulti(name)
|
||||
|
||||
r.multi.mine.create(newMulti, {
|
||||
wait: true,
|
||||
beforeSend: this.showWorkingDeferred,
|
||||
success: _.bind(function(multi) {
|
||||
deferred
|
||||
.done(_.bind(function(multi) {
|
||||
this.trigger('create', multi)
|
||||
if (this.options.navOnCreate) {
|
||||
window.location = multi.get('path') + '#created'
|
||||
}
|
||||
}, this),
|
||||
error: _.bind(function(multi, xhr) {
|
||||
}, this))
|
||||
.fail(_.bind(function(xhr) {
|
||||
var resp = JSON.parse(xhr.responseText)
|
||||
this.showError(resp.explanation)
|
||||
}, this)
|
||||
}, this))
|
||||
|
||||
r.ui.showWorkingDeferred(this.$el, deferred)
|
||||
},
|
||||
|
||||
_createMulti: function(name) {
|
||||
var newMulti = new r.multi.MultiReddit({
|
||||
path: r.multi.mine.pathByName(name)
|
||||
}, {isNew: true})
|
||||
|
||||
this._alterMulti(newMulti)
|
||||
|
||||
var deferred = new $.Deferred
|
||||
r.multi.mine.create(newMulti, {
|
||||
wait: true,
|
||||
success: _.bind(deferred.resolve, deferred),
|
||||
error: function(multi, xhr) {
|
||||
deferred.reject(xhr)
|
||||
}
|
||||
})
|
||||
|
||||
return deferred
|
||||
},
|
||||
|
||||
showError: function(error) {
|
||||
@@ -500,6 +545,18 @@ r.multi.MultiCreateForm = Backbone.View.extend({
|
||||
}
|
||||
})
|
||||
|
||||
r.multi.MultiCopyForm = r.multi.MultiCreateForm.extend({
|
||||
_alterMulti: function(multi) {
|
||||
this.options.sourceMulti.copyTo(multi)
|
||||
}
|
||||
})
|
||||
|
||||
r.multi.MultiRenameForm = r.multi.MultiCopyForm.extend({
|
||||
_createMulti: function(name) {
|
||||
return this.options.sourceMulti.rename(r.multi.mine.pathByName(name))
|
||||
}
|
||||
})
|
||||
|
||||
r.multi.ListingChooser = Backbone.View.extend({
|
||||
events: {
|
||||
'click .create button': 'createClick',
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
%if thing.can_copy:
|
||||
<button class="show-copy">${_('copy')}</button>
|
||||
%endif
|
||||
%if thing.can_rename:
|
||||
<button class="show-rename">${_('rename')}</button>
|
||||
%endif
|
||||
<button class="delete">${_('delete')}</button>
|
||||
%else:
|
||||
%if thing.can_copy:
|
||||
@@ -57,6 +60,14 @@
|
||||
</form>
|
||||
%endif
|
||||
|
||||
%if thing.can_rename:
|
||||
<form class="rename-multi">
|
||||
<p class="warning">${_('warning: renaming a multi will break any links and references to the old name.')}</p>
|
||||
<input type="text" class="multi-name" placeholder="${_('new name')}"><button class="rename">${_('rename')} ›</button>
|
||||
<div class="error rename-error"></div>
|
||||
</form>
|
||||
%endif
|
||||
|
||||
<h3>${unsafe(_('%(count)s subreddits in this multi:') % dict(count='<span class="count">%d</span> ' % len(thing.srs)))}</h3>
|
||||
<ul class="subreddits">
|
||||
%for sr in thing.srs:
|
||||
|
||||
Reference in New Issue
Block a user