diff --git a/app/javascript/dashboard/api/search.js b/app/javascript/dashboard/api/search.js new file mode 100644 index 000000000..2e4c3b198 --- /dev/null +++ b/app/javascript/dashboard/api/search.js @@ -0,0 +1,18 @@ +/* global axios */ +import ApiClient from './ApiClient'; + +class SearchAPI extends ApiClient { + constructor() { + super('search', { accountScoped: true }); + } + + get({ q }) { + return axios.get(this.url, { + params: { + q, + }, + }); + } +} + +export default new SearchAPI(); diff --git a/app/javascript/dashboard/components/widgets/InboxName.vue b/app/javascript/dashboard/components/widgets/InboxName.vue index feb71803c..427772cf5 100644 --- a/app/javascript/dashboard/components/widgets/InboxName.vue +++ b/app/javascript/dashboard/components/widgets/InboxName.vue @@ -31,7 +31,7 @@ export default { line-height: var(--space-slab); font-weight: var(--font-weight-medium); background: none; - color: var(--s-500); + color: var(--s-600); font-size: var(--font-size-mini); margin: 0 var(--space-one); } diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 86cf292b9..7baa50cf5 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -887,6 +887,11 @@ export default { toggleTyping(status) { const conversationId = this.currentChat.id; const isPrivate = this.isPrivate; + + if (!conversationId) { + return; + } + this.$store.dispatch('conversationTypingStatus/toggleTyping', { status, conversationId, diff --git a/app/javascript/dashboard/helper/AnalyticsHelper/events.js b/app/javascript/dashboard/helper/AnalyticsHelper/events.js index b55b5f2c2..0ffccd668 100644 --- a/app/javascript/dashboard/helper/AnalyticsHelper/events.js +++ b/app/javascript/dashboard/helper/AnalyticsHelper/events.js @@ -5,7 +5,7 @@ export const CONVERSATION_EVENTS = Object.freeze({ INSERTED_A_CANNED_RESPONSE: 'Inserted a canned response', INSERTED_A_VARIABLE: 'Inserted a variable', USED_MENTIONS: 'Used mentions', - + SEARCH_CONVERSATION: 'Searched conversations', APPLY_FILTER: 'Applied filters in the conversation list', }); diff --git a/app/javascript/dashboard/i18n/locale/en/index.js b/app/javascript/dashboard/i18n/locale/en/index.js index 0c674eef2..387241f31 100644 --- a/app/javascript/dashboard/i18n/locale/en/index.js +++ b/app/javascript/dashboard/i18n/locale/en/index.js @@ -22,6 +22,7 @@ import login from './login.json'; import macros from './macros.json'; import report from './report.json'; import resetPassword from './resetPassword.json'; +import search from './search.json'; import setNewPassword from './setNewPassword.json'; import settings from './settings.json'; import signup from './signup.json'; @@ -53,6 +54,7 @@ export default { ...macros, ...report, ...resetPassword, + ...search, ...setNewPassword, ...settings, ...signup, diff --git a/app/javascript/dashboard/i18n/locale/en/search.json b/app/javascript/dashboard/i18n/locale/en/search.json new file mode 100644 index 000000000..f3823f134 --- /dev/null +++ b/app/javascript/dashboard/i18n/locale/en/search.json @@ -0,0 +1,22 @@ +{ + "SEARCH": { + "TABS": { + "ALL": "All", + "CONTACTS": "Contacts", + "CONVERSATIONS": "Conversations", + "MESSAGES": "Messages" + }, + "SECTION": { + "CONTACTS": "Contacts", + "CONVERSATIONS": "Conversations", + "MESSAGES": "Messages" + }, + "EMPTY_STATE": "No %{item} found for query '%{query}'", + "EMPTY_STATE_FULL": "No results found for query '%{query}'", + "PLACEHOLDER_KEYBINDING": "/ to focus", + "INPUT_PLACEHOLDER": "Search message content, contact name, email or phone or conversations", + "BOT_LABEL": "Bot", + "READ_MORE": "Read more", + "WROTE": "wrote:" + } +} diff --git a/app/javascript/dashboard/modules/search/components/MessageContent.vue b/app/javascript/dashboard/modules/search/components/MessageContent.vue new file mode 100644 index 000000000..f0aacb91e --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/MessageContent.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/app/javascript/dashboard/modules/search/components/ReadMore.vue b/app/javascript/dashboard/modules/search/components/ReadMore.vue new file mode 100644 index 000000000..db80de4a8 --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/ReadMore.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchHeader.vue b/app/javascript/dashboard/modules/search/components/SearchHeader.vue new file mode 100644 index 000000000..ae0d786d9 --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchHeader.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchResultContactItem.vue b/app/javascript/dashboard/modules/search/components/SearchResultContactItem.vue index cbfb35c83..c4c4d157f 100644 --- a/app/javascript/dashboard/modules/search/components/SearchResultContactItem.vue +++ b/app/javascript/dashboard/modules/search/components/SearchResultContactItem.vue @@ -19,8 +19,8 @@ import { frontendURL } from 'dashboard/helper/URLHelper'; export default { props: { id: { - type: String, - default: '', + type: [String, Number], + default: 0, }, email: { type: String, @@ -39,8 +39,8 @@ export default { default: '', }, accountId: { - type: String, - default: '', + type: [String, Number], + default: 0, }, }, computed: { diff --git a/app/javascript/dashboard/modules/search/components/SearchResultContactsList.vue b/app/javascript/dashboard/modules/search/components/SearchResultContactsList.vue new file mode 100644 index 000000000..1c343451c --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchResultContactsList.vue @@ -0,0 +1,49 @@ + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchResultConversationItem.vue b/app/javascript/dashboard/modules/search/components/SearchResultConversationItem.vue index 1b8ec65d2..2c47a4989 100644 --- a/app/javascript/dashboard/modules/search/components/SearchResultConversationItem.vue +++ b/app/javascript/dashboard/modules/search/components/SearchResultConversationItem.vue @@ -17,10 +17,10 @@
- {{ createdAtTime }} + {{ createdAtTime }}
-
+
from: {{ name }}
@@ -41,12 +41,8 @@ export default { mixins: [timeMixin], props: { id: { - type: String, - default: '', - }, - email: { - type: String, - default: '', + type: Number, + default: 0, }, inbox: { type: Object, @@ -56,12 +52,8 @@ export default { type: String, default: '', }, - thumbnail: { - type: String, - default: '', - }, accountId: { - type: String, + type: [String, Number], default: '', }, createdAt: { @@ -101,6 +93,7 @@ export default { .icon-wrap { width: var(--space-medium); height: var(--space-medium); + flex-shrink: 0; display: flex; align-items: center; justify-content: center; @@ -122,12 +115,13 @@ export default { .conversation-details { margin-left: var(--space-normal); flex-grow: 1; + min-width: 0; } .conversation-id, .name { margin: 0; } - +.created-at, .pre-text { color: var(--s-600); font-size: var(--font-size-mini); diff --git a/app/javascript/dashboard/modules/search/components/SearchResultConversationsList.vue b/app/javascript/dashboard/modules/search/components/SearchResultConversationsList.vue new file mode 100644 index 000000000..40a6ddb7b --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchResultConversationsList.vue @@ -0,0 +1,47 @@ + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchResultMessagesList.vue b/app/javascript/dashboard/modules/search/components/SearchResultMessagesList.vue new file mode 100644 index 000000000..4dbbb3bcd --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchResultMessagesList.vue @@ -0,0 +1,61 @@ + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchResultSection.vue b/app/javascript/dashboard/modules/search/components/SearchResultSection.vue new file mode 100644 index 000000000..a3295c0d6 --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchResultSection.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchTabs.vue b/app/javascript/dashboard/modules/search/components/SearchTabs.vue new file mode 100644 index 000000000..fa6944562 --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchTabs.vue @@ -0,0 +1,40 @@ + + + + diff --git a/app/javascript/dashboard/modules/search/components/SearchView.vue b/app/javascript/dashboard/modules/search/components/SearchView.vue new file mode 100644 index 000000000..3d43cddc3 --- /dev/null +++ b/app/javascript/dashboard/modules/search/components/SearchView.vue @@ -0,0 +1,202 @@ + + + + + diff --git a/app/javascript/dashboard/modules/search/search.routes.js b/app/javascript/dashboard/modules/search/search.routes.js new file mode 100644 index 000000000..a805d2316 --- /dev/null +++ b/app/javascript/dashboard/modules/search/search.routes.js @@ -0,0 +1,12 @@ +/* eslint-disable storybook/default-exports */ +import SearchView from './components/SearchView.vue'; +import { frontendURL } from '../../helper/URLHelper'; + +export const routes = [ + { + path: frontendURL('accounts/:accountId/search'), + name: 'search', + roles: ['administrator', 'agent'], + component: SearchView, + }, +]; diff --git a/app/javascript/dashboard/modules/search/stories/MessageContent.stories.js b/app/javascript/dashboard/modules/search/stories/MessageContent.stories.js new file mode 100644 index 000000000..d82d1979b --- /dev/null +++ b/app/javascript/dashboard/modules/search/stories/MessageContent.stories.js @@ -0,0 +1,28 @@ +import MessageContent from '../components/MessageContent.vue'; + +export default { + title: 'Components/Search/MessageContent', + component: MessageContent, + argTypes: { + content: { + defaultValue: '123', + control: { + type: 'text', + }, + }, + author: { + defaultValue: 'John Doe', + control: { + type: 'text', + }, + }, + }, +}; + +const Template = (args, { argTypes }) => ({ + props: Object.keys(argTypes), + components: { MessageContent }, + template: '', +}); + +export const MessageResultItem = Template.bind({}); diff --git a/app/javascript/dashboard/routes/dashboard/conversation/search/PopOverSearch.vue b/app/javascript/dashboard/routes/dashboard/conversation/search/PopOverSearch.vue index c62ae2e0f..1c5072dd4 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/search/PopOverSearch.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/search/PopOverSearch.vue @@ -1,58 +1,18 @@ @@ -60,15 +20,13 @@ import { mixin as clickaway } from 'vue-clickaway'; import { mapGetters } from 'vuex'; import timeMixin from '../../../../mixins/time'; -import ResultItem from './ResultItem'; import messageFormatterMixin from 'shared/mixins/messageFormatterMixin'; import SwitchLayout from './SwitchLayout.vue'; +import { frontendURL } from 'dashboard/helper/URLHelper'; export default { components: { - ResultItem, SwitchLayout, }, - directives: { focus: { inserted(el) { @@ -76,9 +34,7 @@ export default { }, }, }, - mixins: [timeMixin, messageFormatterMixin, clickaway], - props: { isOnExpandedLayout: { type: Boolean, @@ -95,59 +51,10 @@ export default { computed: { ...mapGetters({ - conversations: 'conversationSearch/getConversations', - uiFlags: 'conversationSearch/getUIFlags', - currentPage: 'conversationPage/getCurrentPage', + accountId: 'getCurrentAccountId', }), - resultsCount() { - return this.conversations.length; - }, - showSearchResult() { - return ( - this.searchTerm && this.conversations.length && !this.uiFlags.isFetching - ); - }, - showEmptyResult() { - return ( - this.searchTerm && - !this.conversations.length && - !this.uiFlags.isFetching - ); - }, - }, - - watch: { - searchTerm(newValue) { - if (this.typingTimer) { - clearTimeout(this.typingTimer); - } - - this.typingTimer = setTimeout(() => { - this.hasSearched = true; - this.$store.dispatch('conversationSearch/get', { q: newValue }); - }, 1000); - }, - currentPage() { - this.clearSearchTerm(); - }, - }, - - mounted() { - this.$store.dispatch('conversationSearch/get', { q: '' }); - bus.$on('clearSearchInput', () => { - this.clearSearchTerm(); - }); - }, - - methods: { - onSearch() { - this.showSearchBox = true; - }, - closeSearch() { - this.showSearchBox = false; - }, - clearSearchTerm() { - this.searchTerm = ''; + searchUrl() { + return frontendURL(`accounts/${this.accountId}/search`); }, }, }; @@ -156,30 +63,34 @@ export default {