frontend: Add ability to search by "group-pm-with" search operator.

This allows user to view all group private conversation messages
with a specific user. That is, it views all the the group private
messages from groups which include the given user.

Add search suggestion for group-pm-with. Add operator name
and description in "Search operators" tab.

Add change in tab name to "Group Messages" when using this operator.
Add frontend_tests for group-pm-with search operator.

Fixes: #3882.
This commit is contained in:
Abhijeet Kaur 2017-06-04 05:21:53 +05:30 committed by Cory Lynch
parent 4bd8638193
commit 2bf3324395
9 changed files with 73 additions and 5 deletions

View File

@ -122,6 +122,7 @@ topic_data.reset();
"is:private is:alerted",
"is:private pm-with:alice@zulip.com",
"is:private sender:alice@zulip.com",
"is:private group-pm-with:alice@zulip.com",
"is:private",
];
assert.deepEqual(suggestions.strings, expected);
@ -224,6 +225,7 @@ topic_data.reset();
"is:starred has:link is:private is:alerted",
"is:starred has:link is:private pm-with:alice@zulip.com",
"is:starred has:link is:private sender:alice@zulip.com",
"is:starred has:link is:private group-pm-with:alice@zulip.com",
"is:starred has:link is:private",
"is:starred has:link",
"is:starred",
@ -759,6 +761,8 @@ init();
"pm-with:ted@zulip.com",
"sender:bob@zulip.com",
"sender:ted@zulip.com",
"group-pm-with:bob@zulip.com",
"group-pm-with:ted@zulip.com",
];
assert.deepEqual(suggestions.strings, expected);
@ -776,6 +780,7 @@ init();
"Ted",
"pm-with:ted@zulip.com",
"sender:ted@zulip.com",
"group-pm-with:ted@zulip.com",
];
assert.deepEqual(suggestions.strings, expected);

View File

@ -112,6 +112,19 @@ function message_matches_search_term(message, operator, operand) {
case 'sender':
return people.id_matches_email_operand(message.sender_id, operand);
case 'group-pm-with':
var operand_id = people.get_user_id(operand);
if (!operand_id) {
return false;
}
var user_ids = people.group_pm_with_user_ids(message);
if (!user_ids) {
return false;
}
return (user_ids.includes(operand_id));
// We should also check if the current user is in the recipient list (user_ids) of the
// message, but it is implicit by the fact that the current user has access to the message.
case 'pm-with':
// TODO: use user_ids, not emails here
if (message.type !== 'private') {
@ -121,7 +134,7 @@ function message_matches_search_term(message, operator, operand) {
if (!operand_ids) {
return false;
}
var user_ids = people.pm_with_user_ids(message);
user_ids = people.pm_with_user_ids(message);
if (!user_ids) {
return false;
}
@ -182,6 +195,9 @@ Filter.canonicalize_term = function (opts) {
operand = people.my_current_email();
}
break;
case 'group-pm-with':
operand = operand.toString().toLowerCase();
break;
case 'search':
// The mac app automatically substitutes regular quotes with curly
// quotes when typing in the search bar. Curly quotes don't trigger our
@ -218,7 +234,7 @@ function encodeOperand(operand) {
function decodeOperand(encoded, operator) {
encoded = encoded.replace(/"/g, '');
if (operator !== 'pm-with' && operator !== 'sender' && operator !== 'from') {
if (_.contains(['group-pm-with','pm-with','sender','from'],operator) === false) {
encoded = encoded.replace(/\+/g, ' ');
}
return util.robust_uri_decode(encoded).trim();
@ -383,6 +399,7 @@ Filter.prototype = {
update_email: function (user_id, new_email) {
_.each(this._operators, function (term) {
switch (term.operator) {
case 'group-pm-with':
case 'pm-with':
case 'sender':
case 'from':
@ -458,6 +475,9 @@ Filter.operator_to_prefix = function (operator, negated) {
// Note: We hack around using this in "describe" below.
case 'is':
return verb + 'messages that are';
case 'group-pm-with':
return verb + 'group personal messages with';
}
return '';
};

View File

@ -12,7 +12,7 @@ exports.encodeHashComponent = function (str) {
};
exports.encode_operand = function (operator, operand) {
if ((operator === 'pm-with') || (operator === 'sender')) {
if ((operator === 'group-pm-with') || (operator === 'pm-with') || (operator === 'sender')) {
var slug = people.emails_to_slug(operand);
if (slug) {
return slug;
@ -27,7 +27,7 @@ exports.decodeHashComponent = function (str) {
};
exports.decode_operand = function (operator, operand) {
if ((operator === 'pm-with') || (operator === 'sender')) {
if ((operator === 'group-pm-with') || (operator === 'pm-with') || (operator === 'sender')) {
var emails = people.slug_to_emails(operand);
if (emails) {
return emails;

View File

@ -69,8 +69,10 @@ exports.activate = function (raw_operators, opts) {
}
} else if (filter.has_operator("is")) {
exports.narrow_title = filter.operands("is")[0];
} else if (filter.has_operator("pm-with")) {
} else if (filter.has_operator("pm-with") ) {
exports.narrow_title = "private";
} else if (filter.has_operator("group-pm-with") ) {
exports.narrow_title = "private group";
}
notifications.redraw_title();

View File

@ -338,6 +338,30 @@ exports.pm_with_user_ids = function (message) {
return sorted_other_user_ids(user_ids);
};
exports.group_pm_with_user_ids = function (message) {
if (message.type !== 'private') {
return;
}
if (message.display_recipient.length === 0) {
blueslip.error('Empty recipient list in message');
return;
}
var user_ids = _.map(message.display_recipient, function (elem) {
return elem.user_id || elem.id;
});
var is_user_present = _.some(user_ids, function (user_id) {
return people.is_my_user_id(user_id);
});
if (is_user_present) {
user_ids.sort();
if (user_ids.length > 2) {
return user_ids;
}
}
return false;
};
exports.pm_with_url = function (message) {
var user_ids = exports.pm_with_user_ids(message);

View File

@ -572,6 +572,9 @@ exports.get_suggestions = function (query) {
suggestions = get_person_suggestions(persons, last, base_operators, 'from');
attach_suggestions(result, base, suggestions);
suggestions = get_person_suggestions(persons, last, base_operators, 'group-pm-with');
attach_suggestions(result, base, suggestions);
suggestions = get_group_suggestions(persons, last, base_operators);
attach_suggestions(result, base, suggestions);

View File

@ -73,6 +73,12 @@ function make_tab_data() {
tabs.push(make_tab(names.join(', '), hashed));
}
} else if (filter.has_operator("group-pm-with")) {
tabs.push(make_tab("Group Private", '#narrow/group-pm-with',
undefined, 'private_message '));
} else if (filter.has_operand("is", "starred")) {
tabs.push(make_tab("Starred", hashed));
} else if (filter.has_operator("near")) {

View File

@ -55,6 +55,10 @@ Listed below are all Zulip search operators.
* `pm-with:foo@bar.com` - This operator narrows the view to show only
private messages sent from the user with the email address
`foo@bar.com`.
* `group-pm-with:foo@bar.com` - This operator narrows the view to show all
private messages from groups that contain both you and the user with
email address `foo@bar.com`. This operator does not show 1:1 private messages
between you and the user with email address `foo@bar.com`
* `sender:foo@bar.com` - This operator narrows the view to show all
messages sent by the user with the email address `foo@bar.com`.
* `sender:me` - This operator narrows the view to show all messages sent by you.

View File

@ -20,6 +20,10 @@
<td class="operator">pm-with:<span class="operator_value">email</span></td>
<td class="definition">{{ _('Narrow to private messages with') }} <span class="operator_value">email</span></td>
</tr>
<tr>
<td class="operator">group-pm-with:<span class="operator_value">email</span></td>
<td class="definition">{{ _('Narrow to group private messages with') }} <span class="operator_value">email</span></td>
</tr>
<tr>
<td class="operator">sender:<span class="operator_value">email</span></td>
<td class="definition">{{ _('Narrow to messages sent by') }} <span class="operator_value">email</span></td>