diff --git a/VERSION_CW b/VERSION_CW index ccbccc3dc..d76bd2ba3 100644 --- a/VERSION_CW +++ b/VERSION_CW @@ -1 +1 @@ -2.2.0 +2.17.0 diff --git a/VERSION_CWCTL b/VERSION_CWCTL index 7ec1d6db4..276cbf9e2 100644 --- a/VERSION_CWCTL +++ b/VERSION_CWCTL @@ -1 +1 @@ -2.1.0 +2.3.0 diff --git a/app/builders/messages/instagram/message_builder.rb b/app/builders/messages/instagram/message_builder.rb index e917af5db..eb34d4052 100644 --- a/app/builders/messages/instagram/message_builder.rb +++ b/app/builders/messages/instagram/message_builder.rb @@ -63,7 +63,9 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder end def conversation - @conversation ||= Conversation.find_by(conversation_params) || build_conversation + @conversation ||= Conversation.where( + "additional_attributes ->> 'type' = 'instagram_direct_message'" + ).find_by(conversation_params) || build_conversation end def message_content @@ -95,7 +97,8 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder def build_conversation @contact_inbox ||= contact.contact_inboxes.find_by!(source_id: message_source_id) Conversation.create!(conversation_params.merge( - contact_inbox_id: @contact_inbox.id + contact_inbox_id: @contact_inbox.id, + additional_attributes: { type: 'instagram_direct_message' } )) end @@ -103,10 +106,7 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder { account_id: @inbox.account_id, inbox_id: @inbox.id, - contact_id: contact.id, - additional_attributes: { - type: 'instagram_direct_message' - } + contact_id: contact.id } end diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index 6e580a497..ebd673d6f 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -22,6 +22,10 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro @conversations_count = result[:count] end + def attachments + @attachments = @conversation.attachments + end + def create ActiveRecord::Base.transaction do @conversation = ConversationBuilder.new(params: params, contact_inbox: @contact_inbox).perform diff --git a/app/controllers/api/v1/widget/messages_controller.rb b/app/controllers/api/v1/widget/messages_controller.rb index 6287c94ee..76efb2c42 100644 --- a/app/controllers/api/v1/widget/messages_controller.rb +++ b/app/controllers/api/v1/widget/messages_controller.rb @@ -48,7 +48,8 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController def message_finder_params { filter_internal_messages: true, - before: permitted_params[:before] + before: permitted_params[:before], + after: permitted_params[:after] } end @@ -62,7 +63,7 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController def permitted_params # timestamp parameter is used in create conversation method - params.permit(:id, :before, :website_token, contact: [:name, :email], message: [:content, :referer_url, :timestamp, :echo_id]) + params.permit(:id, :before, :after, :website_token, contact: [:name, :email], message: [:content, :referer_url, :timestamp, :echo_id]) end def set_message diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb index 9472dc623..7ec0a6d30 100644 --- a/app/finders/conversation_finder.rb +++ b/app/finders/conversation_finder.rb @@ -5,7 +5,8 @@ class ConversationFinder SORT_OPTIONS = { latest: 'latest', sort_on_created_at: 'sort_on_created_at', - last_user_message_at: 'last_user_message_at' + last_user_message_at: 'last_user_message_at', + sort_on_priority: 'sort_on_priority' }.with_indifferent_access # assumptions @@ -53,9 +54,10 @@ class ConversationFinder find_all_conversations filter_by_status unless params[:q] - filter_by_team if @team - filter_by_labels if params[:labels] - filter_by_query if params[:q] + filter_by_team + filter_by_labels + filter_by_query + filter_by_source_id end def set_inboxes @@ -106,6 +108,8 @@ class ConversationFinder end def filter_by_query + return unless params[:q] + allowed_message_types = [Message.message_types[:incoming], Message.message_types[:outgoing]] @conversations = conversations.joins(:messages).where('messages.content ILIKE :search', search: "%#{params[:q]}%") .where(messages: { message_type: allowed_message_types }).includes(:messages) @@ -120,13 +124,24 @@ class ConversationFinder end def filter_by_team + return unless @team + @conversations = @conversations.where(team: @team) end def filter_by_labels + return unless params[:labels] + @conversations = @conversations.tagged_with(params[:labels], any: true) end + def filter_by_source_id + return unless params[:source_id] + + @conversations = @conversations.joins(:contact_inbox) + @conversations = @conversations.where(contact_inboxes: { source_id: params[:source_id] }) + end + def set_count_for_all_conversations [ @conversations.assigned_to(current_user).count, diff --git a/app/javascript/dashboard/assets/scss/_rtl.scss b/app/javascript/dashboard/assets/scss/_rtl.scss index 0ed2fe2f4..4f7efaab9 100644 --- a/app/javascript/dashboard/assets/scss/_rtl.scss +++ b/app/javascript/dashboard/assets/scss/_rtl.scss @@ -261,6 +261,12 @@ } } + // Basic filter dropdown + .basic-filter { + left: 0; + right: unset; + } + // Card label .label-container { .label { diff --git a/app/javascript/dashboard/components/widgets/AIAssistanceButton.vue b/app/javascript/dashboard/components/widgets/AIAssistanceButton.vue index 98629edf3..1da4109da 100644 --- a/app/javascript/dashboard/components/widgets/AIAssistanceButton.vue +++ b/app/javascript/dashboard/components/widgets/AIAssistanceButton.vue @@ -74,6 +74,7 @@ import { mapGetters } from 'vuex'; import { mixin as clickaway } from 'vue-clickaway'; import OpenAPI from 'dashboard/api/integrations/openapi'; import alertMixin from 'shared/mixins/alertMixin'; +import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; export default { mixins: [alertMixin, clickaway], @@ -144,6 +145,15 @@ export default { closeDropdown() { this.showDropdown = false; }, + async recordAnalytics({ type, tone }) { + const event = OPEN_AI_EVENTS[type.toUpperCase()]; + if (event) { + this.$track(event, { + type, + tone, + }); + } + }, async processEvent(type = 'rephrase') { this.uiFlags[type] = true; try { @@ -159,6 +169,7 @@ export default { } = result; this.$emit('replace-text', generatedMessage || this.message); this.closeDropdown(); + this.recordAnalytics({ type, tone: this.activeTone }); } catch (error) { this.showAlert(this.$t('INTEGRATION_SETTINGS.OPEN_AI.GENERATE_ERROR')); } finally { diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue index 83c40e027..c646b9b6f 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue @@ -9,7 +9,7 @@ }" @mouseenter="onCardHover" @mouseleave="onCardLeave" - @click="cardClick(chat)" + @click="onCardClick" @contextmenu="openContextMenu($event)" >