FEATURE: load chat channel settings within drawer (#27346)
This change allows chat drawer users to edit channel settings and members without leaving drawer mode. If a channel is open within chat drawer and the user clicks the Channel name, it will load channel settings within the drawer.
This commit is contained in:
parent
6e56a76b20
commit
891fb17f60
|
@ -0,0 +1,60 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||
import { service } from "@ember/service";
|
||||
import I18n from "discourse-i18n";
|
||||
import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
|
||||
import ChannelMembers from "discourse/plugins/chat/discourse/components/chat/routes/channel-info-members";
|
||||
import ChannelInfoNav from "discourse/plugins/chat/discourse/components/chat/routes/channel-info-nav";
|
||||
|
||||
export default class ChatDrawerRoutesMembers extends Component {
|
||||
@service chat;
|
||||
@service chatStateManager;
|
||||
@service chatChannelsManager;
|
||||
|
||||
get backButton() {
|
||||
return {
|
||||
route: "chat.channel",
|
||||
models: this.chat.activeChannel?.routeModels,
|
||||
title: I18n.t("chat.return_to_channel"),
|
||||
};
|
||||
}
|
||||
|
||||
@action
|
||||
async fetchChannel() {
|
||||
if (!this.args.params?.channelId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = await this.chatChannelsManager.find(
|
||||
this.args.params.channelId
|
||||
);
|
||||
|
||||
this.chat.activeChannel = channel;
|
||||
}
|
||||
|
||||
<template>
|
||||
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
|
||||
<navbar.BackButton
|
||||
@title={{this.backButton.title}}
|
||||
@route={{this.backButton.route}}
|
||||
@routeModels={{this.backButton.models}}
|
||||
/>
|
||||
<navbar.ChannelTitle @channel={{this.chat.activeChannel}} />
|
||||
<navbar.Actions as |a|>
|
||||
<a.ToggleDrawerButton />
|
||||
<a.FullPageButton />
|
||||
<a.CloseDrawerButton />
|
||||
</navbar.Actions>
|
||||
</Navbar>
|
||||
|
||||
{{#if this.chatStateManager.isDrawerExpanded}}
|
||||
<div class="chat-drawer-content" {{didInsert this.fetchChannel}}>
|
||||
{{#if this.chat.activeChannel}}
|
||||
<ChannelInfoNav @channel={{this.chat.activeChannel}} @tab="members" />
|
||||
<ChannelMembers @channel={{this.chat.activeChannel}} />
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||
import { service } from "@ember/service";
|
||||
import I18n from "discourse-i18n";
|
||||
import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
|
||||
import ChannelInfoNav from "discourse/plugins/chat/discourse/components/chat/routes/channel-info-nav";
|
||||
import ChannelSettings from "discourse/plugins/chat/discourse/components/chat/routes/channel-info-settings";
|
||||
|
||||
export default class ChatDrawerRoutesSettings extends Component {
|
||||
@service chat;
|
||||
@service chatStateManager;
|
||||
@service chatChannelsManager;
|
||||
|
||||
get backButton() {
|
||||
return {
|
||||
route: "chat.channel",
|
||||
models: this.chat.activeChannel?.routeModels,
|
||||
title: I18n.t("chat.return_to_channel"),
|
||||
};
|
||||
}
|
||||
|
||||
@action
|
||||
async fetchChannel() {
|
||||
if (!this.args.params?.channelId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = await this.chatChannelsManager.find(
|
||||
this.args.params.channelId
|
||||
);
|
||||
|
||||
this.chat.activeChannel = channel;
|
||||
}
|
||||
|
||||
<template>
|
||||
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
|
||||
<navbar.BackButton
|
||||
@title={{this.backButton.title}}
|
||||
@route={{this.backButton.route}}
|
||||
@routeModels={{this.backButton.models}}
|
||||
/>
|
||||
<navbar.ChannelTitle @channel={{this.chat.activeChannel}} />
|
||||
<navbar.Actions as |a|>
|
||||
<a.ToggleDrawerButton />
|
||||
<a.FullPageButton />
|
||||
<a.CloseDrawerButton />
|
||||
</navbar.Actions>
|
||||
</Navbar>
|
||||
|
||||
{{#if this.chatStateManager.isDrawerExpanded}}
|
||||
<div class="chat-drawer-content" {{didInsert this.fetchChannel}}>
|
||||
{{#if this.chat.activeChannel}}
|
||||
<ChannelInfoNav
|
||||
@channel={{this.chat.activeChannel}}
|
||||
@tab="settings"
|
||||
/>
|
||||
<ChannelSettings @channel={{this.chat.activeChannel}} />
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
|
@ -54,10 +54,7 @@ export default class ChatModalEditChannelName extends Component {
|
|||
this.channel.title = result.channel.title;
|
||||
this.channel.slug = result.channel.slug;
|
||||
await this.args.closeModal();
|
||||
await this.router.replaceWith(
|
||||
"chat.channel",
|
||||
...this.channel.routeModels
|
||||
);
|
||||
this.router.replaceWith("chat.channel", ...this.channel.routeModels);
|
||||
} catch (error) {
|
||||
this.flash = extractError(error);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { LinkTo } from "@ember/routing";
|
||||
import { service } from "@ember/service";
|
||||
import { eq } from "truth-helpers";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
|
||||
export default class ChatRoutesChannelInfoNav extends Component {
|
||||
@service site;
|
||||
|
||||
get showTabs() {
|
||||
return this.site.desktopView && this.args.channel.isOpen;
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if this.showTabs}}
|
||||
<nav class="c-channel-info__nav">
|
||||
<ul class="nav nav-pills">
|
||||
<li>
|
||||
<LinkTo
|
||||
@route="chat.channel.info.settings"
|
||||
@models={{@channel.routeModels}}
|
||||
class={{if (eq @tab "settings") "active"}}
|
||||
@replace={{true}}
|
||||
>
|
||||
{{i18n "chat.channel_info.tabs.settings"}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li>
|
||||
<LinkTo
|
||||
@route="chat.channel.info.members"
|
||||
@models={{@channel.routeModels}}
|
||||
class={{if (eq @tab "members") "active"}}
|
||||
@replace={{true}}
|
||||
>
|
||||
{{i18n "chat.channel_info.tabs.members"}}
|
||||
{{#if @channel.isCategoryChannel}}
|
||||
<span
|
||||
class="c-channel-info__member-count"
|
||||
>({{@channel.membershipsCount}})</span>
|
||||
{{/if}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import { LinkTo } from "@ember/routing";
|
||||
import { service } from "@ember/service";
|
||||
import I18n from "discourse-i18n";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import ChatModalEditChannelName from "discourse/plugins/chat/discourse/components/chat/modal/edit-channel-name";
|
||||
import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
|
||||
import ChatChannelStatus from "discourse/plugins/chat/discourse/components/chat-channel-status";
|
||||
import ChannelInfoNav from "./channel-info-nav";
|
||||
|
||||
export default class ChatRoutesChannelInfo extends Component {
|
||||
@service chatChannelInfoRouteOriginManager;
|
||||
|
@ -13,15 +13,6 @@ export default class ChatRoutesChannelInfo extends Component {
|
|||
@service modal;
|
||||
@service chatGuardian;
|
||||
|
||||
membersLabel = I18n.t("chat.channel_info.tabs.members");
|
||||
settingsLabel = I18n.t("chat.channel_info.tabs.settings");
|
||||
backToChannelLabel = I18n.t("chat.channel_info.back_to_all_channels");
|
||||
backToAllChannelsLabel = I18n.t("chat.channel_info.back_to_channel");
|
||||
|
||||
get showTabs() {
|
||||
return this.site.desktopView && this.args.channel.isOpen;
|
||||
}
|
||||
|
||||
get canEditChannel() {
|
||||
return (
|
||||
this.chatGuardian.canEditChatChannel() &&
|
||||
|
@ -44,13 +35,13 @@ export default class ChatRoutesChannelInfo extends Component {
|
|||
{{#if this.chatChannelInfoRouteOriginManager.isBrowse}}
|
||||
<navbar.BackButton
|
||||
@route="chat.browse"
|
||||
@title={{this.backToAllChannelsLabel}}
|
||||
@title={{i18n "chat.channel_info.back_to_all_channels"}}
|
||||
/>
|
||||
{{else}}
|
||||
<navbar.BackButton
|
||||
@route="chat.channel"
|
||||
@routeModels={{@channel.routeModels}}
|
||||
@title={{this.backToChannelLabel}}
|
||||
@title={{i18n "chat.channel_info.back_to_channel"}}
|
||||
/>
|
||||
{{/if}}
|
||||
<navbar.ChannelTitle @channel={{@channel}} />
|
||||
|
@ -59,36 +50,7 @@ export default class ChatRoutesChannelInfo extends Component {
|
|||
<ChatChannelStatus @channel={{@channel}} />
|
||||
|
||||
<div class="c-channel-info">
|
||||
{{#if this.showTabs}}
|
||||
<nav class="c-channel-info__nav">
|
||||
<ul class="nav nav-pills">
|
||||
<li>
|
||||
<LinkTo
|
||||
@route="chat.channel.info.settings"
|
||||
@model={{@channel}}
|
||||
@replace={{true}}
|
||||
>
|
||||
{{this.settingsLabel}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li>
|
||||
<LinkTo
|
||||
@route="chat.channel.info.members"
|
||||
@model={{@channel}}
|
||||
@replace={{true}}
|
||||
>
|
||||
{{this.membersLabel}}
|
||||
{{#if @channel.isCategoryChannel}}
|
||||
<span
|
||||
class="c-channel-info__member-count"
|
||||
>({{@channel.membershipsCount}})</span>
|
||||
{{/if}}
|
||||
</LinkTo>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{/if}}
|
||||
|
||||
<ChannelInfoNav @channel={{@channel}} />
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -39,6 +39,8 @@ export default class ChatRoute extends DiscourseRoute {
|
|||
"chat.channel.index",
|
||||
"chat.channel.near-message",
|
||||
"chat.channel-legacy",
|
||||
"chat.channel.info.settings",
|
||||
"chat.channel.info.members",
|
||||
"chat",
|
||||
"chat.index",
|
||||
];
|
||||
|
|
|
@ -97,6 +97,9 @@ export default class ChatChannelsManager extends Service {
|
|||
}
|
||||
|
||||
remove(model) {
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
this.chatSubscriptionsManager.stopChannelSubscription(model);
|
||||
delete this._cached[model.id];
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import ChatDrawerRoutesChannel from "discourse/plugins/chat/discourse/components
|
|||
import ChatDrawerRoutesChannelThread from "discourse/plugins/chat/discourse/components/chat/drawer-routes/channel-thread";
|
||||
import ChatDrawerRoutesChannelThreads from "discourse/plugins/chat/discourse/components/chat/drawer-routes/channel-threads";
|
||||
import ChatDrawerRoutesChannels from "discourse/plugins/chat/discourse/components/chat/drawer-routes/channels";
|
||||
import ChatDrawerRoutesMembers from "discourse/plugins/chat/discourse/components/chat/drawer-routes/members";
|
||||
import ChatDrawerRoutesSettings from "discourse/plugins/chat/discourse/components/chat/drawer-routes/settings";
|
||||
import ChatDrawerRoutesThreads from "discourse/plugins/chat/discourse/components/chat/drawer-routes/threads";
|
||||
|
||||
const ROUTES = {
|
||||
|
@ -66,6 +68,22 @@ const ROUTES = {
|
|||
};
|
||||
},
|
||||
},
|
||||
"chat.channel.info.settings": {
|
||||
name: ChatDrawerRoutesSettings,
|
||||
extractParams: (route) => {
|
||||
return {
|
||||
channelId: route.parent.params.channelId,
|
||||
};
|
||||
},
|
||||
},
|
||||
"chat.channel.info.members": {
|
||||
name: ChatDrawerRoutesMembers,
|
||||
extractParams: (route) => {
|
||||
return {
|
||||
channelId: route.parent.params.channelId,
|
||||
};
|
||||
},
|
||||
},
|
||||
"chat.channel-legacy": {
|
||||
name: ChatDrawerRoutesChannel,
|
||||
extractParams: (route) => {
|
||||
|
|
|
@ -43,6 +43,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
.chat-drawer-container .c-channel-settings,
|
||||
.chat-drawer-container .c-channel-info__nav,
|
||||
.chat-drawer-container .c-channel-members,
|
||||
.chat-drawer-container .chat-message-creator-container {
|
||||
padding: 1rem;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.chat-drawer-container .c-channel-info__nav,
|
||||
.chat-drawer-container .c-channel-info__nav .nav-pills {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.chat-drawer-container .c-footer .chat-channel-unread-indicator.-urgent {
|
||||
width: min-content;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ RSpec.describe "Drawer", type: :system do
|
|||
before do
|
||||
chat_system_bootstrap
|
||||
sign_in(current_user)
|
||||
chat_page.prefers_drawer
|
||||
end
|
||||
|
||||
context "when on channel" do
|
||||
|
@ -18,13 +19,32 @@ RSpec.describe "Drawer", type: :system do
|
|||
end
|
||||
|
||||
context "when clicking channel title" do
|
||||
it "opens channel settings page" do
|
||||
before do
|
||||
visit("/")
|
||||
chat_page.open_from_header
|
||||
drawer_page.open_channel(channel)
|
||||
page.find(".c-navbar__channel-title").click
|
||||
end
|
||||
|
||||
expect(page).to have_current_path("/chat/c/#{channel.slug}/#{channel.id}/info/settings")
|
||||
it "opens channel settings page" do
|
||||
expect(drawer_page).to have_channel_settings
|
||||
end
|
||||
|
||||
it "has tabs for settings and members" do
|
||||
expect(drawer_page).to have_css(".c-channel-info__nav li a", text: "Settings")
|
||||
expect(drawer_page).to have_css(".c-channel-info__nav li a", text: "Members")
|
||||
end
|
||||
|
||||
it "opens correct tab when clicked" do
|
||||
page.find(".c-channel-info__nav li a", text: "Members").click
|
||||
expect(drawer_page).to have_channel_members
|
||||
|
||||
page.find(".c-channel-info__nav li a", text: "Settings").click
|
||||
expect(drawer_page).to have_channel_settings
|
||||
end
|
||||
|
||||
it "has a back button" do
|
||||
expect(drawer_page).to have_css(".c-navbar__back-button")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -88,6 +88,14 @@ module PageObjects
|
|||
has_css?("#{VISIBLE_DRAWER} .chat-channel[data-id='#{channel.id}']")
|
||||
end
|
||||
|
||||
def has_channel_settings?
|
||||
has_css?("#{VISIBLE_DRAWER} .c-channel-settings")
|
||||
end
|
||||
|
||||
def has_channel_members?
|
||||
has_css?("#{VISIBLE_DRAWER} .c-channel-members")
|
||||
end
|
||||
|
||||
def has_open_thread_list?
|
||||
has_css?("#{VISIBLE_DRAWER} .chat-thread-list")
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue