Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions app/controllers/api/v1/profile/inbox_signatures_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class Api::V1::Profile::InboxSignaturesController < Api::BaseController
before_action :set_user
before_action :set_inbox_signature, only: %i[show update destroy]

def index
@inbox_signatures = if params[:account_id].present?
account_inbox_ids = Account.find(params[:account_id]).inbox_ids
@user.inbox_signatures.where(inbox_id: account_inbox_ids)
else
@user.inbox_signatures
end
end

def show
head :not_found and return unless @inbox_signature
end

def update
if @inbox_signature
@inbox_signature.update!(inbox_signature_params)
else
@inbox_signature = @user.inbox_signatures.create!(
inbox_signature_params.merge(inbox_id: params[:inbox_id])
)
end
end

def destroy
@inbox_signature&.destroy!
head :no_content
end

private

def set_user
@user = current_user
end

def set_inbox_signature
@inbox_signature = @user.inbox_signatures.find_by(inbox_id: params[:inbox_id])
end

def inbox_signature_params
params.require(:inbox_signature).permit(:message_signature, :signature_position, :signature_separator)
end
end
25 changes: 25 additions & 0 deletions app/javascript/dashboard/api/inboxSignatures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* global axios */

const API_BASE = '/api/v1/profile/inbox_signatures';

