feat: Splits search api by resources to improve query time [cw-47] (#6942)

* feat: Splits search api by resources to improve query time

* Review fixes

* Spacing fixes

* Update app/javascript/dashboard/modules/search/components/SearchView.vue

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>

* Review fixes

* Refactor searchview

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
Nithin David Thomas
2023-04-25 17:59:38 +05:30
committed by GitHub
parent 5600b518ac
commit 402428fb4d
9 changed files with 222 additions and 78 deletions

View File

@@ -16,6 +16,7 @@
:title="$t('SEARCH.PLACEHOLDER_KEYBINDING')"
:show-close="false"
small
class="helper-label"
/>
</div>
</template>
@@ -101,4 +102,8 @@ export default {
color: var(--s-400);
}
}
.helper-label {
margin: 0;
}
</style>

View File

@@ -3,6 +3,8 @@
:title="$t('SEARCH.SECTION.CONTACTS')"
:empty="!contacts.length"
:query="query"
:show-title="showTitle"
:is-fetching="isFetching"
>
<ul class="search-list">
<li v-for="contact in contacts" :key="contact.id">
@@ -39,6 +41,14 @@ export default {
type: String,
default: '',
},
isFetching: {
type: Boolean,
default: false,
},
showTitle: {
type: Boolean,
default: true,
},
},
computed: {
...mapGetters({

View File

@@ -3,6 +3,8 @@
:title="$t('SEARCH.SECTION.CONVERSATIONS')"
:empty="!conversations.length"
:query="query"
:show-title="showTitle || isFetching"
:is-fetching="isFetching"
>
<ul class="search-list">
<li v-for="conversation in conversations" :key="conversation.id">
@@ -37,6 +39,14 @@ export default {
type: String,
default: '',
},
isFetching: {
type: Boolean,
default: false,
},
showTitle: {
type: Boolean,
default: true,
},
},
computed: {
...mapGetters({

View File

@@ -3,6 +3,8 @@
:title="$t('SEARCH.SECTION.MESSAGES')"
:empty="!messages.length"
:query="query"
:show-title="showTitle"
:is-fetching="isFetching"
>
<ul class="search-list">
<li v-for="message in messages" :key="message.id">
@@ -45,6 +47,14 @@ export default {
type: String,
default: '',
},
isFetching: {
type: Boolean,
default: false,
},
showTitle: {
type: Boolean,
default: true,
},
},
computed: {
...mapGetters({

View File

@@ -1,10 +1,11 @@
<template>
<section class="result-section">
<div class="header">
<div v-if="showTitle" class="header">
<h3 class="text-block-title">{{ title }}</h3>
</div>
<slot />
<div v-if="empty" class="empty">
<woot-loading-state v-if="isFetching" :message="'Searching'" />
<slot v-else />
<div v-if="empty && !isFetching" class="empty">
<fluent-icon icon="info" size="16px" class="icon" />
<p class="empty-state__text">
{{ $t('SEARCH.EMPTY_STATE', { item: titleCase, query }) }}
@@ -28,6 +29,14 @@ export default {
type: String,
default: '',
},
showTitle: {
type: Boolean,
default: true,
},
isFetching: {
type: Boolean,
default: true,
},
},
computed: {
titleCase() {
@@ -39,7 +48,7 @@ export default {
<style scoped lang="scss">
.result-section {
margin-bottom: var(--space-normal);
margin: var(--space-small) 0;
}
.search-list {
list-style: none;
@@ -60,7 +69,7 @@ export default {
align-items: center;
justify-content: center;
padding: var(--space-medium) var(--space-normal);
margin: 0 var(--space-small);
margin: var(--space-small);
background: var(--s-25);
border-radius: var(--border-radius-medium);
.icon {

View File

@@ -21,39 +21,44 @@
/>
</header>
<div class="search-results">
<woot-loading-state v-if="uiFlags.isFetching" :message="'Searching'" />
<div v-else>
<div v-if="all.length">
<search-result-contacts-list
v-if="filterContacts"
:contacts="contacts"
:query="query"
/>
<search-result-messages-list
v-if="filterMessages"
:messages="messages"
:query="query"
/>
<search-result-conversations-list
v-if="filterConversations"
:conversations="conversations"
:query="query"
/>
</div>
<div v-else-if="showEmptySearchResults && !all.length" class="empty">
<fluent-icon icon="info" size="16px" class="icon" />
<p class="empty-state__text">
{{ $t('SEARCH.EMPTY_STATE_FULL', { query }) }}
</p>
</div>
<div v-else class="empty text-center">
<p class="text-center margin-bottom-0">
<fluent-icon icon="search" size="24px" class="icon" />
</p>
<p class="empty-state__text">
{{ $t('SEARCH.EMPTY_STATE_DEFAULT') }}
</p>
</div>
<div v-if="all.length">
<search-result-contacts-list
v-if="filterContacts"
:is-fetching="uiFlags.contact.isFetching"
:contacts="contacts"
:query="query"
:show-title="isSelectedTabAll"
/>
<search-result-messages-list
v-if="filterMessages"
:is-fetching="uiFlags.message.isFetching"
:messages="messages"
:query="query"
:show-title="isSelectedTabAll"
/>
<search-result-conversations-list
v-if="filterConversations"
:is-fetching="uiFlags.conversation.isFetching"
:conversations="conversations"
:query="query"
:show-title="isSelectedTabAll"
/>
</div>
<div v-else-if="showEmptySearchResults && !all.length" class="empty">
<fluent-icon icon="info" size="16px" class="icon" />
<p class="empty-state__text">
{{ $t('SEARCH.EMPTY_STATE_FULL', { query }) }}
</p>
</div>
<div v-else class="empty text-center">
<p class="text-center margin-bottom-0">
<fluent-icon icon="search" size="24px" class="icon" />
</p>
<p class="empty-state__text">
{{ $t('SEARCH.EMPTY_STATE_DEFAULT') }}
</p>
</div>
</div>
</section>
@@ -66,7 +71,6 @@ import SearchTabs from './SearchTabs.vue';
import SearchResultConversationsList from './SearchResultConversationsList.vue';
import SearchResultMessagesList from './SearchResultMessagesList.vue';
import SearchResultContactsList from './SearchResultContactsList.vue';
import { isEmptyObject } from 'dashboard/helper/commons.js';
import { mixin as clickaway } from 'vue-clickaway';
import { mapGetters } from 'vuex';
@@ -89,47 +93,40 @@ export default {
computed: {
...mapGetters({
fullSearchRecords: 'conversationSearch/getFullSearchRecords',
contactRecords: 'conversationSearch/getContactRecords',
conversationRecords: 'conversationSearch/getConversationRecords',
messageRecords: 'conversationSearch/getMessageRecords',
uiFlags: 'conversationSearch/getUIFlags',
}),
contacts() {
if (this.fullSearchRecords.contacts) {
return this.fullSearchRecords.contacts.map(contact => ({
...contact,
type: 'contact',
}));
}
return [];
return this.contactRecords.map(contact => ({
...contact,
type: 'contact',
}));
},
conversations() {
if (this.fullSearchRecords.conversations) {
return this.fullSearchRecords.conversations.map(conversation => ({
...conversation,
type: 'conversation',
}));
}
return [];
return this.conversationRecords.map(conversation => ({
...conversation,
type: 'conversation',
}));
},
messages() {
if (this.fullSearchRecords.messages) {
return this.fullSearchRecords.messages.map(message => ({
...message,
type: 'message',
}));
}
return [];
return this.messageRecords.map(message => ({
...message,
type: 'message',
}));
},
all() {
return [...this.contacts, ...this.conversations, ...this.messages];
},
filterContacts() {
return this.selectedTab === 'contacts' || this.selectedTab === 'all';
return this.selectedTab === 'contacts' || this.isSelectedTabAll;
},
filterConversations() {
return this.selectedTab === 'conversations' || this.selectedTab === 'all';
return this.selectedTab === 'conversations' || this.isSelectedTabAll;
},
filterMessages() {
return this.selectedTab === 'messages' || this.selectedTab === 'all';
return this.selectedTab === 'messages' || this.isSelectedTabAll;
},
totalSearchResultsCount() {
return (
@@ -162,10 +159,12 @@ export default {
},
showEmptySearchResults() {
return (
this.totalSearchResultsCount === 0 &&
!isEmptyObject(this.fullSearchRecords)
this.totalSearchResultsCount === 0 && this.uiFlags.isSearchCompleted
);
},
isSelectedTabAll() {
return this.selectedTab === 'all';
},
},
beforeDestroy() {
this.query = '';