mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 08:26:11 +00:00
topic_list: Filter topics by resolved state in "more topics" view.
Fixes: #24200.
This commit is contained in:
committed by
Tim Abbott
parent
2a325b4530
commit
52b83f7b58
@@ -424,6 +424,7 @@ export function zoom_in_topics(options: {stream_id: number | undefined}): void {
|
|||||||
// Add search box for topics list.
|
// Add search box for topics list.
|
||||||
$elt.children("div.bottom_left_row").append($(render_filter_topics()));
|
$elt.children("div.bottom_left_row").append($(render_filter_topics()));
|
||||||
$("#left-sidebar-filter-topic-input").trigger("focus");
|
$("#left-sidebar-filter-topic-input").trigger("focus");
|
||||||
|
topic_list.setup_topic_search_typeahead();
|
||||||
} else {
|
} else {
|
||||||
$elt.hide();
|
$elt.hide();
|
||||||
}
|
}
|
||||||
@@ -769,7 +770,7 @@ export function update_stream_sidebar_for_narrow(filter: Filter): JQuery | undef
|
|||||||
// we want to the topics list here.
|
// we want to the topics list here.
|
||||||
update_inbox_channel_view_callback(stream_id);
|
update_inbox_channel_view_callback(stream_id);
|
||||||
topic_list.rebuild_left_sidebar($stream_li, stream_id);
|
topic_list.rebuild_left_sidebar($stream_li, stream_id);
|
||||||
|
topic_list.topic_state_typeahead?.lookup(true);
|
||||||
return $stream_li;
|
return $stream_li;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import assert from "minimalistic-assert";
|
import assert from "minimalistic-assert";
|
||||||
|
|
||||||
|
import * as resolved_topics from "../shared/src/resolved_topic.ts";
|
||||||
|
|
||||||
import * as echo_state from "./echo_state.ts";
|
import * as echo_state from "./echo_state.ts";
|
||||||
import {FoldDict} from "./fold_dict.ts";
|
import {FoldDict} from "./fold_dict.ts";
|
||||||
import * as message_util from "./message_util.ts";
|
import * as message_util from "./message_util.ts";
|
||||||
@@ -31,6 +33,17 @@ export function stream_has_topics(stream_id: number): boolean {
|
|||||||
return history.has_topics();
|
return history.has_topics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function stream_has_locally_available_resolved_topics(stream_id: number): boolean {
|
||||||
|
if (!stream_dict.has(stream_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const history = stream_dict.get(stream_id);
|
||||||
|
assert(history !== undefined);
|
||||||
|
|
||||||
|
return history.has_resolved_topics();
|
||||||
|
}
|
||||||
|
|
||||||
export type TopicHistoryEntry = {
|
export type TopicHistoryEntry = {
|
||||||
count: number;
|
count: number;
|
||||||
message_id: number;
|
message_id: number;
|
||||||
@@ -67,6 +80,10 @@ export class PerStreamHistory {
|
|||||||
this.stream_id = stream_id;
|
this.stream_id = stream_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_resolved_topics(): boolean {
|
||||||
|
return [...this.topics.keys()].some((topic) => resolved_topics.is_resolved(topic));
|
||||||
|
}
|
||||||
|
|
||||||
has_topics(): boolean {
|
has_topics(): boolean {
|
||||||
return this.topics.size > 0;
|
return this.topics.size > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,14 @@ import render_topic_list_item from "../templates/topic_list_item.hbs";
|
|||||||
|
|
||||||
import {all_messages_data} from "./all_messages_data.ts";
|
import {all_messages_data} from "./all_messages_data.ts";
|
||||||
import * as blueslip from "./blueslip.ts";
|
import * as blueslip from "./blueslip.ts";
|
||||||
|
import {Typeahead} from "./bootstrap_typeahead.ts";
|
||||||
|
import type {TypeaheadInputElement} from "./bootstrap_typeahead.ts";
|
||||||
|
import {$t} from "./i18n.ts";
|
||||||
import * as popover_menus from "./popover_menus.ts";
|
import * as popover_menus from "./popover_menus.ts";
|
||||||
import * as popovers from "./popovers.ts";
|
import * as popovers from "./popovers.ts";
|
||||||
import * as scroll_util from "./scroll_util.ts";
|
import * as scroll_util from "./scroll_util.ts";
|
||||||
|
import type {SearchPillWidget} from "./search_pill.ts";
|
||||||
|
import * as search_pill from "./search_pill.ts";
|
||||||
import * as sidebar_ui from "./sidebar_ui.ts";
|
import * as sidebar_ui from "./sidebar_ui.ts";
|
||||||
import * as stream_topic_history from "./stream_topic_history.ts";
|
import * as stream_topic_history from "./stream_topic_history.ts";
|
||||||
import * as stream_topic_history_util from "./stream_topic_history_util.ts";
|
import * as stream_topic_history_util from "./stream_topic_history_util.ts";
|
||||||
@@ -18,6 +23,7 @@ import type {StreamSubscription} from "./sub_store.ts";
|
|||||||
import * as sub_store from "./sub_store.ts";
|
import * as sub_store from "./sub_store.ts";
|
||||||
import * as topic_list_data from "./topic_list_data.ts";
|
import * as topic_list_data from "./topic_list_data.ts";
|
||||||
import type {TopicInfo} from "./topic_list_data.ts";
|
import type {TopicInfo} from "./topic_list_data.ts";
|
||||||
|
import * as typeahead_helper from "./typeahead_helper.ts";
|
||||||
import * as vdom from "./vdom.ts";
|
import * as vdom from "./vdom.ts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -29,6 +35,8 @@ import * as vdom from "./vdom.ts";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const active_widgets = new Map<number, LeftSidebarTopicListWidget>();
|
const active_widgets = new Map<number, LeftSidebarTopicListWidget>();
|
||||||
|
export let search_pill_widget: SearchPillWidget | null = null;
|
||||||
|
export let topic_state_typeahead: Typeahead<string> | undefined;
|
||||||
|
|
||||||
// We know whether we're zoomed or not.
|
// We know whether we're zoomed or not.
|
||||||
let zoomed = false;
|
let zoomed = false;
|
||||||
@@ -61,7 +69,7 @@ export function clear(): void {
|
|||||||
export function focus_topic_search_filter(): void {
|
export function focus_topic_search_filter(): void {
|
||||||
popovers.hide_all();
|
popovers.hide_all();
|
||||||
sidebar_ui.show_left_sidebar();
|
sidebar_ui.show_left_sidebar();
|
||||||
const $filter = $("#left-sidebar-filter-topic-input").expectOne();
|
const $filter = $("#topic_filter_query");
|
||||||
$filter.trigger("focus");
|
$filter.trigger("focus");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +352,11 @@ export class TopicListWidget {
|
|||||||
|
|
||||||
function filter_topics_left_sidebar(topic_names: string[]): string[] {
|
function filter_topics_left_sidebar(topic_names: string[]): string[] {
|
||||||
const search_term = get_left_sidebar_topic_search_term();
|
const search_term = get_left_sidebar_topic_search_term();
|
||||||
return topic_list_data.filter_topics_by_search_term(topic_names, search_term);
|
return topic_list_data.filter_topics_by_search_term(
|
||||||
|
topic_names,
|
||||||
|
search_term,
|
||||||
|
get_typeahead_search_term(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LeftSidebarTopicListWidget extends TopicListWidget {
|
export class LeftSidebarTopicListWidget extends TopicListWidget {
|
||||||
@@ -362,11 +374,14 @@ export class LeftSidebarTopicListWidget extends TopicListWidget {
|
|||||||
|
|
||||||
export function clear_topic_search(e: JQuery.Event): void {
|
export function clear_topic_search(e: JQuery.Event): void {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const $input = $("#left-sidebar-filter-topic-input");
|
const $input = $("#topic_filter_query");
|
||||||
if ($input.length > 0) {
|
if ($input.length > 0) {
|
||||||
$input.val("");
|
$input.text("");
|
||||||
$input.trigger("blur");
|
$input.trigger("blur");
|
||||||
|
|
||||||
|
search_pill_widget?.clear(true);
|
||||||
|
update_clear_button();
|
||||||
|
|
||||||
// Since this changes the contents of the search input, we
|
// Since this changes the contents of the search input, we
|
||||||
// need to rerender the topic list.
|
// need to rerender the topic list.
|
||||||
const stream_ids = [...active_widgets.keys()];
|
const stream_ids = [...active_widgets.keys()];
|
||||||
@@ -467,6 +482,7 @@ export function zoom_in(): void {
|
|||||||
// position since we just added some topics to the list which moved user
|
// position since we just added some topics to the list which moved user
|
||||||
// to a different position anyway.
|
// to a different position anyway.
|
||||||
left_sidebar_scroll_zoomed_in_topic_into_view();
|
left_sidebar_scroll_zoomed_in_topic_into_view();
|
||||||
|
topic_state_typeahead?.lookup(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,12 +494,123 @@ export function zoom_in(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function get_left_sidebar_topic_search_term(): string {
|
export function get_left_sidebar_topic_search_term(): string {
|
||||||
const $filter = $<HTMLInputElement>("input#left-sidebar-filter-topic-input");
|
return $("#left-sidebar-filter-topic-input .input").text().trim();
|
||||||
const filter_val = $filter.val();
|
|
||||||
if (filter_val === undefined) {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
return filter_val.trim();
|
|
||||||
|
export function get_typeahead_search_term(): string {
|
||||||
|
const $pills = $("#left-sidebar-filter-topic-input .pill");
|
||||||
|
const value = $pills.find(".pill-value").text().trim();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_search_bar_text(text: string): void {
|
||||||
|
const $input = $("#topic_filter_query");
|
||||||
|
$input.text(text);
|
||||||
|
$input.trigger("input");
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter_options = new Map<string, string>([
|
||||||
|
[$t({defaultMessage: "Unresolved topics"}), "-is:resolved"],
|
||||||
|
[$t({defaultMessage: "Resolved topics"}), "is:resolved"],
|
||||||
|
[$t({defaultMessage: "All topics"}), ""],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function update_clear_button(): void {
|
||||||
|
const $filter_query = $("#topic_filter_query");
|
||||||
|
const $clear_button = $("#clear_search_topic_button");
|
||||||
|
if (get_left_sidebar_topic_search_term() === "" && get_typeahead_search_term() === "") {
|
||||||
|
$clear_button.css("visibility", "hidden");
|
||||||
|
// When we use backspace to clear the content of the search box,
|
||||||
|
// a <br> tag is left inside it, preventing the data-placeholder
|
||||||
|
// value from reappearing as the element never becomes truly empty.
|
||||||
|
// Therefore, we manually set the text to empty.
|
||||||
|
$filter_query.empty();
|
||||||
|
} else {
|
||||||
|
$clear_button.css("visibility", "visible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setup_topic_search_typeahead(): void {
|
||||||
|
const $input = $("#topic_filter_query");
|
||||||
|
const $pill_container = $("#left-sidebar-filter-topic-input");
|
||||||
|
|
||||||
|
if ($input.length === 0 || $pill_container.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
search_pill_widget = search_pill.create_pills($pill_container);
|
||||||
|
|
||||||
|
const typeahead_input: TypeaheadInputElement = {
|
||||||
|
$element: $input,
|
||||||
|
type: "contenteditable",
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
items: filter_options.size,
|
||||||
|
source() {
|
||||||
|
const stream_id = active_stream_id();
|
||||||
|
assert(stream_id !== undefined);
|
||||||
|
|
||||||
|
if (!stream_topic_history.stream_has_locally_available_resolved_topics(stream_id)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const $pills = $("#left-sidebar-filter-topic-input .pill");
|
||||||
|
if ($pills.length > 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return [...filter_options.keys()];
|
||||||
|
},
|
||||||
|
highlighter_html(item: string) {
|
||||||
|
return typeahead_helper.render_topic_state(item);
|
||||||
|
},
|
||||||
|
matcher(item: string, query: string) {
|
||||||
|
return item.toLowerCase().includes(query.toLowerCase());
|
||||||
|
},
|
||||||
|
sorter(items: string[]) {
|
||||||
|
return items;
|
||||||
|
},
|
||||||
|
updater(item: string) {
|
||||||
|
const value = filter_options.get(item)!;
|
||||||
|
assert(search_pill_widget !== null);
|
||||||
|
search_pill_widget.clear(true);
|
||||||
|
search_pill_widget.appendValue(value);
|
||||||
|
set_search_bar_text("");
|
||||||
|
$input.trigger("focus");
|
||||||
|
return get_left_sidebar_topic_search_term();
|
||||||
|
},
|
||||||
|
// Prevents key events from propagating to other handlers or triggering default browser actions.
|
||||||
|
stopAdvance: true,
|
||||||
|
// Use dropup, to match compose typeahead.
|
||||||
|
dropup: true,
|
||||||
|
// Display typeahead menu when input gains focus and is empty.
|
||||||
|
helpOnEmptyStrings: true,
|
||||||
|
// Prevents displaying the typeahead menu when a pill is deleted via backspace.
|
||||||
|
hideOnEmptyAfterBackspace: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
topic_state_typeahead = new Typeahead(typeahead_input, options);
|
||||||
|
|
||||||
|
$input.on("keydown", (e: JQuery.KeyDownEvent) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
$input.addClass("shake");
|
||||||
|
} else if (e.key === ",") {
|
||||||
|
e.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
search_pill_widget.onPillRemove(() => {
|
||||||
|
update_clear_button();
|
||||||
|
const stream_id = active_stream_id();
|
||||||
|
if (stream_id !== undefined) {
|
||||||
|
const widget = active_widgets.get(stream_id);
|
||||||
|
if (widget) {
|
||||||
|
widget.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initialize({
|
export function initialize({
|
||||||
@@ -522,5 +649,8 @@ export function initialize({
|
|||||||
const stream_id = active_stream_id();
|
const stream_id = active_stream_id();
|
||||||
assert(stream_id !== undefined);
|
assert(stream_id !== undefined);
|
||||||
active_widgets.get(stream_id)?.build();
|
active_widgets.get(stream_id)?.build();
|
||||||
|
update_clear_button();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
update_clear_button();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,19 +156,31 @@ type TopicListInfo = {
|
|||||||
more_topics_unread_count_muted: boolean;
|
more_topics_unread_count_muted: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function filter_topics_by_search_term(topic_names: string[], search_term: string): string[] {
|
export function filter_topics_by_search_term(
|
||||||
if (search_term === "") {
|
topic_names: string[],
|
||||||
|
search_term: string,
|
||||||
|
topics_state = "",
|
||||||
|
): string[] {
|
||||||
|
if (search_term === "" && topics_state === "") {
|
||||||
return topic_names;
|
return topic_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
const word_separator_regex = /[\s/:_-]/; // Use -, _, :, / as word separators in addition to spaces.
|
const word_separator_regex = /[\s/:_-]/; // Use -, _, :, / as word separators in addition to spaces.
|
||||||
const empty_string_topic_display_name = util.get_final_topic_display_name("");
|
const empty_string_topic_display_name = util.get_final_topic_display_name("");
|
||||||
return util.filter_by_word_prefix_match(
|
topic_names = util.filter_by_word_prefix_match(
|
||||||
topic_names,
|
topic_names,
|
||||||
search_term,
|
search_term,
|
||||||
(topic) => (topic === "" ? empty_string_topic_display_name : topic),
|
(topic) => (topic === "" ? empty_string_topic_display_name : topic),
|
||||||
word_separator_regex,
|
word_separator_regex,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (topics_state === "is: resolved") {
|
||||||
|
topic_names = topic_names.filter((name) => resolved_topic.is_resolved(name));
|
||||||
|
} else if (topics_state === "-is: resolved") {
|
||||||
|
topic_names = topic_names.filter((name) => !resolved_topic.is_resolved(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return topic_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_list_info(
|
export function get_list_info(
|
||||||
|
|||||||
@@ -176,6 +176,15 @@ export function rewire_render_person(value: typeof render_person): void {
|
|||||||
render_person = value;
|
render_person = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export let render_topic_state = (state: string): string =>
|
||||||
|
render_typeahead_item({
|
||||||
|
primary: state,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function rewire_render_topic_state(value: typeof render_topic_state): void {
|
||||||
|
render_topic_state = value;
|
||||||
|
}
|
||||||
|
|
||||||
export let render_user_group = (user_group: {name: string; description: string}): string =>
|
export let render_user_group = (user_group: {name: string; description: string}): string =>
|
||||||
render_typeahead_item({
|
render_typeahead_item({
|
||||||
primary: user_groups.get_display_group_name(user_group.name),
|
primary: user_groups.get_display_group_name(user_group.name),
|
||||||
|
|||||||
@@ -1332,11 +1332,24 @@ li.top_left_scheduled_messages {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
gap: 0.125em; /* 2px at 16px em */
|
||||||
|
background-color: var(--color-background-active-narrow-filter);
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
.input:empty::before {
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
content: attr(data-placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-sidebar-filter-topic-input:placeholder-shown
|
.input {
|
||||||
+ #clear_search_topic_button {
|
flex-grow: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#clear_search_topic_button {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
height: 2em; /* 32px at 16px/1em */
|
||||||
}
|
}
|
||||||
|
|
||||||
.searching-for-more-topics img {
|
.searching-for-more-topics img {
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
<div class="topic_search_section filter-topics left-sidebar-filter-row">
|
<div class="topic_search_section filter-topics left-sidebar-filter-row">
|
||||||
<input class="topic-list-filter home-page-input filter_text_input" id="left-sidebar-filter-topic-input" type="text" autocomplete="off" placeholder="{{t 'Filter topics'}}" />
|
<div class="topic-list-filter home-page-input filter_text_input pill-container" id="left-sidebar-filter-topic-input">
|
||||||
|
<div class="input" contenteditable="true" id="topic_filter_query"
|
||||||
|
data-placeholder="{{t 'Filter topics' }}">
|
||||||
|
{{~! Squash whitespace so that placeholder is displayed when empty. ~}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button type="button" class="clear_search_button" id="clear_search_topic_button">
|
<button type="button" class="clear_search_button" id="clear_search_topic_button">
|
||||||
<i class="zulip-icon zulip-icon-close" aria-hidden="true"></i>
|
<i class="zulip-icon zulip-icon-close" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ let sort_stream_or_group_members_options_called = false;
|
|||||||
const $fake_rendered_person = $.create("fake-rendered-person");
|
const $fake_rendered_person = $.create("fake-rendered-person");
|
||||||
const $fake_rendered_stream = $.create("fake-rendered-stream");
|
const $fake_rendered_stream = $.create("fake-rendered-stream");
|
||||||
const $fake_rendered_group = $.create("fake-rendered-group");
|
const $fake_rendered_group = $.create("fake-rendered-group");
|
||||||
|
const $fake_rendered_topic_state = $.create("fake-rendered-topic-state");
|
||||||
|
|
||||||
function override_typeahead_helper({mock_template, override_rewire}) {
|
function override_typeahead_helper({mock_template, override_rewire}) {
|
||||||
mock_template("typeahead_list_item.hbs", false, (args) => {
|
mock_template("typeahead_list_item.hbs", false, (args) => {
|
||||||
@@ -422,6 +423,21 @@ run_test("set_up_user_group", ({mock_template, override, override_rewire}) => {
|
|||||||
assert.ok(input_pill_typeahead_called);
|
assert.ok(input_pill_typeahead_called);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_test("render_topic_state", ({override_rewire}) => {
|
||||||
|
override_rewire(typeahead_helper, "render_typeahead_item", (args) => {
|
||||||
|
assert.equal(args.primary, "Resolved");
|
||||||
|
return $fake_rendered_topic_state;
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = typeahead_helper.render_topic_state("Resolved");
|
||||||
|
assert.equal(result, $fake_rendered_topic_state);
|
||||||
|
|
||||||
|
override_rewire(typeahead_helper, "render_topic_state", (state) => `${state}`);
|
||||||
|
|
||||||
|
const new_result = typeahead_helper.render_topic_state("Unresolved");
|
||||||
|
assert.equal(new_result, "Unresolved");
|
||||||
|
});
|
||||||
|
|
||||||
run_test("set_up_combined", ({mock_template, override, override_rewire}) => {
|
run_test("set_up_combined", ({mock_template, override, override_rewire}) => {
|
||||||
override_typeahead_helper({mock_template, override_rewire});
|
override_typeahead_helper({mock_template, override_rewire});
|
||||||
mock_template("input_pill.hbs", true, (_data, html) => html);
|
mock_template("input_pill.hbs", true, (_data, html) => html);
|
||||||
|
|||||||
@@ -389,6 +389,8 @@ function elem($obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_ui("zoom_in_and_zoom_out", ({mock_template}) => {
|
test_ui("zoom_in_and_zoom_out", ({mock_template}) => {
|
||||||
|
topic_list.setup_topic_search_typeahead = noop;
|
||||||
|
|
||||||
const $label1 = $.create("label1 stub");
|
const $label1 = $.create("label1 stub");
|
||||||
const $label2 = $.create("label2 stub");
|
const $label2 = $.create("label2 stub");
|
||||||
|
|
||||||
|
|||||||
@@ -279,6 +279,26 @@ test("test_stream_has_topics", () => {
|
|||||||
assert.equal(stream_topic_history.stream_has_topics(stream_id), true);
|
assert.equal(stream_topic_history.stream_has_topics(stream_id), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("test_stream_has_resolved_topics", () => {
|
||||||
|
const stream_id = 89;
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
stream_topic_history.stream_has_locally_available_resolved_topics(stream_id),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
stream_topic_history.add_message({
|
||||||
|
stream_id,
|
||||||
|
message_id: 889,
|
||||||
|
topic_name: "✔ whatever",
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
stream_topic_history.stream_has_locally_available_resolved_topics(stream_id),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("server_history_end_to_end", () => {
|
test("server_history_end_to_end", () => {
|
||||||
stream_topic_history.reset();
|
stream_topic_history.reset();
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,28 @@ function get_list_info(zoom, search) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("filter_topics_by_search_term with resolved topics_state", () => {
|
||||||
|
const topic_names = ["topic 1", "✔ resolved topic", "topic 2"];
|
||||||
|
const search_term = "";
|
||||||
|
|
||||||
|
// Filter for resolved topics.
|
||||||
|
let topics_state = "is: resolved";
|
||||||
|
|
||||||
|
let result = topic_list_data.filter_topics_by_search_term(
|
||||||
|
topic_names,
|
||||||
|
search_term,
|
||||||
|
topics_state,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.deepEqual(result, ["✔ resolved topic"]);
|
||||||
|
|
||||||
|
// Filter for unresolved topics.
|
||||||
|
topics_state = "-is: resolved";
|
||||||
|
result = topic_list_data.filter_topics_by_search_term(topic_names, search_term, topics_state);
|
||||||
|
|
||||||
|
assert.deepEqual(result, ["topic 1", "topic 2"]);
|
||||||
|
});
|
||||||
|
|
||||||
function test(label, f) {
|
function test(label, f) {
|
||||||
run_test(label, (helpers) => {
|
run_test(label, (helpers) => {
|
||||||
stream_topic_history.reset();
|
stream_topic_history.reset();
|
||||||
|
|||||||
Reference in New Issue
Block a user