mirror of
https://github.com/zulip/zulip.git
synced 2025-11-17 04:12:02 +00:00
Support negated searches on staging.
Behind a feature flag you can now do searches like this:
-pm-with:othello@example.com is:private
The "-" in front of "pm-with" tells us to exclude messages
with Othello from our search. We support "-" in front of
all operators, although the behavior for "-search:" and
and "-near:" doesn't really change in this commit.
Note that the filtering out of "negated" predicates only
happens on the client side in this commit. On the server
side we ignore negated predicates and send back a superset
of the results.
(imported from commit 6cdeaf32f2d493fbbb838630f0da3da880b1ca18)
This commit is contained in:
@@ -47,6 +47,7 @@ exports.local_echo = page_params.staging || is_customer4 || _.contains(['custome
|
|||||||
exports.cleanup_before_reload = page_params.staging;
|
exports.cleanup_before_reload = page_params.staging;
|
||||||
|
|
||||||
exports.show_digest_email_setting = page_params.staging;
|
exports.show_digest_email_setting = page_params.staging;
|
||||||
|
exports.negated_search = page_params.staging;
|
||||||
|
|
||||||
exports.fade_at_stream_granularity = page_params.staging;
|
exports.fade_at_stream_granularity = page_params.staging;
|
||||||
|
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ function decodeOperand(encoded, operator) {
|
|||||||
Filter.parse = function (str) {
|
Filter.parse = function (str) {
|
||||||
var operators = [];
|
var operators = [];
|
||||||
var search_term = [];
|
var search_term = [];
|
||||||
|
var negated;
|
||||||
var operator;
|
var operator;
|
||||||
var operand;
|
var operand;
|
||||||
var term;
|
var term;
|
||||||
@@ -219,9 +220,16 @@ Filter.parse = function (str) {
|
|||||||
} else {
|
} else {
|
||||||
// Looks like an operator.
|
// Looks like an operator.
|
||||||
// FIXME: Should we skip unknown operator names here?
|
// FIXME: Should we skip unknown operator names here?
|
||||||
|
negated = false;
|
||||||
operator = parts.shift();
|
operator = parts.shift();
|
||||||
|
if (feature_flags.negated_search) {
|
||||||
|
if (operator[0] === '-') {
|
||||||
|
negated = true;
|
||||||
|
operator = operator.slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
operand = decodeOperand(parts.join(':'), operator);
|
operand = decodeOperand(parts.join(':'), operator);
|
||||||
term = {operator: operator, operand: operand};
|
term = {negated: negated, operator: operator, operand: operand};
|
||||||
operators.push(term);
|
operators.push(term);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -252,7 +260,8 @@ Filter.unparse = function (operators) {
|
|||||||
// a colon are glued together to form a search term.
|
// a colon are glued together to form a search term.
|
||||||
return elem.operand;
|
return elem.operand;
|
||||||
} else {
|
} else {
|
||||||
return elem.operator + ':' + encodeOperand(elem.operand.toString());
|
var sign = elem.negated ? '-' : '';
|
||||||
|
return sign + elem.operator + ':' + encodeOperand(elem.operand.toString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return parts.join(' ');
|
return parts.join(' ');
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ exports.operators_to_hash = function (operators) {
|
|||||||
operand = elem[1];
|
operand = elem[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
hash += '/' + hashchange.encodeHashComponent(operator)
|
var sign = elem.negated ? '-' : '';
|
||||||
|
hash += '/' + sign + hashchange.encodeHashComponent(operator)
|
||||||
+ '/' + hashchange.encodeHashComponent(operand);
|
+ '/' + hashchange.encodeHashComponent(operand);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -95,7 +96,12 @@ function parse_narrow(hash) {
|
|||||||
try {
|
try {
|
||||||
var operator = decodeHashComponent(hash[i]);
|
var operator = decodeHashComponent(hash[i]);
|
||||||
var operand = decodeHashComponent(hash[i+1] || '');
|
var operand = decodeHashComponent(hash[i+1] || '');
|
||||||
operators.push({operator: operator, operand: operand});
|
var negated = false;
|
||||||
|
if (operator[0] === '-') {
|
||||||
|
negated = true;
|
||||||
|
operator = operator.slice(1);
|
||||||
|
}
|
||||||
|
operators.push({negated: negated, operator: operator, operand: operand});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ set_global('page_params', {
|
|||||||
domain: 'zulip.com'
|
domain: 'zulip.com'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
set_global('feature_flags', {});
|
||||||
|
|
||||||
var Filter = require('js/filter.js');
|
var Filter = require('js/filter.js');
|
||||||
var _ = global._;
|
var _ = global._;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ add_dependencies({
|
|||||||
|
|
||||||
var search = require('js/search_suggestion.js');
|
var search = require('js/search_suggestion.js');
|
||||||
|
|
||||||
|
set_global('feature_flags', {});
|
||||||
set_global('page_params', {
|
set_global('page_params', {
|
||||||
email: 'bob@zulip.com'
|
email: 'bob@zulip.com'
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ class NarrowBuilder(object):
|
|||||||
# Python __magic__ stuff.
|
# Python __magic__ stuff.
|
||||||
operator = term['operator']
|
operator = term['operator']
|
||||||
operand = term['operand']
|
operand = term['operand']
|
||||||
|
|
||||||
|
if term.get('negated', False):
|
||||||
|
return query
|
||||||
|
|
||||||
method_name = 'by_' + operator.replace('-', '_')
|
method_name = 'by_' + operator.replace('-', '_')
|
||||||
method = getattr(self, method_name, None)
|
method = getattr(self, method_name, None)
|
||||||
if method is None:
|
if method is None:
|
||||||
@@ -312,7 +316,11 @@ def narrow_parameter(json):
|
|||||||
raise JsonableError(error)
|
raise JsonableError(error)
|
||||||
|
|
||||||
# whitelist the fields we care about for now
|
# whitelist the fields we care about for now
|
||||||
return dict(operator=elem['operator'], operand=elem['operand'])
|
return dict(
|
||||||
|
operator=elem['operator'],
|
||||||
|
operand=elem['operand'],
|
||||||
|
negated=elem.get('negated', False),
|
||||||
|
)
|
||||||
|
|
||||||
raise ValueError("element is not a dictionary")
|
raise ValueError("element is not a dictionary")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user