mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-30 18:47:51 +00:00 
			
		
		
		
	feat: Lets users insert connected portal article into replies [CW-2282] (#8117)
- Lets users insert connected portal articles into replies https://linear.app/chatwoot/issue/CW-2282/list-all-the-top-articles-from-the-connected-help-center https://linear.app/chatwoot/issue/CW-1453/container-view-for-showing-search-input-and-result-items
This commit is contained in:
		 Nithin David Thomas
					Nithin David Thomas
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							b4d20689b7
						
					
				
				
					commit
					39d0748a5b
				
			| @@ -109,6 +109,16 @@ | |||||||
|           </h4> |           </h4> | ||||||
|         </div> |         </div> | ||||||
|       </transition> |       </transition> | ||||||
|  |       <woot-button | ||||||
|  |         v-if="enableInsertArticleInReply" | ||||||
|  |         v-tooltip.top-end="$t('HELP_CENTER.ARTICLE_SEARCH.OPEN_ARTICLE_SEARCH')" | ||||||
|  |         icon="document-text-link" | ||||||
|  |         color-scheme="secondary" | ||||||
|  |         variant="smooth" | ||||||
|  |         size="small" | ||||||
|  |         :title="$t('HELP_CENTER.ARTICLE_SEARCH.OPEN_ARTICLE_SEARCH')" | ||||||
|  |         @click="toggleInsertArticle" | ||||||
|  |       /> | ||||||
|     </div> |     </div> | ||||||
|     <div class="right-wrap"> |     <div class="right-wrap"> | ||||||
|       <woot-button |       <woot-button | ||||||
| @@ -233,6 +243,10 @@ export default { | |||||||
|       type: Boolean, |       type: Boolean, | ||||||
|       default: false, |       default: false, | ||||||
|     }, |     }, | ||||||
|  |     portalSlug: { | ||||||
|  |       type: String, | ||||||
|  |       required: true, | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   computed: { |   computed: { | ||||||
|     ...mapGetters({ |     ...mapGetters({ | ||||||
| @@ -307,6 +321,13 @@ export default { | |||||||
|         ? this.$t('CONVERSATION.FOOTER.DISABLE_SIGN_TOOLTIP') |         ? this.$t('CONVERSATION.FOOTER.DISABLE_SIGN_TOOLTIP') | ||||||
|         : this.$t('CONVERSATION.FOOTER.ENABLE_SIGN_TOOLTIP'); |         : this.$t('CONVERSATION.FOOTER.ENABLE_SIGN_TOOLTIP'); | ||||||
|     }, |     }, | ||||||
|  |     enableInsertArticleInReply() { | ||||||
|  |       const isFeatEnabled = this.isFeatureEnabledonAccount( | ||||||
|  |         this.accountId, | ||||||
|  |         FEATURE_FLAGS.INSERT_ARTICLE_IN_REPLY | ||||||
|  |       ); | ||||||
|  |       return isFeatEnabled && this.portalSlug; | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   mounted() { |   mounted() { | ||||||
|     ActiveStorage.start(); |     ActiveStorage.start(); | ||||||
| @@ -325,6 +346,9 @@ export default { | |||||||
|     replaceText(text) { |     replaceText(text) { | ||||||
|       this.$emit('replace-text', text); |       this.$emit('replace-text', text); | ||||||
|     }, |     }, | ||||||
|  |     toggleInsertArticle() { | ||||||
|  |       this.$emit('toggle-insert-article'); | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|   | |||||||
| @@ -18,6 +18,12 @@ | |||||||
|       :popout-reply-box="popoutReplyBox" |       :popout-reply-box="popoutReplyBox" | ||||||
|       @click="$emit('click')" |       @click="$emit('click')" | ||||||
|     /> |     /> | ||||||
|  |     <article-search-popover | ||||||
|  |       v-if="showArticleSearchPopover && connectedPortalSlug" | ||||||
|  |       :selected-portal-slug="connectedPortalSlug" | ||||||
|  |       @insert="handleInsert" | ||||||
|  |       @close="onSearchPopoverClose" | ||||||
|  |     /> | ||||||
|     <div class="reply-box__top"> |     <div class="reply-box__top"> | ||||||
|       <reply-to-message |       <reply-to-message | ||||||
|         v-if="shouldShowReplyToMessage" |         v-if="shouldShowReplyToMessage" | ||||||
| @@ -35,7 +41,7 @@ | |||||||
|         v-if="showEmojiPicker" |         v-if="showEmojiPicker" | ||||||
|         v-on-clickaway="hideEmojiPicker" |         v-on-clickaway="hideEmojiPicker" | ||||||
|         :class="emojiDialogClassOnExpandedLayoutAndRTLView" |         :class="emojiDialogClassOnExpandedLayoutAndRTLView" | ||||||
|         :on-click="emojiOnClick" |         :on-click="addIntoEditor" | ||||||
|       /> |       /> | ||||||
|       <reply-email-head |       <reply-email-head | ||||||
|         v-if="showReplyHead" |         v-if="showReplyHead" | ||||||
| @@ -121,10 +127,12 @@ | |||||||
|       :toggle-audio-recorder="toggleAudioRecorder" |       :toggle-audio-recorder="toggleAudioRecorder" | ||||||
|       :toggle-emoji-picker="toggleEmojiPicker" |       :toggle-emoji-picker="toggleEmojiPicker" | ||||||
|       :message="message" |       :message="message" | ||||||
|  |       :portal-slug="connectedPortalSlug" | ||||||
|       :new-conversation-modal-active="newConversationModalActive" |       :new-conversation-modal-active="newConversationModalActive" | ||||||
|       @selectWhatsappTemplate="openWhatsappTemplateModal" |       @selectWhatsappTemplate="openWhatsappTemplateModal" | ||||||
|       @toggle-editor="toggleRichContentEditor" |       @toggle-editor="toggleRichContentEditor" | ||||||
|       @replace-text="replaceText" |       @replace-text="replaceText" | ||||||
|  |       @toggle-insert-article="toggleInsertArticle" | ||||||
|     /> |     /> | ||||||
|     <whatsapp-templates |     <whatsapp-templates | ||||||
|       :inbox-id="inbox.id" |       :inbox-id="inbox.id" | ||||||
| @@ -154,6 +162,7 @@ import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview.v | |||||||
| import ReplyTopPanel from 'dashboard/components/widgets/WootWriter/ReplyTopPanel.vue'; | import ReplyTopPanel from 'dashboard/components/widgets/WootWriter/ReplyTopPanel.vue'; | ||||||
| import ReplyEmailHead from './ReplyEmailHead.vue'; | import ReplyEmailHead from './ReplyEmailHead.vue'; | ||||||
| import ReplyBottomPanel from 'dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue'; | import ReplyBottomPanel from 'dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue'; | ||||||
|  | import ArticleSearchPopover from 'dashboard/routes/dashboard/helpcenter/components/ArticleSearch/SearchPopover.vue'; | ||||||
| import MessageSignatureMissingAlert from './MessageSignatureMissingAlert'; | import MessageSignatureMissingAlert from './MessageSignatureMissingAlert'; | ||||||
| import Banner from 'dashboard/components/ui/Banner.vue'; | import Banner from 'dashboard/components/ui/Banner.vue'; | ||||||
| import { REPLY_EDITOR_MODES } from 'dashboard/components/widgets/WootWriter/constants'; | import { REPLY_EDITOR_MODES } from 'dashboard/components/widgets/WootWriter/constants'; | ||||||
| @@ -206,6 +215,7 @@ export default { | |||||||
|     Banner, |     Banner, | ||||||
|     WhatsappTemplates, |     WhatsappTemplates, | ||||||
|     MessageSignatureMissingAlert, |     MessageSignatureMissingAlert, | ||||||
|  |     ArticleSearchPopover, | ||||||
|   }, |   }, | ||||||
|   mixins: [ |   mixins: [ | ||||||
|     clickaway, |     clickaway, | ||||||
| @@ -248,6 +258,7 @@ export default { | |||||||
|       showCannedMenu: false, |       showCannedMenu: false, | ||||||
|       showVariablesMenu: false, |       showVariablesMenu: false, | ||||||
|       newConversationModalActive: false, |       newConversationModalActive: false, | ||||||
|  |       showArticleSearchPopover: false, | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|   computed: { |   computed: { | ||||||
| @@ -506,6 +517,11 @@ export default { | |||||||
|         ? this.messageSignature |         ? this.messageSignature | ||||||
|         : extractTextFromMarkdown(this.messageSignature); |         : extractTextFromMarkdown(this.messageSignature); | ||||||
|     }, |     }, | ||||||
|  |     connectedPortalSlug() { | ||||||
|  |       const { help_center: portal = {} } = this.inbox; | ||||||
|  |       const { slug = '' } = portal; | ||||||
|  |       return slug; | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
|     currentChat(conversation) { |     currentChat(conversation) { | ||||||
| @@ -597,6 +613,23 @@ export default { | |||||||
|     ); |     ); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  |     handleInsert(article) { | ||||||
|  |       const { url, title } = article; | ||||||
|  |       if (this.isRichEditorEnabled) { | ||||||
|  |         // Removing empty lines from the title | ||||||
|  |         const lines = title.split('\n'); | ||||||
|  |         const nonEmptyLines = lines.filter(line => line.trim() !== ''); | ||||||
|  |         const filteredMarkdown = nonEmptyLines.join(' '); | ||||||
|  |         bus.$emit( | ||||||
|  |           BUS_EVENTS.INSERT_INTO_RICH_EDITOR, | ||||||
|  |           `[${filteredMarkdown}](${url})` | ||||||
|  |         ); | ||||||
|  |       } else { | ||||||
|  |         this.addIntoEditor( | ||||||
|  |           `${this.$t('CONVERSATION.REPLYBOX.INSERT_READ_MORE')} ${url}` | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     toggleRichContentEditor() { |     toggleRichContentEditor() { | ||||||
|       this.updateUISettings({ |       this.updateUISettings({ | ||||||
|         display_rich_content_editor: !this.showRichContentEditor, |         display_rich_content_editor: !this.showRichContentEditor, | ||||||
| @@ -862,22 +895,22 @@ export default { | |||||||
|     clearEditorSelection() { |     clearEditorSelection() { | ||||||
|       this.updateEditorSelectionWith = ''; |       this.updateEditorSelectionWith = ''; | ||||||
|     }, |     }, | ||||||
|     insertEmoji(emoji, selectionStart, selectionEnd) { |     insertIntoTextEditor(text, selectionStart, selectionEnd) { | ||||||
|       const { message } = this; |       const { message } = this; | ||||||
|       const newMessage = |       const newMessage = | ||||||
|         message.slice(0, selectionStart) + |         message.slice(0, selectionStart) + | ||||||
|         emoji + |         text + | ||||||
|         message.slice(selectionEnd, message.length); |         message.slice(selectionEnd, message.length); | ||||||
|       this.message = newMessage; |       this.message = newMessage; | ||||||
|     }, |     }, | ||||||
|     emojiOnClick(emoji) { |     addIntoEditor(content) { | ||||||
|       if (this.showRichContentEditor) { |       if (this.showRichContentEditor) { | ||||||
|         this.updateEditorSelectionWith = emoji; |         this.updateEditorSelectionWith = content; | ||||||
|         this.onFocus(); |         this.onFocus(); | ||||||
|       } |       } | ||||||
|       if (!this.showRichContentEditor) { |       if (!this.showRichContentEditor) { | ||||||
|         const { selectionStart, selectionEnd } = this.$refs.messageInput.$el; |         const { selectionStart, selectionEnd } = this.$refs.messageInput.$el; | ||||||
|         this.insertEmoji(emoji, selectionStart, selectionEnd); |         this.insertIntoTextEditor(content, selectionStart, selectionEnd); | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     clearMessage() { |     clearMessage() { | ||||||
| @@ -1136,6 +1169,12 @@ export default { | |||||||
|       // When new conversation modal is open |       // When new conversation modal is open | ||||||
|       this.newConversationModalActive = isActive; |       this.newConversationModalActive = isActive; | ||||||
|     }, |     }, | ||||||
|  |     onSearchPopoverClose() { | ||||||
|  |       this.showArticleSearchPopover = false; | ||||||
|  |     }, | ||||||
|  |     toggleInsertArticle() { | ||||||
|  |       this.showArticleSearchPopover = !this.showArticleSearchPopover; | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
| @@ -1154,7 +1193,7 @@ export default { | |||||||
| } | } | ||||||
|  |  | ||||||
| .reply-box { | .reply-box { | ||||||
|   @apply border-t border-slate-50 dark:border-slate-700 bg-white dark:bg-slate-900; |   @apply relative border-t border-slate-50 dark:border-slate-700 bg-white dark:bg-slate-900; | ||||||
|  |  | ||||||
|   &.is-private { |   &.is-private { | ||||||
|     @apply bg-yellow-50 dark:bg-yellow-200; |     @apply bg-yellow-50 dark:bg-yellow-200; | ||||||
|   | |||||||
| @@ -17,4 +17,5 @@ export const FEATURE_FLAGS = { | |||||||
|   VOICE_RECORDER: 'voice_recorder', |   VOICE_RECORDER: 'voice_recorder', | ||||||
|   AUDIT_LOGS: 'audit_logs', |   AUDIT_LOGS: 'audit_logs', | ||||||
|   MESSAGE_REPLY_TO: 'message_reply_to', |   MESSAGE_REPLY_TO: 'message_reply_to', | ||||||
|  |   INSERT_ARTICLE_IN_REPLY: 'insert_article_in_reply', | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -139,6 +139,7 @@ | |||||||
|       "PRIVATE_NOTE": "Private Note", |       "PRIVATE_NOTE": "Private Note", | ||||||
|       "SEND": "Send", |       "SEND": "Send", | ||||||
|       "CREATE": "Add Note", |       "CREATE": "Add Note", | ||||||
|  |       "INSERT_READ_MORE": "Read more", | ||||||
|       "DISMISS_REPLY": "Dismiss reply", |       "DISMISS_REPLY": "Dismiss reply", | ||||||
|       "REPLYING_TO": "Replying to:", |       "REPLYING_TO": "Replying to:", | ||||||
|       "TIP_FORMAT_ICON": "Show rich text editor", |       "TIP_FORMAT_ICON": "Show rich text editor", | ||||||
|   | |||||||
| @@ -76,6 +76,9 @@ | |||||||
|     }, |     }, | ||||||
|     "ARTICLE_SEARCH_RESULT": { |     "ARTICLE_SEARCH_RESULT": { | ||||||
|       "UNCATEGORIZED": "Uncategorized", |       "UNCATEGORIZED": "Uncategorized", | ||||||
|  |       "SEARCH_RESULTS": "Search results for %{query}", | ||||||
|  |       "EMPTY_TEXT": "Search for articles to insert into replies.", | ||||||
|  |       "SEARCH_LOADER": "Searching...", | ||||||
|       "INSERT_ARTICLE": "Insert", |       "INSERT_ARTICLE": "Insert", | ||||||
|       "NO_RESULT": "No articles found", |       "NO_RESULT": "No articles found", | ||||||
|       "COPY_LINK": "Copy article link to clipboard", |       "COPY_LINK": "Copy article link to clipboard", | ||||||
| @@ -426,6 +429,21 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "ARTICLE_SEARCH": { | ||||||
|  |       "TITLE": "Search articles", | ||||||
|  |       "PLACEHOLDER": "Search articles", | ||||||
|  |       "NO_RESULT": "No articles found", | ||||||
|  |       "SEARCHING": "Searching...", | ||||||
|  |       "SEARCH_BUTTON": "Search", | ||||||
|  |       "INSERT_ARTICLE": "Insert link", | ||||||
|  |       "IFRAME_ERROR": "URL is empty or invalid. Unable to display content.", | ||||||
|  |       "OPEN_ARTICLE_SEARCH": "Insert article from Help Center", | ||||||
|  |       "SUCCESS_ARTICLE_INSERTED": "Article inserted successfully", | ||||||
|  |       "PREVIEW_LINK": "Preview article", | ||||||
|  |       "CANCEL": "Close", | ||||||
|  |       "BACK": "Back", | ||||||
|  |       "BACK_RESULTS": "Back to results" | ||||||
|  |     }, | ||||||
|     "UPGRADE_PAGE": { |     "UPGRADE_PAGE": { | ||||||
|       "TITLE": "Help Center", |       "TITLE": "Help Center", | ||||||
|       "DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Upgrade your subscription to enable this feature.", |       "DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Upgrade your subscription to enable this feature.", | ||||||
|   | |||||||
| @@ -1,17 +1,18 @@ | |||||||
| <template> | <template> | ||||||
|   <div |   <button | ||||||
|     class="flex flex-col gap-1 bg-white dark:bg-slate-900 hover:bg-slate-25 hover:dark:bg-slate-800 rounded-md py-1 px-2 w-full group" |     class="flex flex-col gap-1 bg-white dark:bg-slate-900 hover:bg-slate-25 hover:dark:bg-slate-800 rounded-md py-1 px-2 w-full group border border-transparent border-solid focus:outline-none focus:bg-slate-25 focus:border-slate-500 dark:focus:border-slate-400 dark:focus:bg-slate-800 cursor-pointer" | ||||||
|  |     @click="handlePreview" | ||||||
|   > |   > | ||||||
|     <button @click="handlePreview"> |     <h4 | ||||||
|       <h4 |       class="text-block-title text-left mb-0 text-slate-900 dark:text-slate-25 px-1 -mx-1 rounded-sm width-auto hover:underline group-hover:underline" | ||||||
|         class="text-block-title text-left mb-0 text-slate-900 dark:text-slate-25 px-1 -mx-1 rounded-sm hover:underline cursor-pointer width-auto" |     > | ||||||
|       > |       {{ title }} | ||||||
|         {{ title }} |     </h4> | ||||||
|       </h4> |  | ||||||
|     </button> |  | ||||||
|  |  | ||||||
|     <div class="flex content-between items-center gap-0.5 w-full"> |     <div class="flex content-between items-center gap-0.5 w-full"> | ||||||
|       <p class="text-sm text-slate-600 dark:text-slate-300 mb-0 w-full"> |       <p | ||||||
|  |         class="text-sm text-left text-slate-600 dark:text-slate-300 mb-0 w-full" | ||||||
|  |       > | ||||||
|         {{ locale }} |         {{ locale }} | ||||||
|         {{ ` / ` }} |         {{ ` / ` }} | ||||||
|         {{ category || $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.UNCATEGORIZED') }} |         {{ category || $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.UNCATEGORIZED') }} | ||||||
| @@ -26,26 +27,6 @@ | |||||||
|           class="invisible group-hover:visible" |           class="invisible group-hover:visible" | ||||||
|           @click="handleCopy" |           @click="handleCopy" | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|         <a |  | ||||||
|           :href="url" |  | ||||||
|           class="button hollow button--only-icon tiny secondary invisible group-hover:visible" |  | ||||||
|           rel="noopener noreferrer nofollow" |  | ||||||
|           target="_blank" |  | ||||||
|           :title="$t('HELP_CENTER.ARTICLE_SEARCH_RESULT.OPEN_LINK')" |  | ||||||
|         > |  | ||||||
|           <fluent-icon size="12" icon="arrow-up-right" /> |  | ||||||
|           <span class="show-for-sr">{{ url }}</span> |  | ||||||
|         </a> |  | ||||||
|         <woot-button |  | ||||||
|           variant="hollow" |  | ||||||
|           color-scheme="secondary" |  | ||||||
|           size="tiny" |  | ||||||
|           icon="preview-link" |  | ||||||
|           class="invisible group-hover:visible" |  | ||||||
|           :title="$t('HELP_CENTER.ARTICLE_SEARCH_RESULT.PREVIEW_LINK')" |  | ||||||
|           @click="handlePreview" |  | ||||||
|         /> |  | ||||||
|         <woot-button |         <woot-button | ||||||
|           class="insert-button" |           class="insert-button" | ||||||
|           variant="smooth" |           variant="smooth" | ||||||
| @@ -57,14 +38,16 @@ | |||||||
|         </woot-button> |         </woot-button> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </button> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import { copyTextToClipboard } from 'shared/helpers/clipboard'; | import { copyTextToClipboard } from 'shared/helpers/clipboard'; | ||||||
|  | import alertMixin from 'shared/mixins/alertMixin'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'ArticleSearchResultItem', |   name: 'ArticleSearchResultItem', | ||||||
|  |   mixins: [alertMixin], | ||||||
|   props: { |   props: { | ||||||
|     id: { |     id: { | ||||||
|       type: Number, |       type: Number, | ||||||
| @@ -92,13 +75,16 @@ export default { | |||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     handleInsert() { |     handleInsert(e) { | ||||||
|  |       e.stopPropagation(); | ||||||
|       this.$emit('insert', this.id); |       this.$emit('insert', this.id); | ||||||
|     }, |     }, | ||||||
|     handlePreview() { |     handlePreview(e) { | ||||||
|  |       e.stopPropagation(); | ||||||
|       this.$emit('preview', this.id); |       this.$emit('preview', this.id); | ||||||
|     }, |     }, | ||||||
|     async handleCopy() { |     async handleCopy(e) { | ||||||
|  |       e.stopPropagation(); | ||||||
|       await copyTextToClipboard(this.url); |       await copyTextToClipboard(this.url); | ||||||
|       this.showAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL')); |       this.showAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL')); | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -10,8 +10,10 @@ | |||||||
|         {{ $t('HELP_CENTER.ARTICLE_SEARCH.BACK_RESULTS') }} |         {{ $t('HELP_CENTER.ARTICLE_SEARCH.BACK_RESULTS') }} | ||||||
|       </woot-button> |       </woot-button> | ||||||
|     </div> |     </div> | ||||||
|     <div class="w-full h-full overflow-auto min-h-0"> |     <div class="-ml-4 h-full overflow-y-auto"> | ||||||
|       <iframe-loader :url="url" /> |       <div class="w-full h-full min-h-0"> | ||||||
|  |         <iframe-loader :url="url" /> | ||||||
|  |       </div> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <div class="flex justify-end gap-2 py-2"> |     <div class="flex justify-end gap-2 py-2"> | ||||||
| @@ -41,7 +43,7 @@ | |||||||
| import IframeLoader from 'shared/components/IframeLoader.vue'; | import IframeLoader from 'shared/components/IframeLoader.vue'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'ChatwootSearch', |   name: 'ArticleView', | ||||||
|   components: { |   components: { | ||||||
|     IframeLoader, |     IframeLoader, | ||||||
|   }, |   }, | ||||||
| @@ -52,10 +54,12 @@ export default { | |||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     onBack() { |     onBack(e) { | ||||||
|  |       e.stopPropagation(); | ||||||
|       this.$emit('back'); |       this.$emit('back'); | ||||||
|     }, |     }, | ||||||
|     onInsert() { |     onInsert(e) { | ||||||
|  |       e.stopPropagation(); | ||||||
|       this.$emit('insert'); |       this.$emit('insert'); | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -18,10 +18,13 @@ | |||||||
|         <fluent-icon icon="search" class="" size="16" /> |         <fluent-icon icon="search" class="" size="16" /> | ||||||
|       </div> |       </div> | ||||||
|       <input |       <input | ||||||
|  |         ref="searchInput" | ||||||
|         type="text" |         type="text" | ||||||
|         :placeholder="$t('HELP_CENTER.ARTICLE_SEARCH.PLACEHOLDER')" |         :placeholder="$t('HELP_CENTER.ARTICLE_SEARCH.PLACEHOLDER')" | ||||||
|         class="block w-full pl-8 h-8 text-sm dark:bg-slate-700 bg-slate-25 rounded-md leading-8 py-1 text-slate-700 shadow-sm ring-2 ring-transparent ring-slate-300 border border-solid border-slate-300 placeholder:text-slate-400 focus:border-woot-600 focus:ring-2 focus:ring-woot-100 mb-0 focus:bg-slate-25 dark:focus:bg-slate-700" |         class="block w-full pl-8 h-8 text-sm dark:bg-slate-700 bg-slate-25 rounded-md leading-8 py-1 text-slate-700 shadow-sm ring-2 ring-transparent ring-slate-300 border border-solid border-slate-300 placeholder:text-slate-400 focus:border-woot-600 focus:ring-woot-200 mb-0 focus:bg-slate-25 dark:focus:bg-slate-700 dark:focus:ring-woot-700" | ||||||
|         :value="searchQuery" |         :value="searchQuery" | ||||||
|  |         @focus="onFocus" | ||||||
|  |         @blur="onBlur" | ||||||
|         @input="onInput" |         @input="onInput" | ||||||
|       /> |       /> | ||||||
|     </div> |     </div> | ||||||
| @@ -29,8 +32,15 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
|  | import eventListenerMixins from 'shared/mixins/eventListenerMixins'; | ||||||
|  | import { | ||||||
|  |   buildHotKeys, | ||||||
|  |   isActiveElementTypeable, | ||||||
|  | } from 'shared/helpers/KeyboardHelpers'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'ChatwootSearch', |   name: 'ChatwootSearch', | ||||||
|  |   mixins: [eventListenerMixins], | ||||||
|   props: { |   props: { | ||||||
|     title: { |     title: { | ||||||
|       type: String, |       type: String, | ||||||
| @@ -40,8 +50,12 @@ export default { | |||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       searchQuery: '', |       searchQuery: '', | ||||||
|  |       isInputFocused: false, | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|  |   mounted() { | ||||||
|  |     this.$refs.searchInput.focus(); | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     onInput(e) { |     onInput(e) { | ||||||
|       this.$emit('search', e.target.value); |       this.$emit('search', e.target.value); | ||||||
| @@ -49,6 +63,20 @@ export default { | |||||||
|     onClose() { |     onClose() { | ||||||
|       this.$emit('close'); |       this.$emit('close'); | ||||||
|     }, |     }, | ||||||
|  |     onFocus() { | ||||||
|  |       this.isInputFocused = true; | ||||||
|  |     }, | ||||||
|  |     onBlur() { | ||||||
|  |       this.isInputFocused = false; | ||||||
|  |     }, | ||||||
|  |     handleKeyEvents(e) { | ||||||
|  |       const keyPattern = buildHotKeys(e); | ||||||
|  |  | ||||||
|  |       if (keyPattern === '/' && !isActiveElementTypeable(e)) { | ||||||
|  |         e.preventDefault(); | ||||||
|  |         this.$refs.searchInput.focus(); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|   | |||||||
| @@ -0,0 +1,169 @@ | |||||||
|  | <template> | ||||||
|  |   <div | ||||||
|  |     class="fixed flex items-center justify-center w-screen h-screen bg-white/70 top-0 left-0 z-50" | ||||||
|  |   > | ||||||
|  |     <div | ||||||
|  |       v-on-clickaway="onClose" | ||||||
|  |       class="flex flex-col px-4 pb-4 rounded-md shadow-md border border-solid border-slate-50 dark:border-slate-800 bg-white dark:bg-slate-900 z-[1000] max-w-[720px] md:w-[20rem] lg:w-[24rem] xl:w-[28rem] 2xl:w-[32rem] h-[calc(100vh-20rem)] max-h-[40rem]" | ||||||
|  |     > | ||||||
|  |       <search-header | ||||||
|  |         :title="$t('HELP_CENTER.ARTICLE_SEARCH.TITLE')" | ||||||
|  |         class="w-full sticky top-0 bg-[inherit]" | ||||||
|  |         @close="onClose" | ||||||
|  |         @search="onSearch" | ||||||
|  |       /> | ||||||
|  |  | ||||||
|  |       <article-view | ||||||
|  |         v-if="activeId" | ||||||
|  |         :url="articleViewerUrl" | ||||||
|  |         @back="onBack" | ||||||
|  |         @insert="onInsert" | ||||||
|  |       /> | ||||||
|  |       <search-results | ||||||
|  |         v-else | ||||||
|  |         :search-query="searchQuery" | ||||||
|  |         :is-loading="isLoading" | ||||||
|  |         :portal-slug="selectedPortalSlug" | ||||||
|  |         :articles="searchResultsWithUrl" | ||||||
|  |         @preview="handlePreview" | ||||||
|  |         @insert="onInsert" | ||||||
|  |       /> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import { debounce } from '@chatwoot/utils'; | ||||||
|  | import { mixin as clickaway } from 'vue-clickaway'; | ||||||
|  | import { | ||||||
|  |   isEscape, | ||||||
|  |   isActiveElementTypeable, | ||||||
|  | } from 'shared/helpers/KeyboardHelpers'; | ||||||
|  |  | ||||||
|  | import SearchHeader from './Header.vue'; | ||||||
|  | import SearchResults from './SearchResults.vue'; | ||||||
|  | import ArticleView from './ArticleView.vue'; | ||||||
|  | import ArticlesAPI from 'dashboard/api/helpCenter/articles'; | ||||||
|  | import { buildPortalArticleURL } from 'dashboard/helper/portalHelper'; | ||||||
|  | import portalMixin from '../../mixins/portalMixin'; | ||||||
|  | import alertMixin from 'shared/mixins/alertMixin'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: 'ArticleSearchPopover', | ||||||
|  |   components: { | ||||||
|  |     SearchHeader, | ||||||
|  |     SearchResults, | ||||||
|  |     ArticleView, | ||||||
|  |   }, | ||||||
|  |   mixins: [clickaway, portalMixin, alertMixin], | ||||||
|  |   props: { | ||||||
|  |     selectedPortalSlug: { | ||||||
|  |       type: String, | ||||||
|  |       required: true, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       searchQuery: '', | ||||||
|  |       isLoading: false, | ||||||
|  |       searchResults: [], | ||||||
|  |       activeId: '', | ||||||
|  |       debounceSearch: () => {}, | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   computed: { | ||||||
|  |     articleViewerUrl() { | ||||||
|  |       const article = this.activeArticle(this.activeId); | ||||||
|  |       if (!article) return ''; | ||||||
|  |       const isDark = document.body.classList.contains('dark'); | ||||||
|  |  | ||||||
|  |       const url = new URL(article.url); | ||||||
|  |       url.searchParams.set('show_plain_layout', 'true'); | ||||||
|  |  | ||||||
|  |       if (isDark) { | ||||||
|  |         url.searchParams.set('theme', 'dark'); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       return `${url}`; | ||||||
|  |     }, | ||||||
|  |     searchResultsWithUrl() { | ||||||
|  |       return this.searchResults.map(article => ({ | ||||||
|  |         ...article, | ||||||
|  |         localeName: this.localeName(article.category.locale || 'en'), | ||||||
|  |         url: this.generateArticleUrl(article), | ||||||
|  |       })); | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   mounted() { | ||||||
|  |     this.fetchArticlesByQuery(this.searchQuery); | ||||||
|  |     this.debounceSearch = debounce(this.fetchArticlesByQuery, 500, false); | ||||||
|  |     document.body.addEventListener('keydown', this.closeOnEsc); | ||||||
|  |   }, | ||||||
|  |   beforeDestroy() { | ||||||
|  |     document.body.removeEventListener('keydown', this.closeOnEsc); | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     generateArticleUrl(article) { | ||||||
|  |       return buildPortalArticleURL( | ||||||
|  |         this.selectedPortalSlug, | ||||||
|  |         '', | ||||||
|  |         '', | ||||||
|  |         article.slug | ||||||
|  |       ); | ||||||
|  |     }, | ||||||
|  |     activeArticle(id) { | ||||||
|  |       return this.searchResultsWithUrl.find(article => article.id === id); | ||||||
|  |     }, | ||||||
|  |     onSearch(query) { | ||||||
|  |       this.searchQuery = query; | ||||||
|  |       this.activeId = ''; | ||||||
|  |       this.debounceSearch(query); | ||||||
|  |     }, | ||||||
|  |     onClose() { | ||||||
|  |       this.$emit('close'); | ||||||
|  |       this.searchQuery = ''; | ||||||
|  |       this.activeId = ''; | ||||||
|  |       this.searchResults = []; | ||||||
|  |     }, | ||||||
|  |     async fetchArticlesByQuery(query) { | ||||||
|  |       try { | ||||||
|  |         const sort = query ? '' : 'views'; | ||||||
|  |         this.isLoading = true; | ||||||
|  |         this.searchResults = []; | ||||||
|  |         const { data } = await ArticlesAPI.searchArticles({ | ||||||
|  |           portalSlug: this.selectedPortalSlug, | ||||||
|  |           query, | ||||||
|  |           sort, | ||||||
|  |         }); | ||||||
|  |         this.searchResults = data.payload; | ||||||
|  |         this.isLoading = true; | ||||||
|  |       } catch (error) { | ||||||
|  |         // Show something wrong message | ||||||
|  |       } finally { | ||||||
|  |         this.isLoading = false; | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     handlePreview(id) { | ||||||
|  |       this.activeId = id; | ||||||
|  |     }, | ||||||
|  |     onBack() { | ||||||
|  |       this.activeId = ''; | ||||||
|  |     }, | ||||||
|  |     onInsert(id) { | ||||||
|  |       const article = this.activeArticle(id || this.activeId); | ||||||
|  |  | ||||||
|  |       this.$emit('insert', article); | ||||||
|  |       this.showAlert( | ||||||
|  |         this.$t('HELP_CENTER.ARTICLE_SEARCH.SUCCESS_ARTICLE_INSERTED') | ||||||
|  |       ); | ||||||
|  |       this.onClose(); | ||||||
|  |     }, | ||||||
|  |     closeOnEsc(e) { | ||||||
|  |       if (isEscape(e) && !isActiveElementTypeable(e)) { | ||||||
|  |         e.preventDefault(); | ||||||
|  |         this.onClose(); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | </script> | ||||||
| @@ -1,8 +1,9 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="flex justify-end gap-1 py-4 bg-white dark:bg-slate-900"> |   <div | ||||||
|  |     class="flex justify-end gap-1 py-4 bg-white dark:bg-slate-900 h-full overflow-y-auto" | ||||||
|  |   > | ||||||
|     <div class="flex flex-col gap-1 w-full"> |     <div class="flex flex-col gap-1 w-full"> | ||||||
|       <div v-if="isLoading" class="empty-state-message"> |       <div v-if="isLoading" class="empty-state-message"> | ||||||
|         <spinner /> |  | ||||||
|         {{ $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.SEARCH_LOADER') }} |         {{ $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.SEARCH_LOADER') }} | ||||||
|       </div> |       </div> | ||||||
|       <div v-else-if="showNoResults" class="empty-state-message"> |       <div v-else-if="showNoResults" class="empty-state-message"> | ||||||
| @@ -17,7 +18,7 @@ | |||||||
|         :body="article.content" |         :body="article.content" | ||||||
|         :url="article.url" |         :url="article.url" | ||||||
|         :category="article.category.name" |         :category="article.category.name" | ||||||
|         :locale="article.category.locale" |         :locale="article.localeName" | ||||||
|         @preview="handlePreview" |         @preview="handlePreview" | ||||||
|         @insert="handleInsert" |         @insert="handleInsert" | ||||||
|       /> |       /> | ||||||
| @@ -26,13 +27,11 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import Spinner from 'shared/components/Spinner.vue'; | import SearchResultItem from './ArticleSearchResultItem.vue'; | ||||||
| import SearchResultItem from 'dashboard/routes/dashboard/helpcenter/components/ArticleSearch/ArticleSearchResultItem.vue'; |  | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'SearchResults', |   name: 'SearchResults', | ||||||
|   components: { |   components: { | ||||||
|     Spinner, |  | ||||||
|     SearchResultItem, |     SearchResultItem, | ||||||
|   }, |   }, | ||||||
|   props: { |   props: { | ||||||
|   | |||||||
| @@ -96,6 +96,7 @@ | |||||||
|   "dismiss-outline": "m4.397 4.554.073-.084a.75.75 0 0 1 .976-.073l.084.073L12 10.939l6.47-6.47a.75.75 0 1 1 1.06 1.061L13.061 12l6.47 6.47a.75.75 0 0 1 .072.976l-.073.084a.75.75 0 0 1-.976.073l-.084-.073L12 13.061l-6.47 6.47a.75.75 0 0 1-1.06-1.061L10.939 12l-6.47-6.47a.75.75 0 0 1-.072-.976l.073-.084-.073.084Z", |   "dismiss-outline": "m4.397 4.554.073-.084a.75.75 0 0 1 .976-.073l.084.073L12 10.939l6.47-6.47a.75.75 0 1 1 1.06 1.061L13.061 12l6.47 6.47a.75.75 0 0 1 .072.976l-.073.084a.75.75 0 0 1-.976.073l-.084-.073L12 13.061l-6.47 6.47a.75.75 0 0 1-1.06-1.061L10.939 12l-6.47-6.47a.75.75 0 0 1-.072-.976l.073-.084-.073.084Z", | ||||||
|   "document-outline": "M18.5 20a.5.5 0 0 1-.5.5H6a.5.5 0 0 1-.5-.5V4a.5.5 0 0 1 .5-.5h6V8a2 2 0 0 0 2 2h4.5v10Zm-5-15.379L17.378 8.5H14a.5.5 0 0 1-.5-.5V4.621Zm5.914 3.793-5.829-5.828c-.026-.026-.058-.046-.085-.07a2.072 2.072 0 0 0-.219-.18c-.04-.027-.086-.045-.128-.068-.071-.04-.141-.084-.216-.116a1.977 1.977 0 0 0-.624-.138C12.266 2.011 12.22 2 12.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9.828a2 2 0 0 0-.586-1.414Z", |   "document-outline": "M18.5 20a.5.5 0 0 1-.5.5H6a.5.5 0 0 1-.5-.5V4a.5.5 0 0 1 .5-.5h6V8a2 2 0 0 0 2 2h4.5v10Zm-5-15.379L17.378 8.5H14a.5.5 0 0 1-.5-.5V4.621Zm5.914 3.793-5.829-5.828c-.026-.026-.058-.046-.085-.07a2.072 2.072 0 0 0-.219-.18c-.04-.027-.086-.045-.128-.068-.071-.04-.141-.084-.216-.116a1.977 1.977 0 0 0-.624-.138C12.266 2.011 12.22 2 12.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9.828a2 2 0 0 0-.586-1.414Z", | ||||||
|   "document-error-outline": "M6 2a2 2 0 0 0-2 2v5.207a5.48 5.48 0 0 1 1-.185V4a1 1 0 0 1 1-1h4v3.5A1.5 1.5 0 0 0 11.5 8H15v8a1 1 0 0 1-1 1h-3.6a5.507 5.507 0 0 1-.657 1H14a2 2 0 0 0 2-2V7.414a1.5 1.5 0 0 0-.44-1.06l-3.914-3.915A1.5 1.5 0 0 0 10.586 2H6Zm8.793 5H11.5a.5.5 0 0 1-.5-.5V3.207L14.793 7ZM10 14.5a4.5 4.5 0 1 1-9 0a4.5 4.5 0 0 1 9 0ZM5.5 12a.5.5 0 0 0-.5.5v2a.5.5 0 0 0 1 0v-2a.5.5 0 0 0-.5-.5Zm0 5.125a.625.625 0 1 0 0-1.25a.625.625 0 0 0 0 1.25Z", |   "document-error-outline": "M6 2a2 2 0 0 0-2 2v5.207a5.48 5.48 0 0 1 1-.185V4a1 1 0 0 1 1-1h4v3.5A1.5 1.5 0 0 0 11.5 8H15v8a1 1 0 0 1-1 1h-3.6a5.507 5.507 0 0 1-.657 1H14a2 2 0 0 0 2-2V7.414a1.5 1.5 0 0 0-.44-1.06l-3.914-3.915A1.5 1.5 0 0 0 10.586 2H6Zm8.793 5H11.5a.5.5 0 0 1-.5-.5V3.207L14.793 7ZM10 14.5a4.5 4.5 0 1 1-9 0a4.5 4.5 0 0 1 9 0ZM5.5 12a.5.5 0 0 0-.5.5v2a.5.5 0 0 0 1 0v-2a.5.5 0 0 0-.5-.5Zm0 5.125a.625.625 0 1 0 0-1.25a.625.625 0 0 0 0 1.25Z", | ||||||
|  |   "document-text-link-outline": "M18 20.5a.5.5 0 0 0 .5-.5V10H14a2 2 0 0 1-2-2V3.5H6a.5.5 0 0 0-.5.5v10h-.75c-.255 0-.506.02-.75.059V4a2 2 0 0 1 2-2h6.172c.028 0 .055.004.082.007.02.003.04.006.059.007.215.015.427.056.624.138.057.024.112.056.166.087l.05.029.047.024a.652.652 0 0 1 .081.044c.078.053.148.116.219.18a.63.63 0 0 0 .036.03.491.491 0 0 1 .049.04l5.829 5.828A2 2 0 0 1 20 9.828V20a2 2 0 0 1-2 2h-6.286c.406-.432.731-.94.953-1.5H18Zm-.622-12L13.5 4.621V8a.5.5 0 0 0 .5.5h3.378Zm-7.603 5.75c.854.29 1.6.815 2.158 1.5h3.317a.75.75 0 0 0 0-1.5H9.775ZM12.667 17c.186.468.3.973.326 1.5h2.257a.75.75 0 0 0 0-1.5h-2.583ZM8.75 11.5a.75.75 0 0 0 0 1.5h6.5a.75.75 0 0 0 0-1.5h-6.5ZM12 18.75A3.75 3.75 0 0 0 8.25 15l-.102.007A.75.75 0 0 0 8.25 16.5l.154.005A2.25 2.25 0 0 1 8.25 21l-.003.005-.102.007a.75.75 0 0 0 .108 1.493V22.5l.2-.005A3.75 3.75 0 0 0 12 18.75Zm-6.5-3a.75.75 0 0 0-.75-.75l-.2.005a3.75 3.75 0 0 0 .2 7.495l.102-.007A.75.75 0 0 0 4.75 21l-.154-.005A2.25 2.25 0 0 1 4.75 16.5l.102-.007a.75.75 0 0 0 .648-.743Zm3.5 3a.75.75 0 0 0-.75-.75h-3.5l-.102.007A.75.75 0 0 0 4.75 19.5h3.5l.102-.007A.75.75 0 0 0 9 18.75Z", | ||||||
|   "draft-outline": "m20.877 2.826.153.144.145.153a3.579 3.579 0 0 1-.145 4.908L9.062 19.999a2.25 2.25 0 0 1-1 .58l-5.115 1.395a.75.75 0 0 1-.92-.921l1.394-5.116a2.25 2.25 0 0 1 .58-.999L15.97 2.97a3.579 3.579 0 0 1 4.908-.144ZM15 6.06l-9.938 9.938a.75.75 0 0 0-.193.333l-1.05 3.85 3.85-1.05A.75.75 0 0 0 8 18.938L17.94 9 15 6.06ZM6.525 11l-1.5 1.5H2.75a.75.75 0 0 1 0-1.5h3.775Zm4-4-1.5 1.5H2.75a.75.75 0 1 1 0-1.5h7.775Zm6.505-2.97-.97.97 2.939 2.94.97-.97a2.078 2.078 0 1 0-2.939-2.94ZM14.525 3l-1.5 1.5H2.75a.75.75 0 1 1 0-1.5h11.775Z", |   "draft-outline": "m20.877 2.826.153.144.145.153a3.579 3.579 0 0 1-.145 4.908L9.062 19.999a2.25 2.25 0 0 1-1 .58l-5.115 1.395a.75.75 0 0 1-.92-.921l1.394-5.116a2.25 2.25 0 0 1 .58-.999L15.97 2.97a3.579 3.579 0 0 1 4.908-.144ZM15 6.06l-9.938 9.938a.75.75 0 0 0-.193.333l-1.05 3.85 3.85-1.05A.75.75 0 0 0 8 18.938L17.94 9 15 6.06ZM6.525 11l-1.5 1.5H2.75a.75.75 0 0 1 0-1.5h3.775Zm4-4-1.5 1.5H2.75a.75.75 0 1 1 0-1.5h7.775Zm6.505-2.97-.97.97 2.939 2.94.97-.97a2.078 2.078 0 1 0-2.939-2.94ZM14.525 3l-1.5 1.5H2.75a.75.75 0 1 1 0-1.5h11.775Z", | ||||||
|   "drag-outline": "M15 3.707V8.5a.5.5 0 0 0 1 0V3.707l1.146 1.147a.5.5 0 0 0 .708-.708l-2-2a.499.499 0 0 0-.708 0l-2 2a.5.5 0 0 0 .708.708L15 3.707ZM2 4.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5Zm0 5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5Zm.5 4.5a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6ZM15 16.293V11.5a.5.5 0 0 1 1 0v4.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 .708-.708L15 16.293Z", |   "drag-outline": "M15 3.707V8.5a.5.5 0 0 0 1 0V3.707l1.146 1.147a.5.5 0 0 0 .708-.708l-2-2a.499.499 0 0 0-.708 0l-2 2a.5.5 0 0 0 .708.708L15 3.707ZM2 4.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5Zm0 5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5Zm.5 4.5a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6ZM15 16.293V11.5a.5.5 0 0 1 1 0v4.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 .708-.708L15 16.293Z", | ||||||
|   "dual-screen-clock-outline": "M10.019 6.002a6.632 6.632 0 0 0 .058 1.5H3.75a.25.25 0 0 0-.25.25v12.494c0 .138.112.25.25.25h7.498l-.001-10.167c.416.57.924 1.07 1.5 1.479v8.69h7.498a.25.25 0 0 0 .25-.25v-8.62a6.535 6.535 0 0 0 1.501-1.656V20.25a1.75 1.75 0 0 1-1.75 1.75h-8.998l-.001-.003H3.75A1.75 1.75 0 0 1 2 20.246V7.751c0-.966.784-1.75 1.75-1.75h6.269Zm6.22 11.498a.75.75 0 0 1 .101 1.493L16.24 19h-1.5a.75.75 0 0 1-.102-1.493l.102-.007h1.5Zm-6.996 0a.75.75 0 0 1 .102 1.493L9.243 19H7.74a.75.75 0 0 1-.102-1.493l.102-.007h1.502ZM16.498 1a5.5 5.5 0 1 1 0 11 5.5 5.5 0 0 1 0-11Zm-1 2a.5.5 0 0 0-.5.5v4a.5.5 0 0 0 .5.5h3.001a.5.5 0 0 0 0-1h-2.501V3.5a.5.5 0 0 0-.5-.5Z", |   "dual-screen-clock-outline": "M10.019 6.002a6.632 6.632 0 0 0 .058 1.5H3.75a.25.25 0 0 0-.25.25v12.494c0 .138.112.25.25.25h7.498l-.001-10.167c.416.57.924 1.07 1.5 1.479v8.69h7.498a.25.25 0 0 0 .25-.25v-8.62a6.535 6.535 0 0 0 1.501-1.656V20.25a1.75 1.75 0 0 1-1.75 1.75h-8.998l-.001-.003H3.75A1.75 1.75 0 0 1 2 20.246V7.751c0-.966.784-1.75 1.75-1.75h6.269Zm6.22 11.498a.75.75 0 0 1 .101 1.493L16.24 19h-1.5a.75.75 0 0 1-.102-1.493l.102-.007h1.5Zm-6.996 0a.75.75 0 0 1 .102 1.493L9.243 19H7.74a.75.75 0 0 1-.102-1.493l.102-.007h1.502ZM16.498 1a5.5 5.5 0 1 1 0 11 5.5 5.5 0 0 1 0-11Zm-1 2a.5.5 0 0 0-.5.5v4a.5.5 0 0 0 .5.5h3.001a.5.5 0 0 0 0-1h-2.501V3.5a.5.5 0 0 0-.5-.5Z", | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ | |||||||
| import ArticleSkeletonLoader from 'shared/components/ArticleSkeletonLoader.vue'; | import ArticleSkeletonLoader from 'shared/components/ArticleSkeletonLoader.vue'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'IframeRenderer', |   name: 'IframeLoader', | ||||||
|   components: { |   components: { | ||||||
|     ArticleSkeletonLoader, |     ArticleSkeletonLoader, | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -11,4 +11,5 @@ export const BUS_EVENTS = { | |||||||
|   TOGGLE_REPLY_TO_MESSAGE: 'TOGGLE_REPLY_TO_MESSAGE', |   TOGGLE_REPLY_TO_MESSAGE: 'TOGGLE_REPLY_TO_MESSAGE', | ||||||
|   SHOW_TOAST: 'newToastMessage', |   SHOW_TOAST: 'newToastMessage', | ||||||
|   NEW_CONVERSATION_MODAL: 'newConversationModal', |   NEW_CONVERSATION_MODAL: 'newConversationModal', | ||||||
|  |   INSERT_INTO_RICH_EDITOR: 'insertIntoRichEditor', | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -59,3 +59,5 @@ | |||||||
|   enabled: false |   enabled: false | ||||||
| - name: message_reply_to | - name: message_reply_to | ||||||
|   enabled: false |   enabled: false | ||||||
|  | - name: insert_article_in_reply | ||||||
|  |   enabled: false | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user