diff --git a/app/javascript/dashboard/api/helpCenter/articles.js b/app/javascript/dashboard/api/helpCenter/articles.js index fb21a0847a59..e5847dc1bcd2 100644 --- a/app/javascript/dashboard/api/helpCenter/articles.js +++ b/app/javascript/dashboard/api/helpCenter/articles.js @@ -1,6 +1,7 @@ /* global axios */ import PortalsAPI from './portals'; +import { getArticleSearchURL } from 'dashboard/helper/URLHelper.js'; class ArticlesAPI extends PortalsAPI { constructor() { @@ -12,14 +13,31 @@ class ArticlesAPI extends PortalsAPI { portalSlug, locale, status, - author_id, - category_slug, + authorId, + categorySlug, + sort, }) { - let baseUrl = `${this.url}/${portalSlug}/articles?page=${pageNumber}&locale=${locale}`; - if (status !== undefined) baseUrl += `&status=${status}`; - if (author_id) baseUrl += `&author_id=${author_id}`; - if (category_slug) baseUrl += `&category_slug=${category_slug}`; - return axios.get(baseUrl); + const url = getArticleSearchURL({ + pageNumber, + portalSlug, + locale, + status, + authorId, + categorySlug, + sort, + host: this.url, + }); + + return axios.get(url); + } + + searchArticles({ portalSlug, query }) { + const url = getArticleSearchURL({ + portalSlug, + query, + host: this.url, + }); + return axios.get(url); } getArticle({ id, portalSlug }) { diff --git a/app/javascript/dashboard/api/specs/article.spec.js b/app/javascript/dashboard/api/specs/article.spec.js index b8886b4f8212..02c0f82d8051 100644 --- a/app/javascript/dashboard/api/specs/article.spec.js +++ b/app/javascript/dashboard/api/specs/article.spec.js @@ -34,7 +34,7 @@ describe('#PortalAPI', () => { portalSlug: 'room-rental', locale: 'en-US', status: 'published', - author_id: '1', + authorId: '1', }); expect(axiosMock.get).toHaveBeenCalledWith( '/api/v1/portals/room-rental/articles?page=1&locale=en-US&status=published&author_id=1' @@ -85,6 +85,33 @@ describe('#PortalAPI', () => { window.axios = originalAxios; }); + it('#searchArticles', () => { + articlesAPI.searchArticles({ + query: 'test', + portalSlug: 'room-rental', + }); + expect(axiosMock.get).toHaveBeenCalledWith( + '/api/v1/portals/room-rental/articles?query=test' + ); + }); + }); + describe('API calls', () => { + const originalAxios = window.axios; + const axiosMock = { + post: jest.fn(() => Promise.resolve()), + get: jest.fn(() => Promise.resolve()), + patch: jest.fn(() => Promise.resolve()), + delete: jest.fn(() => Promise.resolve()), + }; + + beforeEach(() => { + window.axios = axiosMock; + }); + + afterEach(() => { + window.axios = originalAxios; + }); + it('#updateArticle', () => { articlesAPI.updateArticle({ articleId: 1, diff --git a/app/javascript/dashboard/helper/URLHelper.js b/app/javascript/dashboard/helper/URLHelper.js index 9ae1f57de6a0..7ea8531d300a 100644 --- a/app/javascript/dashboard/helper/URLHelper.js +++ b/app/javascript/dashboard/helper/URLHelper.js @@ -64,3 +64,35 @@ export const isValidURL = value => { /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/gm; return URL_REGEX.test(value); }; + +export const getArticleSearchURL = ({ + host, + portalSlug, + pageNumber, + locale, + status, + authorId, + categorySlug, + sort, + query, +}) => { + const queryParams = new URLSearchParams({}); + + const params = { + page: pageNumber, + locale, + status, + author_id: authorId, + category_slug: categorySlug, + sort, + query, + }; + + Object.entries(params).forEach(([key, value]) => { + if (value !== null && value !== undefined) { + queryParams.set(key, value); + } + }); + + return `${host}/${portalSlug}/articles?${queryParams.toString()}`; +}; diff --git a/app/javascript/dashboard/helper/specs/URLHelper.spec.js b/app/javascript/dashboard/helper/specs/URLHelper.spec.js index 204d3384fe6e..1b5814556960 100644 --- a/app/javascript/dashboard/helper/specs/URLHelper.spec.js +++ b/app/javascript/dashboard/helper/specs/URLHelper.spec.js @@ -3,6 +3,7 @@ import { conversationUrl, isValidURL, conversationListPageURL, + getArticleSearchURL, } from '../URLHelper'; describe('#URL Helpers', () => { @@ -75,4 +76,92 @@ describe('#URL Helpers', () => { expect(isValidURL('alert.window')).toBe(false); }); }); + + describe('getArticleSearchURL', () => { + it('should generate a basic URL without optional parameters', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + host: 'myurl.com', + }); + expect(url).toBe('myurl.com/news/articles?page=1&locale=en'); + }); + + it('should include status parameter if provided', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + status: 'published', + host: 'myurl.com', + }); + expect(url).toBe( + 'myurl.com/news/articles?page=1&locale=en&status=published' + ); + }); + + it('should include author_id parameter if provided', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + authorId: 123, + host: 'myurl.com', + }); + expect(url).toBe( + 'myurl.com/news/articles?page=1&locale=en&author_id=123' + ); + }); + + it('should include category_slug parameter if provided', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + categorySlug: 'technology', + host: 'myurl.com', + }); + expect(url).toBe( + 'myurl.com/news/articles?page=1&locale=en&category_slug=technology' + ); + }); + + it('should include sort parameter if provided', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + sort: 'views', + host: 'myurl.com', + }); + expect(url).toBe('myurl.com/news/articles?page=1&locale=en&sort=views'); + }); + + it('should handle multiple optional parameters', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + status: 'draft', + authorId: 456, + categorySlug: 'science', + sort: 'views', + host: 'myurl.com', + }); + expect(url).toBe( + 'myurl.com/news/articles?page=1&locale=en&status=draft&author_id=456&category_slug=science&sort=views' + ); + }); + + it('should handle missing optional parameters gracefully', () => { + const url = getArticleSearchURL({ + portalSlug: 'news', + pageNumber: 1, + locale: 'en', + host: 'myurl.com', + }); + expect(url).toBe('myurl.com/news/articles?page=1&locale=en'); + }); + }); }); diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue index 1a1a16561d56..b895db0e264b 100644 --- a/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue +++ b/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/ListAllArticles.vue @@ -139,8 +139,8 @@ export default { portalSlug: this.$route.params.portalSlug, locale: this.$route.params.locale, status: this.status, - author_id: this.author, - category_slug: this.selectedCategorySlug, + authorId: this.author, + categorySlug: this.selectedCategorySlug, }); }, onPageChange(pageNumber) { diff --git a/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js b/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js index 39aefafc0dfe..aa9e5242b493 100644 --- a/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js +++ b/app/javascript/dashboard/store/modules/helpCenterArticles/actions.js @@ -6,7 +6,7 @@ import types from '../../mutation-types'; export const actions = { index: async ( { commit }, - { pageNumber, portalSlug, locale, status, author_id, category_slug } + { pageNumber, portalSlug, locale, status, authorId, categorySlug } ) => { try { commit(types.SET_UI_FLAG, { isFetching: true }); @@ -17,8 +17,8 @@ export const actions = { portalSlug, locale, status, - author_id, - category_slug, + authorId, + categorySlug, }); const articleIds = payload.map(article => article.id); commit(types.CLEAR_ARTICLES);