From 68c4f16a730931bb37d79520c3636a689c302006 Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Mon, 5 Dec 2022 17:03:51 +0100 Subject: [PATCH] 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. --- .../api/chat_channels_controller.rb | 2 +- plugins/chat/app/models/chat_channel.rb | 37 ++--- .../serializers/chat_channel_serializer.rb | 1 + .../chat-channel-settings-saved-indicator.hbs | 11 ++ .../chat-channel-settings-saved-indicator.js | 28 ++++ .../components/chat-channel-settings-view.hbs | 138 ++++++++++++++---- .../components/chat-channel-settings-view.js | 128 +++++++++------- .../discourse/initializers/chat-setup.js | 10 +- .../stylesheets/common/chat-channel-info.scss | 13 +- ...chat-channel-settings-saved-indicator.scss | 9 ++ .../assets/stylesheets/desktop/desktop.scss | 3 +- plugins/chat/config/locales/client.en.yml | 2 + ..._channel_wide_mentions_to_chat_channels.rb | 7 + plugins/chat/lib/chat_notifier.rb | 4 +- plugins/chat/plugin.rb | 1 + plugins/chat/spec/lib/chat_notifier_spec.rb | 9 ++ plugins/chat/spec/models/chat_channel_spec.rb | 20 ++- .../api/chat_channels_controller_spec.rb | 11 ++ .../chat_channel_serializer_spec.rb | 8 + .../chat/test/javascripts/chat-fixtures.js | 9 ++ ...t-channel-settings-saved-indicator-test.js | 31 ++++ .../chat-channel-settings-view-test.js | 60 +++++++- .../test/javascripts/helpers/fabricators.js | 1 + 23 files changed, 417 insertions(+), 126 deletions(-) create mode 100644 plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.hbs create mode 100644 plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.js create mode 100644 plugins/chat/assets/stylesheets/common/chat-channel-settings-saved-indicator.scss create mode 100644 plugins/chat/db/migrate/20221118104708_add_allow_channel_wide_mentions_to_chat_channels.rb create mode 100644 plugins/chat/test/javascripts/components/chat-channel-settings-saved-indicator-test.js diff --git a/plugins/chat/app/controllers/api/chat_channels_controller.rb b/plugins/chat/app/controllers/api/chat_channels_controller.rb index b073936cf48..4e66d16aae4 100644 --- a/plugins/chat/app/controllers/api/chat_channels_controller.rb +++ b/plugins/chat/app/controllers/api/chat_channels_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true 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 def index diff --git a/plugins/chat/app/models/chat_channel.rb b/plugins/chat/app/models/chat_channel.rb index a8e4fdfec7f..b87cf6c9709 100644 --- a/plugins/chat/app/models/chat_channel.rb +++ b/plugins/chat/app/models/chat_channel.rb @@ -121,24 +121,25 @@ end # # Table name: chat_channels # -# id :bigint not null, primary key -# chatable_id :integer not null -# deleted_at :datetime -# deleted_by_id :integer -# featured_in_category_id :integer -# delete_after_seconds :integer -# chatable_type :string not null -# created_at :datetime not null -# updated_at :datetime not null -# name :string -# description :text -# status :integer default("open"), not null -# user_count :integer default(0), not null -# last_message_sent_at :datetime not null -# auto_join_users :boolean default(FALSE), not null -# user_count_stale :boolean default(FALSE), not null -# slug :string -# type :string +# id :bigint not null, primary key +# chatable_id :integer not null +# deleted_at :datetime +# deleted_by_id :integer +# featured_in_category_id :integer +# delete_after_seconds :integer +# chatable_type :string not null +# created_at :datetime not null +# updated_at :datetime not null +# name :string +# description :text +# status :integer default("open"), not null +# user_count :integer default(0), not null +# last_message_sent_at :datetime not null +# auto_join_users :boolean default(FALSE), not null +# allow_channel_wide_mentions :boolean default(TRUE), not null +# user_count_stale :boolean default(FALSE), not null +# slug :string +# type :string # # Indexes # diff --git a/plugins/chat/app/serializers/chat_channel_serializer.rb b/plugins/chat/app/serializers/chat_channel_serializer.rb index d3fedfa9c41..4b7b2c5a8e6 100644 --- a/plugins/chat/app/serializers/chat_channel_serializer.rb +++ b/plugins/chat/app/serializers/chat_channel_serializer.rb @@ -3,6 +3,7 @@ class ChatChannelSerializer < ApplicationSerializer attributes :id, :auto_join_users, + :allow_channel_wide_mentions, :chatable, :chatable_id, :chatable_type, diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.hbs new file mode 100644 index 00000000000..78a6af82fea --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.hbs @@ -0,0 +1,11 @@ + + {{#if this.isActive}} + {{d-icon "check"}} + {{i18n "saved"}} + {{/if}} + diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.js new file mode 100644 index 00000000000..292e3af2308 --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-saved-indicator.js @@ -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); + } +} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs index 39b46b4091a..5597f74a5c9 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs @@ -2,58 +2,122 @@
- - {{#if this.savedMuted}} - - {{d-icon "check"}} {{i18n "saved"}} - - {{/if}} +
+ {{#unless this.channel.current_user_membership.muted}}
- - {{#if this.savedDesktopNotificationLevel}} - - {{d-icon "check"}} {{i18n "saved"}} - - {{/if}} +
- - {{#if this.savedMobileNotificationLevel}} - - {{d-icon "check"}} {{i18n "saved"}} - - {{/if}} +
{{/unless}} -
{{d-icon "info-circle"}}{{i18n "chat.settings.retention_info" days=this.siteSettings.chat_channel_retention_days}}
+
+ {{d-icon "info-circle"}} + {{i18n + "chat.settings.retention_info" + days=this.siteSettings.chat_channel_retention_days + }} +
-{{#if (chat-guardian "can-edit-chat-channel")}} -

{{i18n "chat.settings.admin_title"}}

+{{#if this.adminSectionAvailable}} +

+ {{i18n "chat.settings.admin_title"}} +

{{#if this.autoJoinAvailable}}
- -
{{i18n "chat.settings.auto_join_users_info" category=this.channel.chatable.name}}
+ +

+ {{i18n + "chat.settings.auto_join_users_info" + category=this.channel.chatable.name + }} +

+
+
+ {{/if}} + + {{#if this.togglingChannelWideMentionsAvailable}} +
+
+ + +

+ {{i18n "chat.settings.channel_wide_mentions_description" channel=this.channel.title}} +

{{/if}} @@ -64,22 +128,42 @@ {{#if (chat-guardian "can-edit-chat-channel")}} {{#if (chat-guardian "can-archive-channel" this.channel)}}
- +
{{/if}} {{#if this.channel.isClosed}}
- +
{{else}}
- +
{{/if}}
- +
{{/if}} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.js index 5bcea9b3829..1dc4f4d3c31 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.js @@ -4,8 +4,8 @@ import { inject as service } from "@ember/service"; import ChatApi from "discourse/plugins/chat/discourse/lib/chat-api"; import showModal from "discourse/lib/show-modal"; import I18n from "I18n"; -import { camelize } from "@ember/string"; -import discourseLater from "discourse-common/lib/later"; +import { Promise } from "rsvp"; +import { reads } from "@ember/object/computed"; const NOTIFICATION_LEVELS = [ { 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 }, ]; +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 { @service chat; + @service chatGuardian; @service router; @service dialog; tagName = ""; @@ -33,57 +42,28 @@ export default class ChatChannelSettingsView extends Component { notificationLevels = NOTIFICATION_LEVELS; mutedOptions = MUTED_OPTIONS; autoAddUsersOptions = AUTO_ADD_USERS_OPTIONS; + channelWideMentionsOptions = CHANNEL_WIDE_MENTIONS_OPTIONS; isSavingNotificationSetting = false; savedDesktopNotificationLevel = false; savedMobileNotificationLevel = false; savedMuted = false; - _updateAutoJoinUsers(value) { - return ChatApi.modifyChatChannel(this.channel.id, { - auto_join_users: value, - }) - .then((chatChannel) => { - this.channel.set("auto_join_users", chatChannel.auto_join_users); - }) - .catch((event) => { - if (event.jqXHR?.responseJSON?.errors) { - this.flash(event.jqXHR.responseJSON.errors.join("\n"), "error"); - } - }); + @reads("channel.isCategoryChannel") togglingChannelWideMentionsAvailable; + + @computed("channel.isCategoryChannel") + get autoJoinAvailable() { + return ( + this.siteSettings.max_chat_auto_joined_users > 0 && + this.channel.isCategoryChannel + ); } - @action - saveNotificationSettings(key, value) { - if (this.channel[key] === value) { - return; - } - - 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("autoJoinAvailable", "togglingChannelWideMentionsAvailable") + get adminSectionAvailable() { + return ( + this.chatGuardian.canEditChatChannel && + (this.autoJoinAvailable || this.togglingChannelWideMentionsAvailable) + ); } @computed( @@ -98,12 +78,24 @@ export default class ChatChannelSettingsView extends Component { ); } - @computed("channel.isCategoryChannel") - get autoJoinAvailable() { - return ( - this.siteSettings.max_chat_auto_joined_users > 0 && - this.channel.isCategoryChannel - ); + @action + saveNotificationSettings(key, value) { + if (this.channel[key] === value) { + return; + } + + 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 @@ -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() { - this._updateAutoJoinUsers(false); + return this._updateChannelProperty(this.channel, "auto_join_users", false); } onEnableAutoJoinUsers() { @@ -142,7 +143,26 @@ export default class ChatChannelSettingsView extends Component { message: I18n.t("chat.settings.auto_join_users_warning", { 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"); + } + }); + } } diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js index e00ee2b59b6..333a026f38f 100644 --- a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js +++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js @@ -130,15 +130,15 @@ export default { api.addToHeaderIcons("header-chat-link"); - api.decorateChatMessage(function (chatMessage) { + api.decorateChatMessage(function (chatMessage, chatChannel) { if (!this.currentUser) { return; } - const highlightable = [ - `@${this.currentUser.username}`, - ...MENTION_KEYWORDS.map((k) => `@${k}`), - ]; + const highlightable = [`@${this.currentUser.username}`]; + if (chatChannel.allow_channel_wide_mentions) { + highlightable.push(...MENTION_KEYWORDS.map((k) => `@${k}`)); + } chatMessage.querySelectorAll(".mention").forEach((node) => { const mention = node.textContent.trim(); diff --git a/plugins/chat/assets/stylesheets/common/chat-channel-info.scss b/plugins/chat/assets/stylesheets/common/chat-channel-info.scss index ca997c77258..29f3cb30cda 100644 --- a/plugins/chat/assets/stylesheets/common/chat-channel-info.scss +++ b/plugins/chat/assets/stylesheets/common/chat-channel-info.scss @@ -32,20 +32,11 @@ 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__mobile-notification-level-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; } diff --git a/plugins/chat/assets/stylesheets/common/chat-channel-settings-saved-indicator.scss b/plugins/chat/assets/stylesheets/common/chat-channel-settings-saved-indicator.scss new file mode 100644 index 00000000000..e28129f3e17 --- /dev/null +++ b/plugins/chat/assets/stylesheets/common/chat-channel-settings-saved-indicator.scss @@ -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; + } +} diff --git a/plugins/chat/assets/stylesheets/desktop/desktop.scss b/plugins/chat/assets/stylesheets/desktop/desktop.scss index 7515793b304..da4b054ce10 100644 --- a/plugins/chat/assets/stylesheets/desktop/desktop.scss +++ b/plugins/chat/assets/stylesheets/desktop/desktop.scss @@ -148,7 +148,8 @@ } .chat-form { - &__description.-autojoin { + &__description.-autojoin, + &__description.-channel-wide-mentions { max-width: 50%; } } diff --git a/plugins/chat/config/locales/client.en.yml b/plugins/chat/config/locales/client.en.yml index 4a5f3b61d4a..93215b1a59c 100644 --- a/plugins/chat/config/locales/client.en.yml +++ b/plugins/chat/config/locales/client.en.yml @@ -289,6 +289,8 @@ en: always: "For all activity" 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_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" diff --git a/plugins/chat/db/migrate/20221118104708_add_allow_channel_wide_mentions_to_chat_channels.rb b/plugins/chat/db/migrate/20221118104708_add_allow_channel_wide_mentions_to_chat_channels.rb new file mode 100644 index 00000000000..b06642af164 --- /dev/null +++ b/plugins/chat/db/migrate/20221118104708_add_allow_channel_wide_mentions_to_chat_channels.rb @@ -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 diff --git a/plugins/chat/lib/chat_notifier.rb b/plugins/chat/lib/chat_notifier.rb index d2fcc4496ad..e8a8d662978 100644 --- a/plugins/chat/lib/chat_notifier.rb +++ b/plugins/chat/lib/chat_notifier.rb @@ -164,7 +164,7 @@ class Chat::ChatNotifier def expand_global_mention(to_notify, already_covered_ids) 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 .where.not(username_lower: normalized_mentions(direct_mentions_from_cooked)) .where.not(id: already_covered_ids) @@ -179,7 +179,7 @@ class Chat::ChatNotifier def expand_here_mention(to_notify, already_covered_ids) 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 .where("last_seen_at > ?", 5.minutes.ago) .where.not(username_lower: normalized_mentions(direct_mentions_from_cooked)) diff --git a/plugins/chat/plugin.rb b/plugins/chat/plugin.rb index e8958816dfa..c2f7c56ee44 100644 --- a/plugins/chat/plugin.rb +++ b/plugins/chat/plugin.rb @@ -66,6 +66,7 @@ register_asset "stylesheets/common/chat-onebox.scss" register_asset "stylesheets/common/chat-skeleton.scss" register_asset "stylesheets/colors.scss", :color_definitions 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 "comment-slash" diff --git a/plugins/chat/spec/lib/chat_notifier_spec.rb b/plugins/chat/spec/lib/chat_notifier_spec.rb index fa787797d7a..44837775673 100644 --- a/plugins/chat/spec/lib/chat_notifier_spec.rb +++ b/plugins/chat/spec/lib/chat_notifier_spec.rb @@ -49,6 +49,15 @@ describe Chat::ChatNotifier do expect(to_notify[list_key]).to be_empty 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 msg = build_cooked_msg(mention, user_1) diff --git a/plugins/chat/spec/models/chat_channel_spec.rb b/plugins/chat/spec/models/chat_channel_spec.rb index 475390a07a9..3e1d6ec3529 100644 --- a/plugins/chat/spec/models/chat_channel_spec.rb +++ b/plugins/chat/spec/models/chat_channel_spec.rb @@ -13,13 +13,25 @@ RSpec.describe ChatChannel do end context "when the slug is not nil" do - before do - category_channel.update!(slug: "some-cool-channel") - end + before { category_channel.update!(slug: "some-cool-channel") } 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 + + 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 diff --git a/plugins/chat/spec/requests/api/chat_channels_controller_spec.rb b/plugins/chat/spec/requests/api/chat_channels_controller_spec.rb index 4083ab0c6ba..f3da20c1d77 100644 --- a/plugins/chat/spec/requests/api/chat_channels_controller_spec.rb +++ b/plugins/chat/spec/requests/api/chat_channels_controller_spec.rb @@ -277,6 +277,17 @@ describe Chat::Api::ChatChannelsController do expect(response.parsed_body).to match_response_schema("category_chat_channel") 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 it "sets the channel to auto-update users automatically" do put "/chat/api/chat_channels/#{chat_channel.id}.json", params: { auto_join_users: true } diff --git a/plugins/chat/spec/serializer/chat_channel_serializer_spec.rb b/plugins/chat/spec/serializer/chat_channel_serializer_spec.rb index 4a164ae8720..86ccea5c3fb 100644 --- a/plugins/chat/spec/serializer/chat_channel_serializer_spec.rb +++ b/plugins/chat/spec/serializer/chat_channel_serializer_spec.rb @@ -17,6 +17,10 @@ describe ChatChannelSerializer do it "does not return any sort of archive status" do expect(subject.as_json.key?(:archive_completed)).to eq(false) end + + it "includes allow_channel_wide_mentions" do + expect(subject.as_json.key?(:allow_channel_wide_mentions)).to eq(true) + end end context "when user is staff" do @@ -37,6 +41,10 @@ describe ChatChannelSerializer do chat_channel.reload expect(subject.as_json.key?(:archive_completed)).to eq(true) end + + it "includes allow_channel_wide_mentions" do + expect(subject.as_json.key?(:allow_channel_wide_mentions)).to eq(true) + end end end end diff --git a/plugins/chat/test/javascripts/chat-fixtures.js b/plugins/chat/test/javascripts/chat-fixtures.js index e91f5b563a4..df68bc1597a 100644 --- a/plugins/chat/test/javascripts/chat-fixtures.js +++ b/plugins/chat/test/javascripts/chat-fixtures.js @@ -31,6 +31,7 @@ export const directMessageChannels = [ muted: false, following: true, }, + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-20T08:14:16.950Z", message_bus_last_ids: { new_mentions: 0, @@ -66,6 +67,7 @@ export const directMessageChannels = [ muted: false, following: true, }, + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-05T12:04:00.850Z", message_bus_last_ids: { new_mentions: 0, @@ -107,6 +109,7 @@ export const chatChannels = { title: "Site", status: "open", chatable: chatables[1], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-24T08:14:16.950Z", current_user_membership: { unread_count: 0, @@ -126,6 +129,7 @@ export const chatChannels = { title: "Bug", status: "open", chatable: chatables[1], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-15T08:14:16.950Z", current_user_membership: { unread_count: 0, @@ -145,6 +149,7 @@ export const chatChannels = { title: "Public category", status: "open", chatable: chatables[8], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-14T08:14:16.950Z", current_user_membership: { unread_count: 0, @@ -164,6 +169,7 @@ export const chatChannels = { title: "Public category (read-only)", status: "read_only", chatable: chatables[8], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-10T08:14:16.950Z", current_user_membership: { unread_count: 0, @@ -183,6 +189,7 @@ export const chatChannels = { title: "Public category (closed)", status: "closed", chatable: chatables[8], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-21T08:14:16.950Z", current_user_membership: { unread_count: 0, @@ -202,6 +209,7 @@ export const chatChannels = { title: "Public category (archived)", status: "archived", chatable: chatables[8], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-25T08:14:16.950Z", current_user_membership: { unread_count: 0, @@ -221,6 +229,7 @@ export const chatChannels = { title: "Another Category", status: "open", chatable: chatables[12], + allow_channel_wide_mentions: true, last_message_sent_at: "2021-07-02T08:14:16.950Z", current_user_membership: { unread_count: 0, diff --git a/plugins/chat/test/javascripts/components/chat-channel-settings-saved-indicator-test.js b/plugins/chat/test/javascripts/components/chat-channel-settings-saved-indicator-test.js new file mode 100644 index 00000000000..6f03050cb05 --- /dev/null +++ b/plugins/chat/test/javascripts/components/chat-channel-settings-saved-indicator-test.js @@ -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`` + ); + + 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(); + }); + } +); diff --git a/plugins/chat/test/javascripts/components/chat-channel-settings-view-test.js b/plugins/chat/test/javascripts/components/chat-channel-settings-view-test.js index 73dce053f4f..4a97c2d31ac 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-settings-view-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-settings-view-test.js @@ -9,7 +9,14 @@ import { CHATABLE_TYPES } from "discourse/plugins/chat/discourse/models/chat-cha import { module } from "qunit"; function membershipFixture(id, options = {}) { - options = Object.assign({}, options, { muted: false, following: true }); + options = Object.assign( + {}, + { + muted: false, + following: true, + }, + options + ); return { following: options.following, @@ -99,7 +106,7 @@ module( return [ 200, { "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"); }, }); + + 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 [ 200, { "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"); }, }); + + 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(); + }, + }); } ); diff --git a/plugins/chat/test/javascripts/helpers/fabricators.js b/plugins/chat/test/javascripts/helpers/fabricators.js index fdc766f2c15..924685b6e6e 100644 --- a/plugins/chat/test/javascripts/helpers/fabricators.js +++ b/plugins/chat/test/javascripts/helpers/fabricators.js @@ -31,6 +31,7 @@ export default { name: "My category name", chatable: categoryChatableFabricator(), last_message_sent_at: "2021-11-08T21:26:05.710Z", + allow_channel_wide_mentions: true, message_bus_last_ids: { new_mentions: 0, new_messages: 0,