Skip to content
Draft

This file was deleted.

This file was deleted.

This file was deleted.

12 changes: 0 additions & 12 deletions app/controllers/api/internal/communities_controller.rb

This file was deleted.

71 changes: 71 additions & 0 deletions app/controllers/communities/chat_messages_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

class Communities::ChatMessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_community
before_action :set_message, only: [:update, :destroy]
after_action :verify_authorized

def create
message = @community.community_chat_messages.build(permitted_params)
message.user = current_seller

if message.save
message_props = CommunityChatMessagePresenter.new(message:).props
broadcast_message(message_props, CommunityChannel::CREATE_CHAT_MESSAGE_TYPE)
redirect_to community_path(@community.seller.external_id, @community.external_id),
status: :see_other
else
redirect_to community_path(@community.seller.external_id, @community.external_id),
inertia: { errors: { "community_chat_message.content" => message.errors.full_messages.first } },
status: :see_other
end
end

def update
if @message.update(permitted_params)
message_props = CommunityChatMessagePresenter.new(message: @message).props
broadcast_message(message_props, CommunityChannel::UPDATE_CHAT_MESSAGE_TYPE)
redirect_to community_path(@community.seller.external_id, @community.external_id),
status: :see_other
else
redirect_to community_path(@community.seller.external_id, @community.external_id),
inertia: { errors: { "community_chat_message.content" => @message.errors.full_messages.first } },
status: :see_other
end
end

def destroy
@message.mark_deleted!
message_props = CommunityChatMessagePresenter.new(message: @message).props
broadcast_message(message_props, CommunityChannel::DELETE_CHAT_MESSAGE_TYPE)
redirect_to community_path(@community.seller.external_id, @community.external_id),
status: :see_other
end

private

def set_community
@community = Community.find_by_external_id!(params[:community_id])
authorize @community, :show?
end

def set_message
@message = @community.community_chat_messages.find_by_external_id!(params[:id])
authorize @message
end

def permitted_params
params.require(:community_chat_message).permit(:content)
end

def broadcast_message(message_props, type)
CommunityChannel.broadcast_to(
"community_#{@community.external_id}",
{ type:, message: message_props },
)
rescue => e
Rails.logger.error("Error broadcasting message to community channel: #{e.message}")
Bugsnag.notify(e)
end
end
27 changes: 27 additions & 0 deletions app/controllers/communities/last_read_chat_messages_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

class Communities::LastReadChatMessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_community
after_action :verify_authorized

def create
message = @community.community_chat_messages.find_by_external_id!(params[:message_id])

LastReadCommunityChatMessage.set!(
user_id: current_seller.id,
community_id: @community.id,
community_chat_message_id: message.id
)

redirect_to community_path(@community.seller.external_id, @community.external_id),
status: :see_other
end

private

def set_community
@community = Community.find_by_external_id!(params[:community_id])
authorize @community, :show?
end
end
102 changes: 97 additions & 5 deletions app/controllers/communities_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,109 @@

class CommunitiesController < ApplicationController
before_action :authenticate_user!
before_action :set_default_page_title
before_action :set_community, only: [:show, :update_notification_settings]
after_action :verify_authorized
before_action :set_body_id_as_app

def index
@hide_layouts = true
layout "inertia"

def index
authorize Community

first_community = communities_presenter.first_community
if first_community
redirect_to community_path(first_community.seller.external_id, first_community.external_id)
else
render inertia: "Communities/Index", props: {
has_products: -> { communities_presenter.has_products? },
communities: -> { communities_presenter.communities_props },
notification_settings: -> { communities_presenter.notification_settings_props }
}
end
end

def show
authorize @community

render inertia: "Communities/Index", props: {
has_products: -> { communities_presenter.has_products? },
communities: -> { communities_presenter.communities_props },
notification_settings: -> { communities_presenter.notification_settings_props },
selectedCommunityId: @community.external_id,
messages: messages_scroll_prop
}
end

def update_notification_settings
authorize @community, :show?

settings = current_seller.community_notification_settings.find_or_initialize_by(seller: @community.seller)
settings.update!(permitted_notification_params)

redirect_to community_path(@community.seller.external_id, @community.external_id),
notice: "Changes saved!",
status: :see_other
end

private
def set_default_page_title
set_meta_tag(title: "Communities")

def set_default_page_title
set_meta_tag(title: "Communities")
end

def communities_presenter
@communities_presenter ||= CommunitiesPresenter.new(current_user: current_seller)
end

def set_community
seller = User.find_by_external_id!(params[:seller_id])
@community = Community.alive.find_by_external_id!(params[:community_id])

raise ActiveRecord::RecordNotFound unless @community.seller_id == seller.id
end

def permitted_notification_params
params.permit(:recap_frequency)
end

def messages_scroll_prop
InertiaRails.scroll(messages_metadata) { paginated_messages_data[:messages] }
end

def messages_metadata
data = paginated_messages_data
{
page_name: "cursor",
previous_page: data[:next_newer_timestamp],
next_page: data[:next_older_timestamp],
current_page: message_cursor
}
end

def paginated_messages_data
@_paginated_messages_data ||= PaginatedCommunityChatMessagesPresenter.new(
community: @community,
timestamp: message_cursor,
fetch_type: message_fetch_type
).props
end

def message_cursor
@_message_cursor ||= params[:cursor].presence || last_read_timestamp || Time.current.iso8601
end

def last_read_timestamp
last_read = LastReadCommunityChatMessage
.includes(:community_chat_message)
.find_by(user: current_seller, community: @community)
last_read&.community_chat_message&.created_at&.iso8601
end

def message_fetch_type
case request.headers["X-Inertia-Infinite-Scroll-Merge-Intent"]
when "append" then "older"
when "prepend" then "newer"
else "around"
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useUserAgentInfo } from "$app/components/UserAgent";
import { useRunOnce } from "$app/components/useRunOnce";
import { WithTooltip } from "$app/components/WithTooltip";

import { CommunityViewContext, MAX_MESSAGE_LENGTH, MIN_MESSAGE_LENGTH } from "./CommunityView";
import { CommunityViewContext, MAX_MESSAGE_LENGTH, MIN_MESSAGE_LENGTH } from "$app/pages/Communities/Index";
import { UserAvatar } from "./UserAvatar";

const MAX_TEXTAREA_HEIGHT = 300;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as React from "react";
import { Icon } from "$app/components/Icons";
import { showAlert } from "$app/components/server-components/Alert";

import { MAX_MESSAGE_LENGTH } from "./CommunityView";
import { MAX_MESSAGE_LENGTH } from "$app/pages/Communities/Index";
import { CommunityDraft } from "./useCommunities";

export const ChatMessageInput = React.forwardRef<
Expand Down
Loading