export default {
getAll(accountId) {
return axios.get(API_BASE, {
params: { account_id: accountId },
});
},

get(inboxId) {
return axios.get(`${API_BASE}/${inboxId}`);
},

upsert(inboxId, params) {
return axios.put(`${API_BASE}/${inboxId}`, {
inbox_signature: params,
});
},

delete(inboxId) {
return axios.delete(`${API_BASE}/${inboxId}`);
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useStore, useMapGetter } from 'dashboard/composables/store';
import { useI18n } from 'vue-i18n';
import { useWindowSize } from '@vueuse/core';
import { useUISettings } from 'dashboard/composables/useUISettings';
import { useInboxSignatures } from 'dashboard/composables/useInboxSignatures';
import { vOnClickOutside } from '@vueuse/components';
import { useAlert } from 'dashboard/composables';
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
Expand Down Expand Up @@ -84,6 +85,24 @@ const uiFlags = useMapGetter('contactConversations/getUIFlags');
const messageSignature = useMapGetter('getMessageSignature');
const inboxesList = useMapGetter('inboxes/getInboxes');

const {
fetchInboxSignatures,
getSignatureForInbox,
getSignatureSettingsForInbox,
} = useInboxSignatures();

fetchInboxSignatures();

const resolvedMessageSignature = computed(() => {
if (!targetInbox.value?.id) return messageSignature.value;
return getSignatureForInbox(targetInbox.value.id);
});

const resolvedSignatureSettings = computed(() => {
if (!targetInbox.value?.id) return null;
return getSignatureSettingsForInbox(targetInbox.value.id);
});

const sendWithSignature = computed(() =>
fetchSignatureFlagFromUISettings(targetInbox.value?.channelType)
);
Expand Down Expand Up @@ -307,8 +326,9 @@ useKeyboardEvents(keyboardEvents);
:is-direct-uploads-enabled="directUploadsEnabled"
:contact-conversations-ui-flags="uiFlags"
:contacts-ui-flags="contactsUiFlags"
:message-signature="messageSignature"
:message-signature="resolvedMessageSignature"
:send-with-signature="sendWithSignature"
:signature-settings="resolvedSignatureSettings"
@search-contacts="onContactSearch"
@reset-contact-search="resetContacts"
@update-selected-contact="handleSelectedContact"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const props = defineProps({
contactsUiFlags: { type: Object, default: null },
messageSignature: { type: String, default: '' },
sendWithSignature: { type: Boolean, default: false },
signatureSettings: { type: Object, default: null },
formState: { type: Object, required: true },
});

Expand Down Expand Up @@ -131,6 +132,7 @@ const newMessagePayload = () => {
directUploadsEnabled: props.isDirectUploadsEnabled,
sendWithSignature: props.sendWithSignature,
messageSignature: props.messageSignature,
signatureSettings: props.signatureSettings,
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,15 @@ export const prepareNewMessagePayload = ({
directUploadsEnabled = false,
sendWithSignature = false,
messageSignature = '',
signatureSettings = null,
}) => {
let finalMessage = message;
if (sendWithSignature && messageSignature) {
const { signature_position, signature_separator } =
currentUser?.ui_settings || {};
const signatureSettings = {
position: signature_position || 'top',
separator: signature_separator || 'blank',
const settings = signatureSettings || {
position: currentUser?.ui_settings?.signature_position || 'top',
separator: currentUser?.ui_settings?.signature_separator || 'blank',
};
finalMessage = appendSignature(
message,
messageSignature,
signatureSettings
);
finalMessage = appendSignature(message, messageSignature, settings);
}

const payload = {
Expand Down
19 changes: 16 additions & 3 deletions app/javascript/dashboard/components/widgets/WootWriter/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ const props = defineProps({
// allowSignature is a kill switch, ensuring no signature methods
// are triggered except when this flag is true
allowSignature: { type: Boolean, default: false },
// Per-inbox overrides; when empty, falls back to currentUser.ui_settings
signaturePositionOverride: { type: String, default: '' },
signatureSeparatorOverride: { type: String, default: '' },
channelType: { type: String, default: '' },
conversationId: { type: Number, default: null },
medium: { type: String, default: '' },
Expand Down Expand Up @@ -322,11 +325,19 @@ const sendWithSignature = computed(() => {
});

const signaturePosition = computed(() => {
return currentUser.value?.ui_settings?.signature_position || 'top';
return (
props.signaturePositionOverride ||
currentUser.value?.ui_settings?.signature_position ||
'top'
);
});

const signatureSeparator = computed(() => {
return currentUser.value?.ui_settings?.signature_separator || 'blank';
return (
props.signatureSeparatorOverride ||
currentUser.value?.ui_settings?.signature_separator ||
'blank'
);
});

const shouldShowSignaturePreview = computed(() => {
Expand Down Expand Up @@ -850,6 +861,7 @@ useEmitter(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, insertContentIntoEditor);
<!-- Signature preview at top -->
<div
v-if="shouldShowSignaturePreview && signaturePosition === 'top'"
v-tooltip="t('CONVERSATION.FOOTER.SIGNATURE_LABEL_TOP_TOOLTIP')"
class="signature-preview signature-preview--top"
>
<div class="signature-label">
Expand All @@ -864,6 +876,7 @@ useEmitter(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, insertContentIntoEditor);
<!-- Signature preview at bottom -->
<div
v-if="shouldShowSignaturePreview && signaturePosition === 'bottom'"
v-tooltip="t('CONVERSATION.FOOTER.SIGNATURE_LABEL_BOTTOM_TOOLTIP')"
class="signature-preview signature-preview--bottom"
>
<div class="signature-label">
Expand Down Expand Up @@ -899,7 +912,7 @@ useEmitter(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, insertContentIntoEditor);
@import '@chatwoot/prosemirror-schema/src/styles/base.scss';

.signature-preview {
@apply px-1 py-1 text-n-slate-10 text-sm pointer-events-none select-none opacity-70;
@apply px-1 py-1 text-n-slate-10 text-sm select-none opacity-70 cursor-default;

&--top {
@apply border-b border-n-weak pb-1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { defineAsyncComponent, useTemplateRef } from 'vue';
import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import { useUISettings } from 'dashboard/composables/useUISettings';
import { useInboxSignatures } from 'dashboard/composables/useInboxSignatures';
import { useTrack } from 'dashboard/composables';
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
Expand Down Expand Up @@ -97,6 +98,15 @@ export default {
fetchQuotedReplyFlagFromUISettings,
} = useUISettings();

const {
fetchInboxSignatures,
getSignatureForInbox,
getSignatureSettingsForInbox,
hasFetched: inboxSignaturesFetched,
} = useInboxSignatures();

fetchInboxSignatures();

const { formatMessage } = useMessageFormatter();

const replyEditor = useTemplateRef('replyEditor');
Expand All @@ -109,6 +119,9 @@ export default {
fetchSignatureFlagFromUISettings,
setQuotedReplyFlagForInbox,
fetchQuotedReplyFlagFromUISettings,
getSignatureForInbox,
getSignatureSettingsForInbox,
inboxSignaturesFetched,
replyEditor,
copilot,
shortcutKey,
Expand Down Expand Up @@ -147,7 +160,6 @@ export default {
computed: {
...mapGetters({
currentChat: 'getSelectedChat',
messageSignature: 'getMessageSignature',
currentUser: 'getCurrentUser',
lastEmail: 'getLastEmailInSelectedChat',
globalConfig: 'globalConfig/get',
Expand Down Expand Up @@ -344,6 +356,9 @@ export default {
isSignatureEnabledForInbox() {
return !this.isPrivate && this.sendWithSignature;
},
messageSignature() {
return this.getSignatureForInbox(this.inboxId);
},
isSignatureAvailable() {
return !!this.messageSignature;
},
Expand Down Expand Up @@ -449,10 +464,10 @@ export default {
);
},
signaturePosition() {
return this.currentUser?.ui_settings?.signature_position || 'top';
return this.getSignatureSettingsForInbox(this.inboxId).position;
},
signatureSeparator() {
return this.currentUser?.ui_settings?.signature_separator || 'blank';
return this.getSignatureSettingsForInbox(this.inboxId).separator;
},
formattedSignature() {
if (!this.messageSignature) return '';
Expand Down Expand Up @@ -703,11 +718,9 @@ export default {
if (!this.sendWithSignature || !this.messageSignature) {
return message;
}
const { signature_position, signature_separator } =
this.currentUser?.ui_settings || {};
const signatureSettings = {
position: signature_position || 'top',
separator: signature_separator || 'blank',
position: this.signaturePosition,
separator: this.signatureSeparator,
};
return appendSignature(message, this.messageSignature, signatureSettings);
},
Expand Down Expand Up @@ -1354,6 +1367,8 @@ export default {
:variables="messageVariables"
:signature="messageSignature"
allow-signature
:signature-position-override="signaturePosition"
:signature-separator-override="signatureSeparator"
:channel-type="channelType"
:medium="inbox.medium"
@typing-off="onTypingOff"
Expand Down
Loading