FEATURE: channels can allow/disallow @all/@here mentions (#19317)
The settings tab of each category channel should now present the option to allow or disallow channel wide mentions: @here and @all. When disallowed, using these mentions in the channel should have no effect.
This commit is contained in:
parent
569299b7a9
commit
68c4f16a73
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
CHAT_CHANNEL_EDITABLE_PARAMS = %i[name description]
|
CHAT_CHANNEL_EDITABLE_PARAMS = %i[name description]
|
||||||
CATEGORY_CHAT_CHANNEL_EDITABLE_PARAMS = %i[auto_join_users]
|
CATEGORY_CHAT_CHANNEL_EDITABLE_PARAMS = %i[auto_join_users allow_channel_wide_mentions]
|
||||||
|
|
||||||
class Chat::Api::ChatChannelsController < Chat::Api
|
class Chat::Api::ChatChannelsController < Chat::Api
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -121,24 +121,25 @@ end
|
||||||
#
|
#
|
||||||
# Table name: chat_channels
|
# Table name: chat_channels
|
||||||
#
|
#
|
||||||
# id :bigint not null, primary key
|
# id :bigint not null, primary key
|
||||||
# chatable_id :integer not null
|
# chatable_id :integer not null
|
||||||
# deleted_at :datetime
|
# deleted_at :datetime
|
||||||
# deleted_by_id :integer
|
# deleted_by_id :integer
|
||||||
# featured_in_category_id :integer
|
# featured_in_category_id :integer
|
||||||
# delete_after_seconds :integer
|
# delete_after_seconds :integer
|
||||||
# chatable_type :string not null
|
# chatable_type :string not null
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# name :string
|
# name :string
|
||||||
# description :text
|
# description :text
|
||||||
# status :integer default("open"), not null
|
# status :integer default("open"), not null
|
||||||
# user_count :integer default(0), not null
|
# user_count :integer default(0), not null
|
||||||
# last_message_sent_at :datetime not null
|
# last_message_sent_at :datetime not null
|
||||||
# auto_join_users :boolean default(FALSE), not null
|
# auto_join_users :boolean default(FALSE), not null
|
||||||
# user_count_stale :boolean default(FALSE), not null
|
# allow_channel_wide_mentions :boolean default(TRUE), not null
|
||||||
# slug :string
|
# user_count_stale :boolean default(FALSE), not null
|
||||||
# type :string
|
# slug :string
|
||||||
|
# type :string
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
class ChatChannelSerializer < ApplicationSerializer
|
class ChatChannelSerializer < ApplicationSerializer
|
||||||
attributes :id,
|
attributes :id,
|
||||||
:auto_join_users,
|
:auto_join_users,
|
||||||
|
:allow_channel_wide_mentions,
|
||||||
:chatable,
|
:chatable,
|
||||||
:chatable_id,
|
:chatable_id,
|
||||||
:chatable_type,
|
:chatable_type,
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<span
|
||||||
|
{{did-update this.activate @property}}
|
||||||
|
{{will-destroy this.teardown}}
|
||||||
|
class={{concat-class "chat-channel-settings-saved-indicator" (if this.isActive "is-active")}}
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
{{#if this.isActive}}
|
||||||
|
{{d-icon "check"}}
|
||||||
|
<span>{{i18n "saved"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</span>
|
|
@ -0,0 +1,28 @@
|
||||||
|
import discourseLater from "discourse-common/lib/later";
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { cancel } from "@ember/runloop";
|
||||||
|
|
||||||
|
const ACTIVE_DURATION = 2000;
|
||||||
|
|
||||||
|
export default class ChatChannelSettingsSavedIndicator extends Component {
|
||||||
|
@tracked isActive = false;
|
||||||
|
property = null;
|
||||||
|
|
||||||
|
@action
|
||||||
|
activate() {
|
||||||
|
cancel(this._deactivateHandler);
|
||||||
|
|
||||||
|
this.isActive = true;
|
||||||
|
|
||||||
|
this._deactivateHandler = discourseLater(() => {
|
||||||
|
this.isActive = false;
|
||||||
|
}, ACTIVE_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
teardown() {
|
||||||
|
cancel(this._deactivateHandler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,58 +2,122 @@
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<label class="chat-form__label">
|
<label class="chat-form__label">
|
||||||
<span>{{i18n "chat.settings.mute"}}</span>
|
<span>{{i18n "chat.settings.mute"}}</span>
|
||||||
|
<ChatChannelSettingsSavedIndicator
|
||||||
|
@property={{this.channel.current_user_membership.muted}}
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div class="chat-form__control">
|
<div class="chat-form__control">
|
||||||
<ComboBox @content={{this.mutedOptions}} @value={{this.channel.current_user_membership.muted}} @valueProperty="value" @class="channel-settings-view__muted-selector" @onChange={{action (fn this.saveNotificationSettings "muted")}} />
|
<ComboBox
|
||||||
{{#if this.savedMuted}}
|
@content={{this.mutedOptions}}
|
||||||
<span class="channel-settings-view__saved" role="status" aria-label={{i18n "chat.channel_settings.save_label.mute_channel"}}>
|
@value={{this.channel.current_user_membership.muted}}
|
||||||
{{d-icon "check"}} {{i18n "saved"}}
|
@valueProperty="value"
|
||||||
</span>
|
@class="channel-settings-view__muted-selector"
|
||||||
{{/if}}
|
@onChange={{action (fn this.saveNotificationSettings "muted")}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#unless this.channel.current_user_membership.muted}}
|
{{#unless this.channel.current_user_membership.muted}}
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<label class="chat-form__label">
|
<label class="chat-form__label">
|
||||||
<span>{{i18n "chat.settings.desktop_notification_level"}}</span>
|
<span>{{i18n "chat.settings.desktop_notification_level"}}</span>
|
||||||
|
<ChatChannelSettingsSavedIndicator
|
||||||
|
@property={{this.channel.current_user_membership.desktop_notification_level}}
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div class="chat-form__control">
|
<div class="chat-form__control">
|
||||||
<ComboBox @content={{this.notificationLevels}} @value={{this.channel.current_user_membership.desktop_notification_level}} @valueProperty="value" @class="channel-settings-view__desktop-notification-level-selector" @onChange={{action (fn this.saveNotificationSettings "desktop_notification_level")}} />
|
<ComboBox
|
||||||
{{#if this.savedDesktopNotificationLevel}}
|
@content={{this.notificationLevels}}
|
||||||
<span class="channel-settings-view__saved" role="status" aria-label={{i18n "chat.channel_settings.save_label.desktop_notification"}}>
|
@value={{this.channel.current_user_membership.desktop_notification_level}}
|
||||||
{{d-icon "check"}} {{i18n "saved"}}
|
@valueProperty="value"
|
||||||
</span>
|
@class="channel-settings-view__desktop-notification-level-selector"
|
||||||
{{/if}}
|
@onChange={{action
|
||||||
|
(fn this.saveNotificationSettings "desktop_notification_level")
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<label class="chat-form__label">
|
<label class="chat-form__label">
|
||||||
<span>{{i18n "chat.settings.mobile_notification_level"}}</span>
|
<span>{{i18n "chat.settings.mobile_notification_level"}}</span>
|
||||||
|
<ChatChannelSettingsSavedIndicator
|
||||||
|
@property={{this.channel.current_user_membership.mobile_notification_level}}
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div class="chat-form__control">
|
<div class="chat-form__control">
|
||||||
<ComboBox @content={{this.notificationLevels}} @value={{this.channel.current_user_membership.mobile_notification_level}} @valueProperty="value" @class="channel-settings-view__mobile-notification-level-selector" @onChange={{action (fn this.saveNotificationSettings "mobile_notification_level")}} />
|
<ComboBox
|
||||||
{{#if this.savedMobileNotificationLevel}}
|
@content={{this.notificationLevels}}
|
||||||
<span class="channel-settings-view__saved" role="status" aria-label={{i18n "chat.channel_settings.save_label.mobile_notification"}}>
|
@value={{this.channel.current_user_membership.mobile_notification_level}}
|
||||||
{{d-icon "check"}} {{i18n "saved"}}
|
@valueProperty="value"
|
||||||
</span>
|
@class="channel-settings-view__mobile-notification-level-selector"
|
||||||
{{/if}}
|
@onChange={{action
|
||||||
|
(fn this.saveNotificationSettings "mobile_notification_level")
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
<div class="chat-retention-info">{{d-icon "info-circle"}}{{i18n "chat.settings.retention_info" days=this.siteSettings.chat_channel_retention_days}}</div>
|
<div class="chat-retention-info">
|
||||||
|
{{d-icon "info-circle"}}
|
||||||
|
{{i18n
|
||||||
|
"chat.settings.retention_info"
|
||||||
|
days=this.siteSettings.chat_channel_retention_days
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if (chat-guardian "can-edit-chat-channel")}}
|
{{#if this.adminSectionAvailable}}
|
||||||
<h3 class="chat-form__section-admin-title">{{i18n "chat.settings.admin_title"}}</h3>
|
<h3 class="chat-form__section-admin-title">
|
||||||
|
{{i18n "chat.settings.admin_title"}}
|
||||||
|
</h3>
|
||||||
{{#if this.autoJoinAvailable}}
|
{{#if this.autoJoinAvailable}}
|
||||||
<div class="chat-form__section">
|
<div class="chat-form__section">
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<label class="chat-form__label">
|
<label class="chat-form__label">
|
||||||
<span>{{i18n "chat.settings.auto_join_users_label"}}</span>
|
<span>{{i18n "chat.settings.auto_join_users_label"}}</span>
|
||||||
|
<ChatChannelSettingsSavedIndicator
|
||||||
|
@property={{this.channel.auto_join_users}}
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
<ComboBox @content={{this.autoAddUsersOptions}} @value={{this.channel.auto_join_users}} @valueProperty="value" @class="channel-settings-view__auto-join-selector" @onChange={{action (fn this.onToggleAutoJoinUsers this.channel.auto_join_users)}} />
|
<ComboBox
|
||||||
<div class="chat-form__description -autojoin">{{i18n "chat.settings.auto_join_users_info" category=this.channel.chatable.name}}</div>
|
@content={{this.autoAddUsersOptions}}
|
||||||
|
@value={{this.channel.auto_join_users}}
|
||||||
|
@valueProperty="value"
|
||||||
|
@class="channel-settings-view__auto-join-selector"
|
||||||
|
@onChange={{action
|
||||||
|
(fn this.onToggleAutoJoinUsers this.channel.auto_join_users)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p class="chat-form__description -autojoin">
|
||||||
|
{{i18n
|
||||||
|
"chat.settings.auto_join_users_info"
|
||||||
|
category=this.channel.chatable.name
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.togglingChannelWideMentionsAvailable}}
|
||||||
|
<div class="chat-form__section">
|
||||||
|
<div class="chat-form__field">
|
||||||
|
<label class="chat-form__label">
|
||||||
|
<span>{{i18n "chat.settings.channel_wide_mentions_label"}}</span>
|
||||||
|
<ChatChannelSettingsSavedIndicator
|
||||||
|
@property={{this.channel.allow_channel_wide_mentions}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<ComboBox
|
||||||
|
@content={{this.channelWideMentionsOptions}}
|
||||||
|
@value={{this.channel.allow_channel_wide_mentions}}
|
||||||
|
@valueProperty="value"
|
||||||
|
@class="channel-settings-view__channel-wide-mentions-selector"
|
||||||
|
@onChange={{this.onToggleChannelWideMentions}}
|
||||||
|
/>
|
||||||
|
<p class="chat-form__description -channel-wide-mentions">
|
||||||
|
{{i18n "chat.settings.channel_wide_mentions_description" channel=this.channel.title}}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -64,22 +128,42 @@
|
||||||
{{#if (chat-guardian "can-edit-chat-channel")}}
|
{{#if (chat-guardian "can-edit-chat-channel")}}
|
||||||
{{#if (chat-guardian "can-archive-channel" this.channel)}}
|
{{#if (chat-guardian "can-archive-channel" this.channel)}}
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<DButton @action={{action "onArchiveChannel"}} @label="chat.channel_settings.archive_channel" @class="archive-btn chat-form__btn btn-flat" @icon="archive" />
|
<DButton
|
||||||
|
@action={{action "onArchiveChannel"}}
|
||||||
|
@label="chat.channel_settings.archive_channel"
|
||||||
|
@class="archive-btn chat-form__btn btn-flat"
|
||||||
|
@icon="archive"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if this.channel.isClosed}}
|
{{#if this.channel.isClosed}}
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<DButton @action={{action "onToggleChannelState"}} @label="chat.channel_settings.open_channel" @class="open-btn chat-form__btn btn-flat" @icon="unlock" />
|
<DButton
|
||||||
|
@action={{action "onToggleChannelState"}}
|
||||||
|
@label="chat.channel_settings.open_channel"
|
||||||
|
@class="open-btn chat-form__btn btn-flat"
|
||||||
|
@icon="unlock"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<DButton @action={{action "onToggleChannelState"}} @label="chat.channel_settings.close_channel" @class="close-btn chat-form__btn btn-flat" @icon="lock" />
|
<DButton
|
||||||
|
@action={{action "onToggleChannelState"}}
|
||||||
|
@label="chat.channel_settings.close_channel"
|
||||||
|
@class="close-btn chat-form__btn btn-flat"
|
||||||
|
@icon="lock"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="chat-form__field">
|
<div class="chat-form__field">
|
||||||
<DButton @action={{action "onDeleteChannel"}} @label="chat.channel_settings.delete_channel" @class="delete-btn chat-form__btn btn-flat" @icon="trash-alt" />
|
<DButton
|
||||||
|
@action={{action "onDeleteChannel"}}
|
||||||
|
@label="chat.channel_settings.delete_channel"
|
||||||
|
@class="delete-btn chat-form__btn btn-flat"
|
||||||
|
@icon="trash-alt"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { inject as service } from "@ember/service";
|
||||||
import ChatApi from "discourse/plugins/chat/discourse/lib/chat-api";
|
import ChatApi from "discourse/plugins/chat/discourse/lib/chat-api";
|
||||||
import showModal from "discourse/lib/show-modal";
|
import showModal from "discourse/lib/show-modal";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { camelize } from "@ember/string";
|
import { Promise } from "rsvp";
|
||||||
import discourseLater from "discourse-common/lib/later";
|
import { reads } from "@ember/object/computed";
|
||||||
|
|
||||||
const NOTIFICATION_LEVELS = [
|
const NOTIFICATION_LEVELS = [
|
||||||
{ name: I18n.t("chat.notification_levels.never"), value: "never" },
|
{ name: I18n.t("chat.notification_levels.never"), value: "never" },
|
||||||
|
@ -23,8 +23,17 @@ const AUTO_ADD_USERS_OPTIONS = [
|
||||||
{ name: I18n.t("no_value"), value: false },
|
{ name: I18n.t("no_value"), value: false },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const CHANNEL_WIDE_MENTIONS_OPTIONS = [
|
||||||
|
{ name: I18n.t("yes_value"), value: true },
|
||||||
|
{
|
||||||
|
name: I18n.t("no_value"),
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export default class ChatChannelSettingsView extends Component {
|
export default class ChatChannelSettingsView extends Component {
|
||||||
@service chat;
|
@service chat;
|
||||||
|
@service chatGuardian;
|
||||||
@service router;
|
@service router;
|
||||||
@service dialog;
|
@service dialog;
|
||||||
tagName = "";
|
tagName = "";
|
||||||
|
@ -33,57 +42,28 @@ export default class ChatChannelSettingsView extends Component {
|
||||||
notificationLevels = NOTIFICATION_LEVELS;
|
notificationLevels = NOTIFICATION_LEVELS;
|
||||||
mutedOptions = MUTED_OPTIONS;
|
mutedOptions = MUTED_OPTIONS;
|
||||||
autoAddUsersOptions = AUTO_ADD_USERS_OPTIONS;
|
autoAddUsersOptions = AUTO_ADD_USERS_OPTIONS;
|
||||||
|
channelWideMentionsOptions = CHANNEL_WIDE_MENTIONS_OPTIONS;
|
||||||
isSavingNotificationSetting = false;
|
isSavingNotificationSetting = false;
|
||||||
savedDesktopNotificationLevel = false;
|
savedDesktopNotificationLevel = false;
|
||||||
savedMobileNotificationLevel = false;
|
savedMobileNotificationLevel = false;
|
||||||
savedMuted = false;
|
savedMuted = false;
|
||||||
|
|
||||||
_updateAutoJoinUsers(value) {
|
@reads("channel.isCategoryChannel") togglingChannelWideMentionsAvailable;
|
||||||
return ChatApi.modifyChatChannel(this.channel.id, {
|
|
||||||
auto_join_users: value,
|
@computed("channel.isCategoryChannel")
|
||||||
})
|
get autoJoinAvailable() {
|
||||||
.then((chatChannel) => {
|
return (
|
||||||
this.channel.set("auto_join_users", chatChannel.auto_join_users);
|
this.siteSettings.max_chat_auto_joined_users > 0 &&
|
||||||
})
|
this.channel.isCategoryChannel
|
||||||
.catch((event) => {
|
);
|
||||||
if (event.jqXHR?.responseJSON?.errors) {
|
|
||||||
this.flash(event.jqXHR.responseJSON.errors.join("\n"), "error");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@computed("autoJoinAvailable", "togglingChannelWideMentionsAvailable")
|
||||||
saveNotificationSettings(key, value) {
|
get adminSectionAvailable() {
|
||||||
if (this.channel[key] === value) {
|
return (
|
||||||
return;
|
this.chatGuardian.canEditChatChannel &&
|
||||||
}
|
(this.autoJoinAvailable || this.togglingChannelWideMentionsAvailable)
|
||||||
|
);
|
||||||
const camelizedKey = camelize(`saved_${key}`);
|
|
||||||
this.set(camelizedKey, false);
|
|
||||||
|
|
||||||
const settings = {};
|
|
||||||
settings[key] = value;
|
|
||||||
return ChatApi.updateChatChannelNotificationsSettings(
|
|
||||||
this.channel.id,
|
|
||||||
settings
|
|
||||||
)
|
|
||||||
.then((membership) => {
|
|
||||||
this.channel.current_user_membership.setProperties({
|
|
||||||
muted: membership.muted,
|
|
||||||
desktop_notification_level: membership.desktop_notification_level,
|
|
||||||
mobile_notification_level: membership.mobile_notification_level,
|
|
||||||
});
|
|
||||||
this.set(camelizedKey, true);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
discourseLater(() => {
|
|
||||||
if (this.isDestroying || this.isDestroyed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set(camelizedKey, false);
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed(
|
@computed(
|
||||||
|
@ -98,12 +78,24 @@ export default class ChatChannelSettingsView extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed("channel.isCategoryChannel")
|
@action
|
||||||
get autoJoinAvailable() {
|
saveNotificationSettings(key, value) {
|
||||||
return (
|
if (this.channel[key] === value) {
|
||||||
this.siteSettings.max_chat_auto_joined_users > 0 &&
|
return;
|
||||||
this.channel.isCategoryChannel
|
}
|
||||||
);
|
|
||||||
|
const settings = {};
|
||||||
|
settings[key] = value;
|
||||||
|
return ChatApi.updateChatChannelNotificationsSettings(
|
||||||
|
this.channel.id,
|
||||||
|
settings
|
||||||
|
).then((membership) => {
|
||||||
|
this.channel.current_user_membership.setProperties({
|
||||||
|
muted: membership.muted,
|
||||||
|
desktop_notification_level: membership.desktop_notification_level,
|
||||||
|
mobile_notification_level: membership.mobile_notification_level,
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -133,8 +125,17 @@ export default class ChatChannelSettingsView extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onToggleChannelWideMentions() {
|
||||||
|
return this._updateChannelProperty(
|
||||||
|
this.channel,
|
||||||
|
"allow_channel_wide_mentions",
|
||||||
|
!this.channel.allow_channel_wide_mentions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
onDisableAutoJoinUsers() {
|
onDisableAutoJoinUsers() {
|
||||||
this._updateAutoJoinUsers(false);
|
return this._updateChannelProperty(this.channel, "auto_join_users", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnableAutoJoinUsers() {
|
onEnableAutoJoinUsers() {
|
||||||
|
@ -142,7 +143,26 @@ export default class ChatChannelSettingsView extends Component {
|
||||||
message: I18n.t("chat.settings.auto_join_users_warning", {
|
message: I18n.t("chat.settings.auto_join_users_warning", {
|
||||||
category: this.channel.chatable.name,
|
category: this.channel.chatable.name,
|
||||||
}),
|
}),
|
||||||
didConfirm: () => this._updateAutoJoinUsers(true),
|
didConfirm: () =>
|
||||||
|
this._updateChannelProperty(this.channel, "auto_join_users", true),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateChannelProperty(channel, property, value) {
|
||||||
|
if (channel[property] === value) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {};
|
||||||
|
payload[property] = value;
|
||||||
|
return ChatApi.modifyChatChannel(channel.id, payload)
|
||||||
|
.then((updatedChannel) => {
|
||||||
|
channel.set(property, updatedChannel[property]);
|
||||||
|
})
|
||||||
|
.catch((event) => {
|
||||||
|
if (event.jqXHR?.responseJSON?.errors) {
|
||||||
|
this.flash(event.jqXHR.responseJSON.errors.join("\n"), "error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,15 +130,15 @@ export default {
|
||||||
|
|
||||||
api.addToHeaderIcons("header-chat-link");
|
api.addToHeaderIcons("header-chat-link");
|
||||||
|
|
||||||
api.decorateChatMessage(function (chatMessage) {
|
api.decorateChatMessage(function (chatMessage, chatChannel) {
|
||||||
if (!this.currentUser) {
|
if (!this.currentUser) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const highlightable = [
|
const highlightable = [`@${this.currentUser.username}`];
|
||||||
`@${this.currentUser.username}`,
|
if (chatChannel.allow_channel_wide_mentions) {
|
||||||
...MENTION_KEYWORDS.map((k) => `@${k}`),
|
highlightable.push(...MENTION_KEYWORDS.map((k) => `@${k}`));
|
||||||
];
|
}
|
||||||
|
|
||||||
chatMessage.querySelectorAll(".mention").forEach((node) => {
|
chatMessage.querySelectorAll(".mention").forEach((node) => {
|
||||||
const mention = node.textContent.trim();
|
const mention = node.textContent.trim();
|
||||||
|
|
|
@ -32,20 +32,11 @@
|
||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Settings view
|
|
||||||
.channel-settings-view__saved {
|
|
||||||
color: var(--success);
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
|
|
||||||
.d-icon-check {
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-settings-view__desktop-notification-level-selector,
|
.channel-settings-view__desktop-notification-level-selector,
|
||||||
.channel-settings-view__mobile-notification-level-selector,
|
.channel-settings-view__mobile-notification-level-selector,
|
||||||
.channel-settings-view__muted-selector,
|
.channel-settings-view__muted-selector,
|
||||||
.channel-settings-view__auto-join-selector {
|
.channel-settings-view__auto-join-selector,
|
||||||
|
.channel-settings-view__channel-wide-mentions-selector {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
.chat-channel-settings-saved-indicator {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
color: var(--success);
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
.d-icon-check {
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -148,7 +148,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-form {
|
.chat-form {
|
||||||
&__description.-autojoin {
|
&__description.-autojoin,
|
||||||
|
&__description.-channel-wide-mentions {
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,6 +289,8 @@ en:
|
||||||
always: "For all activity"
|
always: "For all activity"
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
|
channel_wide_mentions_label: "Allow @all and @here mentions"
|
||||||
|
channel_wide_mentions_description: "Allow users to notify all members of #%{channel} with @all or only those who are active in the moment with @here"
|
||||||
auto_join_users_label: "Automatically add users"
|
auto_join_users_label: "Automatically add users"
|
||||||
auto_join_users_info: "Check hourly which users have been active in the last 3 months and, if they have access to the %{category} category, add them to this channel."
|
auto_join_users_info: "Check hourly which users have been active in the last 3 months and, if they have access to the %{category} category, add them to this channel."
|
||||||
enable_auto_join_users: "Automatically add all recently active users"
|
enable_auto_join_users: "Automatically add all recently active users"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddAllowChannelWideMentionsToChatChannels < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
add_column :chat_channels, :allow_channel_wide_mentions, :boolean, null: false, default: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -164,7 +164,7 @@ class Chat::ChatNotifier
|
||||||
def expand_global_mention(to_notify, already_covered_ids)
|
def expand_global_mention(to_notify, already_covered_ids)
|
||||||
typed_global_mention = direct_mentions_from_cooked.include?("@all")
|
typed_global_mention = direct_mentions_from_cooked.include?("@all")
|
||||||
|
|
||||||
if typed_global_mention
|
if typed_global_mention && @chat_channel.allow_channel_wide_mentions
|
||||||
to_notify[:global_mentions] = members_accepting_channel_wide_notifications
|
to_notify[:global_mentions] = members_accepting_channel_wide_notifications
|
||||||
.where.not(username_lower: normalized_mentions(direct_mentions_from_cooked))
|
.where.not(username_lower: normalized_mentions(direct_mentions_from_cooked))
|
||||||
.where.not(id: already_covered_ids)
|
.where.not(id: already_covered_ids)
|
||||||
|
@ -179,7 +179,7 @@ class Chat::ChatNotifier
|
||||||
def expand_here_mention(to_notify, already_covered_ids)
|
def expand_here_mention(to_notify, already_covered_ids)
|
||||||
typed_here_mention = direct_mentions_from_cooked.include?("@here")
|
typed_here_mention = direct_mentions_from_cooked.include?("@here")
|
||||||
|
|
||||||
if typed_here_mention
|
if typed_here_mention && @chat_channel.allow_channel_wide_mentions
|
||||||
to_notify[:here_mentions] = members_accepting_channel_wide_notifications
|
to_notify[:here_mentions] = members_accepting_channel_wide_notifications
|
||||||
.where("last_seen_at > ?", 5.minutes.ago)
|
.where("last_seen_at > ?", 5.minutes.ago)
|
||||||
.where.not(username_lower: normalized_mentions(direct_mentions_from_cooked))
|
.where.not(username_lower: normalized_mentions(direct_mentions_from_cooked))
|
||||||
|
|
|
@ -66,6 +66,7 @@ register_asset "stylesheets/common/chat-onebox.scss"
|
||||||
register_asset "stylesheets/common/chat-skeleton.scss"
|
register_asset "stylesheets/common/chat-skeleton.scss"
|
||||||
register_asset "stylesheets/colors.scss", :color_definitions
|
register_asset "stylesheets/colors.scss", :color_definitions
|
||||||
register_asset "stylesheets/common/reviewable-chat-message.scss"
|
register_asset "stylesheets/common/reviewable-chat-message.scss"
|
||||||
|
register_asset "stylesheets/common/chat-channel-settings-saved-indicator.scss"
|
||||||
|
|
||||||
register_svg_icon "comments"
|
register_svg_icon "comments"
|
||||||
register_svg_icon "comment-slash"
|
register_svg_icon "comment-slash"
|
||||||
|
|
|
@ -49,6 +49,15 @@ describe Chat::ChatNotifier do
|
||||||
expect(to_notify[list_key]).to be_empty
|
expect(to_notify[list_key]).to be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "will never mention when channel is not accepting channel wide mentions" do
|
||||||
|
channel.update!(allow_channel_wide_mentions: false)
|
||||||
|
msg = build_cooked_msg(mention, user_1)
|
||||||
|
|
||||||
|
to_notify = described_class.new(msg, msg.created_at).notify_new
|
||||||
|
|
||||||
|
expect(to_notify[list_key]).to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
it "includes all members of a channel except the sender" do
|
it "includes all members of a channel except the sender" do
|
||||||
msg = build_cooked_msg(mention, user_1)
|
msg = build_cooked_msg(mention, user_1)
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,25 @@ RSpec.describe ChatChannel do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the slug is not nil" do
|
context "when the slug is not nil" do
|
||||||
before do
|
before { category_channel.update!(slug: "some-cool-channel") }
|
||||||
category_channel.update!(slug: "some-cool-channel")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "includes the slug for the channel" do
|
it "includes the slug for the channel" do
|
||||||
expect(category_channel.relative_url).to eq("/chat/channel/#{category_channel.id}/some-cool-channel")
|
expect(category_channel.relative_url).to eq(
|
||||||
|
"/chat/channel/#{category_channel.id}/some-cool-channel",
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#allow_channel_wide_mentions" do
|
||||||
|
it "defaults to true" do
|
||||||
|
expect(category_channel.allow_channel_wide_mentions).to be(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "cant be nullified" do
|
||||||
|
expect { category_channel.update!(allow_channel_wide_mentions: nil) }.to raise_error(
|
||||||
|
ActiveRecord::NotNullViolation,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -277,6 +277,17 @@ describe Chat::Api::ChatChannelsController do
|
||||||
expect(response.parsed_body).to match_response_schema("category_chat_channel")
|
expect(response.parsed_body).to match_response_schema("category_chat_channel")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "when updating allow_channel_wide_mentions" do
|
||||||
|
it "sets the new value" do
|
||||||
|
put "/chat/api/chat_channels/#{chat_channel.id}.json",
|
||||||
|
params: {
|
||||||
|
allow_channel_wide_mentions: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(response.parsed_body["allow_channel_wide_mentions"]).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "Updating a channel to add users automatically" do
|
describe "Updating a channel to add users automatically" do
|
||||||
it "sets the channel to auto-update users automatically" do
|
it "sets the channel to auto-update users automatically" do
|
||||||
put "/chat/api/chat_channels/#{chat_channel.id}.json", params: { auto_join_users: true }
|
put "/chat/api/chat_channels/#{chat_channel.id}.json", params: { auto_join_users: true }
|
||||||
|
|
|
@ -17,6 +17,10 @@ describe ChatChannelSerializer do
|
||||||
it "does not return any sort of archive status" do
|
it "does not return any sort of archive status" do
|
||||||
expect(subject.as_json.key?(:archive_completed)).to eq(false)
|
expect(subject.as_json.key?(:archive_completed)).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "includes allow_channel_wide_mentions" do
|
||||||
|
expect(subject.as_json.key?(:allow_channel_wide_mentions)).to eq(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when user is staff" do
|
context "when user is staff" do
|
||||||
|
@ -37,6 +41,10 @@ describe ChatChannelSerializer do
|
||||||
chat_channel.reload
|
chat_channel.reload
|
||||||
expect(subject.as_json.key?(:archive_completed)).to eq(true)
|
expect(subject.as_json.key?(:archive_completed)).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "includes allow_channel_wide_mentions" do
|
||||||
|
expect(subject.as_json.key?(:allow_channel_wide_mentions)).to eq(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,6 +31,7 @@ export const directMessageChannels = [
|
||||||
muted: false,
|
muted: false,
|
||||||
following: true,
|
following: true,
|
||||||
},
|
},
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-20T08:14:16.950Z",
|
last_message_sent_at: "2021-07-20T08:14:16.950Z",
|
||||||
message_bus_last_ids: {
|
message_bus_last_ids: {
|
||||||
new_mentions: 0,
|
new_mentions: 0,
|
||||||
|
@ -66,6 +67,7 @@ export const directMessageChannels = [
|
||||||
muted: false,
|
muted: false,
|
||||||
following: true,
|
following: true,
|
||||||
},
|
},
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-05T12:04:00.850Z",
|
last_message_sent_at: "2021-07-05T12:04:00.850Z",
|
||||||
message_bus_last_ids: {
|
message_bus_last_ids: {
|
||||||
new_mentions: 0,
|
new_mentions: 0,
|
||||||
|
@ -107,6 +109,7 @@ export const chatChannels = {
|
||||||
title: "Site",
|
title: "Site",
|
||||||
status: "open",
|
status: "open",
|
||||||
chatable: chatables[1],
|
chatable: chatables[1],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-24T08:14:16.950Z",
|
last_message_sent_at: "2021-07-24T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
@ -126,6 +129,7 @@ export const chatChannels = {
|
||||||
title: "Bug",
|
title: "Bug",
|
||||||
status: "open",
|
status: "open",
|
||||||
chatable: chatables[1],
|
chatable: chatables[1],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-15T08:14:16.950Z",
|
last_message_sent_at: "2021-07-15T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
@ -145,6 +149,7 @@ export const chatChannels = {
|
||||||
title: "Public category",
|
title: "Public category",
|
||||||
status: "open",
|
status: "open",
|
||||||
chatable: chatables[8],
|
chatable: chatables[8],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-14T08:14:16.950Z",
|
last_message_sent_at: "2021-07-14T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
@ -164,6 +169,7 @@ export const chatChannels = {
|
||||||
title: "Public category (read-only)",
|
title: "Public category (read-only)",
|
||||||
status: "read_only",
|
status: "read_only",
|
||||||
chatable: chatables[8],
|
chatable: chatables[8],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-10T08:14:16.950Z",
|
last_message_sent_at: "2021-07-10T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
@ -183,6 +189,7 @@ export const chatChannels = {
|
||||||
title: "Public category (closed)",
|
title: "Public category (closed)",
|
||||||
status: "closed",
|
status: "closed",
|
||||||
chatable: chatables[8],
|
chatable: chatables[8],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-21T08:14:16.950Z",
|
last_message_sent_at: "2021-07-21T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
@ -202,6 +209,7 @@ export const chatChannels = {
|
||||||
title: "Public category (archived)",
|
title: "Public category (archived)",
|
||||||
status: "archived",
|
status: "archived",
|
||||||
chatable: chatables[8],
|
chatable: chatables[8],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-25T08:14:16.950Z",
|
last_message_sent_at: "2021-07-25T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
@ -221,6 +229,7 @@ export const chatChannels = {
|
||||||
title: "Another Category",
|
title: "Another Category",
|
||||||
status: "open",
|
status: "open",
|
||||||
chatable: chatables[12],
|
chatable: chatables[12],
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
last_message_sent_at: "2021-07-02T08:14:16.950Z",
|
last_message_sent_at: "2021-07-02T08:14:16.950Z",
|
||||||
current_user_membership: {
|
current_user_membership: {
|
||||||
unread_count: 0,
|
unread_count: 0,
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { module, test } from "qunit";
|
||||||
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
|
import { render, settled } from "@ember/test-helpers";
|
||||||
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
|
|
||||||
|
module(
|
||||||
|
"Discourse Chat | Component | chat-channel-settings-saved-indicator",
|
||||||
|
function (hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
test("when property changes", async function (assert) {
|
||||||
|
await render(
|
||||||
|
hbs`<ChatChannelSettingsSavedIndicator @property={{this.property}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(".chat-channel-settings-saved-indicator.is-active")
|
||||||
|
.doesNotExist();
|
||||||
|
|
||||||
|
this.set("property", 1);
|
||||||
|
|
||||||
|
assert.dom(".chat-channel-settings-saved-indicator.is-active").exists();
|
||||||
|
|
||||||
|
await settled();
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(".chat-channel-settings-saved-indicator.is-active")
|
||||||
|
.doesNotExist();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
|
@ -9,7 +9,14 @@ import { CHATABLE_TYPES } from "discourse/plugins/chat/discourse/models/chat-cha
|
||||||
import { module } from "qunit";
|
import { module } from "qunit";
|
||||||
|
|
||||||
function membershipFixture(id, options = {}) {
|
function membershipFixture(id, options = {}) {
|
||||||
options = Object.assign({}, options, { muted: false, following: true });
|
options = Object.assign(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
muted: false,
|
||||||
|
following: true,
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
following: options.following,
|
following: options.following,
|
||||||
|
@ -99,7 +106,7 @@ module(
|
||||||
return [
|
return [
|
||||||
200,
|
200,
|
||||||
{ "Content-Type": "application/json" },
|
{ "Content-Type": "application/json" },
|
||||||
membershipFixture(this.channel.id, { muted: true }),
|
membershipFixture(this.channel.id, { muted: false }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -111,6 +118,34 @@ module(
|
||||||
assert.equal(sk.header().value(), "false");
|
assert.equal(sk.header().value(), "false");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
componentTest("allow channel wide mentions", {
|
||||||
|
template: hbs`{{chat-channel-settings-view channel=channel}}`,
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
this.set("channel", fabricators.chatChannel());
|
||||||
|
},
|
||||||
|
|
||||||
|
async test(assert) {
|
||||||
|
pretender.put(`/chat/api/chat_channels/${this.channel.id}.json`, () => {
|
||||||
|
return [
|
||||||
|
200,
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
{
|
||||||
|
allow_channel_wide_mentions: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const sk = selectKit(
|
||||||
|
".channel-settings-view__channel-wide-mentions-selector"
|
||||||
|
);
|
||||||
|
await sk.expand();
|
||||||
|
await sk.selectRowByName("No");
|
||||||
|
|
||||||
|
assert.equal(sk.header().value(), "false");
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -205,7 +240,7 @@ module(
|
||||||
return [
|
return [
|
||||||
200,
|
200,
|
||||||
{ "Content-Type": "application/json" },
|
{ "Content-Type": "application/json" },
|
||||||
membershipFixture(this.channel.id, { muted: true }),
|
membershipFixture(this.channel.id, { muted: false }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -217,5 +252,24 @@ module(
|
||||||
assert.equal(sk.header().value(), "false");
|
assert.equal(sk.header().value(), "false");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
componentTest("allow channel wide mentions", {
|
||||||
|
template: hbs`{{chat-channel-settings-view channel=channel}}`,
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
this.set(
|
||||||
|
"channel",
|
||||||
|
fabricators.chatChannel({
|
||||||
|
chatable_type: CHATABLE_TYPES.directMessageChannel,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
async test(assert) {
|
||||||
|
assert
|
||||||
|
.dom(".channel-settings-view__channel-wide-mentions-selector")
|
||||||
|
.doesNotExist();
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,6 +31,7 @@ export default {
|
||||||
name: "My category name",
|
name: "My category name",
|
||||||
chatable: categoryChatableFabricator(),
|
chatable: categoryChatableFabricator(),
|
||||||
last_message_sent_at: "2021-11-08T21:26:05.710Z",
|
last_message_sent_at: "2021-11-08T21:26:05.710Z",
|
||||||
|
allow_channel_wide_mentions: true,
|
||||||
message_bus_last_ids: {
|
message_bus_last_ids: {
|
||||||
new_mentions: 0,
|
new_mentions: 0,
|
||||||
new_messages: 0,
|
new_messages: 0,
|
||||||
|
|
Loading…
Reference in New Issue