[manual] Unify huddles and personals into private messages on the receive path

feedback-bot and zephyr_mirror will need to be updated and restarted
when this is deployed to prod.

(imported from commit fe2b524424c174bcb1b717a851a5d3815fda3f69)
This commit is contained in:
Zev Benjamin 2012-12-03 13:49:12 -05:00
parent 02df4f76b6
commit 7e4776322d
14 changed files with 86 additions and 128 deletions

View File

@ -18,7 +18,7 @@ staging_client = humbug.Client(
site="https://staging.humbughq.com")
def forward_message(message):
if message["type"] != "personal":
if message["type"] != "private" or len(message["recipient"]) != 2:
return
forwarded_message = {
"type": "stream",

View File

@ -461,13 +461,14 @@ def forward_to_zephyr(message):
instance = zephyr_class
zephyr_class = "message"
zwrite_args.extend(["-c", zephyr_class, "-i", instance])
elif message['type'] == "personal":
recipient = to_zephyr_username(message["display_recipient"]["email"])
zwrite_args.extend([recipient])
elif message['type'] == "huddle":
zwrite_args.extend(["-C"])
zwrite_args.extend([to_zephyr_username(user["email"]).replace("@ATHENA.MIT.EDU", "")
for user in message["display_recipient"]])
elif message['type'] == "private":
if len(message['display_recipient']) == 1:
recipient = to_zephyr_username(message["display_recipient"][0]["email"])
zwrite_args.extend([recipient])
else:
zwrite_args.extend(["-C"])
zwrite_args.extend([to_zephyr_username(user["email"]).replace("@ATHENA.MIT.EDU", "")
for user in message["display_recipient"]])
if options.test_mode:
logger.debug("Would have forwarded: %s\n%s" %
@ -522,12 +523,10 @@ received it, Zephyr users did not. The error message from zwrite was:
def maybe_forward_to_zephyr(message):
if (message["sender_email"] == options.user + "@mit.edu"):
if not ((message["type"] == "stream") or
(message["type"] == "personal" and
message["display_recipient"]["email"].lower().endswith("mit.edu")) or
(message["type"] == "huddle" and
(message["type"] == "private" and
False not in [u["email"].lower().endswith("mit.edu") for u in
message["display_recipient"]])):
# Don't try forward personals/huddles with non-MIT users
# Don't try forward private messages with non-MIT users
# to MIT Zephyr.
return
timestamp_now = datetime.datetime.now().strftime("%s")

View File

@ -29,9 +29,9 @@
<td colspan="2" class="message_label_clickable message_header message_header_stream left_part"></td>
<td class="message_label_clickable message_header message_header_stream right_part"></td>
</tr>
<tr style="display: none;" id="current_label_huddle" class="recipient_row">
<td colspan="2" class="message_label_clickable message_header message_header_huddle left_part"></td>
<td class="message_label_clickable message_header message_header_huddle right_part"></td>
<tr style="display: none;" id="current_label_private_message" class="recipient_row">
<td colspan="2" class="message_label_clickable message_header message_header_private_message left_part"></td>
<td class="message_label_clickable message_header message_header_private_message right_part"></td>
</tr>
</table>
</div>
@ -90,15 +90,15 @@
</td>
</tr>
<tr id="private-message">
<td colspan="2" class="message_header message_header_huddle left_part"></td>
<td class="message_header message_header_huddle right_part">
<td colspan="2" class="message_header message_header_private_message left_part"></td>
<td class="message_header message_header_private_message right_part">
You and <input type="text" class="recipient_box" name="recipient" id="private_message_recipient"
value="" placeholder="one or more people..." autocomplete="off" tabindex="130"/>
</td>
</tr>
<tr>
<td class="message_picture">
<div id="stream_or_huddle">
<div id="stream_or_private_message">
<ul class="nav nav-pills nav-stacked" id="message-type-tabs">
<li class="active" id="stream_toggle">
<a href="#stream-message" data-toggle="pill" title="Send a stream message" tabindex="100" onclick="compose.set_mode('stream');">

View File

@ -58,7 +58,7 @@ var globals =
+ ' keep_pointer_in_view move_pointer_at_page_top_and_bottom'
+ ' respond_to_message'
+ ' select_message select_message_by_id'
+ ' scroll_to_selected disable_pointer_movement'
+ ' scroll_to_selected disable_pointer_movement get_private_message_recipient'
+ ' load_old_messages'
+ ' selected_message selected_message_id'
+ ' at_top_of_viewport at_bottom_of_viewport'

View File

@ -35,9 +35,9 @@
{{else}}
<tr zid="{{id}}" class="recipient_row">
<td colspan="2"
class="message_header message_header_huddle left_part">
class="message_header message_header_private_message left_part">
</td>
<td class="message_label_clickable narrows_by_recipient message_header message_header_huddle right_part"
<td class="message_label_clickable narrows_by_recipient message_header message_header_private_message right_part"
title="Narrow to your private messages with {{display_reply_to}}">You and {{display_reply_to}}</td>
</tr>
{{/if}}

View File

@ -5,7 +5,7 @@
<i class="icon-share-alt"></i> Reply to this {{#if is_stream}}stream{{else}}private message{{/if}}
</a>
</li>
{{#unless is_personal}}
{{#unless is_private}}
<li>
<a onclick="respond_to_message('personal');">
<i class="icon-user"></i> Reply to {{sender_full_name}} only

View File

@ -27,38 +27,18 @@ def get_display_recipient(recipient):
"""
recipient: an instance of Recipient.
returns: an appropriate string describing the recipient (the stream
name, for a stream, or the email, for a user).
"""
if recipient.type == Recipient.STREAM:
stream = Stream.objects.get(id=recipient.type_id)
return stream.name
elif recipient.type == Recipient.HUDDLE:
# We don't really care what the ordering is, just that it's deterministic.
user_profile_list = (UserProfile.objects.filter(subscription__recipient=recipient)
.select_related()
.order_by('user__email'))
return [{'email': user_profile.user.email,
'full_name': user_profile.full_name,
'short_name': user_profile.short_name} for user_profile in user_profile_list]
else:
user_profile = UserProfile.objects.select_related().get(id=recipient.type_id)
return {'email': user_profile.user.email,
'full_name': user_profile.full_name,
'short_name': user_profile.short_name}
def get_log_recipient(recipient):
"""
recipient: an instance of Recipient.
returns: an appropriate string describing the recipient (the stream
name, for a stream, or the email, for a user).
returns: an appropriate object describing the recipient. For a
stream this will be the stream name as a string. For a huddle or
personal, it will be an array of dicts about each recipient.
"""
if recipient.type == Recipient.STREAM:
stream = Stream.objects.get(id=recipient.type_id)
return stream.name
user_profile_list = UserProfile.objects.filter(subscription__recipient=recipient).select_related()
# We don't really care what the ordering is, just that it's deterministic.
user_profile_list = (UserProfile.objects.filter(subscription__recipient=recipient)
.select_related()
.order_by('user__email'))
return [{'email': user_profile.user.email,
'full_name': user_profile.full_name,
'short_name': user_profile.short_name} for user_profile in user_profile_list]
@ -427,13 +407,31 @@ class Message(models.Model):
if hasattr(self, 'precomputed_dicts'):
return self.precomputed_dicts['text/html' if apply_markdown else 'text/x-markdown']
display_recipient = get_display_recipient(self.recipient)
if self.recipient.type == Recipient.STREAM:
display_type = "stream"
elif self.recipient.type in (Recipient.HUDDLE, Recipient.PERSONAL):
display_type = "private"
if len(display_recipient) == 1:
# add the sender in if this isn't a message between
# someone and his self, preserving ordering
recip = {'email': self.sender.user.email,
'full_name': self.sender.full_name,
'short_name': self.sender.short_name};
if recip['email'] < display_recipient[0]['email']:
display_recipient = [recip, display_recipient[0]]
elif recip['email'] > display_recipient[0]['email']:
display_recipient = [display_recipient[0], recip]
else:
display_type = self.recipient.type_name()
obj = dict(
id = self.id,
sender_email = self.sender.user.email,
sender_full_name = self.sender.full_name,
sender_short_name = self.sender.short_name,
type = self.recipient.type_name(),
display_recipient = get_display_recipient(self.recipient),
type = display_type,
display_recipient = display_recipient,
recipient_id = self.recipient.id,
subject = self.subject,
timestamp = calendar.timegm(self.pub_date.timetuple()),
@ -456,7 +454,7 @@ class Message(models.Model):
sender_short_name = self.sender.short_name,
sending_client = self.sending_client.name,
type = self.recipient.type_name(),
recipient = get_log_recipient(self.recipient),
recipient = get_display_recipient(self.recipient),
subject = self.subject,
content = self.content,
timestamp = calendar.timegm(self.pub_date.timetuple()))

View File

@ -12,9 +12,9 @@ var directional_hotkeys = {
};
var narrow_hotkeys = {
115: narrow.by_recipient, // 's'
83: narrow.by_subject, // 'S'
118: narrow.all_huddles // 'v'
115: narrow.by_recipient, // 's'
83: narrow.by_subject, // 'S'
118: narrow.all_private_messages // 'v'
};
// Process a keydown or keypress event.
@ -105,7 +105,7 @@ function process_hotkey(e) {
case 99: // 'c': compose
compose.start('stream');
return true;
case 67: // 'C': compose huddle
case 67: // 'C': compose private message
compose.start('private');
return true;
case 13: // Enter or

View File

@ -119,11 +119,11 @@ exports.target = function (id) {
target_id = id;
};
exports.all_huddles = function () {
var new_narrow = {type: "all_huddles"};
exports.all_private_messages = function () {
var new_narrow = {type: "all_private_messages"};
var bar = {icon: 'user', description: 'You and anyone else'};
do_narrow(new_narrow, bar, false, function (other) {
return other.type === "personal" || other.type === "huddle";
return other.type === "private";
});
};
@ -161,15 +161,12 @@ exports.by_stream_name = function (name) {
};
exports.by_private_message_partner = function (their_name, their_email) {
var new_narrow = {type: "huddle", one_on_one_email: their_email};
var new_narrow = {type: "private", one_on_one_email: their_email};
var bar = {icon: 'user', description: "You and " + their_name};
var my_email = email;
do_narrow(new_narrow, bar, false, function (other) {
return (other.type === 'personal') &&
(((other.display_recipient.email === their_email)
&& (other.sender_email === my_email)) ||
((other.display_recipient.email === my_email)
&& (other.sender_email === their_email)));
return (other.type === 'private' &&
get_private_message_recipient(other, 'email') === their_email);
});
};
@ -177,26 +174,14 @@ exports.by_private_message_partner = function (their_name, their_email) {
exports.by_recipient = function () {
var message = message_dict[target_id];
var bar;
var new_narrow;
switch (message.type) {
case 'personal':
// Narrow to personals with a specific user
var new_narrow = {type: "huddle", one_on_one_email: message.reply_to};
case 'private':
new_narrow = {type: "private", recipient_id: message.recipient_id};
bar = {icon: 'user', description: "You and " + message.display_reply_to};
do_narrow(new_narrow, bar, false, function (other) {
return (other.type === 'personal') &&
(((other.display_recipient.email === message.display_recipient.email)
&& (other.sender_email === message.sender_email)) ||
((other.display_recipient.email === message.sender_email)
&& (other.sender_email === message.display_recipient.email)));
});
break;
case 'huddle':
new_narrow = {type: "huddle", recipient_id: message.recipient_id};
bar = {icon: 'user', description: "You and " + message.display_reply_to};
do_narrow(new_narrow, bar, false, function (other) {
return (other.type === "personal" || other.type === "huddle")
&& other.reply_to === message.reply_to;
return (other.type === "private" &&
other.reply_to === message.reply_to);
});
break;

View File

@ -77,7 +77,7 @@ function process_desktop_notification(message) {
notification_object.cancel();
}
if (message.type === "huddle") {
if (message.type === "private" && message.display_recipient.length > 2) {
// If the message has too many recipients to list them all...
if (content.length + title.length + other_recipients.length > 230) {
// Then count how many people are in the conversation and summarize
@ -117,7 +117,7 @@ exports.received_messages = function (messages) {
if (desktop_notifications_enabled &&
browser_desktop_notifications_on() &&
(message.type === "personal" || message.type === "huddle")) {
message.type === "private") {
process_desktop_notification(message);
}
}

View File

@ -139,7 +139,7 @@ function replace_floating_recipient_bar(desired_label) {
if (desired_label !== old_label) {
if (desired_label.children(".message_header_stream").length !== 0) {
new_label = $("#current_label_stream");
other_label = $("#current_label_huddle");
other_label = $("#current_label_private_message");
header = desired_label.children(".message_header_stream.right_part");
$("#current_label_stream td:first").css(
@ -147,9 +147,9 @@ function replace_floating_recipient_bar(desired_label) {
desired_label.children(".message_header_stream.right_part")
.css("background-color"));
} else {
new_label = $("#current_label_huddle");
new_label = $("#current_label_private_message");
other_label = $("#current_label_stream");
header = desired_label.children(".message_header_huddle.right_part");
header = desired_label.children(".message_header_private_message.right_part");
}
new_label.find("td:last").replaceWith(header.clone());
other_label.css('display', 'none');
@ -228,7 +228,7 @@ function update_floating_recipient_bar() {
// If we're narrowed to a huddle or a subject, the floating
// recipient bar would be identical to the narrowing header, so
// don't display it.
if (narrow.narrowing_type() === "huddle" || narrow.narrowing_type() === "subject") {
if (narrow.narrowing_type() === "private" || narrow.narrowing_type() === "subject") {
hide_floating_recipient_bar();
return;
}

View File

@ -79,14 +79,14 @@ function scroll_to_selected() {
recenter_view(selected_message);
}
function get_huddle_recipient(message, attr) {
function get_private_message_recipient(message, attr) {
var recipient, i;
var other_recipients = $.grep(message.display_recipient,
function (element, index) {
return element.email !== email;
});
if (other_recipients.length === 0) {
// huddle with oneself
// private message with oneself
return message.display_recipient[0][attr];
}
@ -109,16 +109,13 @@ function respond_to_message(reply_type) {
}
var pm_recipient = message.reply_to;
if (reply_type === "personal" && message.type === "huddle") {
// reply_to for huddle messages is the whole huddle, so for
// personals replies we need to set the the huddle recipient
// to just the sender
if (reply_type === "personal" && message.type === "private") {
// reply_to for private messages is everyone involved, so for
// personals replies we need to set the the private message
// recipient to just the sender
pm_recipient = message.sender_email;
}
if (reply_type === 'personal'
|| message.type === 'personal'
|| message.type === 'huddle')
{
if (reply_type === 'personal' || message.type === 'private') {
msg_type = 'private';
} else {
msg_type = message.type;
@ -216,9 +213,7 @@ function same_recipient(a, b) {
return false;
switch (a.type) {
case 'huddle':
return a.recipient_id === b.recipient_id;
case 'personal':
case 'private':
return a.reply_to === b.reply_to;
case 'stream':
return same_stream_and_subject(a, b);
@ -448,10 +443,10 @@ function add_message_metadata(message, dummy) {
'email': message.sender_email}];
break;
case 'huddle':
message.is_huddle = true;
message.reply_to = get_huddle_recipient(message, 'email');
message.display_reply_to = get_huddle_recipient(message, 'full_name');
case 'private':
message.is_private = true;
message.reply_to = get_private_message_recipient(message, 'email');
message.display_reply_to = get_private_message_recipient(message, 'full_name');
involved_people = message.display_recipient;
@ -461,25 +456,6 @@ function add_message_metadata(message, dummy) {
typeahead_helper.update_all_recipients(involved_people);
}
break;
case 'personal':
message.is_personal = true;
involved_people = [message.display_recipient,
{'email': message.sender_email,
'full_name': message.sender_full_name}];
if (message.sender_email === email) { // that is, we sent the original message
message.reply_to = message.display_recipient.email;
message.display_reply_to = message.display_recipient.full_name;
typeahead_helper.update_your_recipients(involved_people);
} else {
message.reply_to = message.sender_email;
message.display_reply_to = message.sender_full_name;
typeahead_helper.update_all_recipients(involved_people);
}
break;
}
// Add new people involved in this message to the people list

View File

@ -160,7 +160,7 @@ td.pointer {
border: 1px solid grey;
}
.message_header_huddle {
.message_header_private_message {
color: white;
background-color: #444;
border: 1px solid #444;
@ -204,7 +204,7 @@ td.pointer {
}
/* Brighten hover because of the dark background */
.recipient_row .message_header_huddle:hover {
.recipient_row .message_header_private_message:hover {
color: #3BF;
}
@ -497,7 +497,7 @@ table.floating_recipient {
padding-right: 40px;
}
#stream_or_huddle {
#stream_or_private_message {
margin: 3px;
padding: 5px;
width: 90%;

View File

@ -268,7 +268,7 @@ def get_old_messages_backend(request, anchor = POST(converter=to_non_negative_in
query = query.filter(Q(sender__user__email=narrow['one_on_one_email']) & Q(recipient=recipient))
else:
query = query.filter(Q(sender__user__email=narrow['one_on_one_email']) | Q(recipient=recipient))
elif 'type' in narrow and (narrow['type'] == "huddle" or narrow['type'] == "all_huddles"):
elif 'type' in narrow and (narrow['type'] == "private" or narrow['type'] == "all_private_messages"):
query = query.filter(Q(recipient__type=Recipient.PERSONAL) | Q(recipient__type=Recipient.HUDDLE))
if 'subject' in narrow: