From 32b63ad0c06f715b163879bf1a7f8a27005381a1 Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:41:21 +0530 Subject: [PATCH] feat: add search to Help Center admin pages (#14772) --- .../dashboard/api/helpCenter/articles.js | 2 + .../HelpCenter/ArticleCard/ArticleCard.vue | 16 +++--- .../HelpCenter/HelpCenterLayout.vue | 7 ++- .../Pages/ArticlePage/ArticleList.vue | 5 ++ .../Pages/ArticlePage/ArticlesPage.vue | 34 ++++++++++++- .../Pages/CategoryPage/CategoriesPage.vue | 23 ++++++++- .../CategoryPage/CategoryHeaderControls.vue | 51 ++++++++++++------- .../Pages/CategoryPage/CategoryList.vue | 6 ++- .../Pages/LocalePage/LocalesPage.vue | 49 +++++++++++++++--- .../dashboard/i18n/locale/en/helpCenter.json | 15 ++++++ .../pages/PortalsArticlesIndexPage.vue | 15 +++++- .../modules/helpCenterArticles/actions.js | 3 +- 12 files changed, 184 insertions(+), 42 deletions(-) diff --git a/app/javascript/dashboard/api/helpCenter/articles.js b/app/javascript/dashboard/api/helpCenter/articles.js index bab45bcb5..55b620d1a 100644 --- a/app/javascript/dashboard/api/helpCenter/articles.js +++ b/app/javascript/dashboard/api/helpCenter/articles.js @@ -16,6 +16,7 @@ class ArticlesAPI extends PortalsAPI { authorId, categorySlug, sort, + query, }) { const url = getArticleSearchURL({ pageNumber, @@ -25,6 +26,7 @@ class ArticlesAPI extends PortalsAPI { authorId, categorySlug, sort, + query, host: this.url, }); diff --git a/app/javascript/dashboard/components-next/HelpCenter/ArticleCard/ArticleCard.vue b/app/javascript/dashboard/components-next/HelpCenter/ArticleCard/ArticleCard.vue index 9b1c48a90..564888f0d 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/ArticleCard/ArticleCard.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/ArticleCard/ArticleCard.vue @@ -210,9 +210,9 @@ const handleClick = id => { -
-
-
+
+
+
{ {{ authorName || '-' }}
- + - {{ categoryName }} + {{ categoryName }}
@@ -247,7 +245,7 @@ const handleClick = id => {
- + {{ lastUpdatedAt }}
diff --git a/app/javascript/dashboard/components-next/HelpCenter/HelpCenterLayout.vue b/app/javascript/dashboard/components-next/HelpCenter/HelpCenterLayout.vue index 5b6399da7..fb564622a 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/HelpCenterLayout.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/HelpCenterLayout.vue @@ -67,11 +67,11 @@ const togglePortalSwitcher = () => { > {{ activePortalName }} -
+
+
+ +
diff --git a/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticleList.vue b/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticleList.vue index 575eaa828..75aeb86d1 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticleList.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticleList.vue @@ -24,6 +24,10 @@ const props = defineProps({ type: Set, default: () => new Set(), }, + isSearching: { + type: Boolean, + default: false, + }, }); const emit = defineEmits(['translateArticle', 'toggleSelect']); @@ -41,6 +45,7 @@ const hoveredArticleId = ref(null); const dragEnabled = computed(() => { return ( props.isCategoryArticles && + !props.isSearching && localArticles.value?.length > 1 && props.selectedArticleIds.size === 0 ); diff --git a/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticlesPage.vue b/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticlesPage.vue index 68c93c007..66bcf6831 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticlesPage.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticlePage/ArticlesPage.vue @@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'; import { OnClickOutside } from '@vueuse/components'; import { useMapGetter } from 'dashboard/composables/store.js'; import { useConfig } from 'dashboard/composables/useConfig'; +import { debounce } from '@chatwoot/utils'; import { ARTICLE_TABS, CATEGORY_ALL } from 'dashboard/helper/portalHelper'; import { FEATURE_FLAGS } from 'dashboard/featureFlags'; import { useAlert } from 'dashboard/composables'; @@ -18,6 +19,7 @@ import Spinner from 'dashboard/components-next/spinner/Spinner.vue'; import ArticleEmptyState from 'dashboard/components-next/HelpCenter/EmptyState/Article/ArticleEmptyState.vue'; import BulkSelectBar from 'dashboard/components-next/captain/assistant/BulkSelectBar.vue'; import Button from 'dashboard/components-next/button/Button.vue'; +import Input from 'dashboard/components-next/input/Input.vue'; import Dialog from 'dashboard/components-next/dialog/Dialog.vue'; import DropdownMenu from 'dashboard/components-next/dropdown-menu/DropdownMenu.vue'; import BulkTranslateDialog from './BulkTranslateDialog.vue'; @@ -49,7 +51,12 @@ const props = defineProps({ }, }); -const emit = defineEmits(['pageChange', 'fetchPortal', 'refreshArticles']); +const emit = defineEmits([ + 'pageChange', + 'fetchPortal', + 'refreshArticles', + 'search', +]); const router = useRouter(); const route = useRoute(); @@ -65,6 +72,9 @@ const isFeatureEnabledonAccount = useMapGetter( const selectedArticleIds = ref(new Set()); const deleteConfirmDialogRef = ref(null); const isCategoryMenuOpen = ref(false); +const searchQuery = ref(route.query.search || ''); + +const debouncedSearch = debounce(() => emit('search', searchQuery.value), 500); const { isEnterprise } = useConfig(); @@ -122,6 +132,7 @@ const updateRoute = newParams => { categorySlug: newParams.categorySlug ?? categorySlug, ...newParams, }, + query: route.query, }); }; @@ -145,7 +156,12 @@ const showCategoryHeaderControls = computed( () => props.isCategoryArticles && !isSwitchingPortal.value ); +const isSearching = computed(() => Boolean(searchQuery.value?.trim())); + const getEmptyStateText = type => { + if (isSearching.value) { + return t(`HELP_CENTER.ARTICLES_PAGE.EMPTY_STATE.SEARCH.${type}`); + } if (props.isCategoryArticles) { return t(`HELP_CENTER.ARTICLES_PAGE.EMPTY_STATE.CATEGORY.${type}`); } @@ -291,6 +307,19 @@ watch( :show-pagination-footer="shouldShowPaginationFooter" @update:current-page="handlePageChange" > +