mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 18:36:36 +00:00
navbar: Describe views in top navbar.
Adds description in views styled like stream descriptions also adds a help center link to the appropriate page at the end of each description. Fixes #29769.
This commit is contained in:
committed by
Tim Abbott
parent
d36e19389d
commit
941c5daf36
@@ -912,7 +912,12 @@ export class Filter {
|
|||||||
return "#"; // redirect to All
|
return "#"; // redirect to All
|
||||||
}
|
}
|
||||||
|
|
||||||
add_icon_data(context: {title: string; is_spectator: boolean}): IconData {
|
add_icon_data(context: {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
link?: string;
|
||||||
|
is_spectator: boolean;
|
||||||
|
}): IconData {
|
||||||
// We have special icons for the simple narrows available for the via sidebars.
|
// We have special icons for the simple narrows available for the via sidebars.
|
||||||
const term_types = this.sorted_term_types();
|
const term_types = this.sorted_term_types();
|
||||||
let icon;
|
let icon;
|
||||||
@@ -1046,6 +1051,25 @@ export class Filter {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_description(): {description: string; link: string} | undefined {
|
||||||
|
const term_types = this.sorted_term_types();
|
||||||
|
switch (term_types[0]) {
|
||||||
|
case "is-mentioned":
|
||||||
|
return {
|
||||||
|
description: $t({defaultMessage: "Messages where you are mentioned."}),
|
||||||
|
link: "/help/view-your-mentions",
|
||||||
|
};
|
||||||
|
case "is-starred":
|
||||||
|
return {
|
||||||
|
description: $t({
|
||||||
|
defaultMessage: "Important messages, tasks, and other useful references.",
|
||||||
|
}),
|
||||||
|
link: "/help/star-a-message#view-your-starred-messages",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
allow_use_first_unread_when_narrowing(): boolean {
|
allow_use_first_unread_when_narrowing(): boolean {
|
||||||
return this.can_mark_messages_read() || this.has_operator("is");
|
return this.can_mark_messages_read() || this.has_operator("is");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import type {StreamSubscription} from "./sub_store";
|
|||||||
|
|
||||||
type MessageViewHeaderContext = {
|
type MessageViewHeaderContext = {
|
||||||
title: string;
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
link?: string;
|
||||||
is_spectator?: boolean;
|
is_spectator?: boolean;
|
||||||
sub_count?: string | number;
|
sub_count?: string | number;
|
||||||
formatted_sub_count?: string;
|
formatted_sub_count?: string;
|
||||||
@@ -39,27 +41,56 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
|
|||||||
if (recent_view_util.is_visible()) {
|
if (recent_view_util.is_visible()) {
|
||||||
return {
|
return {
|
||||||
title: $t({defaultMessage: "Recent conversations"}),
|
title: $t({defaultMessage: "Recent conversations"}),
|
||||||
|
description: $t({defaultMessage: "Overview of ongoing conversations."}),
|
||||||
zulip_icon: "recent",
|
zulip_icon: "recent",
|
||||||
|
link: "/help/recent-conversations",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inbox_util.is_visible()) {
|
if (inbox_util.is_visible()) {
|
||||||
return {
|
return {
|
||||||
title: $t({defaultMessage: "Inbox"}),
|
title: $t({defaultMessage: "Inbox"}),
|
||||||
|
description: $t({
|
||||||
|
defaultMessage: "Overview of your conversations with unread messages.",
|
||||||
|
}),
|
||||||
zulip_icon: "inbox",
|
zulip_icon: "inbox",
|
||||||
|
link: "/help/inbox",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (filter === undefined) {
|
|
||||||
|
// TODO: If we're not in the recent or inbox view, there should be
|
||||||
|
// a message feed with a declared filter in the center pane. But
|
||||||
|
// because of an initialization order bug, this function gets
|
||||||
|
// called with a filter of `undefined` when loading the web app
|
||||||
|
// with, say, inbox as the home view.
|
||||||
|
//
|
||||||
|
// TODO: Refactor this function to move the inbox/recent cases
|
||||||
|
// into the caller, and this function can always get a Filter object.
|
||||||
|
//
|
||||||
|
// TODO: This ideally doesn't need a special case, we can just use
|
||||||
|
// `filter.get_description` for it.
|
||||||
|
if (filter === undefined || filter.is_in_home()) {
|
||||||
return {
|
return {
|
||||||
title: $t({defaultMessage: "Combined feed"}),
|
title: $t({defaultMessage: "Combined feed"}),
|
||||||
|
description: $t({
|
||||||
|
defaultMessage: "All your messages except those in muted channels and topics.",
|
||||||
|
}),
|
||||||
zulip_icon: "all-messages",
|
zulip_icon: "all-messages",
|
||||||
|
link: "/help/combined-feed",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = filter.get_title();
|
const title = filter.get_title();
|
||||||
|
const description = filter.get_description()?.description;
|
||||||
|
const link = filter.get_description()?.link;
|
||||||
assert(title !== undefined);
|
assert(title !== undefined);
|
||||||
const icon_data = filter.add_icon_data({
|
const icon_data = filter.add_icon_data({
|
||||||
title,
|
title,
|
||||||
|
description,
|
||||||
|
link,
|
||||||
is_spectator: page_params.is_spectator,
|
is_spectator: page_params.is_spectator,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (filter.has_operator("channel") && !filter._sub) {
|
if (filter.has_operator("channel") && !filter._sub) {
|
||||||
return {
|
return {
|
||||||
...icon_data,
|
...icon_data,
|
||||||
@@ -70,6 +101,7 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter._sub) {
|
if (filter._sub) {
|
||||||
// We can now be certain that the narrow
|
// We can now be certain that the narrow
|
||||||
// involves a stream which exists and
|
// involves a stream which exists and
|
||||||
@@ -85,6 +117,7 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
|
|||||||
stream_settings_link: hash_util.channels_settings_edit_url(current_stream, "general"),
|
stream_settings_link: hash_util.channels_settings_edit_url(current_stream, "general"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return icon_data;
|
return icon_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,11 @@
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
.help_link_widget,
|
||||||
|
.fa {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The very last element in the navbar is the search icon, the second
|
/* The very last element in the navbar is the search icon, the second
|
||||||
|
|||||||
@@ -4,3 +4,12 @@
|
|||||||
<i class="fa fa-{{icon}}" aria-hidden="true"></i>
|
<i class="fa fa-{{icon}}" aria-hidden="true"></i>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span class="message-header-navbar-title">{{title}}</span>
|
<span class="message-header-navbar-title">{{title}}</span>
|
||||||
|
{{#if description}}
|
||||||
|
<span class="narrow_description rendered_markdown">{{description}}
|
||||||
|
{{#if link}}
|
||||||
|
<a class="help_link_widget" href="{{link}}" target="_blank" rel="noopener noreferrer">
|
||||||
|
<i class="fa fa-question-circle-o" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|||||||
@@ -1628,11 +1628,26 @@ test("navbar_helpers", () => {
|
|||||||
assert.deepEqual(filter.get_title(), test_case.title);
|
assert.deepEqual(filter.get_title(), test_case.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_get_description(test_case) {
|
||||||
|
const filter = new Filter(test_case.terms);
|
||||||
|
const description = filter.get_description();
|
||||||
|
|
||||||
|
if (test_case.description !== undefined && test_case.link !== undefined) {
|
||||||
|
assert.deepEqual(description, {
|
||||||
|
description: test_case.description,
|
||||||
|
link: test_case.link,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
assert.strictEqual(description, undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function test_helpers(test_case) {
|
function test_helpers(test_case) {
|
||||||
// debugging tip: add a `console.log(test_case)` here
|
// debugging tip: add a `console.log(test_case)` here
|
||||||
test_common_narrow(test_case);
|
test_common_narrow(test_case);
|
||||||
test_add_icon_data(test_case);
|
test_add_icon_data(test_case);
|
||||||
test_get_title(test_case);
|
test_get_title(test_case);
|
||||||
|
test_get_description(test_case);
|
||||||
test_redirect_url_with_search(test_case);
|
test_redirect_url_with_search(test_case);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1703,6 +1718,8 @@ test("navbar_helpers", () => {
|
|||||||
zulip_icon: "star-filled",
|
zulip_icon: "star-filled",
|
||||||
title: "translated: Starred messages",
|
title: "translated: Starred messages",
|
||||||
redirect_url_with_search: "/#narrow/is/starred",
|
redirect_url_with_search: "/#narrow/is/starred",
|
||||||
|
description: "translated: Important messages, tasks, and other useful references.",
|
||||||
|
link: "/help/star-a-message#view-your-starred-messages",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
terms: in_home,
|
terms: in_home,
|
||||||
@@ -1731,6 +1748,8 @@ test("navbar_helpers", () => {
|
|||||||
zulip_icon: "at-sign",
|
zulip_icon: "at-sign",
|
||||||
title: "translated: Mentions",
|
title: "translated: Mentions",
|
||||||
redirect_url_with_search: "/#narrow/is/mentioned",
|
redirect_url_with_search: "/#narrow/is/mentioned",
|
||||||
|
description: "translated: Messages where you are mentioned.",
|
||||||
|
link: "/help/view-your-mentions",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
terms: is_resolved,
|
terms: is_resolved,
|
||||||
|
|||||||
Reference in New Issue
Block a user