diff --git a/.changeset/stupid-ties-push.md b/.changeset/stupid-ties-push.md new file mode 100644 index 00000000..1a10e128 --- /dev/null +++ b/.changeset/stupid-ties-push.md @@ -0,0 +1,10 @@ +--- +'@axis-backstage/plugin-jira-dashboard-backend': minor +--- + +Querying for components that contain spaces should now return the expected results. Component +names is now wrapped in single quotations. + +Added the `jqlQueryBuilder` function that will create a JQL query based on the arguments. This is +exported from the backend plugin to be used outside the context of the plugin together with the +`searchJira` function. diff --git a/plugins/jira-dashboard-backend/api-report.md b/plugins/jira-dashboard-backend/api-report.md index 993b784c..9e66591d 100644 --- a/plugins/jira-dashboard-backend/api-report.md +++ b/plugins/jira-dashboard-backend/api-report.md @@ -21,6 +21,20 @@ export function createRouter(options: RouterOptions): Promise; const jiraDashboardPlugin: () => BackendFeature; export default jiraDashboardPlugin; +// @public +export const jqlQueryBuilder: ({ + project, + components, + query, +}: JqlQueryBuilderArgs) => string; + +// @public +export type JqlQueryBuilderArgs = { + project: string; + components?: string[]; + query?: string; +}; + // @public export interface RouterOptions { auth?: AuthService; diff --git a/plugins/jira-dashboard-backend/src/api.ts b/plugins/jira-dashboard-backend/src/api.ts index c003990e..d6af164c 100644 --- a/plugins/jira-dashboard-backend/src/api.ts +++ b/plugins/jira-dashboard-backend/src/api.ts @@ -6,6 +6,7 @@ import { Project, } from '@axis-backstage/plugin-jira-dashboard-common'; import { resolveJiraBaseUrl, resolveJiraToken } from './config'; +import { jqlQueryBuilder } from './queries'; export const getProjectInfo = async ( projectKey: string, @@ -51,14 +52,9 @@ export const getIssuesByFilter = async ( query: string, config: Config, ): Promise => { - let componentQuery = ''; - if (components.length) { - componentQuery = `AND component in (${components})`; - } + const jql = jqlQueryBuilder({ project: projectKey, components, query }); const response = await fetch( - `${resolveJiraBaseUrl( - config, - )}search?jql=project in (${projectKey}) ${componentQuery} AND ${query}`, + `${resolveJiraBaseUrl(config)}search?jql=${jql}`, { method: 'GET', headers: { @@ -120,10 +116,12 @@ export const getIssuesByComponent = async ( componentKey: string, config: Config, ): Promise => { + const jql = jqlQueryBuilder({ + project: projectKey, + components: [componentKey], + }); const response = await fetch( - `${resolveJiraBaseUrl( - config, - )}search?jql=project=${projectKey} AND component = "${componentKey}"`, + `${resolveJiraBaseUrl(config)}search?jql=${jql}`, { method: 'GET', headers: { diff --git a/plugins/jira-dashboard-backend/src/index.ts b/plugins/jira-dashboard-backend/src/index.ts index 289e9421..c3cd98da 100644 --- a/plugins/jira-dashboard-backend/src/index.ts +++ b/plugins/jira-dashboard-backend/src/index.ts @@ -8,3 +8,5 @@ export * from './service/router'; export { jiraDashboardPlugin as default } from './plugin'; export { searchJira } from './api'; export type { SearchOptions } from './api'; +export { jqlQueryBuilder } from './queries'; +export type { JqlQueryBuilderArgs } from './queries'; diff --git a/plugins/jira-dashboard-backend/src/queries.test.ts b/plugins/jira-dashboard-backend/src/queries.test.ts new file mode 100644 index 00000000..bbd24b68 --- /dev/null +++ b/plugins/jira-dashboard-backend/src/queries.test.ts @@ -0,0 +1,20 @@ +import { jqlQueryBuilder } from './queries'; + +describe('queries', () => { + it('can use all arguments build a query.', async () => { + const jql = jqlQueryBuilder({ + project: 'BS', + components: ['comp 1', 'comp 2'], + query: 'filter=example', + }); + expect(jql).toBe( + "project in (BS) AND component in ('comp 1','comp 2') AND filter=example", + ); + }); + it('can create a query using only a project as argument.', async () => { + const jql = jqlQueryBuilder({ + project: 'BS', + }); + expect(jql).toBe('project in (BS)'); + }); +}); diff --git a/plugins/jira-dashboard-backend/src/queries.ts b/plugins/jira-dashboard-backend/src/queries.ts new file mode 100644 index 00000000..a254b563 --- /dev/null +++ b/plugins/jira-dashboard-backend/src/queries.ts @@ -0,0 +1,41 @@ +/** + * Types for the arguments to the jqlQueryBuilder function. + * + * @public + */ +export type JqlQueryBuilderArgs = { + project: string; + components?: string[]; + query?: string; +}; + +/** + * Creates a jql query string. + * + * @public + */ +export const jqlQueryBuilder = ({ + project, + components, + query, +}: JqlQueryBuilderArgs) => { + let jql = `project in (${project})`; + if (components && components.length > 0) { + let componentsInclude = '('; + for (let index = 0; index < components.length; index++) { + const component = components[index]; + componentsInclude += `'${component}'`; + // Add either the "," separator or close the parentheses. + if (index === components.length - 1) { + componentsInclude += ')'; + } else { + componentsInclude += ','; + } + } + jql += ` AND component in ${componentsInclude}`; + } + if (query) { + jql += ` AND ${query}`; + } + return jql; +};