UX: improves search of message creator

- correctly show unread indicator
- handles disabled user correctly
- do not show new-group-chat when filtering
This commit is contained in:
Joffrey JAFFEUX 2023-11-13 22:03:47 +01:00 committed by GitHub
parent a814348176
commit a0769f6f43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 17 deletions

View File

@ -16,10 +16,11 @@ export default class Channel extends Component {
} }
<template> <template>
<div class="chat-message-creator__chatable-category-channel"> <div class="chat-message-creator__chatable -category-channel">
<ChatChannelTitle @channel={{@item.model}} /> <ChatChannelTitle @channel={{@item.model}} />
{{#if (gt @item.tracking.unreadCount 0)}} {{#if (gt @item.tracking.unreadCount 0)}}
<div <div
class={{concatClass "unread-indicator" (if this.isUrgent "-urgent")}} class={{concatClass "unread-indicator" (if this.isUrgent "-urgent")}}
></div> ></div>

View File

@ -5,6 +5,7 @@ import { action } from "@ember/object";
import concatClass from "discourse/helpers/concat-class"; import concatClass from "discourse/helpers/concat-class";
import I18n from "discourse-i18n"; import I18n from "discourse-i18n";
import eq from "truth-helpers/helpers/eq"; import eq from "truth-helpers/helpers/eq";
import not from "truth-helpers/helpers/not";
import Channel from "./channel"; import Channel from "./channel";
import ListAction from "./list-action"; import ListAction from "./list-action";
import User from "./user"; import User from "./user";
@ -73,6 +74,7 @@ export default class List extends Component {
tabindex="0" tabindex="0"
data-identifier={{item.identifier}} data-identifier={{item.identifier}}
id={{item.id}} id={{item.id}}
data-disabled={{not item.enabled}}
> >
{{component (this.componentForItem item.type) item=item}} {{component (this.componentForItem item.type) item=item}}
</li> </li>

View File

@ -43,6 +43,10 @@ export default class MembersSelector extends Component {
@action @action
selectChatable(chatable) { selectChatable(chatable) {
if (!chatable.enabled) {
return;
}
if ( if (
this.args.members.length + (this.args.channel?.membershipsCount ?? 0) >= this.args.members.length + (this.args.channel?.membershipsCount ?? 0) >=
this.siteSettings.chat_max_direct_message_users this.siteSettings.chat_max_direct_message_users

View File

@ -21,19 +21,28 @@ export default class ChatMessageCreatorSearch extends Component {
@tracked chatables = []; @tracked chatables = [];
@tracked highlightedChatable; @tracked highlightedChatable;
@tracked term;
@tracked loading = false;
get items() { get items() {
return [ const items = [];
{
if (this.loading) {
return items;
}
if (!this.term?.length) {
items.push({
identifier: "new-group", identifier: "new-group",
type: "list-action", type: "list-action",
label: I18n.t("chat.new_message_modal.new_group_chat"), label: I18n.t("chat.new_message_modal.new_group_chat"),
enabled: true, enabled: true,
icon: "users", icon: "users",
id: "new-group-chat", id: "new-group-chat",
}, });
...this.chatables, }
];
return [...items, ...this.chatables];
} }
@action @action
@ -53,6 +62,10 @@ export default class ChatMessageCreatorSearch extends Component {
this.args.onChangeMode(MODES.new_group); this.args.onChangeMode(MODES.new_group);
break; break;
case "user": case "user":
if (!item.enabled) {
return;
}
await this.startOneToOneChannel(item.model.username); await this.startOneToOneChannel(item.model.username);
break; break;
default: default:
@ -64,6 +77,9 @@ export default class ChatMessageCreatorSearch extends Component {
@action @action
onFilter(event) { onFilter(event) {
this.chatables = [];
this.term = event?.target?.value;
this.searchHandler = discourseDebounce( this.searchHandler = discourseDebounce(
this, this,
this.fetch, this.fetch,
@ -73,9 +89,11 @@ export default class ChatMessageCreatorSearch extends Component {
} }
@action @action
async fetch(term) { async fetch() {
const loader = new ChatablesLoader(this); const loader = new ChatablesLoader(this);
this.chatables = await loader.search(term, { preloadChannels: true }); this.chatables = await loader.search(this.term, {
preloadChannels: !this.term,
});
this.highlightedChatable = this.items[0]; this.highlightedChatable = this.items[0];
} }
@ -109,7 +127,7 @@ export default class ChatMessageCreatorSearch extends Component {
class="chat-message-creator__section" class="chat-message-creator__section"
{{didInsert (fn this.fetch null)}} {{didInsert (fn this.fetch null)}}
> >
<SearchInput @onFilter={{this.onFilter}} /> <SearchInput @filter={{this.term}} @onFilter={{this.onFilter}} />
<DButton <DButton
class="btn-flat chat-message-creator__search-input__cancel-button" class="btn-flat chat-message-creator__search-input__cancel-button"

View File

@ -12,7 +12,7 @@ export default class ChatableUser extends Component {
disabledUserLabel = I18n.t("chat.new_message_modal.disabled_user"); disabledUserLabel = I18n.t("chat.new_message_modal.disabled_user");
<template> <template>
<div class="chat-message-creator__chatable-user"> <div class="chat-message-creator__chatable -user">
<ChatUserAvatar @user={{@item.model}} @interactive={{false}} /> <ChatUserAvatar @user={{@item.model}} @interactive={{false}} />
<ChatUserDisplayName @user={{@item.model}} /> <ChatUserDisplayName @user={{@item.model}} />
@ -23,7 +23,7 @@ export default class ChatableUser extends Component {
{{userStatus @item.model currentUser=this.currentUser}} {{userStatus @item.model currentUser=this.currentUser}}
{{#unless @item.enabled}} {{#unless @item.enabled}}
<span class="disabled-text"> <span class="chat-message-creator__chatable -disabled-chat">
{{this.disabledUserLabel}} {{this.disabledUserLabel}}
</span> </span>
{{/unless}} {{/unless}}

View File

@ -175,14 +175,19 @@
display: flex; display: flex;
align-items: center; align-items: center;
&[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.d-icon-users { .d-icon-users {
padding: 2px 2px; padding: 4px 4px;
box-sizing: border-box; box-sizing: border-box;
color: var(--tertiary); color: var(--tertiary);
background: var(--primary-low); background: var(--primary-low);
border-radius: 100%; border-radius: 100%;
width: 18px; width: 24px;
height: 18px; height: 22px;
} }
.btn { .btn {
@ -195,12 +200,35 @@
} }
} }
.chat-message-creator__chatable-user { .chat-message-creator__chatable.-user {
.chat-user-display-name {
padding-left: 0.5rem;
}
.chat-message-creator__chatable.-disabled-chat {
padding-left: 0.25rem;
}
}
.chat-message-creator__chatable.-category-channel {
.chat-channel-title__category-badge {
display: flex;
justify-content: center;
width: 24px;
}
}
.chat-message-creator__chatable.-user,
.chat-message-creator__chatable.-category-channel {
display: flex; display: flex;
align-items: center; align-items: center;
.chat-user-display-name { .unread-indicator {
padding-left: 0.5rem; margin-left: 0.5rem;
width: 8px;
height: 8px;
background: var(--tertiary);
border-radius: 100%;
} }
} }

View File

@ -20,6 +20,14 @@ RSpec.describe "Flag message", type: :system do
expect(chat_page.message_creator).to be_listing(channel_1) expect(chat_page.message_creator).to be_listing(channel_1)
end end
it "doesn’t show create group option when filtered" do
visit("/")
chat_page.open_new_message
chat_page.message_creator.filter("x")
expect(chat_page).to have_no_css("#new-group-chat")
end
it "can filter channels" do it "can filter channels" do
channel_1 = Fabricate(:chat_channel) channel_1 = Fabricate(:chat_channel)
channel_2 = Fabricate(:chat_channel) channel_2 = Fabricate(:chat_channel)