Skip to content

Commit

Permalink
Merge branch 'staging' into master-staging
Browse files Browse the repository at this point in the history
  • Loading branch information
jderecho committed May 14, 2024
2 parents 5aff293 + 4d2c808 commit 6df35a3
Show file tree
Hide file tree
Showing 49 changed files with 1,205 additions and 160 deletions.
4 changes: 3 additions & 1 deletion app/builders/csat_surveys/response_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ def csat_template_question
end

def update_message_content_attributes
return unless (attrs = message.content_attributes.dig(:submitted_values)).present?
return if (attrs = message.content_attributes[:submitted_values]).blank?

attrs['csat_template_question_id'] = csat_template_question&.id
# rubocop:disable Rails/SkipsModelValidations
message.update_column(:content_attributes, attrs)
# rubocop:enable Rails/SkipsModelValidations
end
end
46 changes: 46 additions & 0 deletions app/builders/smart_action_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class SmartActionBuilder
attr_accessor :errors

def initialize(conversation, params)
@conversation = conversation
@params = params
@errors = []
end

def perform
validate_params
return if @errors.present?

build_smart_action
rescue StandardError => e
@errors << e.message
nil
end

private

def validate_params
return if @params.present?

@errors << 'Missing parameters'
end

def build_smart_action
@smart_action = @conversation.smart_actions.create(smart_action_params)
end

def smart_action_params
@params.permit(
:name,
:label,
:description,
:event,
:intent_type,
:message_id,
:to,
:from,
:link,
:content
)
end
end
4 changes: 2 additions & 2 deletions app/controllers/api/v1/accounts/contacts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
RESULTS_PER_PAGE = 15

before_action :check_authorization
before_action :set_current_page, only: [:index, :active, :search, :filter]
before_action :set_current_page, only: [:index, :active, :search, :filter, :phone_search, :email_search]
before_action :fetch_contact, only: [:show, :update, :destroy, :avatar, :contactable_inboxes, :destroy_custom_attributes]
before_action :set_include_contact_inboxes, only: [:index, :search, :filter]
before_action :set_include_contact_inboxes, only: [:index, :search, :filter, :phone_search, :email_search]

def index
@contacts_count = resolved_contacts.count
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Api::V1::Accounts::Conversations::SmartActionsController < Api::V1::Accounts::Conversations::BaseController
def index
@smart_actions = @conversation.smart_actions
end

def create
builder = SmartActionBuilder.new(@conversation, params)
@smart_action = builder.perform

render json: {
success: @smart_action.present?,
message: builder.errors.present? ? builder.errors.join(', ') : 'Successfully created'
}
end

def event_data
# todo move to service action
case params[:event]
when 'ask_copilot'
event = @conversation.smart_actions.ask_copilot.last
render json: event.present? ? event.event_data : {}
else
render json: {success: false}
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def pending_to_open_by_bot?
end

def should_assign_conversation?
@conversation.status == 'open' && Current.user.is_a?(User) && Current.user&.agent?
(@conversation.status == 'open' || @conversation.assignee.blank?) && Current.user.is_a?(User) && Current.user&.agent?
end

def toggle_priority
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/v1/widget/conversations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def destroy_custom_attributes
end

def total_csat_questions
render json: { total: inbox.csat_template.questions_count }
render json: { total: inbox.csat_template&.questions_count }
end

def csat_template_status
Expand Down
5 changes: 2 additions & 3 deletions app/controllers/public/api/v1/csat_survey_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Public::Api::V1::CsatSurveyController < PublicController
before_action :set_conversation
before_action :set_message
before_action :message

def show; end

Expand All @@ -18,9 +18,8 @@ def set_conversation
@conversation = Conversation.find_by!(uuid: params[:id])
end

def set_message
def message
@message = @conversation.messages.find_by(id: message_id) if message_id.present?

@message ||= @conversation.messages.find_by!(content_type: 'input_csat')
end

Expand Down
24 changes: 24 additions & 0 deletions app/javascript/dashboard/api/inbox/smart_action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* eslint no-console: 0 */
/* global axios */
import ApiClient from '../ApiClient';
import { SMART_ACTION_EVENTS } from 'shared/constants/smartActionEvents';

class SmartActionApi extends ApiClient {
constructor() {
super('conversations', { accountScoped: true });
}

getSmartActions(conversationId) {
return axios.get(`${this.url}/${conversationId}/smart_actions`);
}

askCopilot(conversationId) {
return axios.get(`${this.url}/${conversationId}/smart_actions/event_data`, {
params: {
event: SMART_ACTION_EVENTS.ASK_COPILOT,
},
});
}
}

