diff --git a/app/javascript/dashboard/components/widgets/WootWriter/Editor.vue b/app/javascript/dashboard/components/widgets/WootWriter/Editor.vue index 8248c0003..b2875bc18 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/Editor.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/Editor.vue @@ -86,6 +86,7 @@ const props = defineProps({ // are triggered except when this flag is true allowSignature: { type: Boolean, default: false }, channelType: { type: String, default: '' }, + forceSignature: { type: Boolean, default: false }, medium: { type: String, default: '' }, showImageResizeToolbar: { type: Boolean, default: false }, // A kill switch to show or hide the image toolbar focusOnMount: { type: Boolean, default: true }, @@ -304,6 +305,10 @@ const plugins = computed(() => { const sendWithSignature = computed(() => { // this is considered the source of truth, we watch this property // on change, we toggle the signature in the editor + if (props.forceSignature && props.allowSignature && !props.isPrivate) { + return true; + } + if (props.allowSignature && !props.isPrivate && props.channelType) { return fetchSignatureFlagFromUISettings(props.channelType); } diff --git a/app/javascript/react-components/doc.md b/app/javascript/react-components/doc.md index 334a61573..8fe6a20b4 100644 --- a/app/javascript/react-components/doc.md +++ b/app/javascript/react-components/doc.md @@ -134,6 +134,7 @@ interface ChatwootProviderProps { pubsubToken?: string; // PubSub authentication token disableUpload?: boolean; // Disable file attachments disableEditor?: boolean; // Disable reply editor + signature?: string; // Custom message signature (overrides user profile signature) } ``` @@ -147,6 +148,7 @@ window.__PUBSUB_TOKEN__ // Real-time auth token window.__WOOT_CONVERSATION_ID__ // Active conversation window.__EDITOR_DISABLE_UPLOAD__ // Upload flag window.__DISABLE_EDITOR__ // Editor flag +window.__WOOT_CUSTOM_SIGNATURE__ // Custom signature (overrides profile) window.__WOOT_ISOLATED_SHELL__ // Disables audio notifications window.__CHATWOOT_STORE__ // Vuex store reference window.WootConstants // Global constants diff --git a/app/javascript/react-components/src/components/ChatwootProvider.jsx b/app/javascript/react-components/src/components/ChatwootProvider.jsx index 90600889f..c28efbed2 100644 --- a/app/javascript/react-components/src/components/ChatwootProvider.jsx +++ b/app/javascript/react-components/src/components/ChatwootProvider.jsx @@ -18,6 +18,7 @@ export const ChatwootProvider = ({ conversationId, disableUpload, disableEditor, + signature, children, }) => { const isInitialized = useRef(false); @@ -41,6 +42,7 @@ export const ChatwootProvider = ({ disableUpload: disableUpload || false, websocketURL: websocketURL, pubsubToken: pubsubToken, + signature: signature || '', }; function initializeChatwootGlobals() { @@ -57,6 +59,7 @@ export const ChatwootProvider = ({ window.__WOOT_CONVERSATION_ID__ = config.conversationId; window.__EDITOR_DISABLE_UPLOAD__ = config.disableUpload; window.__DISABLE_EDITOR__ = config.disableEditor; + window.__WOOT_CUSTOM_SIGNATURE__ = config.signature || undefined; window.__WOOT_ISOLATED_SHELL__ = true; /* eslint-enable no-underscore-dangle */ @@ -87,6 +90,16 @@ export const ChatwootProvider = ({ config.pubsubToken, ]); + // Keep signature global in sync when the prop changes after init + useEffect(() => { + const value = signature || undefined; + // eslint-disable-next-line no-underscore-dangle + window.__WOOT_CUSTOM_SIGNATURE__ = value; + window.dispatchEvent( + new CustomEvent('chatwoot:signature-change', { detail: value || '' }) + ); + }, [signature]); + if (!initializationComplete) { return null; } diff --git a/app/javascript/ui/LiteReplyBox.vue b/app/javascript/ui/LiteReplyBox.vue index 2333b910c..5ca37d48b 100644 --- a/app/javascript/ui/LiteReplyBox.vue +++ b/app/javascript/ui/LiteReplyBox.vue @@ -38,6 +38,8 @@ export default { hasSlashCommand: false, doAutoSaveDraft: () => {}, updateEditorSelectionWith: '', + // eslint-disable-next-line no-underscore-dangle + customSignatureValue: window.__WOOT_CUSTOM_SIGNATURE__ || '', }; }, computed: { @@ -158,15 +160,26 @@ export default { editorStateId() { return `draft-${this.conversationId}-${this.replyType}`; }, + customSignature() { + return this.customSignatureValue; + }, + hasCustomSignature() { + return !!this.customSignature; + }, signatureToApply() { + const signature = this.customSignature || this.messageSignature; return this.showRichContentEditor - ? this.messageSignature - : extractTextFromMarkdown(this.messageSignature); + ? signature + : extractTextFromMarkdown(signature); }, }, mounted() { document.addEventListener('paste', this.onPaste); document.addEventListener('keydown', this.handleKeyEvents); + window.addEventListener( + 'chatwoot:signature-change', + this.onSignatureChange + ); // // A hacky fix to solve the drag and drop // // Is showing on top of new conversation modal drag and drop @@ -180,8 +193,15 @@ export default { unmounted() { document.removeEventListener('paste', this.onPaste); document.removeEventListener('keydown', this.handleKeyEvents); + window.removeEventListener( + 'chatwoot:signature-change', + this.onSignatureChange + ); }, methods: { + onSignatureChange(event) { + this.customSignatureValue = event.detail || ''; + }, getElementToBind() { return this.replyEditor; }, @@ -404,6 +424,7 @@ export default { :variables="messageVariables" :signature="signatureToApply" allow-signature + :force-signature="hasCustomSignature" :channel-type="channelType" @typing-off="onTypingOff" @typing-on="onTypingOn"