Add a checkbox that propagates topic edits to subsequent messages.

Trac #1348

(imported from commit 28e2a8cb3ecda5ec50d17501f4ccbd8644212065)
This commit is contained in:
Kevin Mehall 2013-09-03 16:07:59 -04:00
parent 07d692758e
commit 19a835e7d5
6 changed files with 69 additions and 25 deletions

View File

@ -14,6 +14,10 @@ exports.save = function (row) {
var new_topic = row.find(".message_edit_topic").val();
if (new_topic !== message.subject && new_topic.trim() !== "") {
request.subject = new_topic;
if (row.find(".message_edit_topic_propagate>input").is(":checked")) {
request.propagate_subject = true;
}
changed = true;
}
}

View File

@ -734,23 +734,33 @@ function update_messages(events) {
}
if (event.subject !== undefined) {
// Remove the recent subjects entry for the old subject;
// must be called before we update msg.subject
process_message_for_recent_subjects(msg, true);
// Update the unread counts; again, this must be called
// before we update msg.subject
unread.update_unread_subjects(msg, event);
// A topic edit may affect multiple messages, listed in
// event.message_ids. event.message_id is still the first message
// where the user initiated the edit.
_.each(event.message_ids, function (id) {
var msg = all_msg_list.get(id);
if (msg === undefined) {
return;
}
msg.subject = event.subject;
msg.subject_links = event.subject_links;
if (msg.subject === compose.empty_subject_placeholder()) {
msg.empty_subject = true;
} else {
msg.empty_subject = false;
}
// Add the recent subjects entry for the new subject; must
// be called after we update msg.subject
process_message_for_recent_subjects(msg);
// Remove the recent subjects entry for the old subject;
// must be called before we update msg.subject
process_message_for_recent_subjects(msg, true);
// Update the unread counts; again, this must be called
// before we update msg.subject
unread.update_unread_subjects(msg, event);
msg.subject = event.subject;
msg.subject_links = event.subject_links;
if (msg.subject === compose.empty_subject_placeholder()) {
msg.empty_subject = true;
} else {
msg.empty_subject = false;
}
// Add the recent subjects entry for the new subject; must
// be called after we update msg.subject
process_message_for_recent_subjects(msg);
});
}
var row = current_msg_list.get_row(event.message_id);

View File

@ -1134,6 +1134,9 @@ table.focused_table {
.message_edit_content {
line-height: 18px;
}
.message_edit_topic_propagate{
display: inline-block;
}
.message_content.condensed {
max-height: 8.5em;

View File

@ -6,6 +6,9 @@
<label class="control-label edit-control-label" for="message_edit_topic">Topic</label>
<div class="controls edit-controls">
<input type="text" value="{{topic}}" class="message_edit_topic" id="message_edit_topic">
<label class='message_edit_topic_propagate'>
<input type="checkbox"> Change all later messages on this topic
</label>
</div>
</div>
{{/if}}

View File

@ -1026,7 +1026,7 @@ def do_update_onboarding_steps(user_profile, steps):
users=[user_profile.id])
tornado_callbacks.send_notification(notice)
def do_update_message(user_profile, message_id, subject, content):
def do_update_message(user_profile, message_id, subject, propagate_subject, content):
try:
message = Message.objects.select_related().get(id=message_id)
except Message.DoesNotExist:
@ -1036,6 +1036,7 @@ def do_update_message(user_profile, message_id, subject, content):
'sender': user_profile.email,
'message_id': message_id}
edit_history_event = {}
changed_messages = [message]
if message.sender != user_profile:
if not (message.subject == "(no topic)" and content is None):
@ -1078,17 +1079,36 @@ def do_update_message(user_profile, message_id, subject, content):
event["rendered_content"] = rendered_content
if subject is not None:
orig_subject = message.subject
subject = subject.strip()
if subject == "":
raise JsonableError("Topic can't be empty")
if len(subject) > MAX_SUBJECT_LENGTH:
raise JsonableError("Topic too long")
event["orig_subject"] = message.subject
event["orig_subject"] = orig_subject
message.subject = subject
event["subject"] = subject
event['subject_links'] = bugdown.subject_links(message.sender.realm.domain.lower(), subject)
edit_history_event["prev_subject"] = event['orig_subject']
edit_history_event["prev_subject"] = orig_subject
if propagate_subject:
messages = Message.objects.filter(
recipient = message.recipient,
subject = orig_subject,
id__gt = message.id
).select_related()
# Evaluate the query before running the update
messages_list = list(messages)
messages.update(subject=subject)
for m in messages_list:
# The cached ORM object is not changed by messages.update()
# and the memcached update requires the new value
m.subject = subject
changed_messages += messages_list
message.last_edit_time = timezone.now()
event['edit_timestamp'] = datetime_to_timestamp(message.last_edit_time)
@ -1107,12 +1127,15 @@ def do_update_message(user_profile, message_id, subject, content):
# Update the message as stored in both the (deprecated) message
# cache (for shunting the message over to Tornado in the old
# get_messages API) and also the to_dict caches.
cache_save_message(message)
items_for_memcached = {}
items_for_memcached[to_dict_cache_key(message, True)] = \
(stringify_message_dict(message.to_dict_uncached(apply_markdown=True)),)
items_for_memcached[to_dict_cache_key(message, False)] = \
(stringify_message_dict(message.to_dict_uncached(apply_markdown=False)),)
event['message_ids'] = []
for changed_message in changed_messages:
event['message_ids'].append(changed_message.id)
cache_save_message(changed_message)
items_for_memcached[to_dict_cache_key(changed_message, True)] = \
(stringify_message_dict(changed_message.to_dict_uncached(apply_markdown=True)),)
items_for_memcached[to_dict_cache_key(changed_message, False)] = \
(stringify_message_dict(changed_message.to_dict_uncached(apply_markdown=False)),)
cache_set_many(items_for_memcached)
recipients = [um.user_profile_id for um in UserMessage.objects.filter(message=message_id)]

View File

@ -1267,10 +1267,11 @@ def json_fetch_raw_message(request, user_profile,
def update_message_backend(request, user_profile,
message_id=REQ(converter=to_non_negative_int),
subject=REQ(default=None),
propagate_subject=REQ(default=False),
content=REQ(default=None)):
if subject is None and content is None:
return json_error("Nothing to change")
do_update_message(user_profile, message_id, subject, content)
do_update_message(user_profile, message_id, subject, propagate_subject, content)
return json_success()
# We do not @require_login for send_message_backend, since it is used