export default new SmartActionApi();
49 changes: 47 additions & 2 deletions app/javascript/dashboard/components/widgets/WootWriter/Editor.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<template>
<div ref="editorRoot" class="relative editor-root">
<div
ref="editorRoot"
class="relative editor-root"
:class="{ 'copilot-enabled': showCopilot }"
>
<tag-agents
v-if="showUserMentions && isPrivate"
:search-key="mentionSearchKey"
Expand All @@ -15,6 +19,11 @@
:search-key="variableSearchTerm"
@click="insertVariable"
/>
<copilot
:show-loading-smart-response-icon="loadingSmartResponse"
:show-copilot="showCopilot"
@ask-copilot="askCopilot"
/>
<input
ref="imageUpload"
type="file"
Expand Down Expand Up @@ -62,6 +71,7 @@ import { BUS_EVENTS } from 'shared/constants/busEvents';
import TagAgents from '../conversation/TagAgents.vue';
import CannedResponse from '../conversation/CannedResponse.vue';
import Copilot from '../conversation/Copilot.vue';
import VariableList from '../conversation/VariableList.vue';
import {
appendSignature,
Expand Down Expand Up @@ -120,7 +130,7 @@ const createState = (
export default {
name: 'WootMessageEditor',
components: { TagAgents, CannedResponse, VariableList },
components: { TagAgents, CannedResponse, VariableList, Copilot },
mixins: [eventListenerMixins, uiSettingsMixin, alertMixin],
props: {
value: { type: String, default: '' },
Expand All @@ -140,6 +150,8 @@ export default {
allowSignature: { type: Boolean, default: false },
channelType: { type: String, default: '' },
showImageResizeToolbar: { type: Boolean, default: false }, // A kill switch to show or hide the image toolbar
enableSmartActions: { type: Boolean, default: false },
enableCopilot: { type: Boolean, default: false },
},
data() {
return {
Expand All @@ -165,6 +177,7 @@ export default {
toolbarPosition: { top: 0, left: 0 },
sizes: MESSAGE_EDITOR_IMAGE_RESIZES,
selectedImageNode: null,
loadingSmartResponse: false,
};
},
computed: {
Expand Down Expand Up @@ -285,6 +298,9 @@ export default {
return false;
},
showCopilot() {
return this.enableCopilot && !this.isPrivate;
},
},
watch: {
showUserMentions(updatedValue) {
Expand All @@ -309,6 +325,9 @@ export default {
isPrivate() {
this.reloadState(this.value);
},
enableCopilot() {
this.reloadState(this.value);
},
updateSelectionWith(newValue, oldValue) {
if (!this.editorView) {
return null;
Expand Down Expand Up @@ -671,6 +690,7 @@ export default {
onKeyup() {
this.typingIndicator.start();
this.updateImgToolbarOnDelete();
this.checkCoPilot();
},
onKeydown(event) {
if (this.isEnterToSendEnabled()) {
Expand Down Expand Up @@ -700,6 +720,22 @@ export default {
scrollCursorIntoView(this.editorView);
});
},
askCopilot() {
this.$emit('ask-copilot');
},
checkCoPilot() {
if (!this.enableCopilot) {
this.loadingSmartResponse = false;
return;
}
if (this.value === ' ') {
this.loadingSmartResponse = true;
this.askCopilot();
} else {
this.loadingSmartResponse = false;
}
},
},
};
</script>
Expand Down Expand Up @@ -795,4 +831,13 @@ export default {
.editor-warning__message {
@apply text-red-400 dark:text-red-400 font-normal text-sm pt-1 pb-0 px-0;
}
.copilot {
position: absolute;
bottom: 45px;
display: flex;
margin-right: 5px;
}
.copilot-enabled .ProseMirror.ProseMirror-woot-style {
margin-left: 125px;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div class="copilot">
<woot-button
v-if="showCopilot"
color-scheme="primary"
icon="star-glitters"
size="tiny"
@click="askCopilot"
>
Ask Copilot
</woot-button>
<fluent-icon
v-if="showLoadingSmartResponseIcon"
icon="star-glitters"
class="ml-2 mt-1"
size="12"
/>
</div>
</template>

<script>
export default {
props: {
showCopilot: { type: Boolean, default: false },
showLoadingSmartResponseIcon: { type: Boolean, default: false },
},
methods: {
askCopilot() {
this.$emit('ask-copilot');
},
},
};
</script>
Loading

0 comments on commit 6df35a3

Please sign in to comment.