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 @@
+
+
+
+
+
+ {{ $t('SEARCH.READ_MORE') }}
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
{{ title }}
+
+
+
+
+
+ {{ $t('SEARCH.EMPTY_STATE', { item: titleCase, query }) }}
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+ (selectedTab = tab)" />
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('SEARCH.EMPTY_STATE_FULL', { query }) }}
+
+
+
+
+
+
+
+
+
+
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 @@
-
-