mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 08:26:11 +00:00
filter: Use "channel" operator for the Filter class.
Update the Filter class to use "channel" as the canoncial operator for streams, but keep using "stream" for user-facing text and URLs. When searching, "channel" does not create any suggestions until a colon is added and then it shows suggestions with "stream". And when a search string with channel as an operator is entered, then it is replaced by "stream" as well. Part of stream to channel rename project.
This commit is contained in:
committed by
Tim Abbott
parent
e3a521f4ba
commit
1e7c5b38f8
@@ -164,9 +164,9 @@ export function initialize(): void {
|
|||||||
if (narrow_filter === undefined) {
|
if (narrow_filter === undefined) {
|
||||||
display_current_view = $t({defaultMessage: "Currently viewing all messages."});
|
display_current_view = $t({defaultMessage: "Currently viewing all messages."});
|
||||||
} else if (
|
} else if (
|
||||||
_.isEqual(narrow_filter.sorted_term_types(), ["stream"]) &&
|
_.isEqual(narrow_filter.sorted_term_types(), ["channel"]) &&
|
||||||
compose_state.get_message_type() === "stream" &&
|
compose_state.get_message_type() === "stream" &&
|
||||||
narrow_filter.operands("stream")[0] === compose_state.stream_name()
|
narrow_filter.operands("channel")[0] === compose_state.stream_name()
|
||||||
) {
|
) {
|
||||||
display_current_view = $t({
|
display_current_view = $t({
|
||||||
defaultMessage: "Currently viewing the entire stream.",
|
defaultMessage: "Currently viewing the entire stream.",
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ type Part =
|
|||||||
operand: string;
|
operand: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: When "stream" is renamed to "channel", this placeholder
|
||||||
|
// should be removed, or replaced with helper functions similar
|
||||||
|
// to util.is_topic_synonym.
|
||||||
|
const CHANNEL_SYNONYM = "stream";
|
||||||
|
|
||||||
function zephyr_stream_name_match(message: Message & {type: "stream"}, operand: string): boolean {
|
function zephyr_stream_name_match(message: Message & {type: "stream"}, operand: string): boolean {
|
||||||
// Zephyr users expect narrowing to "social" to also show messages to /^(un)*social(.d)*$/
|
// Zephyr users expect narrowing to "social" to also show messages to /^(un)*social(.d)*$/
|
||||||
// (unsocial, ununsocial, social.d, etc)
|
// (unsocial, ununsocial, social.d, etc)
|
||||||
@@ -172,7 +177,7 @@ function message_matches_search_term(message: Message, operator: string, operand
|
|||||||
case "id":
|
case "id":
|
||||||
return message.id.toString() === operand;
|
return message.id.toString() === operand;
|
||||||
|
|
||||||
case "stream": {
|
case "channel": {
|
||||||
if (message.type !== "stream") {
|
if (message.type !== "stream") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -244,8 +249,8 @@ export class Filter {
|
|||||||
|
|
||||||
constructor(terms: NarrowTerm[]) {
|
constructor(terms: NarrowTerm[]) {
|
||||||
this._terms = this.fix_terms(terms);
|
this._terms = this.fix_terms(terms);
|
||||||
if (this.has_operator("stream")) {
|
if (this.has_operator("channel")) {
|
||||||
this._sub = stream_data.get_sub_by_name(this.operands("stream")[0]);
|
this._sub = stream_data.get_sub_by_name(this.operands("channel")[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +274,10 @@ export class Filter {
|
|||||||
if (util.is_topic_synonym(operator)) {
|
if (util.is_topic_synonym(operator)) {
|
||||||
return "topic";
|
return "topic";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (operator === CHANNEL_SYNONYM) {
|
||||||
|
return "channel";
|
||||||
|
}
|
||||||
return operator;
|
return operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +298,7 @@ export class Filter {
|
|||||||
operand = operand.replace(/s$/, "");
|
operand = operand.replace(/s$/, "");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "stream":
|
case "channel":
|
||||||
operand = stream_data.get_name(operand);
|
operand = stream_data.get_name(operand);
|
||||||
break;
|
break;
|
||||||
case "topic":
|
case "topic":
|
||||||
@@ -397,6 +406,9 @@ export class Filter {
|
|||||||
negated = true;
|
negated = true;
|
||||||
operator = operator.slice(1);
|
operator = operator.slice(1);
|
||||||
}
|
}
|
||||||
|
if (operator === CHANNEL_SYNONYM) {
|
||||||
|
operator = "channel";
|
||||||
|
}
|
||||||
operand = Filter.decodeOperand(parts.join(":"), operator);
|
operand = Filter.decodeOperand(parts.join(":"), operator);
|
||||||
|
|
||||||
// We use Filter.operator_to_prefix() to check if the
|
// We use Filter.operator_to_prefix() to check if the
|
||||||
@@ -442,7 +454,8 @@ export class Filter {
|
|||||||
if (term.operator === "") {
|
if (term.operator === "") {
|
||||||
return term.operand;
|
return term.operand;
|
||||||
}
|
}
|
||||||
return sign + term.operator + ":" + Filter.encodeOperand(term.operand.toString());
|
const operator = util.canonicalize_stream_synonym(term.operator);
|
||||||
|
return sign + operator + ":" + Filter.encodeOperand(term.operand.toString());
|
||||||
});
|
});
|
||||||
return term_strings.join(" ");
|
return term_strings.join(" ");
|
||||||
}
|
}
|
||||||
@@ -467,7 +480,7 @@ export class Filter {
|
|||||||
const levels = [
|
const levels = [
|
||||||
"in",
|
"in",
|
||||||
"streams-public",
|
"streams-public",
|
||||||
"stream",
|
"channel",
|
||||||
"topic",
|
"topic",
|
||||||
"dm",
|
"dm",
|
||||||
"dm-including",
|
"dm-including",
|
||||||
@@ -515,8 +528,8 @@ export class Filter {
|
|||||||
const verb = negated ? "exclude " : "";
|
const verb = negated ? "exclude " : "";
|
||||||
|
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case "stream":
|
case "channel":
|
||||||
return verb + "stream";
|
return verb + CHANNEL_SYNONYM;
|
||||||
case "streams":
|
case "streams":
|
||||||
return verb + "streams";
|
return verb + "streams";
|
||||||
case "near":
|
case "near":
|
||||||
@@ -562,9 +575,9 @@ export class Filter {
|
|||||||
|
|
||||||
if (terms.length >= 2) {
|
if (terms.length >= 2) {
|
||||||
const is = (term: NarrowTerm, expected: string): boolean =>
|
const is = (term: NarrowTerm, expected: string): boolean =>
|
||||||
term.operator === expected && !term.negated;
|
Filter.canonicalize_operator(term.operator) === expected && !term.negated;
|
||||||
|
|
||||||
if (is(terms[0], "stream") && is(terms[1], "topic")) {
|
if (is(terms[0], "channel") && is(terms[1], "topic")) {
|
||||||
const stream = terms[0].operand;
|
const stream = terms[0].operand;
|
||||||
const topic = terms[1].operand;
|
const topic = terms[1].operand;
|
||||||
parts.push({
|
parts.push({
|
||||||
@@ -659,7 +672,7 @@ export class Filter {
|
|||||||
(term) =>
|
(term) =>
|
||||||
!(
|
!(
|
||||||
page_params.narrow_stream !== undefined &&
|
page_params.narrow_stream !== undefined &&
|
||||||
term.operator === "stream" &&
|
term.operator === "channel" &&
|
||||||
term.operand.toLowerCase() === page_params.narrow_stream.toLowerCase()
|
term.operand.toLowerCase() === page_params.narrow_stream.toLowerCase()
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -717,8 +730,8 @@ export class Filter {
|
|||||||
// message sharing its recipient (stream/topic or direct
|
// message sharing its recipient (stream/topic or direct
|
||||||
// message recipient) must also be present in the view.
|
// message recipient) must also be present in the view.
|
||||||
const valid_term_types = new Set([
|
const valid_term_types = new Set([
|
||||||
"stream",
|
"channel",
|
||||||
"not-stream",
|
"not-channel",
|
||||||
"topic",
|
"topic",
|
||||||
"not-topic",
|
"not-topic",
|
||||||
"dm",
|
"dm",
|
||||||
@@ -766,10 +779,10 @@ export class Filter {
|
|||||||
const term_types = this.sorted_term_types();
|
const term_types = this.sorted_term_types();
|
||||||
|
|
||||||
// "topic" alone cannot guarantee all messages of a conversation because
|
// "topic" alone cannot guarantee all messages of a conversation because
|
||||||
// it is limited by the user's message history. Therefore, we check "stream"
|
// it is limited by the user's message history. Therefore, we check "channel"
|
||||||
// and "topic" together to ensure that the current filter will return all the
|
// and "topic" together to ensure that the current filter will return all the
|
||||||
// messages of a conversation.
|
// messages of a conversation.
|
||||||
if (_.isEqual(term_types, ["stream", "topic"])) {
|
if (_.isEqual(term_types, ["channel", "topic"])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,7 +790,7 @@ export class Filter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.isEqual(term_types, ["stream"])) {
|
if (_.isEqual(term_types, ["channel"])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,14 +855,16 @@ export class Filter {
|
|||||||
const term_types = this.sorted_term_types();
|
const term_types = this.sorted_term_types();
|
||||||
|
|
||||||
// this comes first because it has 3 term_types but is not a "complex filter"
|
// this comes first because it has 3 term_types but is not a "complex filter"
|
||||||
if (_.isEqual(term_types, ["stream", "topic", "search"])) {
|
if (_.isEqual(term_types, ["channel", "topic", "search"])) {
|
||||||
// if stream does not exist, redirect to All
|
// if stream does not exist, redirect to All
|
||||||
if (!this._sub) {
|
if (!this._sub) {
|
||||||
return "#";
|
return "#";
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
"/#narrow/stream/" +
|
"/#narrow/" +
|
||||||
stream_data.name_to_slug(this.operands("stream")[0]) +
|
CHANNEL_SYNONYM +
|
||||||
|
"/" +
|
||||||
|
stream_data.name_to_slug(this.operands("channel")[0]) +
|
||||||
"/topic/" +
|
"/topic/" +
|
||||||
this.operands("topic")[0]
|
this.operands("topic")[0]
|
||||||
);
|
);
|
||||||
@@ -862,13 +877,16 @@ export class Filter {
|
|||||||
|
|
||||||
if (term_types[1] === "search") {
|
if (term_types[1] === "search") {
|
||||||
switch (term_types[0]) {
|
switch (term_types[0]) {
|
||||||
case "stream":
|
case "channel":
|
||||||
// if stream does not exist, redirect to All
|
// if stream does not exist, redirect to All
|
||||||
if (!this._sub) {
|
if (!this._sub) {
|
||||||
return "#";
|
return "#";
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
"/#narrow/stream/" + stream_data.name_to_slug(this.operands("stream")[0])
|
"/#narrow/" +
|
||||||
|
CHANNEL_SYNONYM +
|
||||||
|
"/" +
|
||||||
|
stream_data.name_to_slug(this.operands("channel")[0])
|
||||||
);
|
);
|
||||||
case "is-dm":
|
case "is-dm":
|
||||||
return "/#narrow/is/dm";
|
return "/#narrow/is/dm";
|
||||||
@@ -902,7 +920,7 @@ export class Filter {
|
|||||||
case "in-all":
|
case "in-all":
|
||||||
icon = "home";
|
icon = "home";
|
||||||
break;
|
break;
|
||||||
case "stream":
|
case "channel":
|
||||||
if (!this._sub) {
|
if (!this._sub) {
|
||||||
icon = "question-circle-o";
|
icon = "question-circle-o";
|
||||||
break;
|
break;
|
||||||
@@ -946,12 +964,12 @@ export class Filter {
|
|||||||
// Nice explanatory titles for common views.
|
// Nice explanatory titles for common views.
|
||||||
const term_types = this.sorted_term_types();
|
const term_types = this.sorted_term_types();
|
||||||
if (
|
if (
|
||||||
(term_types.length === 3 && _.isEqual(term_types, ["stream", "topic", "near"])) ||
|
(term_types.length === 3 && _.isEqual(term_types, ["channel", "topic", "near"])) ||
|
||||||
(term_types.length === 2 && _.isEqual(term_types, ["stream", "topic"])) ||
|
(term_types.length === 2 && _.isEqual(term_types, ["channel", "topic"])) ||
|
||||||
(term_types.length === 1 && _.isEqual(term_types, ["stream"]))
|
(term_types.length === 1 && _.isEqual(term_types, ["channel"]))
|
||||||
) {
|
) {
|
||||||
if (!this._sub) {
|
if (!this._sub) {
|
||||||
const search_text = this.operands("stream")[0];
|
const search_text = this.operands("channel")[0];
|
||||||
return $t({defaultMessage: "Unknown stream #{search_text}"}, {search_text});
|
return $t({defaultMessage: "Unknown stream #{search_text}"}, {search_text});
|
||||||
}
|
}
|
||||||
return this._sub.name;
|
return this._sub.name;
|
||||||
@@ -1039,7 +1057,7 @@ export class Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
includes_full_stream_history(): boolean {
|
includes_full_stream_history(): boolean {
|
||||||
return this.has_operator("stream") || this.has_operator("streams");
|
return this.has_operator("channel") || this.has_operator("streams");
|
||||||
}
|
}
|
||||||
|
|
||||||
is_personal_filter(): boolean {
|
is_personal_filter(): boolean {
|
||||||
@@ -1112,7 +1130,7 @@ export class Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
has_topic(stream_name: string, topic: string): boolean {
|
has_topic(stream_name: string, topic: string): boolean {
|
||||||
return this.has_operand("stream", stream_name) && this.has_operand("topic", topic);
|
return this.has_operand("channel", stream_name) && this.has_operand("topic", topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted_term_types(): string[] {
|
sorted_term_types(): string[] {
|
||||||
@@ -1131,7 +1149,7 @@ export class Filter {
|
|||||||
|
|
||||||
can_bucket_by(...wanted_term_types: string[]): boolean {
|
can_bucket_by(...wanted_term_types: string[]): boolean {
|
||||||
// Examples call:
|
// Examples call:
|
||||||
// filter.can_bucket_by('stream', 'topic')
|
// filter.can_bucket_by('channel', 'topic')
|
||||||
//
|
//
|
||||||
// The use case of this function is that we want
|
// The use case of this function is that we want
|
||||||
// to know if a filter can start with a bucketing
|
// to know if a filter can start with a bucketing
|
||||||
@@ -1204,7 +1222,7 @@ export class Filter {
|
|||||||
|
|
||||||
is_conversation_view(): boolean {
|
is_conversation_view(): boolean {
|
||||||
const term_type = this.sorted_term_types();
|
const term_type = this.sorted_term_types();
|
||||||
if (_.isEqual(term_type, ["stream", "topic"]) || _.isEqual(term_type, ["dm"])) {
|
if (_.isEqual(term_type, ["channel", "topic"]) || _.isEqual(term_type, ["dm"])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1213,7 +1231,7 @@ export class Filter {
|
|||||||
excludes_muted_topics(): boolean {
|
excludes_muted_topics(): boolean {
|
||||||
return (
|
return (
|
||||||
// not narrowed to a topic
|
// not narrowed to a topic
|
||||||
!(this.has_operator("stream") && this.has_operator("topic")) &&
|
!(this.has_operator("channel") && this.has_operator("topic")) &&
|
||||||
// not narrowed to search
|
// not narrowed to search
|
||||||
!this.is_keyword_search() &&
|
!this.is_keyword_search() &&
|
||||||
// not narrowed to dms
|
// not narrowed to dms
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ export function is_create_new_stream_narrow(): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const allowed_web_public_narrows = [
|
export const allowed_web_public_narrows = [
|
||||||
|
"channel",
|
||||||
"streams",
|
"streams",
|
||||||
"stream",
|
"stream",
|
||||||
"topic",
|
"topic",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import * as sub_store from "./sub_store";
|
|||||||
import type {StreamSubscription} from "./sub_store";
|
import type {StreamSubscription} from "./sub_store";
|
||||||
import * as user_groups from "./user_groups";
|
import * as user_groups from "./user_groups";
|
||||||
import type {UserGroup} from "./user_groups";
|
import type {UserGroup} from "./user_groups";
|
||||||
|
import * as util from "./util";
|
||||||
|
|
||||||
export function build_reload_url(): string {
|
export function build_reload_url(): string {
|
||||||
let hash = window.location.hash;
|
let hash = window.location.hash;
|
||||||
@@ -93,7 +94,7 @@ export function search_terms_to_hash(terms?: NarrowTerm[]): string {
|
|||||||
|
|
||||||
for (const term of terms) {
|
for (const term of terms) {
|
||||||
// Support legacy tuples.
|
// Support legacy tuples.
|
||||||
const operator = term.operator;
|
const operator = util.canonicalize_stream_synonym(term.operator);
|
||||||
const operand = term.operand;
|
const operand = term.operand;
|
||||||
|
|
||||||
const sign = term.negated ? "-" : "";
|
const sign = term.negated ? "-" : "";
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ export class MessageListView {
|
|||||||
// we can infer that whenever the historical flag flips
|
// we can infer that whenever the historical flag flips
|
||||||
// between adjacent messages, the current user must have
|
// between adjacent messages, the current user must have
|
||||||
// (un)subscribed in between those messages.
|
// (un)subscribed in between those messages.
|
||||||
if (!this.list.data.filter.has_operator("stream")) {
|
if (!this.list.data.filter.has_operator("channel")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (last_msg_container === undefined) {
|
if (last_msg_container === undefined) {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
|
|||||||
title,
|
title,
|
||||||
is_spectator: page_params.is_spectator,
|
is_spectator: page_params.is_spectator,
|
||||||
});
|
});
|
||||||
if (filter.has_operator("stream") && !filter._sub) {
|
if (filter.has_operator("channel") && !filter._sub) {
|
||||||
return {
|
return {
|
||||||
...icon_data,
|
...icon_data,
|
||||||
sub_count: "0",
|
sub_count: "0",
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ export function activate(raw_terms, opts) {
|
|||||||
// message in case the message was moved after the link was
|
// message in case the message was moved after the link was
|
||||||
// created. This ensures near / id links work and will redirect
|
// created. This ensures near / id links work and will redirect
|
||||||
// correctly if the topic was moved (including being resolved).
|
// correctly if the topic was moved (including being resolved).
|
||||||
if (id_info.target_id && filter.has_operator("stream") && filter.has_operator("topic")) {
|
if (id_info.target_id && filter.has_operator("channel") && filter.has_operator("topic")) {
|
||||||
const target_message = message_store.get(id_info.target_id);
|
const target_message = message_store.get(id_info.target_id);
|
||||||
|
|
||||||
function adjusted_terms_if_moved(terms, message) {
|
function adjusted_terms_if_moved(terms, message) {
|
||||||
@@ -230,7 +230,7 @@ export function activate(raw_terms, opts) {
|
|||||||
for (const term of terms) {
|
for (const term of terms) {
|
||||||
const adjusted_term = {...term};
|
const adjusted_term = {...term};
|
||||||
if (
|
if (
|
||||||
term.operator === "stream" &&
|
term.operator === "channel" &&
|
||||||
!util.lower_same(term.operand, message.display_recipient)
|
!util.lower_same(term.operand, message.display_recipient)
|
||||||
) {
|
) {
|
||||||
adjusted_term.operand = message.display_recipient;
|
adjusted_term.operand = message.display_recipient;
|
||||||
@@ -262,7 +262,7 @@ export function activate(raw_terms, opts) {
|
|||||||
// location, then we should retarget this narrow operation
|
// location, then we should retarget this narrow operation
|
||||||
// to where the message is located now.
|
// to where the message is located now.
|
||||||
const narrow_topic = filter.operands("topic")[0];
|
const narrow_topic = filter.operands("topic")[0];
|
||||||
const narrow_stream_name = filter.operands("stream")[0];
|
const narrow_stream_name = filter.operands("channel")[0];
|
||||||
const narrow_stream_data = stream_data.get_sub(narrow_stream_name);
|
const narrow_stream_data = stream_data.get_sub(narrow_stream_name);
|
||||||
if (!narrow_stream_data) {
|
if (!narrow_stream_data) {
|
||||||
// The id of the target message is correct but the stream name is
|
// The id of the target message is correct but the stream name is
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ function retrieve_search_query_data(): SearchData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add in stream:foo and topic:bar if present
|
// Add in stream:foo and topic:bar if present
|
||||||
if (current_filter.has_operator("stream") || current_filter.has_operator("topic")) {
|
if (current_filter.has_operator("channel") || current_filter.has_operator("topic")) {
|
||||||
const stream = current_filter.operands("stream")[0];
|
const stream = current_filter.operands("channel")[0];
|
||||||
const topic = current_filter.operands("topic")[0];
|
const topic = current_filter.operands("topic")[0];
|
||||||
if (stream) {
|
if (stream) {
|
||||||
search_string_result.stream_query = stream;
|
search_string_result.stream_query = stream;
|
||||||
@@ -103,7 +103,7 @@ function pick_empty_narrow_banner(): NarrowBannerData {
|
|||||||
|
|
||||||
if (num_terms !== 1) {
|
if (num_terms !== 1) {
|
||||||
// For invalid-multi-operator narrows, we display an invalid narrow message
|
// For invalid-multi-operator narrows, we display an invalid narrow message
|
||||||
const streams = current_filter.operands("stream");
|
const streams = current_filter.operands("channel");
|
||||||
const topics = current_filter.operands("topic");
|
const topics = current_filter.operands("topic");
|
||||||
|
|
||||||
// No message can have multiple streams
|
// No message can have multiple streams
|
||||||
@@ -147,7 +147,7 @@ function pick_empty_narrow_banner(): NarrowBannerData {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
page_params.is_spectator &&
|
page_params.is_spectator &&
|
||||||
first_operator === "stream" &&
|
first_operator === "channel" &&
|
||||||
!stream_data.is_web_public_by_stream_name(first_operand)
|
!stream_data.is_web_public_by_stream_name(first_operand)
|
||||||
) {
|
) {
|
||||||
// For non web-public streams, show `login_to_access` modal.
|
// For non web-public streams, show `login_to_access` modal.
|
||||||
@@ -242,7 +242,7 @@ function pick_empty_narrow_banner(): NarrowBannerData {
|
|||||||
}
|
}
|
||||||
// fallthrough to default case if no match is found
|
// fallthrough to default case if no match is found
|
||||||
break;
|
break;
|
||||||
case "stream":
|
case "channel":
|
||||||
if (!stream_data.is_subscribed_by_name(first_operand)) {
|
if (!stream_data.is_subscribed_by_name(first_operand)) {
|
||||||
// You are narrowed to a stream which does not exist or is a private stream
|
// You are narrowed to a stream which does not exist or is a private stream
|
||||||
// in which you were never subscribed.
|
// in which you were never subscribed.
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export function set_compose_defaults(): {
|
|||||||
// Set the stream, topic, and/or direct message recipient
|
// Set the stream, topic, and/or direct message recipient
|
||||||
// if they are uniquely specified in the narrow view.
|
// if they are uniquely specified in the narrow view.
|
||||||
|
|
||||||
if (single.has("stream")) {
|
if (single.has("channel")) {
|
||||||
// The raw stream name from collect_single may be an arbitrary
|
// The raw stream name from collect_single may be an arbitrary
|
||||||
// unvalidated string from the URL fragment and thus not be valid.
|
// unvalidated string from the URL fragment and thus not be valid.
|
||||||
// So we look up the resolved stream and return that if appropriate.
|
// So we look up the resolved stream and return that if appropriate.
|
||||||
@@ -125,7 +125,7 @@ export function stream_name(current_filter: Filter | undefined = filter()): stri
|
|||||||
if (current_filter === undefined) {
|
if (current_filter === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const stream_operands = current_filter.operands("stream");
|
const stream_operands = current_filter.operands("channel");
|
||||||
if (stream_operands.length === 1) {
|
if (stream_operands.length === 1) {
|
||||||
const name = stream_operands[0];
|
const name = stream_operands[0];
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ export function stream_sub(
|
|||||||
if (current_filter === undefined) {
|
if (current_filter === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const stream_operands = current_filter.operands("stream");
|
const stream_operands = current_filter.operands("channel");
|
||||||
if (stream_operands.length !== 1) {
|
if (stream_operands.length !== 1) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -269,7 +269,7 @@ export function _possible_unread_message_ids(
|
|||||||
let topic_name;
|
let topic_name;
|
||||||
let current_filter_pm_string;
|
let current_filter_pm_string;
|
||||||
|
|
||||||
if (current_filter.can_bucket_by("stream", "topic")) {
|
if (current_filter.can_bucket_by("channel", "topic")) {
|
||||||
sub = stream_sub(current_filter);
|
sub = stream_sub(current_filter);
|
||||||
topic_name = topic(current_filter);
|
topic_name = topic(current_filter);
|
||||||
if (sub === undefined || topic_name === undefined) {
|
if (sub === undefined || topic_name === undefined) {
|
||||||
@@ -278,7 +278,7 @@ export function _possible_unread_message_ids(
|
|||||||
return unread.get_msg_ids_for_topic(sub.stream_id, topic_name);
|
return unread.get_msg_ids_for_topic(sub.stream_id, topic_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_filter.can_bucket_by("stream")) {
|
if (current_filter.can_bucket_by("channel")) {
|
||||||
sub = stream_sub(current_filter);
|
sub = stream_sub(current_filter);
|
||||||
if (sub === undefined) {
|
if (sub === undefined) {
|
||||||
return [];
|
return [];
|
||||||
@@ -342,7 +342,7 @@ export function narrowed_by_topic_reply(current_filter: Filter | undefined = fil
|
|||||||
const terms = current_filter.terms();
|
const terms = current_filter.terms();
|
||||||
return (
|
return (
|
||||||
terms.length === 2 &&
|
terms.length === 2 &&
|
||||||
current_filter.operands("stream").length === 1 &&
|
current_filter.operands("channel").length === 1 &&
|
||||||
current_filter.operands("topic").length === 1
|
current_filter.operands("topic").length === 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -359,14 +359,14 @@ export function narrowed_by_stream_reply(current_filter: Filter | undefined = fi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const terms = current_filter.terms();
|
const terms = current_filter.terms();
|
||||||
return terms.length === 1 && current_filter.operands("stream").length === 1;
|
return terms.length === 1 && current_filter.operands("channel").length === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function narrowed_to_topic(current_filter: Filter | undefined = filter()): boolean {
|
export function narrowed_to_topic(current_filter: Filter | undefined = filter()): boolean {
|
||||||
if (current_filter === undefined) {
|
if (current_filter === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return current_filter.has_operator("stream") && current_filter.has_operator("topic");
|
return current_filter.has_operator("channel") && current_filter.has_operator("topic");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function is_for_stream_id(stream_id: number, filter?: Filter): boolean {
|
export function is_for_stream_id(stream_id: number, filter?: Filter): boolean {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export function compute_narrow_title(filter?: Filter): string {
|
|||||||
return $t({defaultMessage: "Search results"});
|
return $t({defaultMessage: "Search results"});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.has_operator("stream")) {
|
if (filter.has_operator("channel")) {
|
||||||
if (!filter._sub) {
|
if (!filter._sub) {
|
||||||
// The stream is not set because it does not currently
|
// The stream is not set because it does not currently
|
||||||
// exist (possibly due to a stream name change), or it
|
// exist (possibly due to a stream name change), or it
|
||||||
|
|||||||
@@ -120,9 +120,9 @@ function compare_by_huddle(huddle_emails: string[]): (person1: User, person2: Us
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get_stream_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestion[] {
|
function get_stream_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestion[] {
|
||||||
const valid = ["stream", "search", ""];
|
const valid = ["channel", "search", ""];
|
||||||
const incompatible_patterns = [
|
const incompatible_patterns = [
|
||||||
{operator: "stream"},
|
{operator: "channel"},
|
||||||
{operator: "streams"},
|
{operator: "streams"},
|
||||||
{operator: "is", operand: "dm"},
|
{operator: "is", operand: "dm"},
|
||||||
{operator: "dm"},
|
{operator: "dm"},
|
||||||
@@ -148,7 +148,7 @@ function get_stream_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggesti
|
|||||||
const verb = last.negated ? "exclude " : "";
|
const verb = last.negated ? "exclude " : "";
|
||||||
const description_html = verb + prefix + " " + highlighted_stream;
|
const description_html = verb + prefix + " " + highlighted_stream;
|
||||||
const term = {
|
const term = {
|
||||||
operator: "stream",
|
operator: "channel",
|
||||||
operand: stream,
|
operand: stream,
|
||||||
negated: last.negated,
|
negated: last.negated,
|
||||||
};
|
};
|
||||||
@@ -162,7 +162,7 @@ function get_stream_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggesti
|
|||||||
function get_group_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestion[] {
|
function get_group_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestion[] {
|
||||||
// For users with "pm-with" in their muscle memory, still
|
// For users with "pm-with" in their muscle memory, still
|
||||||
// have group direct message suggestions with "dm:" operator.
|
// have group direct message suggestions with "dm:" operator.
|
||||||
if (!check_validity(last, terms, ["dm", "pm-with"], [{operator: "stream"}])) {
|
if (!check_validity(last, terms, ["dm", "pm-with"], [{operator: "channel"}])) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,14 +286,14 @@ function get_person_suggestions(
|
|||||||
|
|
||||||
switch (autocomplete_operator) {
|
switch (autocomplete_operator) {
|
||||||
case "dm-including":
|
case "dm-including":
|
||||||
incompatible_patterns = [{operator: "stream"}, {operator: "is", operand: "resolved"}];
|
incompatible_patterns = [{operator: "channel"}, {operator: "is", operand: "resolved"}];
|
||||||
break;
|
break;
|
||||||
case "dm":
|
case "dm":
|
||||||
case "pm-with":
|
case "pm-with":
|
||||||
incompatible_patterns = [
|
incompatible_patterns = [
|
||||||
{operator: "dm"},
|
{operator: "dm"},
|
||||||
{operator: "pm-with"},
|
{operator: "pm-with"},
|
||||||
{operator: "stream"},
|
{operator: "channel"},
|
||||||
{operator: "is", operand: "resolved"},
|
{operator: "is", operand: "resolved"},
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
@@ -397,7 +397,7 @@ function get_topic_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestio
|
|||||||
{operator: "dm-including"},
|
{operator: "dm-including"},
|
||||||
{operator: "topic"},
|
{operator: "topic"},
|
||||||
];
|
];
|
||||||
if (!check_validity(last, terms, ["stream", "topic", "search"], incompatible_patterns)) {
|
if (!check_validity(last, terms, ["channel", "topic", "search"], incompatible_patterns)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +425,7 @@ function get_topic_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestio
|
|||||||
// in terms of telling us whether they provided the operator,
|
// in terms of telling us whether they provided the operator,
|
||||||
// i.e. "foo" and "search:foo" both become [{operator: 'search', operand: 'foo'}].
|
// i.e. "foo" and "search:foo" both become [{operator: 'search', operand: 'foo'}].
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case "stream":
|
case "channel":
|
||||||
guess = "";
|
guess = "";
|
||||||
stream = operand;
|
stream = operand;
|
||||||
suggest_terms.push(last);
|
suggest_terms.push(last);
|
||||||
@@ -433,12 +433,12 @@ function get_topic_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestio
|
|||||||
case "topic":
|
case "topic":
|
||||||
case "search":
|
case "search":
|
||||||
guess = operand;
|
guess = operand;
|
||||||
if (filter.has_operator("stream")) {
|
if (filter.has_operator("channel")) {
|
||||||
stream = filter.operands("stream")[0];
|
stream = filter.operands("channel")[0];
|
||||||
} else {
|
} else {
|
||||||
stream = narrow_state.stream_name();
|
stream = narrow_state.stream_name();
|
||||||
if (stream) {
|
if (stream) {
|
||||||
suggest_terms.push({operator: "stream", operand: stream});
|
suggest_terms.push({operator: "channel", operand: stream});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -553,7 +553,7 @@ function get_streams_filter_suggestions(last: NarrowTerm, terms: NarrowTerm[]):
|
|||||||
description_html: "All public streams in organization",
|
description_html: "All public streams in organization",
|
||||||
incompatible_patterns: [
|
incompatible_patterns: [
|
||||||
{operator: "is", operand: "dm"},
|
{operator: "is", operand: "dm"},
|
||||||
{operator: "stream"},
|
{operator: "channel"},
|
||||||
{operator: "dm-including"},
|
{operator: "dm-including"},
|
||||||
{operator: "dm"},
|
{operator: "dm"},
|
||||||
{operator: "in"},
|
{operator: "in"},
|
||||||
@@ -571,7 +571,7 @@ function get_is_filter_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Sugge
|
|||||||
incompatible_patterns: [
|
incompatible_patterns: [
|
||||||
{operator: "is", operand: "dm"},
|
{operator: "is", operand: "dm"},
|
||||||
{operator: "is", operand: "resolved"},
|
{operator: "is", operand: "resolved"},
|
||||||
{operator: "stream"},
|
{operator: "channel"},
|
||||||
{operator: "dm"},
|
{operator: "dm"},
|
||||||
{operator: "in"},
|
{operator: "in"},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ export function get_sidebar_stream_topic_info(filter: Filter): {
|
|||||||
topic_selected: false,
|
topic_selected: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const op_stream = filter.operands("stream");
|
const op_stream = filter.operands("channel");
|
||||||
if (op_stream.length === 0) {
|
if (op_stream.length === 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,21 +83,50 @@ function test(label, f) {
|
|||||||
|
|
||||||
test("basics", () => {
|
test("basics", () => {
|
||||||
let terms = [
|
let terms = [
|
||||||
{operator: "stream", operand: "foo"},
|
{operator: "channel", operand: "foo"},
|
||||||
{operator: "stream", operand: "exclude_stream", negated: true},
|
{operator: "channel", operand: "exclude_stream", negated: true},
|
||||||
{operator: "topic", operand: "bar"},
|
{operator: "topic", operand: "bar"},
|
||||||
];
|
];
|
||||||
let filter = new Filter(terms);
|
let filter = new Filter(terms);
|
||||||
|
|
||||||
assert_same_terms(filter.terms(), terms);
|
assert_same_terms(filter.terms(), terms);
|
||||||
assert.deepEqual(filter.operands("stream"), ["foo"]);
|
assert.deepEqual(filter.operands("channel"), ["foo"]);
|
||||||
|
|
||||||
assert.ok(filter.has_operator("stream"));
|
assert.ok(filter.has_operator("channel"));
|
||||||
assert.ok(!filter.has_operator("search"));
|
assert.ok(!filter.has_operator("search"));
|
||||||
|
|
||||||
assert.ok(filter.has_operand("stream", "foo"));
|
assert.ok(filter.has_operand("channel", "foo"));
|
||||||
assert.ok(!filter.has_operand("stream", "exclude_stream"));
|
assert.ok(!filter.has_operand("channel", "exclude_stream"));
|
||||||
assert.ok(!filter.has_operand("stream", "nada"));
|
assert.ok(!filter.has_operand("channel", "nada"));
|
||||||
|
|
||||||
|
assert.ok(!filter.is_keyword_search());
|
||||||
|
assert.ok(!filter.can_mark_messages_read());
|
||||||
|
assert.ok(filter.supports_collapsing_recipients());
|
||||||
|
assert.ok(!filter.contains_only_private_messages());
|
||||||
|
assert.ok(!filter.allow_use_first_unread_when_narrowing());
|
||||||
|
assert.ok(filter.includes_full_stream_history());
|
||||||
|
assert.ok(filter.can_apply_locally());
|
||||||
|
assert.ok(!filter.is_personal_filter());
|
||||||
|
assert.ok(!filter.is_conversation_view());
|
||||||
|
|
||||||
|
assert.ok(filter.can_bucket_by("channel"));
|
||||||
|
assert.ok(filter.can_bucket_by("channel", "topic"));
|
||||||
|
|
||||||
|
terms = [
|
||||||
|
{operator: "stream", operand: "foo"},
|
||||||
|
{operator: "stream", operand: "exclude_stream", negated: true},
|
||||||
|
{operator: "topic", operand: "bar"},
|
||||||
|
];
|
||||||
|
filter = new Filter(terms);
|
||||||
|
|
||||||
|
assert.deepEqual(filter.operands("channel"), ["foo"]);
|
||||||
|
|
||||||
|
assert.ok(filter.has_operator("channel"));
|
||||||
|
assert.ok(!filter.has_operator("search"));
|
||||||
|
|
||||||
|
assert.ok(filter.has_operand("channel", "foo"));
|
||||||
|
assert.ok(!filter.has_operand("channel", "exclude_stream"));
|
||||||
|
assert.ok(!filter.has_operand("channel", "nada"));
|
||||||
|
|
||||||
assert.ok(!filter.is_keyword_search());
|
assert.ok(!filter.is_keyword_search());
|
||||||
assert.ok(!filter.can_mark_messages_read());
|
assert.ok(!filter.can_mark_messages_read());
|
||||||
@@ -123,8 +152,8 @@ test("basics", () => {
|
|||||||
assert.ok(!filter.allow_use_first_unread_when_narrowing());
|
assert.ok(!filter.allow_use_first_unread_when_narrowing());
|
||||||
assert.ok(!filter.can_apply_locally());
|
assert.ok(!filter.can_apply_locally());
|
||||||
assert.ok(!filter.is_personal_filter());
|
assert.ok(!filter.is_personal_filter());
|
||||||
assert.ok(filter.can_bucket_by("stream"));
|
assert.ok(filter.can_bucket_by("channel"));
|
||||||
assert.ok(filter.can_bucket_by("stream", "topic"));
|
assert.ok(filter.can_bucket_by("channel", "topic"));
|
||||||
assert.ok(!filter.is_conversation_view());
|
assert.ok(!filter.is_conversation_view());
|
||||||
|
|
||||||
terms = [
|
terms = [
|
||||||
@@ -141,8 +170,8 @@ test("basics", () => {
|
|||||||
assert.ok(!filter.allow_use_first_unread_when_narrowing());
|
assert.ok(!filter.allow_use_first_unread_when_narrowing());
|
||||||
assert.ok(filter.can_apply_locally());
|
assert.ok(filter.can_apply_locally());
|
||||||
assert.ok(!filter.is_personal_filter());
|
assert.ok(!filter.is_personal_filter());
|
||||||
assert.ok(filter.can_bucket_by("stream"));
|
assert.ok(filter.can_bucket_by("channel"));
|
||||||
assert.ok(filter.can_bucket_by("stream", "topic"));
|
assert.ok(filter.can_bucket_by("channel", "topic"));
|
||||||
assert.ok(!filter.is_conversation_view());
|
assert.ok(!filter.is_conversation_view());
|
||||||
|
|
||||||
// If our only stream operator is negated, then for all intents and purposes,
|
// If our only stream operator is negated, then for all intents and purposes,
|
||||||
@@ -151,7 +180,7 @@ test("basics", () => {
|
|||||||
terms = [{operator: "stream", operand: "exclude", negated: true}];
|
terms = [{operator: "stream", operand: "exclude", negated: true}];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
assert.ok(!filter.contains_only_private_messages());
|
assert.ok(!filter.contains_only_private_messages());
|
||||||
assert.ok(!filter.has_operator("stream"));
|
assert.ok(!filter.has_operator("channel"));
|
||||||
assert.ok(!filter.can_mark_messages_read());
|
assert.ok(!filter.can_mark_messages_read());
|
||||||
assert.ok(filter.supports_collapsing_recipients());
|
assert.ok(filter.supports_collapsing_recipients());
|
||||||
assert.ok(!filter.is_personal_filter());
|
assert.ok(!filter.is_personal_filter());
|
||||||
@@ -332,6 +361,22 @@ test("basics", () => {
|
|||||||
assert.ok(filter.can_apply_locally());
|
assert.ok(filter.can_apply_locally());
|
||||||
assert.ok(!filter.is_personal_filter());
|
assert.ok(!filter.is_personal_filter());
|
||||||
assert.ok(filter.is_conversation_view());
|
assert.ok(filter.is_conversation_view());
|
||||||
|
|
||||||
|
terms = [
|
||||||
|
{operator: "channel", operand: "foo"},
|
||||||
|
{operator: "topic", operand: "bar"},
|
||||||
|
];
|
||||||
|
filter = new Filter(terms);
|
||||||
|
|
||||||
|
assert.ok(!filter.is_keyword_search());
|
||||||
|
assert.ok(filter.can_mark_messages_read());
|
||||||
|
assert.ok(filter.supports_collapsing_recipients());
|
||||||
|
assert.ok(!filter.contains_only_private_messages());
|
||||||
|
assert.ok(filter.allow_use_first_unread_when_narrowing());
|
||||||
|
assert.ok(filter.includes_full_stream_history());
|
||||||
|
assert.ok(filter.can_apply_locally());
|
||||||
|
assert.ok(!filter.is_personal_filter());
|
||||||
|
assert.ok(filter.is_conversation_view());
|
||||||
});
|
});
|
||||||
|
|
||||||
function assert_not_mark_read_with_has_operands(additional_terms_to_test) {
|
function assert_not_mark_read_with_has_operands(additional_terms_to_test) {
|
||||||
@@ -557,7 +602,7 @@ test("filter_with_new_params_topic", () => {
|
|||||||
operand: "new topic",
|
operand: "new topic",
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.deepEqual(new_filter.operands("stream"), ["foo"]);
|
assert.deepEqual(new_filter.operands("channel"), ["foo"]);
|
||||||
assert.deepEqual(new_filter.operands("topic"), ["new topic"]);
|
assert.deepEqual(new_filter.operands("topic"), ["new topic"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -577,7 +622,7 @@ test("filter_with_new_params_stream", () => {
|
|||||||
operand: "new stream",
|
operand: "new stream",
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.deepEqual(new_filter.operands("stream"), ["new stream"]);
|
assert.deepEqual(new_filter.operands("channel"), ["new stream"]);
|
||||||
assert.deepEqual(new_filter.operands("topic"), ["old topic"]);
|
assert.deepEqual(new_filter.operands("topic"), ["old topic"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -589,8 +634,8 @@ test("new_style_terms", () => {
|
|||||||
const terms = [term];
|
const terms = [term];
|
||||||
const filter = new Filter(terms);
|
const filter = new Filter(terms);
|
||||||
|
|
||||||
assert.deepEqual(filter.operands("stream"), ["foo"]);
|
assert.deepEqual(filter.operands("channel"), ["foo"]);
|
||||||
assert.ok(filter.can_bucket_by("stream"));
|
assert.ok(filter.can_bucket_by("channel"));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("public_terms", ({override}) => {
|
test("public_terms", ({override}) => {
|
||||||
@@ -600,13 +645,17 @@ test("public_terms", ({override}) => {
|
|||||||
{operator: "in", operand: "all"},
|
{operator: "in", operand: "all"},
|
||||||
{operator: "topic", operand: "bar"},
|
{operator: "topic", operand: "bar"},
|
||||||
];
|
];
|
||||||
|
|
||||||
let filter = new Filter(terms);
|
let filter = new Filter(terms);
|
||||||
|
const expected_terms = [
|
||||||
|
{operator: "channel", operand: "some_stream"},
|
||||||
|
{operator: "in", operand: "all"},
|
||||||
|
{operator: "topic", operand: "bar"},
|
||||||
|
];
|
||||||
override(page_params, "narrow_stream", undefined);
|
override(page_params, "narrow_stream", undefined);
|
||||||
assert_same_terms(filter.public_terms(), terms);
|
assert_same_terms(filter.public_terms(), expected_terms);
|
||||||
assert.ok(filter.can_bucket_by("stream"));
|
assert.ok(filter.can_bucket_by("channel"));
|
||||||
|
|
||||||
terms = [{operator: "stream", operand: "default"}];
|
terms = [{operator: "channel", operand: "default"}];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
override(page_params, "narrow_stream", "default");
|
override(page_params, "narrow_stream", "default");
|
||||||
assert_same_terms(filter.public_terms(), []);
|
assert_same_terms(filter.public_terms(), []);
|
||||||
@@ -633,13 +682,17 @@ test("redundancies", () => {
|
|||||||
|
|
||||||
test("canonicalization", () => {
|
test("canonicalization", () => {
|
||||||
assert.equal(Filter.canonicalize_operator("Is"), "is");
|
assert.equal(Filter.canonicalize_operator("Is"), "is");
|
||||||
assert.equal(Filter.canonicalize_operator("Stream"), "stream");
|
assert.equal(Filter.canonicalize_operator("Stream"), "channel");
|
||||||
assert.equal(Filter.canonicalize_operator("Subject"), "topic");
|
assert.equal(Filter.canonicalize_operator("Subject"), "topic");
|
||||||
assert.equal(Filter.canonicalize_operator("FROM"), "sender");
|
assert.equal(Filter.canonicalize_operator("FROM"), "sender");
|
||||||
|
|
||||||
let term;
|
let term;
|
||||||
term = Filter.canonicalize_term({operator: "Stream", operand: "Denmark"});
|
term = Filter.canonicalize_term({operator: "Stream", operand: "Denmark"});
|
||||||
assert.equal(term.operator, "stream");
|
assert.equal(term.operator, "channel");
|
||||||
|
assert.equal(term.operand, "Denmark");
|
||||||
|
|
||||||
|
term = Filter.canonicalize_term({operator: "Channel", operand: "Denmark"});
|
||||||
|
assert.equal(term.operator, "channel");
|
||||||
assert.equal(term.operand, "Denmark");
|
assert.equal(term.operand, "Denmark");
|
||||||
|
|
||||||
term = Filter.canonicalize_term({operator: "sender", operand: "me"});
|
term = Filter.canonicalize_term({operator: "sender", operand: "me"});
|
||||||
@@ -1027,9 +1080,17 @@ test("parse", () => {
|
|||||||
assert_same_terms(result, terms);
|
assert_same_terms(result, terms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string = "channel:Foo topic:Bar yo";
|
||||||
|
terms = [
|
||||||
|
{operator: "channel", operand: "Foo"},
|
||||||
|
{operator: "topic", operand: "Bar"},
|
||||||
|
{operator: "search", operand: "yo"},
|
||||||
|
];
|
||||||
|
_test();
|
||||||
|
|
||||||
string = "stream:Foo topic:Bar yo";
|
string = "stream:Foo topic:Bar yo";
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "stream", operand: "Foo"},
|
{operator: "channel", operand: "Foo"},
|
||||||
{operator: "topic", operand: "Bar"},
|
{operator: "topic", operand: "Bar"},
|
||||||
{operator: "search", operand: "yo"},
|
{operator: "search", operand: "yo"},
|
||||||
];
|
];
|
||||||
@@ -1044,23 +1105,23 @@ test("parse", () => {
|
|||||||
_test();
|
_test();
|
||||||
|
|
||||||
string = "stream:With+Space";
|
string = "stream:With+Space";
|
||||||
terms = [{operator: "stream", operand: "With Space"}];
|
terms = [{operator: "channel", operand: "With Space"}];
|
||||||
_test();
|
_test();
|
||||||
|
|
||||||
string = 'stream:"with quoted space" topic:and separate';
|
string = 'stream:"with quoted space" topic:and separate';
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "stream", operand: "with quoted space"},
|
{operator: "channel", operand: "with quoted space"},
|
||||||
{operator: "topic", operand: "and"},
|
{operator: "topic", operand: "and"},
|
||||||
{operator: "search", operand: "separate"},
|
{operator: "search", operand: "separate"},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
|
|
||||||
string = 'stream:"unclosed quote';
|
string = 'stream:"unclosed quote';
|
||||||
terms = [{operator: "stream", operand: "unclosed quote"}];
|
terms = [{operator: "channel", operand: "unclosed quote"}];
|
||||||
_test();
|
_test();
|
||||||
|
|
||||||
string = 'stream:""';
|
string = 'stream:""';
|
||||||
terms = [{operator: "stream", operand: ""}];
|
terms = [{operator: "channel", operand: ""}];
|
||||||
_test();
|
_test();
|
||||||
|
|
||||||
string = "https://www.google.com";
|
string = "https://www.google.com";
|
||||||
@@ -1069,15 +1130,15 @@ test("parse", () => {
|
|||||||
|
|
||||||
string = "stream:foo -stream:exclude";
|
string = "stream:foo -stream:exclude";
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "stream", operand: "foo"},
|
{operator: "channel", operand: "foo"},
|
||||||
{operator: "stream", operand: "exclude", negated: true},
|
{operator: "channel", operand: "exclude", negated: true},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
|
|
||||||
string = "text stream:foo more text";
|
string = "text stream:foo more text";
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "search", operand: "text"},
|
{operator: "search", operand: "text"},
|
||||||
{operator: "stream", operand: "foo"},
|
{operator: "channel", operand: "foo"},
|
||||||
{operator: "search", operand: "more text"},
|
{operator: "search", operand: "more text"},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
@@ -1100,7 +1161,7 @@ test("parse", () => {
|
|||||||
|
|
||||||
string = "stream:foo :emoji: are cool";
|
string = "stream:foo :emoji: are cool";
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "stream", operand: "foo"},
|
{operator: "channel", operand: "foo"},
|
||||||
{operator: "search", operand: ":emoji: are cool"},
|
{operator: "search", operand: ":emoji: are cool"},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
@@ -1108,7 +1169,7 @@ test("parse", () => {
|
|||||||
string = ":stream: stream:foo :emoji: are cool";
|
string = ":stream: stream:foo :emoji: are cool";
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "search", operand: ":stream:"},
|
{operator: "search", operand: ":stream:"},
|
||||||
{operator: "stream", operand: "foo"},
|
{operator: "channel", operand: "foo"},
|
||||||
{operator: "search", operand: ":emoji: are cool"},
|
{operator: "search", operand: ":emoji: are cool"},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
@@ -1116,7 +1177,7 @@ test("parse", () => {
|
|||||||
string = ":stream: stream:foo -:emoji: are cool";
|
string = ":stream: stream:foo -:emoji: are cool";
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "search", operand: ":stream:"},
|
{operator: "search", operand: ":stream:"},
|
||||||
{operator: "stream", operand: "foo"},
|
{operator: "channel", operand: "foo"},
|
||||||
{operator: "search", operand: "-:emoji: are cool"},
|
{operator: "search", operand: "-:emoji: are cool"},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
@@ -1127,7 +1188,7 @@ test("parse", () => {
|
|||||||
|
|
||||||
string = 'stream: separated topic: "with space"';
|
string = 'stream: separated topic: "with space"';
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "stream", operand: "separated"},
|
{operator: "channel", operand: "separated"},
|
||||||
{operator: "topic", operand: "with space"},
|
{operator: "topic", operand: "with space"},
|
||||||
];
|
];
|
||||||
_test();
|
_test();
|
||||||
@@ -1138,7 +1199,7 @@ test("unparse", () => {
|
|||||||
let terms;
|
let terms;
|
||||||
|
|
||||||
terms = [
|
terms = [
|
||||||
{operator: "stream", operand: "Foo"},
|
{operator: "channel", operand: "Foo"},
|
||||||
{operator: "topic", operand: "Bar", negated: true},
|
{operator: "topic", operand: "Bar", negated: true},
|
||||||
{operator: "search", operand: "yo"},
|
{operator: "search", operand: "yo"},
|
||||||
];
|
];
|
||||||
@@ -1294,8 +1355,8 @@ test("describe", ({mock_template}) => {
|
|||||||
test("can_bucket_by", () => {
|
test("can_bucket_by", () => {
|
||||||
let terms = [{operator: "stream", operand: "My stream"}];
|
let terms = [{operator: "stream", operand: "My stream"}];
|
||||||
let filter = new Filter(terms);
|
let filter = new Filter(terms);
|
||||||
assert.equal(filter.can_bucket_by("stream"), true);
|
assert.equal(filter.can_bucket_by("channel"), true);
|
||||||
assert.equal(filter.can_bucket_by("stream", "topic"), false);
|
assert.equal(filter.can_bucket_by("channel", "topic"), false);
|
||||||
assert.equal(filter.can_bucket_by("dm"), false);
|
assert.equal(filter.can_bucket_by("dm"), false);
|
||||||
|
|
||||||
terms = [
|
terms = [
|
||||||
@@ -1304,8 +1365,8 @@ test("can_bucket_by", () => {
|
|||||||
{operator: "stream", operand: "My stream"},
|
{operator: "stream", operand: "My stream"},
|
||||||
];
|
];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
assert.equal(filter.can_bucket_by("stream"), true);
|
assert.equal(filter.can_bucket_by("channel"), true);
|
||||||
assert.equal(filter.can_bucket_by("stream", "topic"), true);
|
assert.equal(filter.can_bucket_by("channel", "topic"), true);
|
||||||
assert.equal(filter.can_bucket_by("dm"), false);
|
assert.equal(filter.can_bucket_by("dm"), false);
|
||||||
|
|
||||||
terms = [
|
terms = [
|
||||||
@@ -1313,20 +1374,20 @@ test("can_bucket_by", () => {
|
|||||||
{operator: "topic", operand: "My topic"},
|
{operator: "topic", operand: "My topic"},
|
||||||
];
|
];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
assert.equal(filter.can_bucket_by("stream"), false);
|
assert.equal(filter.can_bucket_by("channel"), false);
|
||||||
assert.equal(filter.can_bucket_by("stream", "topic"), false);
|
assert.equal(filter.can_bucket_by("channel", "topic"), false);
|
||||||
assert.equal(filter.can_bucket_by("dm"), false);
|
assert.equal(filter.can_bucket_by("dm"), false);
|
||||||
|
|
||||||
terms = [{operator: "dm", operand: "foo@example.com", negated: true}];
|
terms = [{operator: "dm", operand: "foo@example.com", negated: true}];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
assert.equal(filter.can_bucket_by("stream"), false);
|
assert.equal(filter.can_bucket_by("channel"), false);
|
||||||
assert.equal(filter.can_bucket_by("stream", "topic"), false);
|
assert.equal(filter.can_bucket_by("channel", "topic"), false);
|
||||||
assert.equal(filter.can_bucket_by("dm"), false);
|
assert.equal(filter.can_bucket_by("dm"), false);
|
||||||
|
|
||||||
terms = [{operator: "dm", operand: "foo@example.com,bar@example.com"}];
|
terms = [{operator: "dm", operand: "foo@example.com,bar@example.com"}];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
assert.equal(filter.can_bucket_by("stream"), false);
|
assert.equal(filter.can_bucket_by("channel"), false);
|
||||||
assert.equal(filter.can_bucket_by("stream", "topic"), false);
|
assert.equal(filter.can_bucket_by("channel", "topic"), false);
|
||||||
assert.equal(filter.can_bucket_by("dm"), true);
|
assert.equal(filter.can_bucket_by("dm"), true);
|
||||||
assert.equal(filter.can_bucket_by("is-mentioned"), false);
|
assert.equal(filter.can_bucket_by("is-mentioned"), false);
|
||||||
assert.equal(filter.can_bucket_by("is-dm"), false);
|
assert.equal(filter.can_bucket_by("is-dm"), false);
|
||||||
@@ -1361,8 +1422,8 @@ test("can_bucket_by", () => {
|
|||||||
|
|
||||||
terms = [{operator: "is", operand: "resolved"}];
|
terms = [{operator: "is", operand: "resolved"}];
|
||||||
filter = new Filter(terms);
|
filter = new Filter(terms);
|
||||||
assert.equal(filter.can_bucket_by("stream", "topic"), false);
|
assert.equal(filter.can_bucket_by("channel", "topic"), false);
|
||||||
assert.equal(filter.can_bucket_by("stream"), false);
|
assert.equal(filter.can_bucket_by("channel"), false);
|
||||||
assert.equal(filter.can_bucket_by("dm"), false);
|
assert.equal(filter.can_bucket_by("dm"), false);
|
||||||
assert.equal(filter.can_bucket_by("is-mentioned"), false);
|
assert.equal(filter.can_bucket_by("is-mentioned"), false);
|
||||||
assert.equal(filter.can_bucket_by("is-dm"), false);
|
assert.equal(filter.can_bucket_by("is-dm"), false);
|
||||||
@@ -1382,7 +1443,7 @@ test("term_type", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert_term_type(term("streams", "public"), "streams-public");
|
assert_term_type(term("streams", "public"), "streams-public");
|
||||||
assert_term_type(term("stream", "whatever"), "stream");
|
assert_term_type(term("channel", "whatever"), "channel");
|
||||||
assert_term_type(term("dm", "whomever"), "dm");
|
assert_term_type(term("dm", "whomever"), "dm");
|
||||||
assert_term_type(term("dm", "whomever", true), "not-dm");
|
assert_term_type(term("dm", "whomever", true), "not-dm");
|
||||||
assert_term_type(term("is", "dm"), "is-dm");
|
assert_term_type(term("is", "dm"), "is-dm");
|
||||||
@@ -1395,27 +1456,27 @@ test("term_type", () => {
|
|||||||
assert.deepEqual(sorted_terms, expected);
|
assert.deepEqual(sorted_terms, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_term_sort(["topic", "stream", "sender"], ["stream", "topic", "sender"]);
|
assert_term_sort(["topic", "channel", "sender"], ["channel", "topic", "sender"]);
|
||||||
|
|
||||||
assert_term_sort(
|
assert_term_sort(
|
||||||
["has-link", "near", "is-unread", "dm"],
|
["has-link", "near", "is-unread", "dm"],
|
||||||
["dm", "near", "is-unread", "has-link"],
|
["dm", "near", "is-unread", "has-link"],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_term_sort(["bogus", "stream", "topic"], ["stream", "topic", "bogus"]);
|
assert_term_sort(["bogus", "channel", "topic"], ["channel", "topic", "bogus"]);
|
||||||
assert_term_sort(["stream", "topic", "stream"], ["stream", "stream", "topic"]);
|
assert_term_sort(["channel", "topic", "channel"], ["channel", "channel", "topic"]);
|
||||||
|
|
||||||
assert_term_sort(["search", "streams-public"], ["streams-public", "search"]);
|
assert_term_sort(["search", "streams-public"], ["streams-public", "search"]);
|
||||||
|
|
||||||
const terms = [
|
const terms = [
|
||||||
{operator: "topic", operand: "lunch"},
|
{operator: "topic", operand: "lunch"},
|
||||||
{operator: "sender", operand: "steve@foo.com"},
|
{operator: "sender", operand: "steve@foo.com"},
|
||||||
{operator: "stream", operand: "Verona"},
|
{operator: "channel", operand: "Verona"},
|
||||||
];
|
];
|
||||||
let filter = new Filter(terms);
|
let filter = new Filter(terms);
|
||||||
const term_types = filter.sorted_term_types();
|
const term_types = filter.sorted_term_types();
|
||||||
|
|
||||||
assert.deepEqual(term_types, ["stream", "topic", "sender"]);
|
assert.deepEqual(term_types, ["channel", "topic", "sender"]);
|
||||||
|
|
||||||
// test caching of term types
|
// test caching of term types
|
||||||
// init and stub
|
// init and stub
|
||||||
@@ -1429,13 +1490,13 @@ test("term_type", () => {
|
|||||||
// uncached trial
|
// uncached trial
|
||||||
filter._build_sorted_term_types_called = false;
|
filter._build_sorted_term_types_called = false;
|
||||||
const built_terms = filter.sorted_term_types();
|
const built_terms = filter.sorted_term_types();
|
||||||
assert.deepEqual(built_terms, ["stream", "topic", "sender"]);
|
assert.deepEqual(built_terms, ["channel", "topic", "sender"]);
|
||||||
assert.ok(filter._build_sorted_term_types_called);
|
assert.ok(filter._build_sorted_term_types_called);
|
||||||
|
|
||||||
// cached trial
|
// cached trial
|
||||||
filter._build_sorted_term_types_called = false;
|
filter._build_sorted_term_types_called = false;
|
||||||
const cached_terms = filter.sorted_term_types();
|
const cached_terms = filter.sorted_term_types();
|
||||||
assert.deepEqual(cached_terms, ["stream", "topic", "sender"]);
|
assert.deepEqual(cached_terms, ["channel", "topic", "sender"]);
|
||||||
assert.ok(!filter._build_sorted_term_types_called);
|
assert.ok(!filter._build_sorted_term_types_called);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1471,7 +1532,7 @@ test("update_email", () => {
|
|||||||
filter.update_email(steve.user_id, "showell@foo.com");
|
filter.update_email(steve.user_id, "showell@foo.com");
|
||||||
assert.deepEqual(filter.operands("dm"), ["showell@foo.com"]);
|
assert.deepEqual(filter.operands("dm"), ["showell@foo.com"]);
|
||||||
assert.deepEqual(filter.operands("sender"), ["showell@foo.com"]);
|
assert.deepEqual(filter.operands("sender"), ["showell@foo.com"]);
|
||||||
assert.deepEqual(filter.operands("stream"), ["steve@foo.com"]);
|
assert.deepEqual(filter.operands("channel"), ["steve@foo.com"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
function make_private_sub(name, stream_id) {
|
function make_private_sub(name, stream_id) {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ test("stream", () => {
|
|||||||
assert.ok(narrow_state.is_for_stream_id(test_stream.stream_id));
|
assert.ok(narrow_state.is_for_stream_id(test_stream.stream_id));
|
||||||
|
|
||||||
const expected_terms = [
|
const expected_terms = [
|
||||||
{negated: false, operator: "stream", operand: "Test"},
|
{negated: false, operator: "channel", operand: "Test"},
|
||||||
{negated: false, operator: "topic", operand: "Bar"},
|
{negated: false, operator: "topic", operand: "Bar"},
|
||||||
{negated: false, operator: "search", operand: "yo"},
|
{negated: false, operator: "search", operand: "yo"},
|
||||||
];
|
];
|
||||||
@@ -130,7 +130,7 @@ test("terms", () => {
|
|||||||
]);
|
]);
|
||||||
let result = narrow_state.search_terms();
|
let result = narrow_state.search_terms();
|
||||||
assert.equal(result.length, 3);
|
assert.equal(result.length, 3);
|
||||||
assert.equal(result[0].operator, "stream");
|
assert.equal(result[0].operator, "channel");
|
||||||
assert.equal(result[0].operand, "Foo");
|
assert.equal(result[0].operand, "Foo");
|
||||||
|
|
||||||
assert.equal(result[1].operator, "topic");
|
assert.equal(result[1].operator, "topic");
|
||||||
@@ -146,7 +146,7 @@ test("terms", () => {
|
|||||||
page_params.narrow = [{operator: "stream", operand: "Foo"}];
|
page_params.narrow = [{operator: "stream", operand: "Foo"}];
|
||||||
result = narrow_state.search_terms();
|
result = narrow_state.search_terms();
|
||||||
assert.equal(result.length, 1);
|
assert.equal(result.length, 1);
|
||||||
assert.equal(result[0].operator, "stream");
|
assert.equal(result[0].operator, "channel");
|
||||||
assert.equal(result[0].operand, "Foo");
|
assert.equal(result[0].operand, "Foo");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ test("update_email", () => {
|
|||||||
const filter = narrow_state.filter();
|
const filter = narrow_state.filter();
|
||||||
assert.deepEqual(filter.operands("dm"), ["showell@foo.com"]);
|
assert.deepEqual(filter.operands("dm"), ["showell@foo.com"]);
|
||||||
assert.deepEqual(filter.operands("sender"), ["showell@foo.com"]);
|
assert.deepEqual(filter.operands("sender"), ["showell@foo.com"]);
|
||||||
assert.deepEqual(filter.operands("stream"), ["steve@foo.com"]);
|
assert.deepEqual(filter.operands("channel"), ["steve@foo.com"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("topic", () => {
|
test("topic", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user