From 09828853f6cc0e07da74f4da885dfa93f5204662 Mon Sep 17 00:00:00 2001 From: Michael Kohl Date: Thu, 18 Nov 2021 21:21:00 +0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=82=E2=9C=82=E2=9C=82=20Remove=20Connect?= =?UTF-8?q?=20(#14734)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove Connect * Remove more Connect specs * Remove a lot more Connect code * 🚮 * It all has to go * Explicitly add httpclient * Update application layout * Remove messages association from User * Start fixing specs * reintroduce util function and refactor references * Remove Connect Cypress test * Fix more specs * Remove Connect from listings * Ignore contact_via_connect column on listings * Remove contact_via_connect usages * Ignore mod_chat_channel_id on tags * Drop Connect tables * Remove email_connect_messages from user notification settings * Re-add httpclient 2.8.3 This was mistakenly removed as a merge conflict * Don't need to exclude removed chat channel file * Remove unneeded style for chat channels * Remove unneeded channel list prop type * Remove chat channels index/connect-link from getPageEntries * Re-add comment from httpclient in Gemfile * Remove connect references from mailers Tag Moderators no longer have a chat channel No longer will users be notified about new messages (there won't be any) No longer will users be notified about channel invites (you can't invite anyone anymore) * Don't configure Pusher and remove PUSHER_* from .env_sample since it's removed from gemfile, the Pusher constant will not resolve, if this is configured in the environment variables we'll fail to boot. Co-authored-by: Suzanne Aitchison Co-authored-by: Dan Uber --- .env_sample | 7 - .rubocop_todo.yml | 1 - Gemfile | 2 +- Gemfile.lock | 7 +- app/assets/javascripts/initializePage.js | 3 +- .../initializers/initializeAllChatButtons.js | 119 - app/assets/javascripts/utilities/sendFetch.js | 6 - app/assets/stylesheets/chat.scss | 1344 ----------- .../stylesheets/connect/_channel-details.scss | 134 -- app/assets/stylesheets/minimal.scss | 2 - app/assets/stylesheets/scaffolds.scss | 1 - .../admin/application_controller.rb | 1 - .../admin/chat_channels_controller.rb | 59 - .../chat_channel_memberships_controller.rb | 285 --- app/controllers/chat_channels_controller.rb | 268 --- app/controllers/concerns/listings_toolkit.rb | 2 +- .../email_subscriptions_controller.rb | 1 - app/controllers/listings_controller.rb | 2 +- app/controllers/messages_controller.rb | 117 - app/controllers/moderations_controller.rb | 1 - app/controllers/pusher_controller.rb | 27 - app/controllers/search_controller.rb | 32 +- app/controllers/user_blocks_controller.rb | 2 - .../users/notification_settings_controller.rb | 1 - app/helpers/application_helper.rb | 4 +- .../chat_channel_memberships_helper.rb | 36 - app/helpers/chat_channels_helper.rb | 44 - app/helpers/messages_helper.rb | 41 - app/helpers/notifications_helper.rb | 2 +- .../ActiveMembershipsSection.jsx | 51 - .../ChannelDescriptionSection.jsx | 22 - .../ChatChannelMembershipSection.jsx | 49 - .../ChatChannelSettings.jsx | 440 ---- .../ChatChannelSettingsSection.jsx | 103 - .../chat/ChatChannelSettings/InviteForm.jsx | 42 - .../LeaveMembershipSection.jsx | 32 - .../chat/ChatChannelSettings/Membership.jsx | 62 - .../InvitationLinkManager.jsx | 95 - .../ManageActiveMembership.jsx | 123 - .../MembershipManager/Membership.jsx | 129 -- .../MembershipManager/MembershipSection.jsx | 50 - .../ChatChannelSettings/ModFaqSection.jsx | 28 - .../chat/ChatChannelSettings/ModSection.jsx | 49 - .../PendingMembershipSection.jsx | 42 - .../ChatChannelSettings/PersonalSetting.jsx | 42 - .../RequestedMembershipSection.jsx | 46 - .../chat/ChatChannelSettings/SettingsForm.jsx | 60 - app/javascript/chat/ReportAbuse/index.jsx | 147 -- .../RequestManager/ChannelRequestSection.jsx | 48 - .../chat/RequestManager/HeaderSection.jsx | 12 - .../PersonalInvitationListItem.jsx | 57 - .../PersonalInvitationSection.jsx | 45 - .../chat/RequestManager/RequestListItem.jsx | 57 - .../chat/RequestManager/RequestManager.jsx | 152 -- .../__tests__/ManageActiveMembership.test.jsx | 41 - .../chat/__tests__/Membership.test.jsx | 46 - .../PersonalInvitationListItem.test.jsx | 44 - .../PersonalInvitationSection.test.jsx | 42 - .../chat/__tests__/RequestListItem.test.jsx | 40 - .../activeMembershipsSection.test.jsx | 111 - app/javascript/chat/__tests__/alert.test.jsx | 27 - .../chat/__tests__/article.test.jsx | 30 - .../chat/__tests__/channelButton.test.jsx | 36 - .../chat/__tests__/channelRequest.test.jsx | 41 - .../__tests__/channelRequestSection.test.jsx | 41 - .../chat/__tests__/channels.test.jsx | 171 -- app/javascript/chat/__tests__/chat.test.jsx | 244 -- .../__tests__/chatChannelDescription.test.jsx | 33 - .../chatChannelMembersection.test.jsx | 80 - .../chatChannelSettingActions.test.js | 226 -- .../__tests__/chatChannelSettings.test.jsx | 26 - .../chat/__tests__/compose.test.jsx | 234 -- .../chat/__tests__/content.test.jsx | 92 - app/javascript/chat/__tests__/draw.test.jsx | 21 - .../__tests__/invitationLinkManager.test.jsx | 74 - .../chat/__tests__/inviteForm.test.jsx | 32 - .../__tests__/leaveMembershipSection.test.jsx | 32 - .../chat/__tests__/message.test.jsx | 60 - .../chat/__tests__/modFaqSection.test.jsx | 21 - .../chat/__tests__/modSection.test.jsx | 23 - .../pendingMembershipsSection.test.jsx | 95 - .../chat/__tests__/personalSetting.test.jsx | 33 - .../chat/__tests__/reportAbuse.test.jsx | 44 - .../chat/__tests__/requestManager.test.jsx | 51 - .../requestedMembershipSection.test.jsx | 94 - .../chat/__tests__/settingsForm.test.jsx | 42 - app/javascript/chat/__tests__/util.test.js | 58 - app/javascript/chat/actionMessage.jsx | 88 - app/javascript/chat/actions/actions.js | 182 -- .../actions/chat_channel_setting_actions.js | 186 -- app/javascript/chat/actions/requestActions.js | 143 -- app/javascript/chat/alert.jsx | 20 - app/javascript/chat/article.jsx | 18 - app/javascript/chat/channelRequest.jsx | 47 - app/javascript/chat/channels.jsx | 119 - app/javascript/chat/chat.jsx | 1981 ----------------- .../chat/components/ChannelButton.jsx | 93 - .../chat/components/ChannelFilterButton.jsx | 45 - .../chat/components/ChannelImage.jsx | 59 - .../chat/components/ConnectStateProvider.jsx | 21 - .../chat/components/CreateChatModal.jsx | 87 - .../__tests__/ConnectStateProvider.test.jsx | 60 - app/javascript/chat/compose.jsx | 143 -- app/javascript/chat/configMenu.jsx | 53 - app/javascript/chat/content.jsx | 132 -- app/javascript/chat/draw/index.jsx | 187 -- app/javascript/chat/message.jsx | 213 -- app/javascript/chat/messages/errorMessage.jsx | 21 - app/javascript/chat/util.js | 136 -- .../channel-list-prop-type.js | 14 - .../__tests__/ContactViaConnect.test.jsx | 38 - .../listings/__tests__/MessageModal.test.jsx | 83 - .../listings/__tests__/Modal.test.jsx | 19 - .../listings/__tests__/SingleListing.test.jsx | 1 - .../listings/components/ContactViaConnect.jsx | 31 - .../listings/components/MessageModal.jsx | 74 - app/javascript/listings/components/Modal.jsx | 19 - app/javascript/listings/listings.jsx | 41 - .../singleListing/listingPropTypes.js | 1 - app/javascript/packs/Chat.jsx | 24 - app/javascript/packs/Onboarding.jsx | 4 +- app/javascript/packs/articleForm.jsx | 2 +- app/javascript/packs/base.jsx | 1 - .../packs/onboardingRedirectCheck.jsx | 4 +- app/javascript/profileDropdown/flagButton.js | 2 +- .../__tests__/getUserDataAndCsrfToken.test.js | 56 + .../utilities/connect/getUnopenedChannels.jsx | 236 -- app/javascript/utilities/connect/index.js | 2 - .../utilities/connect/newMessageNotify.js | 16 - app/javascript/utilities/connect/pusher.js | 33 - .../utilities/getUserDataAndCsrfToken.js | 35 + app/lib/constants/role.rb | 1 - app/mailers/notify_mailer.rb | 23 - app/models/admin_menu.rb | 8 +- app/models/chat_channel.rb | 189 -- app/models/chat_channel_membership.rb | 101 - app/models/follow.rb | 16 - app/models/listing.rb | 1 + app/models/message.rb | 224 -- app/models/organization_membership.rb | 23 - app/models/role.rb | 1 - app/models/tag.rb | 3 +- app/models/user.rb | 7 - app/models/users/notification_setting.rb | 1 + .../chat_channel_membership_policy.rb | 33 - app/policies/chat_channel_policy.rb | 81 - app/policies/user_policy.rb | 1 - .../chat_channel_membership_serializer.rb | 9 - app/serializers/search/listing_serializer.rb | 1 - .../chat_channels/create_with_users.rb | 45 - app/services/chat_channels/find_or_create.rb | 35 - app/services/chat_channels/send_invitation.rb | 31 - app/services/chat_channels/update_channel.rb | 19 - app/services/moderator/banish_user.rb | 1 - app/services/moderator/merge_user.rb | 12 +- .../search/chat_channel_membership.rb | 59 - app/services/search/listing.rb | 1 - app/services/tag_moderators/add.rb | 26 +- app/services/user_blocks/channel_handler.rb | 36 - app/services/users/cleanup_chat_channels.rb | 12 - app/services/users/delete_activity.rb | 2 - app/views/admin/chat_channels/index.html.erb | 71 - .../_apple_auth_provider_settings.html.erb | 2 +- .../chat_channel_info.json.jbuilder | 20 - .../chat_channel_memberships/index.html.erb | 29 - .../join_channel_invitation.html.erb | 17 - .../request_details.json.jbuilder | 5 - .../chat_channels/channel_info.json.jbuilder | 13 - app/views/chat_channels/index.html.erb | 46 - app/views/chat_channels/index.json.jbuilder | 20 - app/views/chat_channels/show.json.jbuilder | 15 - app/views/layouts/_top_bar.html.erb | 7 - app/views/layouts/application.html.erb | 2 - app/views/listings/_form.html.erb | 13 - app/views/listings/edit.html.erb | 7 - .../channel_invite_email.html.erb | 55 - .../channel_invite_email.text.erb | 3 - .../notify_mailer/new_message_email.html.erb | 18 - .../notify_mailer/new_message_email.text.erb | 3 - .../tag_moderator_confirmation_email.html.erb | 20 - .../tag_moderator_confirmation_email.text.erb | 10 - app/views/users/_account.html.erb | 2 +- app/views/users/_extensions.html.erb | 29 - app/views/users/_notifications.html.erb | 4 - app/views/users/confirm_destroy.html.erb | 2 +- app/views/users/show.html.erb | 18 +- .../follows/create_chat_channel_worker.rb | 15 - .../metrics/record_data_counts_worker.rb | 17 +- config/fastly/snippets/safe_params_list.vcl | 2 +- config/initializers/pusher.rb | 8 - config/initializers/rack/attack.rb | 9 +- config/initializers/reserved_words.rb | 1 - config/routes.rb | 36 - config/routes/admin.rb | 7 - cypress/fixtures/search/listings.json | 2 - cypress/fixtures/users/chatUser2.json | 5 - .../chatFlows/messageOptions.spec.js | 71 - .../listingFlows/viewListing.spec.js | 19 - cypress/util/networkUtils.js | 4 +- .../20210917023320_drop_connect_tables.rb | 17 + db/schema.rb | 45 - db/seeds.rb | 33 +- spec/factories/chat_channel_memberships.rb | 6 - spec/factories/chat_channels.rb | 7 - spec/factories/messages.rb | 6 - spec/factories/users_notification_settings.rb | 1 - spec/initializers/rack/attack_spec.rb | 28 +- .../update_articles_cached_entities_spec.rb | 4 +- spec/mailers/notify_mailer_spec.rb | 50 - .../mailers/previews/notify_mailer_preview.rb | 8 +- spec/models/chat_channel_membership_spec.rb | 37 - spec/models/chat_channel_spec.rb | 92 - spec/models/follow_spec.rb | 31 - spec/models/message_spec.rb | 193 -- spec/models/organization_membership_spec.rb | 19 - spec/models/role_spec.rb | 2 +- spec/models/tag_spec.rb | 12 - spec/models/user_spec.rb | 3 - .../chat_channel_membership_policy_spec.rb | 30 - spec/policies/chat_channel_policy_spec.rb | 33 - spec/requests/admin/chat_channel_spec.rb | 59 - spec/requests/admin/users_manage_spec.rb | 3 - spec/requests/api/v0/listings_spec.rb | 5 +- .../requests/chat_channel_memberships_spec.rb | 505 ----- spec/requests/chat_channels_spec.rb | 471 ---- spec/requests/feedback_messages_spec.rb | 20 - spec/requests/github_repos_spec.rb | 2 +- spec/requests/listings_spec.rb | 6 +- spec/requests/messages_spec.rb | 110 - spec/requests/pusher_auth_spec.rb | 15 - spec/requests/search_spec.rb | 16 - spec/requests/user/user_settings_spec.rb | 2 +- spec/requests/user_blocks_spec.rb | 18 - ...chat_channel_membership_serializer_spec.rb | 14 - .../search/listing_serializer_spec.rb | 5 +- .../chat_channels/create_with_users_spec.rb | 44 - .../chat_channels/find_or_create_spec.rb | 37 - .../search/chat_channel_membership_spec.rb | 48 - spec/services/search/listing_spec.rb | 5 +- spec/services/tag_moderators/add_spec.rb | 76 - .../user_blocks/channel_handler_spec.rb | 45 - .../users/cleanup_chat_channels_spec.rb | 27 - spec/services/users/delete_spec.rb | 16 - spec/support/seeds/seeds_e2e.rb | 69 - .../admin/admin_manages_chat_channels_spec.rb | 59 - .../create_chat_channel_worker_spec.rb | 47 - .../github_repos/repo_sync_worker_spec.rb | 2 +- .../moderator/banish_user_worker_spec.rb | 2 - vendor/cache/pusher-2.0.2.gem | Bin 18432 -> 0 bytes vendor/cache/pusher-signature-0.1.8.gem | Bin 11776 -> 0 bytes 250 files changed, 176 insertions(+), 15427 deletions(-) delete mode 100644 app/assets/javascripts/initializers/initializeAllChatButtons.js delete mode 100644 app/assets/stylesheets/chat.scss delete mode 100644 app/assets/stylesheets/connect/_channel-details.scss delete mode 100644 app/controllers/admin/chat_channels_controller.rb delete mode 100644 app/controllers/chat_channel_memberships_controller.rb delete mode 100644 app/controllers/chat_channels_controller.rb delete mode 100644 app/controllers/messages_controller.rb delete mode 100644 app/controllers/pusher_controller.rb delete mode 100644 app/helpers/chat_channel_memberships_helper.rb delete mode 100644 app/helpers/chat_channels_helper.rb delete mode 100644 app/helpers/messages_helper.rb delete mode 100644 app/javascript/chat/ChatChannelSettings/ActiveMembershipsSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/ChannelDescriptionSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/ChatChannelMembershipSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/ChatChannelSettings.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/ChatChannelSettingsSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/InviteForm.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/LeaveMembershipSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/Membership.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/MembershipManager/InvitationLinkManager.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/MembershipManager/ManageActiveMembership.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/MembershipManager/Membership.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/MembershipManager/MembershipSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/ModFaqSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/ModSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/PendingMembershipSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/PersonalSetting.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/RequestedMembershipSection.jsx delete mode 100644 app/javascript/chat/ChatChannelSettings/SettingsForm.jsx delete mode 100644 app/javascript/chat/ReportAbuse/index.jsx delete mode 100644 app/javascript/chat/RequestManager/ChannelRequestSection.jsx delete mode 100644 app/javascript/chat/RequestManager/HeaderSection.jsx delete mode 100644 app/javascript/chat/RequestManager/PersonalInvitationListItem.jsx delete mode 100644 app/javascript/chat/RequestManager/PersonalInvitationSection.jsx delete mode 100644 app/javascript/chat/RequestManager/RequestListItem.jsx delete mode 100644 app/javascript/chat/RequestManager/RequestManager.jsx delete mode 100644 app/javascript/chat/__tests__/ManageActiveMembership.test.jsx delete mode 100644 app/javascript/chat/__tests__/Membership.test.jsx delete mode 100644 app/javascript/chat/__tests__/PersonalInvitationListItem.test.jsx delete mode 100644 app/javascript/chat/__tests__/PersonalInvitationSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/RequestListItem.test.jsx delete mode 100644 app/javascript/chat/__tests__/activeMembershipsSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/alert.test.jsx delete mode 100644 app/javascript/chat/__tests__/article.test.jsx delete mode 100644 app/javascript/chat/__tests__/channelButton.test.jsx delete mode 100644 app/javascript/chat/__tests__/channelRequest.test.jsx delete mode 100644 app/javascript/chat/__tests__/channelRequestSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/channels.test.jsx delete mode 100644 app/javascript/chat/__tests__/chat.test.jsx delete mode 100644 app/javascript/chat/__tests__/chatChannelDescription.test.jsx delete mode 100644 app/javascript/chat/__tests__/chatChannelMembersection.test.jsx delete mode 100644 app/javascript/chat/__tests__/chatChannelSettingActions.test.js delete mode 100644 app/javascript/chat/__tests__/chatChannelSettings.test.jsx delete mode 100644 app/javascript/chat/__tests__/compose.test.jsx delete mode 100644 app/javascript/chat/__tests__/content.test.jsx delete mode 100644 app/javascript/chat/__tests__/draw.test.jsx delete mode 100644 app/javascript/chat/__tests__/invitationLinkManager.test.jsx delete mode 100644 app/javascript/chat/__tests__/inviteForm.test.jsx delete mode 100644 app/javascript/chat/__tests__/leaveMembershipSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/message.test.jsx delete mode 100644 app/javascript/chat/__tests__/modFaqSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/modSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/pendingMembershipsSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/personalSetting.test.jsx delete mode 100644 app/javascript/chat/__tests__/reportAbuse.test.jsx delete mode 100644 app/javascript/chat/__tests__/requestManager.test.jsx delete mode 100644 app/javascript/chat/__tests__/requestedMembershipSection.test.jsx delete mode 100644 app/javascript/chat/__tests__/settingsForm.test.jsx delete mode 100644 app/javascript/chat/__tests__/util.test.js delete mode 100644 app/javascript/chat/actionMessage.jsx delete mode 100644 app/javascript/chat/actions/actions.js delete mode 100644 app/javascript/chat/actions/chat_channel_setting_actions.js delete mode 100644 app/javascript/chat/actions/requestActions.js delete mode 100644 app/javascript/chat/alert.jsx delete mode 100644 app/javascript/chat/article.jsx delete mode 100644 app/javascript/chat/channelRequest.jsx delete mode 100644 app/javascript/chat/channels.jsx delete mode 100644 app/javascript/chat/chat.jsx delete mode 100644 app/javascript/chat/components/ChannelButton.jsx delete mode 100644 app/javascript/chat/components/ChannelFilterButton.jsx delete mode 100644 app/javascript/chat/components/ChannelImage.jsx delete mode 100644 app/javascript/chat/components/ConnectStateProvider.jsx delete mode 100644 app/javascript/chat/components/CreateChatModal.jsx delete mode 100644 app/javascript/chat/components/__tests__/ConnectStateProvider.test.jsx delete mode 100644 app/javascript/chat/compose.jsx delete mode 100644 app/javascript/chat/configMenu.jsx delete mode 100644 app/javascript/chat/content.jsx delete mode 100644 app/javascript/chat/draw/index.jsx delete mode 100644 app/javascript/chat/message.jsx delete mode 100644 app/javascript/chat/messages/errorMessage.jsx delete mode 100644 app/javascript/chat/util.js delete mode 100644 app/javascript/common-prop-types/channel-list-prop-type.js delete mode 100644 app/javascript/listings/__tests__/ContactViaConnect.test.jsx delete mode 100644 app/javascript/listings/__tests__/MessageModal.test.jsx delete mode 100644 app/javascript/listings/components/ContactViaConnect.jsx delete mode 100644 app/javascript/listings/components/MessageModal.jsx delete mode 100644 app/javascript/packs/Chat.jsx create mode 100644 app/javascript/utilities/__tests__/getUserDataAndCsrfToken.test.js delete mode 100644 app/javascript/utilities/connect/getUnopenedChannels.jsx delete mode 100644 app/javascript/utilities/connect/index.js delete mode 100644 app/javascript/utilities/connect/newMessageNotify.js delete mode 100644 app/javascript/utilities/connect/pusher.js create mode 100644 app/javascript/utilities/getUserDataAndCsrfToken.js delete mode 100644 app/models/chat_channel.rb delete mode 100644 app/models/chat_channel_membership.rb delete mode 100644 app/models/message.rb delete mode 100644 app/policies/chat_channel_membership_policy.rb delete mode 100644 app/policies/chat_channel_policy.rb delete mode 100644 app/serializers/search/chat_channel_membership_serializer.rb delete mode 100644 app/services/chat_channels/create_with_users.rb delete mode 100644 app/services/chat_channels/find_or_create.rb delete mode 100644 app/services/chat_channels/send_invitation.rb delete mode 100644 app/services/chat_channels/update_channel.rb delete mode 100644 app/services/search/chat_channel_membership.rb delete mode 100644 app/services/user_blocks/channel_handler.rb delete mode 100644 app/services/users/cleanup_chat_channels.rb delete mode 100644 app/views/admin/chat_channels/index.html.erb delete mode 100644 app/views/chat_channel_memberships/chat_channel_info.json.jbuilder delete mode 100644 app/views/chat_channel_memberships/index.html.erb delete mode 100644 app/views/chat_channel_memberships/join_channel_invitation.html.erb delete mode 100644 app/views/chat_channel_memberships/request_details.json.jbuilder delete mode 100644 app/views/chat_channels/channel_info.json.jbuilder delete mode 100644 app/views/chat_channels/index.html.erb delete mode 100644 app/views/chat_channels/index.json.jbuilder delete mode 100644 app/views/chat_channels/show.json.jbuilder delete mode 100644 app/views/mailers/notify_mailer/channel_invite_email.html.erb delete mode 100644 app/views/mailers/notify_mailer/channel_invite_email.text.erb delete mode 100644 app/views/mailers/notify_mailer/new_message_email.html.erb delete mode 100644 app/views/mailers/notify_mailer/new_message_email.text.erb delete mode 100644 app/workers/follows/create_chat_channel_worker.rb delete mode 100644 config/initializers/pusher.rb delete mode 100644 cypress/fixtures/users/chatUser2.json delete mode 100644 cypress/integration/seededFlows/chatFlows/messageOptions.spec.js create mode 100644 db/migrate/20210917023320_drop_connect_tables.rb delete mode 100644 spec/factories/chat_channel_memberships.rb delete mode 100644 spec/factories/chat_channels.rb delete mode 100644 spec/factories/messages.rb delete mode 100644 spec/models/chat_channel_membership_spec.rb delete mode 100644 spec/models/chat_channel_spec.rb delete mode 100644 spec/models/message_spec.rb delete mode 100644 spec/policies/chat_channel_membership_policy_spec.rb delete mode 100644 spec/policies/chat_channel_policy_spec.rb delete mode 100644 spec/requests/admin/chat_channel_spec.rb delete mode 100644 spec/requests/chat_channel_memberships_spec.rb delete mode 100644 spec/requests/chat_channels_spec.rb delete mode 100644 spec/requests/messages_spec.rb delete mode 100644 spec/requests/pusher_auth_spec.rb delete mode 100644 spec/serializers/search/chat_channel_membership_serializer_spec.rb delete mode 100644 spec/services/chat_channels/create_with_users_spec.rb delete mode 100644 spec/services/chat_channels/find_or_create_spec.rb delete mode 100644 spec/services/search/chat_channel_membership_spec.rb delete mode 100644 spec/services/tag_moderators/add_spec.rb delete mode 100644 spec/services/user_blocks/channel_handler_spec.rb delete mode 100644 spec/services/users/cleanup_chat_channels_spec.rb delete mode 100644 spec/system/admin/admin_manages_chat_channels_spec.rb delete mode 100644 spec/workers/follows/create_chat_channel_worker_spec.rb delete mode 100644 vendor/cache/pusher-2.0.2.gem delete mode 100644 vendor/cache/pusher-signature-0.1.8.gem diff --git a/.env_sample b/.env_sample index ed0de8d83..50100c7a5 100644 --- a/.env_sample +++ b/.env_sample @@ -123,13 +123,6 @@ GA_TRACKING_ID="Optional" # (https://mailchimp.com/developer/) MAILCHIMP_API_KEY="Optional-valid" -# Pusher for DEV Connect/notfications -# (https://pusher.com/docs) -PUSHER_APP_ID= -PUSHER_CLUSTER= -PUSHER_KEY= -PUSHER_SECRET= - # Google recaptcha (Optional) # (https://developers.google.com/recaptcha/intro) RECAPTCHA_SECRET= diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d20ddcd13..dacf06539 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -18,6 +18,5 @@ require: Rails/HasManyOrHasOneDependent: Exclude: - 'app/models/article.rb' - - 'app/models/chat_channel.rb' - 'app/models/organization.rb' - 'app/models/user.rb' diff --git a/Gemfile b/Gemfile index e0432adf0..26b9cf47f 100644 --- a/Gemfile +++ b/Gemfile @@ -48,6 +48,7 @@ gem "honeycomb-beeline", "~> 2.7.1" # Monitoring and Observability gem gem "html_truncator", "~> 0.4" # Truncate an HTML string properly gem "htmlentities", "~> 4.3", ">= 4.3.4" # A module for encoding and decoding (X)HTML entities gem "httparty", "~> 0.20" # Makes http fun! Also, makes consuming restful web services dead easy +gem "httpclient", "~> 2.8.3" # Gives something like the functionality of libwww-perl (LWP) in Ruby gem "i18n-js", "~> 3.9.0" # Helps with internationalization in Rails. gem "imgproxy", "~> 2.0" # A gem that easily generates imgproxy URLs for your images gem "inline_svg", "~> 1.7" # Embed SVG documents in your Rails views and style them with CSS @@ -74,7 +75,6 @@ gem "pg_search", "~> 2.3.5" # PgSearch builds Active Record named scopes that ta gem "pghero", "~> 2.8" # Dashboard for Postgres gem "puma", "~> 5.5.2" # Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server gem "pundit", "~> 2.1" # Object oriented authorization for Rails applications -gem "pusher", "~> 2.0" # Ruby library for Pusher Channels HTTP API gem "rack-attack", "~> 6.5.0" # Used to throttle requests to prevent brute force attacks gem "rack-cors", "~> 1.1" # Middleware that will make Rack-based apps CORS compatible gem "rack-timeout", "~> 0.6" # Rack middleware which aborts requests that have been running for longer than a specified timeout diff --git a/Gemfile.lock b/Gemfile.lock index 88eeb2b8c..3a1b9bd2e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -561,11 +561,6 @@ GEM activesupport (>= 3.0.0) pundit-matchers (1.7.0) rspec-rails (>= 3.0.0) - pusher (2.0.2) - httpclient (~> 2.8) - multi_json (~> 1.15) - pusher-signature (~> 0.1.8) - pusher-signature (0.1.8) raabro (1.4.0) racc (1.6.0) rack (2.2.3) @@ -946,6 +941,7 @@ DEPENDENCIES html_truncator (~> 0.4) htmlentities (~> 4.3, >= 4.3.4) httparty (~> 0.20) + httpclient (~> 2.8.3) hypershield (~> 0.2.2) i18n-js (~> 3.9.0) i18n-tasks (~> 0.9.35) @@ -982,7 +978,6 @@ DEPENDENCIES puma (~> 5.5.2) pundit (~> 2.1) pundit-matchers (~> 1.7) - pusher (~> 2.0) rack-attack (~> 6.5.0) rack-cors (~> 1.1) rack-host-redirect (~> 1.3) diff --git a/app/assets/javascripts/initializePage.js b/app/assets/javascripts/initializePage.js index 78d6ed4dc..6f2930e7b 100644 --- a/app/assets/javascripts/initializePage.js +++ b/app/assets/javascripts/initializePage.js @@ -1,6 +1,6 @@ /* global initializeLocalStorageRender, initializeBodyData, - initializeAllChatButtons, initializeAllTagEditButtons, initializeUserFollowButts, + initializeAllTagEditButtons, initializeUserFollowButts, initializeBaseTracking, initializeCommentsPage, initializeArticleDate, initializeArticleReactions, initNotifications, initializeCommentDate, initializeSettings, @@ -50,7 +50,6 @@ function initializePage() { clearInterval(waitingForDataLoad); if (document.body.getAttribute('data-user-status') === 'logged-in') { initializeBaseUserData(); - initializeAllChatButtons(); initializeAllTagEditButtons(); } initializeBroadcast(); diff --git a/app/assets/javascripts/initializers/initializeAllChatButtons.js b/app/assets/javascripts/initializers/initializeAllChatButtons.js deleted file mode 100644 index 352478d33..000000000 --- a/app/assets/javascripts/initializers/initializeAllChatButtons.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -function showChatModal(modal) { - // eslint-disable-next-line no-param-reassign - modal.style.display = 'block'; - document.getElementById('new-message').focus(); -} - -function hideChatModal(modal) { - // eslint-disable-next-line no-param-reassign - modal.style.display = 'none'; -} - -function toggleModal() { - var modal = document.getElementsByClassName('crayons-modal')[0]; - modal.classList.toggle('hidden'); -} - -function initModal() { - var modal = document.getElementsByClassName('crayons-modal')[0]; - modal - .getElementsByClassName('close-modal')[0] - .addEventListener('click', toggleModal); - modal - .getElementsByClassName('crayons-modal__overlay')[0] - .addEventListener('click', toggleModal); -} - -function handleChatButtonPress(form) { - var message = document.getElementById('new-message').value; - var formDataInfo = JSON.parse(form.dataset.info); - var formData = new FormData(); - - if (message.replace(/\s/g, '').length === 0) { - return; - } - - formData.append('user_id', formDataInfo.id); - formData.append('message', message); - formData.append('controller', 'chat_channels'); - - getCsrfToken() - .then(sendFetch('chat-creation', formData)) - .then(() => { - window.location.href = `/connect/@${formDataInfo.username}`; - }); -} - -function addButtonClickHandle(response, button, modalInfo) { - var linkWrap = document.getElementById('user-connect-redirect'); - var form = document.getElementById('new-message-form'); - button.classList.add('showing'); - if (modalInfo.showChat === 'open' && response !== 'mutual') { - linkWrap.removeAttribute('href'); // remove link - button.addEventListener('click', toggleModal); - // eslint-disable-next-line no-param-reassign - button.classList.remove('hidden'); // show button - linkWrap.classList.remove('hidden'); // show button - form.onsubmit = () => { - handleChatButtonPress(form); - return false; - }; - } else if (response === 'mutual') { - button.removeEventListener('click', toggleModal); - // eslint-disable-next-line no-param-reassign - button.classList.remove('hidden'); // show button - linkWrap.classList.remove('hidden'); // show button - } -} - -function fetchButton(button, modalInfo) { - var dataRequester; - // button.dataset.fetched = 'fetched'; // telling initialize that this button has been fetched - if (window.XMLHttpRequest) { - dataRequester = new XMLHttpRequest(); - } else { - dataRequester = new ActiveXObject('Microsoft.XMLHTTP'); - } - dataRequester.onreadystatechange = () => { - if ( - dataRequester.readyState === XMLHttpRequest.DONE && - dataRequester.status === 200 - ) { - addButtonClickHandle(dataRequester.response, button, modalInfo); - } - }; - dataRequester.open( - 'GET', - '/follows/' + modalInfo.id + '?followable_type=' + modalInfo.className, - ); - dataRequester.send(); -} - -function initializeChatButton(button, modalInfo) { - // if user logged out, do nothing - var user = userData(); - if (user === null || user.id === modalInfo.id) { - return; - } - fetchButton(button, modalInfo); -} - -// finds all elements with chat action button class -function initializeAllChatButtons() { - var buttons = document.getElementsByClassName('chat-action-button'); - var modal = document.getElementById('new-message-form'); - var i; - - if (!modal) { - return; - } - - var modalInfo = JSON.parse(modal.dataset.info); - initModal(); - - for (i = 0; i < buttons.length; i += 1) { - initializeChatButton(buttons[i], modalInfo); - } -} diff --git a/app/assets/javascripts/utilities/sendFetch.js b/app/assets/javascripts/utilities/sendFetch.js index bcb7c0b05..333aa7ed2 100644 --- a/app/assets/javascripts/utilities/sendFetch.js +++ b/app/assets/javascripts/utilities/sendFetch.js @@ -46,12 +46,6 @@ function sendFetch(switchStatement, body) { addTokenToBody: true, body, }); - case 'chat-creation': - return fetchCallback({ - url: '/chat_channels/create_chat', - addTokenToBody: true, - body, - }); case 'block-user': return fetchCallback({ url: '/user_blocks', diff --git a/app/assets/stylesheets/chat.scss b/app/assets/stylesheets/chat.scss deleted file mode 100644 index 97b48d233..000000000 --- a/app/assets/stylesheets/chat.scss +++ /dev/null @@ -1,1344 +0,0 @@ -@import 'variables'; -@import 'mixins'; -@import 'config/import'; - -// High level classes -.chat-page-wrapper { - margin: 0px auto 0px; - width: 100%; - max-width: calc(1540px + 10vw); - - --layout-chat-left-sidebar-width: 260px; -} - -.live-chat { - &.live-chat--iossafari { - height: calc(100vh - 56px); - } - - overflow-y: hidden; -} - -.live-chat { - padding: 0; - width: 100%; -} - -.chat { - display: flex; - height: calc(100 * var(--vh) - var(--header-height)); - position: relative; - overflow-x: hidden; - overflow-y: hidden; - - &.chat--iossafari { - height: 100%; - } -} - -.chat__channels { - box-sizing: border-box; - height: inherit; - padding: var(--su-3); - position: relative; - width: 100%; - overflow-y: auto; - @media screen and (min-width: $breakpoint-m) { - min-width: var(--layout-chat-left-sidebar-width); - max-width: var(--layout-chat-left-sidebar-width); - } -} - -.chat__channelssearchtoggle { - background: transparent; - border: 0; - margin-left: 2px; - svg { - vertical-align: -5px; - fill: var(--indicator-default-color); - } -} - -.chat__notificationsbutton { - border: 0px; - font-size: 12px; - padding: 15px 0px; - width: 100%; - color: darken($green, 30%); - font-weight: bold; - width: 95%; - border-radius: 3px; - border: 1px solid darken($green, 30%); - box-shadow: 3px 3px 0px darken($green, 30%); - background: lighten($green, 30%); - margin-bottom: 5px; - - &:hover { - @include themeable( - background, - theme-container-background-hover, - lighten($green, 20%) - ); - } -} - -.chat__channels--placeholder { - .chat__channelstogglebutt--placeholderunexpanded { - display: none; - } - - @media screen and (max-width: 599px) { - width: 45px; - min-width: 45px; - - input { - display: none; - } - - .chat__channelstogglebutt--placeholderunexpanded { - display: block; - width: 100%; - } - } -} - -.chat__channels input { - width: 100%; -} - -.chat__channeltypefilter { - width: 100%; - margin-top: 15px; -} - -.chat__channeltypefilterbutton { - margin: 1px; - @media screen and (min-width: 1300px) { - margin: 5px 4px; - } -} - -.chat_chatconfig { - position: absolute; - bottom: 0px; - left: 0px; - right: 6px; - font-size: 12px; - padding: 3px 12px; - display: inline-block; - border-radius: 3px; - background: var(--body-bg); - border: 1px solid $light-medium-gray; - font-weight: bold; - cursor: default; -} - -.chat_chatconfig--on { - color: $green; -} - -.chat_chatconfig--off { - color: $red; -} - -.chat__channels--hidden { - display: none; -} - -.active-channel__back-btn { - display: inherit; - - @media screen and (min-width: $breakpoint-m) { - display: none; - } -} - -.chat__activechat { - height: inherit; - width: 100%; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - transform: translateX(0); - transition: transform 0.22s linear; - z-index: var(--z-elevate); - - @media screen and (min-width: $breakpoint-m) { - position: inherit; - } -} - -.chat__activechat--hidden { - transform: translateX(100%); - transition: transform 0.18s linear; - - @media screen and (min-width: $breakpoint-m) { - transform: translateX(0); - } -} - -.activechatchannel { - height: inherit; - max-height: inherit; - display: flex; - flex-direction: row; - justify-content: space-between; - background: var(--card-bg); - flex-flow: row nowrap; - position: relative; - - @include themeable( - border-left, - theme-container-border, - 1px solid $outline-color - ); - - @media screen and (min-width: 1540px) { - @include themeable( - border, - theme-container-border, - 1px solid $outline-color - ); - border-top: 0px; - } -} - -.activechatchannel__conversation { - position: relative; - order: 1; - display: flex; - flex-direction: column; - flex: 0 1 auto; - width: 100%; - min-width: 50%; - @media screen and (min-width: 1440px) { - min-width: 35%; - } - @media screen and (max-width: 426px) { - overflow-x: hidden; - } -} - -.active-channel__header { - align-items: center; - box-shadow: 0 0 0 1px var(--card-border); - box-sizing: border-box; - display: flex; - height: var(--header-height); - position: relative; - padding: var(--su-4); - justify-content: space-between; -} - -.active-channel__title { - font-weight: var(--fw-bold); - font-size: var(--fs-base); - color: var(--body-color); -} - -.activechatchannel__messages { - padding-top: var(--su-2); - padding-bottom: var(--su-2); - font-size: var(--fs-base); - flex-grow: 1; - height: 300px; - // Setting it to scroll so there is no jump when it's auto. Also, since it's chat, - // it will almost always need scrolling right away. - overflow-y: scroll; - overflow-x: hidden; - text-align: left; - overscroll-behavior-y: contain; - -webkit-overflow-scrolling: touch; -} - -.activechatchannel__alerts { - position: relative; -} - -.chatalert__default { - align-items: center; - background-color: rgba(0, 0, 0, 0.5); - color: white; - display: flex; - height: 25px; - justify-content: center; - position: absolute; - top: -25px; - width: 100%; - font-size: 13px; -} - -.chatalert__default--hidden { - display: none; -} - -.activechatchannel__form { - width: 100%; - position: relative; -} - -.activechatchannel__activecontent { - order: 2; - flex: 0 1 auto; - @include themeable(border, theme-border, 1px solid $outline-color); - padding: 13px; - min-width: 50%; - overflow-x: hidden; - @media screen and (min-width: 1440px) { - min-width: 45%; - } - -webkit-overflow-scrolling: touch; - background: var(--body-bg); - z-index: 200; - position: relative; - box-sizing: border-box; - overflow-y: auto; - max-width: 100%; - - @media screen and (max-width: 426px) { - padding: 10px; - min-width: 50%; - width: calc(100%); - position: fixed; - height: 100%; - margin-left: 0; - margin-top: 0; - } - - @media screen and (min-width: 1000px) { - h2 { - font-size: 2rem; - } - margin-left: initial; - padding: 18px; - max-width: 480px; - } - - @media screen and (min-width: 1300px) { - margin-left: initial; - padding: 18px; - width: 750px; - max-width: 750px; - } -} - -.chat--video-visible { - .activechatchannel__conversation { - min-width: 20%; - } - .activechatchannel__activecontent { - &.activechatchannel__activecontent--video { - width: 380px; - min-width: 380px; - @media screen and (max-width: 426px) { - width: calc(100% - 16px); - min-width: calc(100% - 16px); - } - iframe { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - height: 100%; - width: 100%; - border: 0px; - } - } - width: 300px; - min-width: 300px; - @media screen and (min-width: 1000px) { - width: 400px; - min-width: 400px; - } - @media screen and (min-width: 1500px) { - width: 750px; - min-width: 750px; - } - } -} - -.chat--content-visible .activechatchannel__conversation { - max-width: 52%; -} - -.chat--content-visible - .activechatchannel__activecontent.activechatchannel__activecontent--video { - width: 180px; - min-width: 180px; -} - -.live-chat-wrapper .activechatchannel__activecontent { - min-width: 310px; - margin-left: -180px; - max-width: 96%; - padding: 13px; -} - -.chat--content-visible-full { - .activechatchannel__activecontent.activechatchannel__activecontent--sidecar { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - width: 100%; - min-width: 100%; - } - .activechatchannel__activecontent.activechatchannel__activecontent--video { - position: absolute; - right: 0; - bottom: 0; - width: 200px; - min-width: 200px; - height: 300px; - z-index: 250; - } -} - -.chat--video-visible-full { - .activechatchannel__activecontent.activechatchannel__activecontent--video { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - width: 100%; - min-width: 100%; - } - .activechatchannel__activecontent.activechatchannel__activecontent--sidecar { - display: none; - } -} - -.activechatchannel__activecontentexitbutton { - font-size: 30px; - position: absolute; - margin-left: 80%; - margin-top: -4px; - left: 4px; - top: 4px; - z-index: 10; - padding: 0px; - height: 30px; - width: 30px; - line-height: 0; - @media screen and (max-width: 800px) { - &.activechatchannel__activecontentexitbutton--fullscreen { - display: none; - } - } -} - -.activechatchannel__activeArticle { - position: absolute; - top: 0px; - left: 0; - right: 0; - bottom: 0; -} - -.activechatchannel__activeArticle iframe { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - height: 100%; - width: 100%; - border: 0px; -} - -.activechatchannel__activecontentuserdetails { - margin-top: 20px; - font-family: var(--ff-monospace); - font-size: 0.9em; - - .key { - color: $medium-gray; - margin-bottom: 3px; - font-size: 0.9em; - } -} - -.userdetails__blockreport { - margin: 10px 0; - - button { - background-color: rgb(255, 0, 0); - color: rgb(255, 255, 254); - font-size: 1em; - cursor: pointer; - padding: 5px; - margin: 2px 5px; - border-radius: 3px; - border-width: 0px; - border-style: initial; - border-color: initial; - border-image: initial; - - &:first-child { - margin-left: 0; - } - } -} - -.userdetails__reportabuse, -.userdetails__blockmsg { - a { - background-color: rgb(255, 0, 0); - color: rgb(255, 255, 254); - font-size: 1em; - cursor: pointer; - padding: 5px; - margin: 2px 5px; - border-radius: 3px; - border-width: 0px; - border-style: initial; - border-color: initial; - border-image: initial; - } - - .no { - background-color: rgb(78, 87, 239); - } -} - -.chatchannels { - box-sizing: border-box; - display: flex; - flex-direction: column; - height: auto; - justify-content: space-between; - width: 100%; -} - -.chatchannels__channelslist { - flex-grow: 1; - overflow-y: auto; - overflow-x: hidden; - margin: var(--su-4) auto; - width: 100%; - -webkit-overflow-scrolling: touch; -} - -.chatchannels__channelslistheader { - background: lighten($purple, 5%); - border: 1px solid darken($purple, 20%); - font-size: 12px; - color: $dark-purple; - box-sizing: border-box; - padding: 5px; - width: 98%; - border-radius: 3px; -} - -.chatchannels__channelslistfooter { - font-size: 12px; - color: $medium-gray; - padding: 10px; - opacity: 0.8; - padding-bottom: 70px; -} - -.chatchannels__config { - position: fixed; - bottom: 0; - left: 0; - right: 0; - background: var(--body-bg); - border-top: 1px solid $light-medium-gray; - padding: var(--su-3); - font-weight: bold; - cursor: pointer; - - button { - opacity: 0.6; - border: none; - height: 18px; - width: 18px; - background-size: cover; - background-color: transparent; - } - - ul { - padding: 12px 10px; - } - - &:hover { - .chatchannels__configmenu { - display: block; - } - } -} - -.chatchannels__configmenu { - position: absolute; - bottom: 42px; - min-width: 150px; - left: 0; - right: 0; - background: $lightest-gray; - border-top: 1px solid $light-medium-gray; - font-size: 13px; - - li { - list-style: none; - a { - color: $dark-gray; - display: block; - padding: 5px 0px; - } - } -} - -.chatchannels__misc { - height: 70px; - border-top: 1px solid #c9c9c9; -} - -// Chatmessage -.chatmessage { - padding: var(--su-2) var(--su-6); - display: flex; - max-width: 100%; - @media not all and (pointer: coarse) { - &:hover { - @include themeable( - background, - theme-container-background-hover, - $light-gray - ); - - .chatmessagebody__username--link { - @include themeable( - background, - theme-container-background-hover, - transparent - ); - } - } - } -} - -.chat__channelinvitationsindicator a, -.chat__channelinvitationsindicator button { - background: linear-gradient(10deg, darken($green, 25%), darken($green, 15%)); - text-align: center; - padding: 30px 0px; - display: block; - border-radius: var(--radius); - margin: 3px 0px; - border: 0px; - width: 94%; - color: white; - font-size: 1.1em; - font-weight: var(--fw-bold); - -webkit-appearance: unset; -} - -.chatchanneltabbutton { - border: none; - width: 100%; - background: transparent; - box-sizing: border-box; - color: var(--body-color); - display: block; - position: relative; - padding: 0; - - .crayons-indicator { - vertical-align: -1px; - margin-right: var(--su-1); - } -} - -.chatchanneltab { - display: inline-block; - width: 100%; - background: inherit; - text-align: start; - border-radius: var(--radius); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - box-sizing: border-box; - border: 1px solid transparent; - font-size: 13px; - padding: var(--su-3); - display: flex; - align-items: center; -} - -.chatchanneltab--active { - border: 1px solid var(--base-30); - background: var(--base-10); - img { - border: 1px solid var(--base-30); - } -} - -.chatchanneltab__name { - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; -} - -.chatchanneltab--new { - border: 1px solid var(--accent-brand-darker); - color: var(--accent-brand-darker); -} - -.chatchanneltab--video { - background: lighten($green, 10%); - animation: small-pulser 0.5s linear infinite; -} - -.chatchanneltabindicator { - display: inline-block; - min-height: 0.3em; - min-width: 0.3em; - margin-right: 5px; - flex-shrink: 0; - - img { - height: calc(22px + 0.3vw); - width: calc(22px + 0.3vw); - vertical-align: calc(-6px - 0.14vw); - border-radius: 100px; - border: 1px solid var(--base-30); - background: white; - } - - .chatchanneltabgroupicon { - display: inline-block; - margin-left: calc(20px + 0.3vw); - } -} - -.chatchanneltabindicator .chatchanneltabindicatorgroupimage { - border-radius: var(--radius); -} - -.chatchanneltabindicator--new img { - border: 1px solid var(--accent-brand); -} - -.chatmessage__body { - flex-grow: 1; - max-width: calc(100% - 37px); -} - -.message__info { - display: flex; - align-items: center; - flex-wrap: wrap; -} - -.chatmessagebody__username { - font-size: var(--fs-base); - font-weight: var(--fw-medium); - margin-right: var(--su-2); -} - -.chatmessage__timestamp { - font-size: var(--fs-s); - color: var(--base-60); -} - -.chatmessage__bodytext { - overflow-wrap: break-word; - word-wrap: break-word; - word-break: break-word; - - pre { - background: #29292e; - } - - code { - background: #29292e; - padding: 0.1em 0.3em; - border-radius: 2px; - color: #eff0f9; - font-size: 0.95em; - vertical-align: 0.05em; - max-width: 100%; - line-height: 1.4em; - font-family: var(--ff-monospace); - } -} - -.chatmessage__profilepic { - margin-right: var(--su-2); -} - -.chatmessagebody__profileimage { - height: var(--su-7); - width: var(--su-7); - border-radius: 100%; -} - -.chatmessagebody__username--link { - color: inherit; - border-radius: 3px; - padding: 0px 2px; - display: inline-block; - - &:hover { - @include themeable( - background, - theme-container-background-hover, - transparent - ); - } -} - -.chatmessagebody__message { - p { - margin-top: 0; - margin-bottom: 9px; - - &:last-child { - margin-bottom: 0; - } - } - - blockquote { - border-left: 4px solid $black; - margin-left: 0px; - padding-left: 8px; - } - - a h1 { - color: var(--card-color); - border-color: var(--card-color); - } - - img { - max-width: 100%; - } -} - -.chatmessagebody__currentuser { - background: black; - color: white; - padding: 1px 5px; - border-radius: 2px; -} - -// Messagecomposer -.messagecomposer { - display: flex; - height: inherit; - align-items: stretch; - position: relative; - height: auto; - padding: var(--su-4); - - textarea { - margin-right: var(--su-4); - } -} - -.messagelist__sentinel { - height: 5px; -} - -.chatcodeeditor { - position: absolute; - top: 40px; - left: 0px; - right: 24px; - bottom: 0px; -} - -.chatcodeeditor__header { - position: absolute; - top: -27px; - left: 35px; - font-family: var(--ff-monospace); - @include themeable(color, theme-color, $dark-gray); -} - -.cursorelement { - border-left: 3px solid $red; - animation: blinker 1s linear infinite; - padding: 0px; - z-index: 0; -} - -@keyframes blinker { - 50% { - opacity: 0; - } -} - -@keyframes pulser { - 50% { - opacity: 0.8; - box-shadow: 2px 2px 0px $green; - padding: 18px; - } -} - -@keyframes small-pulser { - 50% { - opacity: 0.6; - box-shadow: 2px 2px 0px $green; - } -} - -.chatchanneljumpback { - position: relative; -} - -.chatchanneljumpback__messages { - position: absolute; - bottom: 12px; - right: 8px; - background: var(--body-bg); - color: var(--body-color); - border: 2px solid $black; - padding: 7px 15px; - border-radius: 20px; - cursor: pointer; - font-size: 13px; - text-transform: uppercase; - font-weight: bold; - z-index: 7; -} - -.chatchanneljumpback__hide { - display: none; -} - -.message__info__actions { - display: grid; - grid-template-columns: 19fr 1fr; -} - -.message__actions { - position: relative; - justify-content: end; - -webkit-justify-content: flex-end; - - .ellipsis__menubutton img { - height: 17px; - vertical-align: middle; - color: var(--theme-color, #0a0a0a); - } - - &:hover { - .ellipsis__menubutton { - opacity: 1; - } - } - - &:focus-within { - .ellipsis__menubutton { - opacity: 1; - } - } - - img { - height: 100%; - opacity: 0.6; - } - - .messagebody__dropdownmenu { - position: absolute; - background-color: var(--theme-container-background, #fff); - border-style: solid; - border-color: var(--theme-color, #0a0a0a); - border-radius: 5px; - border-width: 1px; - top: 100%; - right: 0; - - button { - width: 100%; - text-align: left; - } - } -} - -.message__actions span { - margin-left: 7px; - font-size: var(--fs-s); - font-weight: bold; - cursor: pointer; -} - -.chatmessage:hover .message__actions { - display: -webkit-flex; - display: flex; -} - -.chatchannels__richlink { - border: 1px solid darken($light-medium-gray, 15%); - border-radius: 3px; - box-shadow: 2px 2px 0px darken($light-medium-gray, 15%); - color: $black; - display: block; - max-width: 670px; - padding: 0px; - margin-bottom: 6px; - background: var(--card-bg); - font-size: 0.9em; - &.chatchannels__richlink--base { - h1 { - margin: 18px auto; - } - } - .chatchannels__richlinkmainimage { - position: relative; - width: 100%; - margin: auto; - background: transparent no-repeat center center; - background-size: cover; - z-index: 2; - padding-top: 42%; - } - h1 { - margin-top: 8px; - padding: 0px calc(10px + 0.2vw); - line-height: 1.1em; - font-size: 1.8em; - img { - height: 1.2em; - width: 1.2em; - margin-right: 5px; - vertical-align: -0.25em; - &.chatchannels__richlinkprofilepic { - border-radius: 100px; - border: 1px solid var(--card-color-tertiary); - } - } - } - h4 { - margin-top: 12px; - margin-bottom: 15px; - color: var(--card-color-tertiary); - font-weight: 500; - padding: 0px calc(10px + 0.2vw); - img { - height: 22px; - width: 22px; - border-radius: 100px; - margin-right: 3px; - border: 1px solid var(--card-color-tertiary); - vertical-align: -6px; - } - } -} - -.delete-actions__container { - margin-top: var(--su-4); -} - -.message__delete__button { - margin-right: var(--su-2); -} - -.message__delete__modal__hide { - display: none; -} - -.composer-container__edit { - height: auto; - padding: var(--su-4); - display: flex; - flex-direction: column; -} - -.composer-textarea__edit { - height: 80px; - max-height: 8rem; - margin-bottom: var(--su-4); -} - -.composer-textarea { - height: auto; - margin-bottom: var(--su-4); - min-height: 2.5rem; - resize: vertical; - max-height: 8rem; - overflow: hidden; -} - -.composer-btn-group { - button { - margin-right: var(--su-2); - - &:last-child { - margin-right: 0; - } - } -} - -.mention__list { - position: absolute; - background: var(--card-bg); - display: none; - z-index: 1; - border-top: 1px solid #dbdbdb; - bottom: 90px; - width: 100%; - max-height: 280px; - overflow-x: scroll; -} -.mention__list .mention__user { - padding: 5px 10px; - border-bottom: 1px solid #dbdbdb; - cursor: pointer; -} -.compose__outer__container { - position: relative; - box-shadow: 0 0 0 1px var(--card-border); -} -.mention__user__image { - height: 25px; - width: 25px; - margin-right: 6px; - border-radius: 20px; - align-self: center; -} -.mention__visible { - display: block; -} -.mention__user { - display: grid; - grid-template-columns: 30px 1fr; -} -.mention__user p { - margin: 0px; - font-size: 9px; - color: gray; - width: max-content; -} -.mentioned-all { - color: rgb(213, 138, 0); -} - -.active__message__list { - background: var(--theme-container-accent-background, #f5f6f7); -} -.chatmessage__action { - &:hover { - background: none; - } - - .chatmessage__bodytext { - margin: 0; - font-size: 12px; - font-style: italic; - color: var(--card-color-tertiary); - a { - text-decoration: none; - color: var(--card-color-tertiary); - &:hover { - text-decoration: underline; - } - } - } -} -.joining-message { - display: grid; - margin-top: 30px; - justify-content: center; - h3, - h2 { - width: 90%; - margin-top: 10px; - text-align: center; - justify-self: center; - } -} -.user-picture, -.send-request { - display: flex; - justify-content: center; - margin-top: 10vh; -} -.user-picture { - .chatmessage__profilepic { - .chatmessagebody__profileimage { - width: 50px; - height: 50px; - border: 1px solid var(--base-30); - } - } -} - -.loading-user { - height: '210px'; - width: '210px'; - margin: ' 15px auto'; - display: 'block'; - border-radius: '500px'; - background-color: '#f5f6f7'; -} -.request-card { - display: grid; - grid-template-columns: 200px 1fr; -} - -.request-actions { - justify-content: space-between; - display: flex; -} - -.request-message { - width: 100%; - - @media screen and (min-width: $breakpoint-s) { - width: 60%; - } -} - -.channel_details { - margin-top: 30px; -} -.channel-request-card { - display: flex; - justify-content: space-between; - flex-wrap: wrap; -} -.request_manager_header { - margin-top: 30px; -} - -.requests-badge { - position: absolute; - height: 17px; - width: 17px; - padding: 2px; - margin-left: -10px; - margin-top: -2px; -} - -.chat_channel-member-list { - height: 300px; - overflow-y: scroll; -} - -.member-list-item { - justify-content: space-between; - - .admin-emoji { - width: 6%; - } - - .admin-emoji-button { - width: 10%; - } -} - -.connect-draw { - margin-top: 30px; - .draw-title { - display: flex; - justify-content: flex-start; - } - .connect-draw__colors { - z-index: 2; - margin: 5px 20px; - text-align: center; - pointer-events: all; - } - - .connect-draw__color { - height: 30px; - width: 30px; - margin-right: 10px; - border-radius: 50%; - border: none; - } - .color:hover { - opacity: 0.7; - cursor: pointer; - } - - .color:focus { - outline: 0; - } - .connect-draw__draw-area { - display: grid; - - .connect-draw__draw { - border: 1px solid black; - background-color: white; - justify-self: center; - } - .connect-draw__actions { - margin: 20px 0px; - display: flex; - button { - margin-left: 10px; - } - } - } -} - -.report__abuse-options { - .crayons-field + .crayons-field { - margin-top: var(--su-2); - } -} - -.report__abuse__button { - width: 135px; -} -.reported__message { - border: 1px solid; - max-height: 300px; - overflow: scroll; -} - -.membership-section { - position: relative; - - .membership-actions { - position: relative; - - .membership-management__dropdown-memu { - display: none; - position: absolute; - background-color: var(--theme-container-background, #fff); - border-style: solid; - border-color: var(--theme-color, #0a0a0a); - border-radius: 5px; - border-width: 1px; - z-index: 100; - width: 200px; - right: 78px; - top: 20px; - - button { - width: 100%; - text-align: left; - } - - &:hover { - display: block; - } - } - - .membership-management__dropdown-button { - height: 17px; - cursor: pointer; - color: var(--theme-color, #0a0a0a); - - &:hover + .membership-management__dropdown-memu { - display: block; - } - - img { - height: 100%; - opacity: 0.6; - } - } - } -} diff --git a/app/assets/stylesheets/connect/_channel-details.scss b/app/assets/stylesheets/connect/_channel-details.scss deleted file mode 100644 index 852a3f06d..000000000 --- a/app/assets/stylesheets/connect/_channel-details.scss +++ /dev/null @@ -1,134 +0,0 @@ -@import '../variables'; - -.channeldetails { - .channeldetails__name { - font-family: var(--ff-sans-serif); - font-size: 48px; - } - - .channeldetails__description { - font-family: var(--ff-sans-serif); - color: $dark-gray; - } - - // channel users - .channeldetails__user { - a { - padding: 0 4px !important; - border-radius: 3px; - background: white; - } - padding: 2px 0; - margin-bottom: 10px; - .channeldetails__userprofileimage { - height: 25px; - width: 25px; - margin-right: 6px; - border-radius: 20px; - vertical-align: -6px; - } - a { - font-family: var(--ff-sans-serif); - } - } - - .channeldetails__inviteusers { - h2 { - font-family: var(--ff-sans-serif); - } - - // find users - input { - border-radius: 3px; - border: 1px solid #dbdbdb; - box-sizing: border-box; - padding: 8px; - margin-left: 2px; - font-size: 18px; - -webkit-appearance: none; - } - - .channeldetails__searchresults { - padding: 5px 0; - - .channeldetails__searchedusers { - padding: 1px 0; - - // profile pic - img { - height: 22px; - width: 22px; - margin-right: 6px; - border-radius: 20px; - vertical-align: -6px; - } - - a { - font-size: 14px; - font-family: var(--ff-sans-serif); - } - - // invite button - button { - width: 45px; - height: 24px; - background-color: $purple; - border-radius: 3px; - color: $white; - } - - // in channel message - span { - color: $dark-gray; - font-size: 14px; - font-family: var(--ff-sans-serif); - } - } - } - - .channeldetails__pendingusers { - a { - font-size: 18px; - font-family: var(--ff-sans-serif); - } - } - } - - .channeldetails__leavechannel { - // Danger Zone - h2 { - color: $red; - font-family: $helvetica-condensed; - font-size: 2.5em; - } - // leave channel - button { - width: 180px; - padding: 3px 0px; - border-radius: 3px; - background-color: $red; - color: $white; - font-size: 1.2em; - font-weight: bold; - cursor: pointer; - } - } - - .channeldetails__leftchannel { - h2 { - font-family: var(--ff-sans-serif); - font-size: 32px; - } - h3 { - font-family: var(--ff-sans-serif); - font-size: 18px; - } - h4 { - font-family: var(--ff-sans-serif); - font-size: 18px; - } - p { - font-family: var(--ff-sans-serif); - } - } -} diff --git a/app/assets/stylesheets/minimal.scss b/app/assets/stylesheets/minimal.scss index 56fe1ac67..6388f0558 100644 --- a/app/assets/stylesheets/minimal.scss +++ b/app/assets/stylesheets/minimal.scss @@ -19,8 +19,6 @@ @import 'ltags/LiquidTags'; -@import 'chat'; - @import 'email_subscriptions'; @import 'runtime'; diff --git a/app/assets/stylesheets/scaffolds.scss b/app/assets/stylesheets/scaffolds.scss index c311e80f6..43adee8a5 100644 --- a/app/assets/stylesheets/scaffolds.scss +++ b/app/assets/stylesheets/scaffolds.scss @@ -46,7 +46,6 @@ body.dark-theme { .image-upload-button button, .icon-image, .dev-badge, - .chatchannels__config img, .message__actions img { -webkit-filter: invert(95%); filter: invert(95%); diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index 102237786..e60d26669 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -8,7 +8,6 @@ module Admin articles: "https://admin.forem.com/docs/forem-basics/posts", badges: "https://admin.forem.com/docs/forem-basics/badges", badge_achievements: "https://admin.forem.com/docs/forem-basics/badges", - chat_channels: "https://admin.forem.com/docs/advanced-customization/chat-channels", display_ads: "https://admin.forem.com/docs/advanced-customization/display-ads", feedback_messages: "https://admin.forem.com/docs/advanced-customization/reports", html_variants: "https://admin.forem.com/docs/advanced-customization/html-variants", diff --git a/app/controllers/admin/chat_channels_controller.rb b/app/controllers/admin/chat_channels_controller.rb deleted file mode 100644 index 4a585f539..000000000 --- a/app/controllers/admin/chat_channels_controller.rb +++ /dev/null @@ -1,59 +0,0 @@ -module Admin - class ChatChannelsController < Admin::ApplicationController - layout "admin" - - CHAT_ALLOWED_PARAMS = %i[usernames_string channel_name username_string].freeze - - def index - @q = ChatChannel.where(channel_type: "invite_only").includes(:users).ransack(params[:q]) - @group_chat_channels = @q.result.page(params[:page]).per(50) - end - - def create - ChatChannels::CreateWithUsers.call( - users: users_by_param, - channel_type: "invite_only", - contrived_name: chat_channel_params[:channel_name], - membership_role: "mod", - ) - redirect_back(fallback_location: admin_chat_channels_path) - end - - def update - @chat_channel = ChatChannel.find(params[:id]) - @chat_channel.invite_users(users: users_by_param) - redirect_back(fallback_location: admin_chat_channels_path) - end - - def remove_user - @chat_channel = ChatChannel.find(params[:id]) - @chat_channel.remove_user(user_by_param) - redirect_back(fallback_location: admin_chat_channels_path) - end - - def destroy - @chat_channel = ChatChannel.find(params[:id]) - if @chat_channel.users.count.zero? - @chat_channel.destroy - flash[:success] = "Channel was successfully deleted." - else - flash[:alert] = "Channel NOT deleted, because it still has users." - end - redirect_back(fallback_location: admin_chat_channels_path) - end - - private - - def users_by_param - User.where(username: chat_channel_params[:usernames_string].downcase.delete(" ").split(",")) - end - - def user_by_param - User.find_by(username: chat_channel_params[:username_string]) - end - - def chat_channel_params - params.require(:chat_channel).permit(CHAT_ALLOWED_PARAMS) - end - end -end diff --git a/app/controllers/chat_channel_memberships_controller.rb b/app/controllers/chat_channel_memberships_controller.rb deleted file mode 100644 index b55e393b8..000000000 --- a/app/controllers/chat_channel_memberships_controller.rb +++ /dev/null @@ -1,285 +0,0 @@ -class ChatChannelMembershipsController < ApplicationController - before_action :authenticate_user! - after_action :verify_authorized, except: %w[join_channel request_details] - - include MessagesHelper - include ChatChannelMembershipsHelper - - rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized - rescue_from ActiveRecord::RecordNotFound, with: :record_not_found - - def index - skip_authorization - memberships = current_user.chat_channel_memberships.includes(:chat_channel) - @pending_invites = memberships.filter_by_status("pending") - end - - def find_by_chat_channel_id - @membership = ChatChannelMembership.where(chat_channel_id: params[:chat_channel_id], - user_id: current_user.id).first! - authorize @membership - render json: @membership.to_json( - only: %i[id status viewable_by chat_channel_id last_opened_at], - methods: %i[channel_text channel_last_message_at channel_status channel_username - channel_type channel_text channel_name channel_image channel_modified_slug channel_messages_count], - ) - end - - def chat_channel_info - @membership = ChatChannelMembership.find(params[:id]) - authorize @membership - @channel = @membership.chat_channel - invite_cache_key = "chat-channel-invite-#{@channel.id}" - invitation_slug = Rails.cache.fetch(invite_cache_key, expires_in: 80.hours) do - "invitation-link-#{SecureRandom.hex(3)}" - end - @invitation_link = "/join_channel_invitation/#{@channel.slug}?invitation_slug=#{invitation_slug}" - end - - def create_membership_request - chat_channel = ChatChannel.find_by(id: channel_membership_params[:chat_channel_id]) - authorize chat_channel, :update? - message = ChatChannels::SendInvitation.call( - channel_membership_params[:invitation_usernames], - current_user, - chat_channel, - ) - - render json: { success: true, message: message, data: {} }, status: :ok - end - - def join_channel - membership_params = params[:chat_channel_membership] - chat_channel = ChatChannel.find(membership_params[:chat_channel_id]) - existing_membership = ChatChannelMembership.find_by(user_id: current_user.id, chat_channel_id: chat_channel.id) - if existing_membership.present? && %w[active joining_request].exclude?(existing_membership.status) - status = existing_membership.update(status: "joining_request", role: "member") - else - membership = ChatChannelMembership.new(user_id: current_user.id, chat_channel_id: chat_channel.id, - role: "member", status: "joining_request") - status = membership.save - end - if status - render json: { status: "success", message: "Request Sent" }, status: :ok - else - render json: { status: 400, message: "Unable to join channel" }, status: :bad_request - end - end - - def remove_membership - @chat_channel = ChatChannel.find(params[:chat_channel_id]) - authorize @chat_channel, :update? - @chat_channel_membership = @chat_channel.chat_channel_memberships.find(params[:membership_id]) - if params[:status] == "pending" - @chat_channel_membership.destroy - message = "Invitation removed." - else - membership = @chat_channel_membership - message = "@#{current_user.username} removed @#{membership.user.username} from #{membership.channel_name}" - send_chat_action_message( - message, current_user, @chat_channel_membership.chat_channel_id, "removed_from_channel" - ) - @chat_channel_membership.update(status: "removed_from_channel") - message = "Removed #{@chat_channel_membership.user.name}" - end - - render json: { status: "success", message: message, success: true }, status: :ok - end - - def add_membership - @chat_channel = ChatChannel.find(params[:chat_channel_id]) - authorize @chat_channel, :update? - @chat_channel_membership = @chat_channel.chat_channel_memberships.find(params[:membership_id]) - - return unless permitted_params[:user_action].present? && @chat_channel_membership.status == "joining_request" - - respond_to_invitation(@chat_channel_membership.status) - end - - def update - @chat_channel_membership = ChatChannelMembership.find(params[:id]) - authorize @chat_channel_membership - respond_to_invitation(@chat_channel_membership.status) - end - - def update_membership - @chat_channel_membership = ChatChannelMembership.find(params[:id]) - authorize @chat_channel_membership - @chat_channel_membership.update(permitted_params) - if @chat_channel_membership.errors.any? - render json: { success: false, errors: @chat_channel_membership.errors.full_messages, - message: "Failed to update settings." }, status: :bad_request - else - render json: { success: true, message: "Personal settings updated." }, status: :ok - end - end - - def leave_membership - chat_channel_membership = ChatChannelMembership.find_by(id: params[:id]) - authorize chat_channel_membership - channel_name = chat_channel_membership.chat_channel.channel_name - send_chat_action_message("@#{current_user.username} left #{chat_channel_membership.channel_name}", current_user, - chat_channel_membership.chat_channel_id, "left_channel") - chat_channel_membership.update(status: "left_channel") - message = "You have left the channel #{channel_name}. It may take a moment to be removed from your list." - if chat_channel_membership.errors.any? - render json: { success: false, message: "Failed to update membership", - errors: chat_channel_membership.errors.full_messages }, status: :bad_request - else - render json: { success: true, message: message }, status: :ok - end - end - - def request_details - user_chat_channels = ChatChannel.includes(:chat_channel_memberships).where( - chat_channel_memberships: { user_id: current_user.id, role: "mod", status: "active" }, - ) - @memberships = user_chat_channels.flat_map(&:requested_memberships) - @user_invitations = ChatChannelMembership.where( - user_id: current_user.id, - status: %w[pending], - ).order("created_at DESC") - end - - def update_membership_role - @chat_channel = ChatChannel.find_by(id: params[:id]) - authorize @chat_channel, :update? - membership = ChatChannelMembership.find_by( - id: channel_membership_params[:membership_id], - chat_channel_id: @chat_channel.id, - ) - - membership.update(role: channel_membership_params[:role]) - if membership.errors.any? - render json: { - success: false, - message: "Failed to update membership", - errors: chat_channel_membership.errors.full_messages - }, status: :bad_request - else - role = membership.reload.role - send_chat_action_message( - "@#{membership.user.username} role is updated as #{role}", - current_user, @chat_channel.id, - "updated" - ) - - render json: { success: true, message: "User Membership is updated" }, status: :ok - end - end - - def join_channel_invitation - @chat_channel = ChatChannel.find_by(slug: params[:channel_slug]) - authorize @chat_channel - invite_cache_key = "chat-channel-invite-#{@chat_channel.id}" - invitation_slug = Rails.cache.read(invite_cache_key) - existing_membership = ChatChannelMembership.find_by(user_id: current_user.id, chat_channel_id: @chat_channel.id) - redirect_to URI.parse("/connect/#{@chat_channel.slug}").path if existing_membership&.status == "active" - @link_expired = true if invitation_slug != params[:invitation_slug] - end - - def joining_invitation_response - chat_channel = ChatChannel.find_by(id: params[:chat_channel_id]) - authorize chat_channel - if params[:user_action] == "accept" - membership = ChatChannelMembership.find_by(user_id: current_user.id, chat_channel_id: chat_channel.id) - if !membership - membership = ChatChannelMembership.create(user_id: current_user.id, chat_channel_id: chat_channel.id) - unless membership&.errors&.any? - send_chat_action_message("@#{membership.user.username} join the channel", current_user, chat_channel.id, - "joined") - end - elsif membership.status != "active" - # This check checks if the user already has the chatChannelMembership with the status pending, joining_request - # Then update it to as active. - membership.update(role: "member", status: "active") - send_chat_action_message("@#{membership.user.username} join the channel", current_user, - membership.chat_channel_id, "joined") - end - - if membership&.errors&.any? - flash[:settings_notice] = membership.errors.full_messages - redirect_to root_path - end - - redirect_to connect_path(chat_channel.slug) - else - redirect_to root_path - end - end - - private - - def permitted_params - params.require(:chat_channel_membership).permit(:user_action, :show_global_badge_notification) - end - - def channel_membership_params - params.require(:chat_channel_membership).permit(:chat_channel_id, :invitation_usernames, :membership_id, :role) - end - - def respond_to_invitation(previous_status) - if permitted_params[:user_action] == "accept" - @chat_channel_membership.update(status: "active") - channel_name = @chat_channel_membership.chat_channel.channel_name - - if previous_status == "pending" - send_chat_action_message( - "@#{current_user.username} joined #{@chat_channel_membership.channel_name}", - current_user, - @chat_channel_membership.chat_channel_id, - "joined", - ) - - notice = "Invitation to #{channel_name} accepted. It may take a moment to show up in your list." - else - send_chat_action_message( - "@#{current_user.username} added @#{@chat_channel_membership.user.username}", - current_user, - @chat_channel_membership.chat_channel_id, - "joined", - ) - - NotifyMailer - .with(membership: @chat_channel_membership, inviter: @chat_channel_membership.user) - .channel_invite_email - .deliver_later - - notice = "Accepted request of #{@chat_channel_membership.user.username} to join #{channel_name}." - end - else - @chat_channel_membership.update(status: "rejected") - notice = "Invitation rejected." - end - - membership_user = format_membership(@chat_channel_membership) - flash[:settings_notice] = notice - - respond_to do |format| - format.html { redirect_to chat_channel_memberships_path } - format.json do - render json: { - status: "success", - message: flash[:settings_notice], - success: true, - membership: membership_user - }, status: :ok - end - end - end - - def send_chat_action_message(message, user, channel_id, action) - temp_message_id = SecureRandom.hex(20) - message = Message.create("message_markdown" => message, "user_id" => user.id, "chat_channel_id" => channel_id, - "chat_action" => action) - pusher_message_created(false, message, temp_message_id) unless message.left_channel? - end - - def user_not_authorized - render json: { success: false, message: "User not authorized" }, status: :unauthorized - end - - def record_not_found - render json: { success: false, message: "not found" }, status: :not_found - end -end diff --git a/app/controllers/chat_channels_controller.rb b/app/controllers/chat_channels_controller.rb deleted file mode 100644 index 35842d49b..000000000 --- a/app/controllers/chat_channels_controller.rb +++ /dev/null @@ -1,268 +0,0 @@ -class ChatChannelsController < ApplicationController - before_action :authenticate_user!, only: %i[moderate] - before_action :set_channel, only: %i[show update update_channel open moderate] - after_action :verify_authorized - - include MessagesHelper - include ChatChannelsHelper - - CHANNEL_ATTRIBUTES_FOR_SERIALIZATION = %i[id description channel_name].freeze - private_constant :CHANNEL_ATTRIBUTES_FOR_SERIALIZATION - - def index - case params[:state] - when "unopened" - authorize ChatChannel - @chat_channels_memberships = unopened_json_response - render "index", formats: :json - when "unopened_ids" - authorize ChatChannel - @unopened_ids = unopened_ids_response - render json: { unopened_ids: @unopened_ids } - when "pending" - authorize ChatChannel - @chat_channels_memberships = pending_json_response - render "index", formats: :json - when "joining_request" - authorize ChatChannel - @chat_channels_memberships = joining_request_json_response - render "index", formats: :json - else - skip_authorization - render_channels_html - end - end - - def show - @chat_messages = @chat_channel.messages - .includes(:user) - .order(created_at: :desc) - .offset(params[:message_offset]) - .limit(50) - end - - def create - authorize ChatChannel - @chat_channel = current_user.chat_channels.create( - channel_type: "invite_only", - channel_name: chat_channel_params[:channel_name], - slug: chat_channel_params[:slug], - ) - render_chat_channel - end - - def update - chat_channel = ChatChannels::UpdateChannel.call(@chat_channel, chat_channel_params) - if chat_channel.errors.any? - flash[:error] = chat_channel.errors.full_messages.to_sentence - else - if chat_channel_params[:discoverable].to_i.zero? - ChatChannelMembership.create(user_id: Settings::General.mascot_user_id, chat_channel_id: chat_channel.id, - role: "member", status: "active") - else - ChatChannelMembership.find_by(user_id: Settings::General.mascot_user_id)&.destroy - end - flash[:settings_notice] = "Channel settings updated." - end - current_user_membership = @chat_channel.mod_memberships.find_by!(user: current_user) - - redirect_to edit_chat_channel_membership_path(current_user_membership) - end - - def update_channel - @chat_channel.update(chat_channel_params) - if @chat_channel.errors.any? - render json: { success: false, errors: @chat_channel.errors.full_messages, - message: "Channel settings updation failed. Try again later." }, success: :bad_request - else - if chat_channel_params[:discoverable] - ChatChannelMembership.create(user_id: Settings::General.mascot_user_id, chat_channel_id: @chat_channel.id, - role: "member", status: "active") - else - ChatChannelMembership.find_by(user_id: Settings::General.mascot_user_id)&.destroy - end - render json: { success: true, message: "Channel settings updated.", data: {} }, success: :ok - end - end - - def open - membership = @chat_channel.chat_channel_memberships.where(user_id: current_user.id).first - membership.update(last_opened_at: 1.second.from_now, has_unopened_messages: false) - send_open_notification - render json: { status: "success", channel: params[:id] }, status: :ok - end - - def moderate - chat_channel = ChatChannel.find_by(id: params[:id]) - authorize chat_channel - command, username = chat_channel_params[:command].split - case command - when "/ban" - user = User.find_by(username: username) - membership = user&.chat_channel_memberships&.find_by(chat_channel: chat_channel) - if user && membership - user.add_role(:suspended) - user.messages.where(chat_channel: chat_channel).delete_all - membership.update(status: "removed_from_channel") - Pusher.trigger(chat_channel.pusher_channels, "user-banned", { userId: user.id }.to_json) - render json: { status: "moderation-success", message: "#{username} was suspended.", userId: user.id, - chatChannelId: chat_channel.id }, status: :ok - else - render json: { - status: "error", - message: "Suspend failed. user with username '#{username}' not found in this channel." - }, status: :bad_request - end - when "/unban" - user = User.find_by(username: username) - if user - user.remove_role(:suspended) - render json: { status: "moderation-success", message: "#{username} was unsuspended." }, status: :ok - else - render json: { - status: "error", - message: "Unsuspend failed. User with username '#{username}' not found in this channel." - }, status: :bad_request - end - when "/clearchannel" - @chat_channel.clear_channel - render json: { status: "success", message: "cleared!" }, status: :ok - else - render json: { status: "error", message: "invalid command" }, status: :bad_request - end - end - - def create_chat - chat_recipient = User.find(params[:user_id]) - valid_listing = Listing.where(user_id: params[:user_id], contact_via_connect: true).limit(1) - authorize ChatChannel - - if chat_recipient.setting.inbox_type == "open" || valid_listing.length == 1 - chat = ChatChannels::CreateWithUsers.call(users: [current_user, chat_recipient], channel_type: "direct") - message_markdown = params[:message] - message = Message.new( - chat_channel: chat, - message_markdown: message_markdown, - user: current_user, - ) - chat.messages.append(message) - render json: { status: "success", message: "chat channel created!" }, status: :ok - else - render json: { status: "error", message: "not allowed!" }, status: :bad_request - end - rescue StandardError => e - render json: { status: "error", message: e.message }, status: :bad_request - end - - def block_chat - chat_channel = ChatChannel.find(params[:chat_id]) - authorize chat_channel - chat_channel.status = "blocked" - chat_channel.save - render json: { status: "success", message: "chat channel blocked" }, status: :ok - end - - # NOTE: this is part of an effort of moving some things from the external to - # the internal API. No behavior was changes as part of this refactoring, so - # this action is a bit unusual. - def channel_info - skip_authorization - - @chat_channel = - ChatChannel - .select(CHANNEL_ATTRIBUTES_FOR_SERIALIZATION) - .find_by(id: params[:id]) - - return if @chat_channel&.has_member?(current_user) - - render json: { error: "not found", status: 404 }, status: :not_found - end - - def create_channel - chat_channel_params = params[:chat_channel] - chat_channel_name = chat_channel_params[:channel_name].split.join("-") - chat_channel = ChatChannel.new( - channel_type: "invite_only", - channel_name: chat_channel_params[:channel_name], - slug: "#{chat_channel_name}-#{SecureRandom.hex(5)}", - ) - authorize chat_channel - chat_channel.save - membership = chat_channel.chat_channel_memberships.new(user_id: current_user.id, role: "mod") - if membership.save - message = ChatChannels::SendInvitation.call( - chat_channel_params[:invitation_usernames], - current_user, - chat_channel, - ) - - send_chat_action_message( - "channel is created by #{current_user.username}", - current_user, membership.chat_channel_id, - "chat channel is created" - ) - render json: { - success: true, - message: "Channel is created #{message ? "& #{message}" : nil}" - }, status: :ok - else - render json: { - success: false, - message: membership.errors_as_sentence - }, status: 445 - end - end - - private - - def set_channel - @chat_channel = ChatChannel.find_by(id: params[:id]) || not_found - authorize @chat_channel - end - - def chat_channel_params - params.require(:chat_channel).permit(policy(ChatChannel).permitted_attributes) - end - - def render_channels_html - return unless current_user && params[:slug] - - slug = if params[:slug]&.start_with?("@") - [current_user.username, params[:slug].delete("@")].sort.join("/") - else - params[:slug] - end - chat_channel = ChatChannel.find_by(slug: slug) - return unless chat_channel - - membership = chat_channel.chat_channel_memberships.find_by(user_id: current_user.id) - @active_channel = membership&.status == "active" ? chat_channel : nil - end - - def render_chat_channel - if @chat_channel.valid? - render json: { status: "success", - chat_channel: @chat_channel.to_json(only: %i[channel_name slug]) }, - status: :ok - else - render json: { errors: @chat_channel.errors.full_messages } - end - end - - def send_open_notification - adjusted_slug = if @chat_channel.group? - @chat_channel.adjusted_slug - else - @chat_channel.adjusted_slug(current_user) - end - payload = { channel_type: @chat_channel.channel_type, adjusted_slug: adjusted_slug }.to_json - Pusher.trigger(ChatChannel.pm_notifications_channel(session_current_user_id), "message-opened", payload) - end - - def send_chat_action_message(message, user, channel_id, action) - temp_message_id = SecureRandom.hex(20) - message = Message.create(message_markdown: message, user_id: user.id, chat_channel_id: channel_id, - chat_action: action) - pusher_message_created(false, message, temp_message_id) - end -end diff --git a/app/controllers/concerns/listings_toolkit.rb b/app/controllers/concerns/listings_toolkit.rb index 6a93538e1..0ef3b154d 100644 --- a/app/controllers/concerns/listings_toolkit.rb +++ b/app/controllers/concerns/listings_toolkit.rb @@ -80,7 +80,7 @@ module ListingsToolkit ALLOWED_PARAMS = %i[ title body_markdown listing_category_id tag_list - expires_at contact_via_connect location organization_id action + expires_at location organization_id action ].freeze # Filter for a set of known safe params diff --git a/app/controllers/email_subscriptions_controller.rb b/app/controllers/email_subscriptions_controller.rb index c8dc37d3b..9748b589a 100644 --- a/app/controllers/email_subscriptions_controller.rb +++ b/app/controllers/email_subscriptions_controller.rb @@ -19,7 +19,6 @@ class EmailSubscriptionsController < ApplicationController email_comment_notifications: "comment notifications", email_follower_notifications: "follower notifications", email_mention_notifications: "mention notifications", - email_connect_messages: "#{Settings::Community.community_name} connect messages", email_unread_notifications: "unread notifications", email_badge_notifications: "badge notifications" }.freeze diff --git a/app/controllers/listings_controller.rb b/app/controllers/listings_controller.rb index 73f99e363..3f480247d 100644 --- a/app/controllers/listings_controller.rb +++ b/app/controllers/listings_controller.rb @@ -3,7 +3,7 @@ class ListingsController < ApplicationController INDEX_JSON_OPTIONS = { only: %i[ - title processed_html tag_list category id user_id slug contact_via_connect location bumped_at + title processed_html tag_list category id user_id slug location bumped_at originally_published_at ], methods: %i[category], diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb deleted file mode 100644 index 9f22cd42d..000000000 --- a/app/controllers/messages_controller.rb +++ /dev/null @@ -1,117 +0,0 @@ -class MessagesController < ApplicationController - before_action :set_message, only: %i[destroy update] - before_action :authenticate_user!, only: %i[create] - include MessagesHelper - - def create - @message = Message.new(message_params) - @message.user_id = session_current_user_id - @temp_message_id = (0...20).map { ("a".."z").to_a[rand(8)] }.join - authorize @message - - # sending temp message only to sender - pusher_message_created(true, @message, @temp_message_id) - if @message.save - pusher_message_created(false, @message, @temp_message_id) - notify_mentioned_users(@mentioned_users_id) - render json: { status: "success", message: { temp_id: @temp_message_id, id: @message.id } }, status: :created - else - render json: { - status: "error", - message: { - chat_channel_id: @message.chat_channel_id, - message: @message.errors.full_messages, - type: "error" - } - }, status: :unauthorized - end - end - - def destroy - authorize @message - - if @message.valid? - begin - Pusher.trigger(@message.chat_channel.pusher_channels, "message-deleted", @message.to_json) - rescue Pusher::Error => e - Honeybadger.notify(e) - end - end - - if @message.destroy - render json: { status: "success", message: "Message was deleted" } - else - render json: { - status: "error", - message: { - chat_channel_id: @message.chat_channel_id, - message: @message.errors.full_messages, - type: "error" - } - }, status: :unauthorized - end - end - - def update - authorize @message - - if @message.update(permitted_attributes(@message).merge(edited_at: Time.zone.now)) - if @message.valid? - begin - message_json = create_pusher_payload(@message, "") - Pusher.trigger(@message.chat_channel.pusher_channels, "message-edited", message_json) - rescue Pusher::Error => e - Honeybadger.notify(e) - end - end - render json: { status: "success", message: "Message was edited" } - else - render json: { - status: "error", - message: { - chat_channel_id: @message.chat_channel_id, - message: @message.errors.full_messages, - type: "error" - } - }, status: :unauthorized - end - end - - private - - def message_params - @mentioned_users_id = params[:message][:mentioned_users_id] - params.require(:message).permit(:message_markdown, :user_id, :chat_channel_id) - end - - def set_message - @message = Message.find(params[:id]) - end - - def user_not_authorized - respond_to do |format| - format.json do - render json: { - status: "error", - message: { - chat_channel_id: message_params[:chat_channel_id], - message: "You can not do that because you are suspended", - type: "error" - } - }, status: :unauthorized - end - end - end - - def notify_mentioned_users(user_ids) - # If @all is mentioned then we get an array of all of the channel's users IDs from the channel - # https://github.com/forem/forem/blob/9bdef4d4ae0b41612001a62c2409121b654bf71f/app/javascript/chat/chat.jsx#L1562 - return unless user_ids - - message_json = create_pusher_payload(@message, @temp_message_id) - - user_ids.each do |id| - Pusher.trigger(ChatChannel.pm_notifications_channel(id), "mentioned", message_json) - end - end -end diff --git a/app/controllers/moderations_controller.rb b/app/controllers/moderations_controller.rb index 16933070a..143b6ff5c 100644 --- a/app/controllers/moderations_controller.rb +++ b/app/controllers/moderations_controller.rb @@ -22,7 +22,6 @@ class ModerationsController < ApplicationController @articles = articles.includes(:user).to_json(JSON_OPTIONS) @tag = Tag.find_by(name: params[:tag]) || not_found if params[:tag].present? @current_user_tags = current_user.moderator_for_tags - @community_mod_channel = current_user.chat_channels.find_by("channel_name LIKE ?", "Community Mods: Team%") end def article diff --git a/app/controllers/pusher_controller.rb b/app/controllers/pusher_controller.rb deleted file mode 100644 index 38092aceb..000000000 --- a/app/controllers/pusher_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -class PusherController < ApplicationController - def auth - if valid_channel - response = Pusher.authenticate(params[:channel_name], params[:socket_id], - user_id: current_user.id) # => required - render json: response - else - render json: { text: "Forbidden", status: "403" } - end - end - - def valid_channel - valid_private_dm_channel || valid_private_group_channel - end - - def valid_private_dm_channel - current_user && params[:channel_name] == ChatChannel.pm_notifications_channel(current_user.id) - end - - def valid_private_group_channel - return false unless params[:channel_name].include?("private-channel-") - - id = params[:channel_name].split("-").last - channel = ChatChannel.find(id) - channel.has_member?(current_user) - end -end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index d9a96043f..155d8f808 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -1,17 +1,8 @@ class SearchController < ApplicationController - before_action :authenticate_user!, only: %i[tags chat_channels reactions usernames] + before_action :authenticate_user!, only: %i[tags reactions usernames] before_action :format_integer_params before_action :sanitize_params, only: %i[listings reactions feed_content] - CHAT_CHANNEL_PARAMS = %i[ - channel_status - channel_type - page - per_page - status - user_id - ].freeze - LISTINGS_PARAMS = [ :category, :listing_search, @@ -65,23 +56,6 @@ class SearchController < ApplicationController render json: { result: result } end - def chat_channels - user_ids = - if chat_channel_params[:user_id].present? - [current_user.id, Settings::General.mascot_user_id, chat_channel_params[:user_id]].reject(&:blank?) - else - [current_user.id] - end - - result = Search::ChatChannelMembership.search_documents( - user_ids: user_ids, - page: chat_channel_params[:page], - per_page: chat_channel_params[:per_page], - ) - - render json: { result: result } - end - def listings result = Search::Listing.search_documents( category: listing_params[:category], @@ -193,10 +167,6 @@ class SearchController < ApplicationController ) end - def chat_channel_params - params.permit(CHAT_CHANNEL_PARAMS) - end - def listing_params params.permit(LISTINGS_PARAMS) end diff --git a/app/controllers/user_blocks_controller.rb b/app/controllers/user_blocks_controller.rb index 20e484b45..232babe16 100644 --- a/app/controllers/user_blocks_controller.rb +++ b/app/controllers/user_blocks_controller.rb @@ -19,7 +19,6 @@ class UserBlocksController < ApplicationController @user_block.config = "default" if @user_block.save - UserBlocks::ChannelHandler.new(@user_block).block_chat_channel current_user.stop_following(@user_block.blocked) @user_block.blocked.stop_following(current_user) render json: { result: "blocked" } @@ -39,7 +38,6 @@ class UserBlocksController < ApplicationController authorize @user_block if @user_block.destroy - UserBlocks::ChannelHandler.new(@user_block).unblock_chat_channel render json: { result: "unblocked" } else render json: { error: @user_block.errors_as_sentence, status: 422 }, status: :unprocessable_entity diff --git a/app/controllers/users/notification_settings_controller.rb b/app/controllers/users/notification_settings_controller.rb index 5a4daf5be..6cf2c216e 100644 --- a/app/controllers/users/notification_settings_controller.rb +++ b/app/controllers/users/notification_settings_controller.rb @@ -7,7 +7,6 @@ module Users ALLOWED_PARAMS = %i[email_badge_notifications email_comment_notifications email_community_mod_newsletter - email_connect_messages email_digest_periodic email_follower_notifications email_membership_newsletter diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3bcc3ea75..4174af3a7 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,5 +1,5 @@ module ApplicationHelper - # rubocop:disable Performance/OpenStruct + # rubocop:disable Style/OpenStructUse, Performance/OpenStruct USER_COLORS = ["#19063A", "#dce9f3"].freeze DELETED_USER = OpenStruct.new( @@ -11,7 +11,7 @@ module ApplicationHelper twitter_username: nil, github_username: nil, ) - # rubocop:enable Performance/OpenStruct + # rubocop:enable Style/OpenStructUse, Performance/OpenStruct LARGE_USERBASE_THRESHOLD = 1000 diff --git a/app/helpers/chat_channel_memberships_helper.rb b/app/helpers/chat_channel_memberships_helper.rb deleted file mode 100644 index df74ba335..000000000 --- a/app/helpers/chat_channel_memberships_helper.rb +++ /dev/null @@ -1,36 +0,0 @@ -module ChatChannelMembershipsHelper - def formatted_membership_user(memberships) - memberships.map do |membership| - { - name: membership.user.name, - username: membership.user.username, - user_id: membership.user.id, - membership_id: membership.id, - role: membership.role, - status: membership.status, - image: Images::Profile.call(membership.user.profile_image_url, length: 90), - chat_channel_name: membership.chat_channel.channel_name, - chat_channel_id: membership.chat_channel.id, - slug: membership.chat_channel.slug - } - end - end - - def membership_users(memberships) - memberships.includes(:user).map do |membership| - format_membership(membership) - end - end - - def format_membership(membership) - { - name: membership.user.name, - username: membership.user.username, - user_id: membership.user.id, - membership_id: membership.id, - role: membership.role, - status: membership.status, - image: Images::Profile.call(membership.user.profile_image_url, length: 90) - } - end -end diff --git a/app/helpers/chat_channels_helper.rb b/app/helpers/chat_channels_helper.rb deleted file mode 100644 index 1b1a13b6f..000000000 --- a/app/helpers/chat_channels_helper.rb +++ /dev/null @@ -1,44 +0,0 @@ -module ChatChannelsHelper - def unopened_json_response - if session_current_user_id - ChatChannelMembership.where(user_id: session_current_user_id) - .where(has_unopened_messages: true) - .where(show_global_badge_notification: true) - .where.not(status: %w[removed_from_channel left_channel]) - .includes(%i[chat_channel user]) - .order("chat_channel_memberships.updated_at" => :desc) - else - ChatChannelMembership.none - end - end - - def pending_json_response - if current_user - current_user - .chat_channel_memberships.includes(:chat_channel) - .where(status: "pending") - .order("chat_channel_memberships.updated_at" => :desc) - else - ChatChannelMembership.none - end - end - - def unopened_ids_response - ChatChannelMembership.where(user_id: session_current_user_id).includes(:chat_channel) - .where(has_unopened_messages: true).where.not(status: %w[removed_from_channel - left_channel]).pluck(:chat_channel_id) - end - - def joining_request_json_response - requested_memberships_id = current_user - .chat_channel_memberships - .includes(:chat_channel) - .where(chat_channels: { discoverable: true }, role: "mod") - .pluck(:chat_channel_id) - .flat_map { |membership_id| ChatChannel.find_by(id: membership_id).requested_memberships.ids } - - ChatChannelMembership - .includes(%i[user chat_channel]) - .where(id: requested_memberships_id) - end -end diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb deleted file mode 100644 index 46098d6b5..000000000 --- a/app/helpers/messages_helper.rb +++ /dev/null @@ -1,41 +0,0 @@ -module MessagesHelper - def create_pusher_payload(new_message, temp_id) - payload = { - temp_id: temp_id, - id: new_message.id, - user_id: new_message.user.id, - chat_channel_id: new_message.chat_channel.id, - chat_channel_adjusted_slug: new_message.chat_channel.adjusted_slug(current_user, "sender"), - channel_type: new_message.chat_channel.channel_type, - username: new_message.user.username, - profile_image_url: Images::Profile.call(new_message.user.profile_image_url, length: 90), - message: new_message.message_html, - markdown: new_message.message_markdown, - edited_at: new_message.edited_at, - timestamp: Time.current, - color: new_message.preferred_user_color, - reception_method: "pushed", - action: new_message.chat_action - } - - if new_message.chat_channel.group? - payload[:chat_channel_adjusted_slug] = new_message.chat_channel.adjusted_slug - end - payload.to_json - end - - def pusher_message_created(is_single, message, temp_message_id) - return unless message.valid? - - begin - message_json = create_pusher_payload(message, temp_message_id) - if is_single - Pusher.trigger(ChatChannel.pm_notifications_channel(message.user_id), "message-created", message_json) - else - Pusher.trigger(message.chat_channel.pusher_channels, "message-created", message_json) - end - rescue Pusher::Error => e - Honeybadger.notify(e) - end - end -end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 78e98a74e..3d8007ba7 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -23,6 +23,6 @@ module NotificationsHelper ) else I18n.t(action, user: key_to_link.call("user")) - end.html_safe + end.html_safe # rubocop:disable Rails/OutputSafety end end diff --git a/app/javascript/chat/ChatChannelSettings/ActiveMembershipsSection.jsx b/app/javascript/chat/ChatChannelSettings/ActiveMembershipsSection.jsx deleted file mode 100644 index 54165c455..000000000 --- a/app/javascript/chat/ChatChannelSettings/ActiveMembershipsSection.jsx +++ /dev/null @@ -1,51 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -import { defaultMembershipPropType } from '../../common-prop-types/membership-prop-type'; -import { Membership } from './Membership'; -import { Button } from '@crayons'; - -export const ActiveMembershipsSection = ({ - activeMemberships, - removeMembership, - currentMembershipRole, - toggleScreens, -}) => { - const activeMembershipList = activeMemberships.slice(0, 4); - - return ( -
-

Members

- {activeMembershipList.map((activeMembership) => ( - - ))} -
- -
-
- ); -}; - -ActiveMembershipsSection.propTypes = { - activeMemberships: PropTypes.arrayOf(defaultMembershipPropType).isRequired, - removeMembership: PropTypes.func.isRequired, - currentMembershipRole: PropTypes.string.isRequired, - toggleScreens: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/ChannelDescriptionSection.jsx b/app/javascript/chat/ChatChannelSettings/ChannelDescriptionSection.jsx deleted file mode 100644 index fded19b28..000000000 --- a/app/javascript/chat/ChatChannelSettings/ChannelDescriptionSection.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -export const ChannelDescriptionSection = ({ - channelName, - channelDescription, - currentMembershipRole, -}) => { - return ( -
-

{channelName}

-

{channelDescription}

-

You are a channel {currentMembershipRole}

-
- ); -}; - -ChannelDescriptionSection.propTypes = { - channelName: PropTypes.string.isRequired, - currentMembershipRole: PropTypes.string.isRequired, - channelDescription: PropTypes.string.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/ChatChannelMembershipSection.jsx b/app/javascript/chat/ChatChannelSettings/ChatChannelMembershipSection.jsx deleted file mode 100644 index 8eca79010..000000000 --- a/app/javascript/chat/ChatChannelSettings/ChatChannelMembershipSection.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -import { defaultMembershipPropType } from '../../common-prop-types/membership-prop-type'; -import { ActiveMembershipsSection } from './ActiveMembershipsSection'; -import { PendingMembershipSection } from './PendingMembershipSection'; -import { RequestedMembershipSection } from './RequestedMembershipSection'; - -export const ChatChannelMembershipSection = ({ - pendingMemberships, - requestedMemberships, - chatChannelAcceptMembership, - activeMemberships, - removeMembership, - currentMembershipRole, - toggleScreens, -}) => { - return ( -
- - - -
- ); -}; - -ChatChannelMembershipSection.propTypes = { - pendingMemberships: PropTypes.arrayOf(defaultMembershipPropType).isRequired, - requestedMemberships: PropTypes.arrayOf(defaultMembershipPropType).isRequired, - activeMemberships: PropTypes.arrayOf(defaultMembershipPropType).isRequired, - removeMembership: PropTypes.func.isRequired, - chatChannelAcceptMembership: PropTypes.func.isRequired, - currentMembershipRole: PropTypes.string.isRequired, - toggleScreens: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/ChatChannelSettings.jsx b/app/javascript/chat/ChatChannelSettings/ChatChannelSettings.jsx deleted file mode 100644 index 9d143eef8..000000000 --- a/app/javascript/chat/ChatChannelSettings/ChatChannelSettings.jsx +++ /dev/null @@ -1,440 +0,0 @@ -import { h, Component } from 'preact'; -import PropTypes from 'prop-types'; - -import { - getChannelDetails, - updatePersonalChatChannelNotificationSettings, - rejectChatChannelJoiningRequest, - acceptChatChannelJoiningRequest, - updateChatChannelDescription, - sendChatChannelInvitation, - leaveChatChannelMembership, - updateMembershipRole, -} from '../actions/chat_channel_setting_actions'; - -import { addSnackbarItem } from '../../Snackbar'; -import { ManageActiveMembership } from './MembershipManager/ManageActiveMembership'; -import { ChatChannelSettingsSection } from './ChatChannelSettingsSection'; - -export class ChatChannelSettings extends Component { - static propTypes = { - handleLeavingChannel: PropTypes.func.isRequired, - activeMembershipId: PropTypes.number.isRequired, - }; - - constructor(props) { - super(props); - - this.state = { - successMessages: null, - errorMessages: null, - activeMemberships: [], - pendingMemberships: [], - requestedMemberships: [], - chatChannel: null, - currentMembership: null, - activeMembershipId: null, - channelDescription: null, - channelDiscoverable: null, - invitationUsernames: null, - showGlobalBadgeNotification: null, - displaySettings: true, - displayMembershipManager: false, - invitationLink: null, - }; - } - - componentDidMount() { - this.updateChannelDetails(); - } - - componentWillReceiveProps() { - const { activeMembershipId } = this.props; - this.setState({ - activeMembershipId, - }); - } - - updateChannelDetails = () => { - const { activeMembershipId } = this.props; - - getChannelDetails(activeMembershipId) - .then((response) => { - if (response.success) { - const { result } = response; - this.setState({ - chatChannel: result.chat_channel, - activeMemberships: result.memberships.active, - pendingMemberships: result.memberships.pending, - requestedMemberships: result.memberships.requested, - currentMembership: result.current_membership, - channelDescription: result.chat_channel.description, - channelDiscoverable: result.chat_channel.discoverable, - showGlobalBadgeNotification: - result.current_membership.show_global_badge_notification, - invitationLink: result.invitation_link, - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - }); - } - }) - .catch((error) => { - this.setState({ - successMessages: null, - errorMessages: error.message, - }); - }); - }; - - handleDescriptionChange = (e) => { - const description = e.target.value; - this.setState({ - channelDescription: description, - }); - }; - - handlePersonChannelSetting = (e) => { - const status = e.target.checked; - this.setState({ - showGlobalBadgeNotification: status, - }); - }; - - updateCurrentMembershipNotificationSettings = async () => { - const { currentMembership, showGlobalBadgeNotification } = this.state; - const response = await updatePersonalChatChannelNotificationSettings( - currentMembership.id, - showGlobalBadgeNotification, - ); - const { message } = response; - if (response.success) { - this.setState((prevState) => { - return { - errorMessages: null, - successMessages: response.message, - currentMembership: { - ...prevState.currentMembership, - show_global_badge_notification: showGlobalBadgeNotification, - }, - }; - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - showGlobalBadgeNotification: - currentMembership.show_global_badge_notification, - }); - } - addSnackbarItem({ message }); - }; - - chatChannelRemoveMembership = async (membershipId, membershipStatus) => { - const { chatChannel } = this.state; - const response = await rejectChatChannelJoiningRequest( - chatChannel.id, - membershipId, - membershipStatus, - ); - return response; - }; - - filterMemberships = (memberships, membershipId) => { - const filteredMembership = memberships.filter( - (membership) => membership.membership_id !== Number(membershipId), - ); - return filteredMembership; - }; - - removeMembership = async (e) => { - const { membershipId, membershipStatus } = e.target.dataset; - const response = await this.chatChannelRemoveMembership( - membershipId, - membershipStatus, - ); - const { message } = response; - this.updateMemberships(membershipId, response, membershipStatus); - addSnackbarItem({ message }); - }; - - updateMemberships = (membershipId, response, membershipStatus) => { - if (response.success) { - this.updateChannelDetails(); - this.setState((prevState) => { - return { - errorMessages: null, - successMessages: response.message, - activeMemberships: - membershipStatus === 'active' - ? this.filterMemberships( - prevState.activeMemberships, - membershipId, - ) - : prevState.activeMemberships, - pendingMemberships: - membershipStatus === 'pending' - ? this.filterMemberships( - prevState.pendingMemberships, - membershipId, - ) - : prevState.pendingMemberships, - requestedMemberships: - membershipStatus === 'joining_request' - ? this.filterMemberships( - prevState.requestedMemberships, - membershipId, - ) - : prevState.requestedMembership, - }; - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - }); - } - }; - - chatChannelAcceptMembership = async (e) => { - const { chatChannel } = this.state; - const { membershipId } = e.target.dataset; - const response = await acceptChatChannelJoiningRequest( - chatChannel.id, - membershipId, - ); - const { message } = response; - if (response.success) { - this.setState((prevState) => { - const filteredRequestedMemberships = prevState.requestedMemberships.filter( - (requestedMembership) => - requestedMembership.membership_id !== Number(membershipId), - ); - const updatedActiveMembership = [ - ...prevState.activeMemberships, - response.membership, - ]; - return { - errorMessages: null, - successMessages: response.message, - requestedMemberships: filteredRequestedMemberships, - activeMemberships: updatedActiveMembership, - }; - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - }); - } - addSnackbarItem({ message }); - }; - - handleChannelDiscoverableStatus = (e) => { - const status = e.target.checked; - this.setState({ - channelDiscoverable: status, - }); - }; - - handleChannelDescriptionChanges = async () => { - const { chatChannel, channelDescription, channelDiscoverable } = this.state; - const { id } = chatChannel; - const response = await updateChatChannelDescription( - id, - channelDescription, - channelDiscoverable, - ); - const { message } = response; - - if (response.success) { - this.updateChannelDetails(); - this.setState((prevState) => { - return { - errorMessages: null, - successMessages: response.message, - chatChannel: { - ...prevState, - description: channelDescription, - discoverable: channelDiscoverable, - }, - }; - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - channelDiscoverable: chatChannel.discoverable, - }); - } - addSnackbarItem({ message }); - }; - - handleInvitationUsernames = (e) => { - const invitationUsernameValue = e.target.value; - this.setState({ - invitationUsernames: invitationUsernameValue, - }); - }; - - handleChannelInvitations = async () => { - const { invitationUsernames, chatChannel } = this.state; - const { id } = chatChannel; - const response = await sendChatChannelInvitation(id, invitationUsernames); - const { message } = response; - if (response.success) { - this.updateChannelDetails(); - this.setState({ - errorMessages: null, - successMessages: response.message, - invitationUsernames: null, - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - }); - } - addSnackbarItem({ message }); - }; - - handleleaveChannelMembership = async () => { - // eslint-disable-next-line no-restricted-globals - const actionStatus = confirm( - 'Are you absolutely sure you want to leave this channel? This action is permanent.', - ); - const { currentMembership } = this.state; - if (actionStatus) { - const response = await leaveChatChannelMembership(currentMembership.id); - const { message } = response; - if (response.success) { - this.setState({ - successMessages: message, - errorMessages: null, - }); - this.props.handleLeavingChannel(currentMembership.id); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - }); - } - addSnackbarItem({ message }); - } - }; - - toggleScreens = () => { - const { displaySettings, displayMembershipManager } = this.state; - - this.setState({ - displaySettings: !displaySettings, - displayMembershipManager: !displayMembershipManager, - }); - }; - - handleUpdateMembershipRole = async (e) => { - const { membershipId, role } = e.target.dataset; - const { chatChannel } = this.state; - const response = await updateMembershipRole( - membershipId, - chatChannel.id, - role, - ); - const { message } = response; - if (response.success) { - this.updateChannelDetails(); - this.setState((prevState) => { - const { activeMemberships } = prevState; - const updatedActiveMemberships = activeMemberships.map( - (activeMembership) => { - if (activeMembership.membership_id === Number(membershipId)) { - return { ...activeMembership, role }; - } - return activeMembership; - }, - ); - return { - ...prevState, - activeMemberships: updatedActiveMemberships, - errorMessages: null, - successMessages: response.message, - }; - }); - } else { - this.setState({ - successMessages: null, - errorMessages: response.message, - }); - } - - addSnackbarItem({ message }); - }; - - render() { - const { - chatChannel, - currentMembership, - activeMemberships, - pendingMemberships, - requestedMemberships, - channelDescription, - channelDiscoverable, - invitationUsernames, - showGlobalBadgeNotification, - displaySettings, - invitationLink, - } = this.state; - - if (!chatChannel) { - return null; - } - - return ( -
-
- {displaySettings ? ( - - ) : ( - - )} -
-
- ); - } -} diff --git a/app/javascript/chat/ChatChannelSettings/ChatChannelSettingsSection.jsx b/app/javascript/chat/ChatChannelSettings/ChatChannelSettingsSection.jsx deleted file mode 100644 index c0be562b9..000000000 --- a/app/javascript/chat/ChatChannelSettings/ChatChannelSettingsSection.jsx +++ /dev/null @@ -1,103 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -import { ModSection } from './ModSection'; -import { PersonalSettings } from './PersonalSetting'; -import { LeaveMembershipSection } from './LeaveMembershipSection'; -import { ModFaqSection } from './ModFaqSection'; -import { ChannelDescriptionSection } from './ChannelDescriptionSection'; -import { ChatChannelMembershipSection } from './ChatChannelMembershipSection'; - -export const ChatChannelSettingsSection = ({ - channelDiscoverable, - updateCurrentMembershipNotificationSettings, - handleleaveChannelMembership, - handlePersonChannelSetting, - handleChannelDescriptionChanges, - handleChannelDiscoverableStatus, - handleDescriptionChange, - handleChannelInvitations, - handleInvitationUsernames, - toggleScreens, - removeMembership, - chatChannelAcceptMembership, - channelDescription, - chatChannel, - currentMembership, - activeMemberships, - pendingMemberships, - requestedMemberships, - invitationUsernames, - showGlobalBadgeNotification, -}) => ( -
- - - - - - -
-); - -ChatChannelSettingsSection.propTypes = { - chatChannel: PropTypes.isRequired, - currentMembership: PropTypes.isRequired, - activeMemberships: PropTypes.isRequired, - pendingMemberships: PropTypes.isRequired, - requestedMemberships: PropTypes.isRequired, - invitationUsernames: PropTypes.string.isRequired, - channelDescription: PropTypes.string.isRequired, - channelDiscoverable: PropTypes.bool.isRequired, - showGlobalBadgeNotification: PropTypes.bool.isRequired, - handleleaveChannelMembership: PropTypes.func.isRequired, - chatChannelAcceptMembership: PropTypes.func.isRequired, - removeMembership: PropTypes.func.isRequired, - toggleScreens: PropTypes.func.isRequired, - handleInvitationUsernames: PropTypes.func.isRequired, - handleChannelInvitations: PropTypes.func.isRequired, - handleDescriptionChange: PropTypes.func.isRequired, - handleChannelDiscoverableStatus: PropTypes.func.isRequired, - handleChannelDescriptionChanges: PropTypes.func.isRequired, - handlePersonChannelSetting: PropTypes.func.isRequired, - updateCurrentMembershipNotificationSettings: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/InviteForm.jsx b/app/javascript/chat/ChatChannelSettings/InviteForm.jsx deleted file mode 100644 index 86325d38c..000000000 --- a/app/javascript/chat/ChatChannelSettings/InviteForm.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { Button } from '@crayons'; - -export const InviteForm = ({ - handleChannelInvitations, - invitationUsernames, - handleInvitationUsernames, -}) => { - return ( -
-
- - -
-
- -
-
- ); -}; - -InviteForm.propTypes = { - handleInvitationUsernames: PropTypes.func.isRequired, - handleChannelInvitations: PropTypes.func.isRequired, - invitationUsernames: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/LeaveMembershipSection.jsx b/app/javascript/chat/ChatChannelSettings/LeaveMembershipSection.jsx deleted file mode 100644 index 6c3644955..000000000 --- a/app/javascript/chat/ChatChannelSettings/LeaveMembershipSection.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import { h } from 'preact'; -import PropsType from 'prop-types'; -import { Button } from '@crayons'; - -export const LeaveMembershipSection = ({ - handleleaveChannelMembership, - currentMembershipRole, -}) => { - if (currentMembershipRole === 'mod') { - return null; - } - - return ( -
-

Danger Zone

-
- -
-
- ); -}; - -LeaveMembershipSection.propTypes = { - handleleaveChannelMembership: PropsType.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/Membership.jsx b/app/javascript/chat/ChatChannelSettings/Membership.jsx deleted file mode 100644 index 7b7737988..000000000 --- a/app/javascript/chat/ChatChannelSettings/Membership.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { defaultMembershipPropType } from '../../common-prop-types/membership-prop-type'; -import { Button } from '@crayons'; - -export const Membership = ({ - membership, - removeMembership, - membershipType, - chatChannelAcceptMembership, - currentMembershipRole, -}) => { - return ( -
- - - {`${membership.name} - - {membership.name} - - {membershipType === 'requested' ? ( - - ) : null} - {membership.role !== 'mod' && currentMembershipRole === 'mod' ? ( - - ) : null} -
- ); -}; - -Membership.propTypes = { - membership: PropTypes.objectOf(defaultMembershipPropType).isRequired, - removeMembership: PropTypes.func.isRequired, - membershipType: PropTypes.func.isRequired, - chatChannelAcceptMembership: PropTypes.func.isRequired, - currentMembershipRole: PropTypes.string.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/MembershipManager/InvitationLinkManager.jsx b/app/javascript/chat/ChatChannelSettings/MembershipManager/InvitationLinkManager.jsx deleted file mode 100644 index feea5e249..000000000 --- a/app/javascript/chat/ChatChannelSettings/MembershipManager/InvitationLinkManager.jsx +++ /dev/null @@ -1,95 +0,0 @@ -/* global Runtime */ - -import { h, Component } from 'preact'; -import PropTypes from 'prop-types'; - -import { Button } from '@crayons'; - -const CopyIcon = () => ( - - Copy Invitation Url - - -); - -export class InvitationLinkManager extends Component { - static propTypes = { - invitationLink: PropTypes.string.isRequired, - currentMembership: PropTypes.isRequired, - }; - - constructor(props) { - super(props); - - this.state = { - invitationLink: props.invitationLink, - showImageCopiedMessage: false, - currentMembership: props.currentMembership, - }; - } - - copyText = () => { - this.imageMarkdownInput = document.getElementById( - 'chat-channel-unviation-url', - ); - - Runtime.copyToClipboard(this.imageMarkdownInput.value).then(() => { - this.setState({ showImageCopiedMessage: true }); - }); - }; - - render() { - const { - showImageCopiedMessage, - invitationLink, - currentMembership, - } = this.state; - - if (currentMembership.role !== 'mod') { - return null; - } - - return ( -
-

Invitation Link

- - -
- ); - } -} diff --git a/app/javascript/chat/ChatChannelSettings/MembershipManager/ManageActiveMembership.jsx b/app/javascript/chat/ChatChannelSettings/MembershipManager/ManageActiveMembership.jsx deleted file mode 100644 index f6c315f28..000000000 --- a/app/javascript/chat/ChatChannelSettings/MembershipManager/ManageActiveMembership.jsx +++ /dev/null @@ -1,123 +0,0 @@ -import { h, Component } from 'preact'; -import PropTypes from 'prop-types'; - -import { MembershipSection } from './MembershipSection'; -import { InvitationLinkManager } from './InvitationLinkManager'; - -export class ManageActiveMembership extends Component { - static propTypes = { - activeMemberships: PropTypes.arrayOf( - PropTypes.shape({ - name: PropTypes.string.isRequired, - membership_id: PropTypes.number.isRequired, - user_id: PropTypes.number.isRequired, - role: PropTypes.string.isRequired, - image: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - }), - ).isRequired, - currentMembership: PropTypes.isRequired, - invitationLink: PropTypes.string.isRequired, - removeMembership: PropTypes.func.isRequired, - handleUpdateMembershipRole: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - this.state = { - activeMemberships: props.activeMemberships, - searchMembers: null, - listAllMemberShips: props.activeMemberships, - currentMembership: props.currentMembership, - invitationLink: props.invitationLink, - removeMembership: props.removeMembership, - handleUpdateMembershipRole: props.handleUpdateMembershipRole, - }; - } - - componentWillReceiveProps() { - const { - activeMemberships, - currentMembership, - removeMembership, - invitationLink, - } = this.props; - this.setState({ - listAllMemberShips: activeMemberships, - currentMembership, - invitationLink, - removeMembership, - activeMemberships, - searchMembers: null, - }); - } - - searchTheMembershipUser = (e) => { - const query = e.target?.value?.toLowerCase(); - - this.setState((prevState) => { - const filteredActiveMemberships = prevState.activeMemberships.filter( - (activeMembership) => { - const value = activeMembership.name.toLowerCase(); - return value.includes(query); - }, - ); - - return { - searchMembers: query, - listAllMemberShips: filteredActiveMemberships, - }; - }); - }; - - render() { - const { - searchMembers, - listAllMemberShips, - currentMembership, - invitationLink, - removeMembership, - handleUpdateMembershipRole, - activeMemberships, - } = this.state; - - const membershipCount = activeMemberships.length; - return ( -
-
-

Chat Channel Membership manager

-
-
- -
- -
-
- -
- ); - } -} diff --git a/app/javascript/chat/ChatChannelSettings/MembershipManager/Membership.jsx b/app/javascript/chat/ChatChannelSettings/MembershipManager/Membership.jsx deleted file mode 100644 index 3a2fba273..000000000 --- a/app/javascript/chat/ChatChannelSettings/MembershipManager/Membership.jsx +++ /dev/null @@ -1,129 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import adminEmoji from '../../../../assets/images/twemoji/fire.svg'; -import { Button } from '@crayons'; - -export const Membership = ({ - membership, - currentMembership, - removeMembership, - handleUpdateMembershipRole, - showActionButton, -}) => { - const addAsModButton = - membership.role === 'member' ? ( - - ) : null; - - const addAsMemberButton = - membership.role === 'mod' ? ( - - ) : null; - - const removeMembershipButton = - membership.role === 'member' ? ( - - ) : null; - - const dropdown = - currentMembership.role === 'mod' && showActionButton ? ( - - {removeMembershipButton} - {addAsModButton} - {addAsMemberButton} - - ) : null; - - return ( -
-
- - - {`${membership.name} - - {membership.name} - - {membership.role === 'mod' ? ( - admin emoji - ) : null} - - -
-
{dropdown}
-
- ); -}; - -Membership.propTypes = { - membership: PropTypes.objectOf( - PropTypes.shape({ - name: PropTypes.string.isRequired, - membership_id: PropTypes.number.isRequired, - user_id: PropTypes.number.isRequired, - role: PropTypes.string.isRequired, - image: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - }), - ).isRequired, - currentMembership: PropTypes.isRequired, - removeMembership: PropTypes.func.isRequired, - handleUpdateMembershipRole: PropTypes.func.isRequired, - showActionButton: PropTypes.bool.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/MembershipManager/MembershipSection.jsx b/app/javascript/chat/ChatChannelSettings/MembershipManager/MembershipSection.jsx deleted file mode 100644 index 477dab148..000000000 --- a/app/javascript/chat/ChatChannelSettings/MembershipManager/MembershipSection.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { Membership } from './Membership'; - -export const MembershipSection = ({ - memberships, - currentMembership, - removeMembership, - handleUpdateMembershipRole, - membershipCount, -}) => { - if (!memberships || memberships.length === 0) { - return

No membership

; - } - - return ( -
- {memberships.map((activeMembership) => ( - {}} - className="active-member" - currentMembership={currentMembership} - removeMembership={removeMembership} - handleUpdateMembershipRole={handleUpdateMembershipRole} - showActionButton={membershipCount > 1} - /> - ))} -
- ); -}; - -MembershipSection.propType = { - memberships: PropTypes.arrayOf( - PropTypes.shape({ - name: PropTypes.string.isRequired, - membership_id: PropTypes.number.isRequired, - user_id: PropTypes.number.isRequired, - role: PropTypes.string.isRequired, - image: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - }), - ).isRequired, - currentMembership: PropTypes.isRequired, - removeMembership: PropTypes.func.isRequired, - handleUpdateMembershipRole: PropTypes.func.isRequired, - membershipCount: PropTypes.number.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/ModFaqSection.jsx b/app/javascript/chat/ChatChannelSettings/ModFaqSection.jsx deleted file mode 100644 index 9b743ac36..000000000 --- a/app/javascript/chat/ChatChannelSettings/ModFaqSection.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -export const ModFaqSection = ({ currentMembershipRole }) => { - if (currentMembershipRole === 'member') { - return null; - } - - return ( -
-

- Questions about Connect moderation? - - Contact site admins - -

-
- ); -}; - -ModFaqSection.propTypes = { - currentMembershipRole: PropTypes.string.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/ModSection.jsx b/app/javascript/chat/ChatChannelSettings/ModSection.jsx deleted file mode 100644 index c69355409..000000000 --- a/app/javascript/chat/ChatChannelSettings/ModSection.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -import { InviteForm } from './InviteForm'; -import { SettingsForm } from './SettingsForm'; - -export const ModSection = ({ - handleChannelInvitations, - invitationUsernames, - handleInvitationUsernames, - channelDescription, - handleDescriptionChange, - channelDiscoverable, - handleChannelDiscoverableStatus, - handleChannelDescriptionChanges, - currentMembershipRole, -}) => { - if (currentMembershipRole === 'member') { - return null; - } - - return ( -
- - -
- ); -}; - -ModSection.propTypes = { - handleInvitationUsernames: PropTypes.func.isRequired, - handleChannelInvitations: PropTypes.func.isRequired, - invitationUsernames: PropTypes.func.isRequired, - channelDescription: PropTypes.string.isRequired, - handleDescriptionChange: PropTypes.func.isRequired, - handleChannelDiscoverableStatus: PropTypes.func.isRequired, - handleChannelDescriptionChanges: PropTypes.func.isRequired, - channelDiscoverable: PropTypes.bool.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/PendingMembershipSection.jsx b/app/javascript/chat/ChatChannelSettings/PendingMembershipSection.jsx deleted file mode 100644 index 7d8b81ebe..000000000 --- a/app/javascript/chat/ChatChannelSettings/PendingMembershipSection.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; - -import { defaultMembershipPropType } from '../../common-prop-types/membership-prop-type'; -import { Membership } from './Membership'; - -export const PendingMembershipSection = ({ - pendingMemberships, - removeMembership, - currentMembershipRole, -}) => { - if (currentMembershipRole === 'member') { - return null; - } - - return ( -
-

Pending Invitations

- {pendingMemberships && pendingMemberships.length > 0 - ? pendingMemberships.map((pendingMembership) => ( - - )) - : null} -
- ); -}; - -PendingMembershipSection.propTypes = { - pendingMemberships: PropTypes.arrayOf(defaultMembershipPropType).isRequired, - removeMembership: PropTypes.func.isRequired, - currentMembershipRole: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/PersonalSetting.jsx b/app/javascript/chat/ChatChannelSettings/PersonalSetting.jsx deleted file mode 100644 index 7806aec8c..000000000 --- a/app/javascript/chat/ChatChannelSettings/PersonalSetting.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { Button } from '@crayons'; - -export const PersonalSettings = ({ - handlePersonChannelSetting, - showGlobalBadgeNotification, - updateCurrentMembershipNotificationSettings, -}) => { - return ( -
-

Personal Settings

-

Notifications

-
- - -
-
- -
-
- ); -}; - -PersonalSettings.propTypes = { - updateCurrentMembershipNotificationSettings: PropTypes.func.isRequired, - showGlobalBadgeNotification: PropTypes.bool.isRequired, - handlePersonChannelSetting: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/RequestedMembershipSection.jsx b/app/javascript/chat/ChatChannelSettings/RequestedMembershipSection.jsx deleted file mode 100644 index c4a5965d0..000000000 --- a/app/javascript/chat/ChatChannelSettings/RequestedMembershipSection.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { defaultMembershipPropType } from '../../common-prop-types/membership-prop-type'; - -import { Membership } from './Membership'; - -export const RequestedMembershipSection = ({ - requestedMemberships, - removeMembership, - chatChannelAcceptMembership, - currentMembershipRole, -}) => { - if (currentMembershipRole === 'member') { - return null; - } - - return ( -
-

Joining Request

- {requestedMemberships && requestedMemberships.length > 0 - ? requestedMemberships.map((pendingMembership) => ( - - )) - : null} -
- ); -}; - -RequestedMembershipSection.propTypes = { - requestedMemberships: PropTypes.arrayOf(defaultMembershipPropType).isRequired, - removeMembership: PropTypes.func.isRequired, - chatChannelAcceptMembership: PropTypes.func.isRequired, - currentMembershipRole: PropTypes.func.isRequired, -}; diff --git a/app/javascript/chat/ChatChannelSettings/SettingsForm.jsx b/app/javascript/chat/ChatChannelSettings/SettingsForm.jsx deleted file mode 100644 index b28549a26..000000000 --- a/app/javascript/chat/ChatChannelSettings/SettingsForm.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { Button } from '@crayons'; - -export const SettingsForm = ({ - channelDescription, - handleDescriptionChange, - channelDiscoverable, - handleChannelDiscoverableStatus, - handleChannelDescriptionChanges, -}) => { - return ( -
-

Channel Settings

-
- -