From 072fd51e7177f3a713e3cc8987d8c1a8ade858e1 Mon Sep 17 00:00:00 2001 From: Martin Duffy Date: Wed, 5 Feb 2025 09:16:10 -0500 Subject: [PATCH 01/15] Filter runners by Group and Project on Admin dashboard --- .../ci/runner/admin_runners/admin_runners_app.vue | 15 +++++++++++++++ .../search_tokens/group_token_config.js | 11 +++++++++++ .../search_tokens/project_token_config.js | 11 +++++++++++ app/assets/javascripts/ci/runner/constants.js | 4 ++++ .../runner/graphql/list/all_runners.query.graphql | 2 ++ .../graphql/list/all_runners_count.query.graphql | 2 ++ .../javascripts/ci/runner/runner_search_utils.js | 8 ++++++++ .../runner/graphql/list/all_runners.query.graphql | 2 ++ .../graphql/list/all_runners_count.query.graphql | 2 ++ 9 files changed, 57 insertions(+) create mode 100644 app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js create mode 100644 app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js diff --git a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue index 30045b956fbe9d..844baf6c6ff563 100644 --- a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue @@ -13,6 +13,7 @@ import { import allRunnersQuery from 'ee_else_ce/ci/runner/graphql/list/all_runners.query.graphql'; import allRunnersCountQuery from 'ee_else_ce/ci/runner/graphql/list/all_runners_count.query.graphql'; import usersSearchAllQuery from '~/graphql_shared/queries/users_search_all.query.graphql'; +import groupsAutocompleteQuery from '~/graphql_shared/queries/groups_autocomplete.query.graphql'; import RunnerListHeader from '../components/runner_list_header.vue'; import RegistrationDropdown from '../components/registration/registration_dropdown.vue'; @@ -30,6 +31,8 @@ import { statusTokenConfig } from '../components/search_tokens/status_token_conf import { tagTokenConfig } from '../components/search_tokens/tag_token_config'; import { versionTokenConfig } from '../components/search_tokens/version_token_config'; import { creatorTokenConfig } from '../components/search_tokens/creator_token_config'; +import { groupTokenConfig } from '../components/search_tokens/group_token_config'; +import { projectTokenConfig } from '../components/search_tokens/project_token_config'; import { ADMIN_FILTERED_SEARCH_NAMESPACE, INSTANCE_TYPE, @@ -157,6 +160,18 @@ export default { recentSuggestionsStorageKey: `${this.$options.filteredSearchNamespace}-recent-tags`, }, upgradeStatusTokenConfig, + { + ...groupTokenConfig, + fetchGroups: (search) => { + return this.$apollo + .query({ + query: groupsAutocompleteQuery, + variables: { search }, + }) + .then(({ data }) => data.currentUser.groups.nodes); + }, + }, + projectTokenConfig, ]; }, isSearchFiltered() { diff --git a/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js b/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js new file mode 100644 index 00000000000000..e510d86efa0af8 --- /dev/null +++ b/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js @@ -0,0 +1,11 @@ +import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants'; +import GroupToken from '~/vue_shared/components/filtered_search_bar/tokens/group_token.vue'; +import { PARAM_KEY_GROUP, I18N_GROUP } from '../../constants'; + +export const groupTokenConfig = { + icon: 'group', + title: I18N_GROUP, + type: PARAM_KEY_GROUP, + token: GroupToken, + operators: OPERATORS_IS, +}; diff --git a/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js b/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js new file mode 100644 index 00000000000000..496e11968c539e --- /dev/null +++ b/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js @@ -0,0 +1,11 @@ +import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants'; +import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue'; +import { PARAM_KEY_PROJECT, I18N_PROJECT } from '../../constants'; + +export const projectTokenConfig = { + icon: 'project', + title: I18N_PROJECT, + type: PARAM_KEY_PROJECT, + token: BaseToken, + operators: OPERATORS_IS, +}; diff --git a/app/assets/javascripts/ci/runner/constants.js b/app/assets/javascripts/ci/runner/constants.js index 597d31f9015482..ce1a28061e4b71 100644 --- a/app/assets/javascripts/ci/runner/constants.js +++ b/app/assets/javascripts/ci/runner/constants.js @@ -75,6 +75,8 @@ export const I18N_DELETED_TOAST = s__('Runners|Runner %{name} was deleted'); // List export const I18N_CREATOR = s__('Runners|Creator'); +export const I18N_GROUP = s__('Runners|Group'); +export const I18N_PROJECT = s__('Runners|Project'); export const I18N_LOCKED_RUNNER_DESCRIPTION = s__( 'Runners|Runner is locked and available for currently assigned projects only. Only administrators can change the assigned projects.', ); @@ -122,6 +124,8 @@ export const RUNNER_TAG_BG_CLASS = 'gl-bg-blue-100'; // - GlFilteredSearch tokens type export const PARAM_KEY_CREATOR = 'creator'; +export const PARAM_KEY_GROUP = 'group'; +export const PARAM_KEY_PROJECT = 'project'; export const PARAM_KEY_STATUS = 'status'; export const PARAM_KEY_PAUSED = 'paused'; export const PARAM_KEY_RUNNER_TYPE = 'runner_type'; diff --git a/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql b/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql index b11fb74b3bb46d..59ea75e119e9fe 100644 --- a/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql +++ b/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql @@ -12,6 +12,7 @@ query getAllRunners( $search: String $versionPrefix: String $creator: String + $group: String $sort: CiRunnerSort ) { runners( @@ -26,6 +27,7 @@ query getAllRunners( search: $search versionPrefix: $versionPrefix creatorUsername: $creator + ownerFullPath: $group sort: $sort ) { ...AllRunnersConnection diff --git a/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql b/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql index c6f59b404bdecd..ce87488b8f0520 100644 --- a/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql +++ b/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql @@ -6,6 +6,7 @@ query getAllRunnersCount( $search: String $versionPrefix: String $creator: String + $owner: String ) { runners( paused: $paused @@ -15,6 +16,7 @@ query getAllRunnersCount( search: $search versionPrefix: $versionPrefix creatorUsername: $creator + ownerFullPath: $owner ) { count } diff --git a/app/assets/javascripts/ci/runner/runner_search_utils.js b/app/assets/javascripts/ci/runner/runner_search_utils.js index 170057aae370c8..01c2add5a6dab8 100644 --- a/app/assets/javascripts/ci/runner/runner_search_utils.js +++ b/app/assets/javascripts/ci/runner/runner_search_utils.js @@ -15,6 +15,8 @@ import { PARAM_KEY_VERSION, PARAM_KEY_SEARCH, PARAM_KEY_CREATOR, + PARAM_KEY_GROUP, + PARAM_KEY_PROJECT, PARAM_KEY_MEMBERSHIP, PARAM_KEY_SORT, PARAM_KEY_AFTER, @@ -159,6 +161,8 @@ export const fromUrlQueryToSearch = (query = window.location.search) => { PARAM_KEY_TAG, PARAM_KEY_VERSION, PARAM_KEY_CREATOR, + PARAM_KEY_GROUP, + PARAM_KEY_PROJECT, ], filteredSearchTermKey: PARAM_KEY_SEARCH, }), @@ -188,6 +192,8 @@ export const fromSearchToUrl = ( [PARAM_KEY_PAUSED]: [], [PARAM_KEY_VERSION]: [], [PARAM_KEY_CREATOR]: [], + [PARAM_KEY_GROUP]: [], + [PARAM_KEY_PROJECT]: [], // Current filters ...filterToQueryObject(processFilters(filters), { filteredSearchTermKey: PARAM_KEY_SEARCH, @@ -241,6 +247,8 @@ export const fromSearchToVariables = ({ filterVariables.tagList = queryObj[PARAM_KEY_TAG]; [filterVariables.versionPrefix] = queryObj[PARAM_KEY_VERSION] || []; [filterVariables.creator] = queryObj[PARAM_KEY_CREATOR] || []; + [filterVariables.group] = queryObj[PARAM_KEY_GROUP] || []; + [filterVariables.project] = queryObj[PARAM_KEY_PROJECT] || []; if (queryObj[PARAM_KEY_PAUSED]) { filterVariables.paused = parseBoolean(queryObj[PARAM_KEY_PAUSED]); diff --git a/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql b/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql index 9b251c077ffc61..3575355ed49140 100644 --- a/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql +++ b/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql @@ -15,6 +15,7 @@ query getAllRunnersEE( $search: String $versionPrefix: String $creator: String + $group: String $sort: CiRunnerSort ) { runners( @@ -30,6 +31,7 @@ query getAllRunnersEE( search: $search versionPrefix: $versionPrefix creatorUsername: $creator + ownerFullPath: $group sort: $sort ) { ...AllRunnersConnection diff --git a/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql b/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql index 4ff2ad03a3a515..5fc86e41473aad 100644 --- a/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql +++ b/ee/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql @@ -7,6 +7,7 @@ query getAllRunnersCountEE( $search: String $versionPrefix: String $creator: String + $group: String ) { runners( paused: $paused @@ -17,6 +18,7 @@ query getAllRunnersCountEE( search: $search versionPrefix: $versionPrefix creatorUsername: $creator + ownerFullPath: $group ) { count } -- GitLab From f3cb5737b1a2c2415f1be10578ae72609ecdcb44 Mon Sep 17 00:00:00 2001 From: Joseph Snyder Date: Thu, 12 Jun 2025 10:06:49 -0400 Subject: [PATCH 02/15] Make Project and group exclusive Follow the advice in the review to make it such that if a project or group query is already selected to filter over, do not show the other option --- .../admin_runners/admin_runners_app.vue | 86 +++++++++++-------- .../admin_runners/admin_runners_app_spec.js | 24 ++++-- 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue index 844baf6c6ff563..dd185607f709bc 100644 --- a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue @@ -38,6 +38,8 @@ import { INSTANCE_TYPE, I18N_FETCH_ERROR, FILTER_CSS_CLASSES, + PARAM_KEY_PROJECT, + PARAM_KEY_GROUP, } from '../constants'; import { captureException } from '../sentry_utils'; @@ -137,42 +139,58 @@ export default { avatar_url: gon.current_user_avatar_url, }); } - - return [ - pausedTokenConfig, - statusTokenConfig, - versionTokenConfig, - { - ...creatorTokenConfig, - fetchUsers: (search) => { - return this.$apollo - .query({ - query: usersSearchAllQuery, - variables: { search }, - }) - .then(({ data }) => data.users.nodes); - }, - defaultUsers: [], - preloadedUsers, - }, - { - ...tagTokenConfig, - recentSuggestionsStorageKey: `${this.$options.filteredSearchNamespace}-recent-tags`, + const isFilteringByProject = Boolean( + this.search.filters.find((f) => f.type === PARAM_KEY_PROJECT), + ); + const isFilteringByGroup = Boolean( + this.search.filters.find((f) => f.type === PARAM_KEY_GROUP), + ); + const notExclusive = !isFilteringByProject && !isFilteringByProject; + const groupTokenObject = { + ...groupTokenConfig, + fetchGroups: (search) => { + return this.$apollo + .query({ + query: groupsAutocompleteQuery, + variables: { search }, + }) + .then(({ data }) => data.currentUser.groups.nodes); }, - upgradeStatusTokenConfig, - { - ...groupTokenConfig, - fetchGroups: (search) => { - return this.$apollo - .query({ - query: groupsAutocompleteQuery, - variables: { search }, - }) - .then(({ data }) => data.currentUser.groups.nodes); - }, + defaultGroups: [], + }; + + const tokens = []; + // Add tokens one at a time, to allow for exclusive options + // to still be alphabetically ordered + tokens.push({ + ...creatorTokenConfig, + fetchUsers: (search) => { + return this.$apollo + .query({ + query: usersSearchAllQuery, + variables: { search }, + }) + .then(({ data }) => data.users.nodes); }, - projectTokenConfig, - ]; + defaultUsers: [], + preloadedUsers, + }); + if (isFilteringByGroup || notExclusive) { + tokens.push(groupTokenObject); + } + tokens.push(pausedTokenConfig); + if (isFilteringByProject || notExclusive) { + tokens.push(projectTokenConfig); + } + tokens.push(statusTokenConfig); + tokens.push({ + ...tagTokenConfig, + recentSuggestionsStorageKey: `${this.$options.filteredSearchNamespace}-recent-tags`, + }); + tokens.push(versionTokenConfig); + tokens.push(upgradeStatusTokenConfig); + + return tokens; }, isSearchFiltered() { return isSearchFiltered(this.search); diff --git a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js index 37d07f7d33de64..b6f9dbb861ea1c 100644 --- a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js +++ b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js @@ -43,6 +43,8 @@ import { PARAM_KEY_TAG, PARAM_KEY_VERSION, PARAM_KEY_CREATOR, + PARAM_KEY_GROUP, + PARAM_KEY_PROJECT, STATUS_ONLINE, DEFAULT_MEMBERSHIP, RUNNER_PAGE_SIZE, @@ -299,25 +301,33 @@ describe('AdminRunnersApp', () => { expect(findRunnerFilteredSearchBar().props('tokens')).toEqual([ expect.objectContaining({ - type: PARAM_KEY_PAUSED, - options: expect.any(Array), + type: PARAM_KEY_CREATOR, + title: 'Creator', }), expect.objectContaining({ - type: PARAM_KEY_STATUS, + type: PARAM_KEY_GROUP, + title: 'Group', + }), + expect.objectContaining({ + type: PARAM_KEY_PAUSED, options: expect.any(Array), }), expect.objectContaining({ - type: PARAM_KEY_VERSION, - title: 'Version starts with', + type: PARAM_KEY_PROJECT, + title: 'Project', }), expect.objectContaining({ - type: PARAM_KEY_CREATOR, - title: 'Creator', + type: PARAM_KEY_STATUS, + options: expect.any(Array), }), expect.objectContaining({ type: PARAM_KEY_TAG, recentSuggestionsStorageKey: `${ADMIN_FILTERED_SEARCH_NAMESPACE}-recent-tags`, }), + expect.objectContaining({ + type: PARAM_KEY_VERSION, + title: 'Version starts with', + }), upgradeStatusTokenConfig, ]); }); -- GitLab From cb657a2f018c16ecd861b336129571addf59ad6a Mon Sep 17 00:00:00 2001 From: Joseph Snyder Date: Fri, 27 Jun 2025 11:43:47 -0400 Subject: [PATCH 03/15] Restructure group_token to use config call Introduce the code needed to populate the group_token object with the query generated in the configuration object instead of relying on the existing subGroup call. --- .../admin_runners/admin_runners_app.vue | 23 ++++++-------- .../tokens/group_token.vue | 31 +++++++++++++------ 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue index dd185607f709bc..6b556c55b51d43 100644 --- a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue @@ -146,18 +146,6 @@ export default { this.search.filters.find((f) => f.type === PARAM_KEY_GROUP), ); const notExclusive = !isFilteringByProject && !isFilteringByProject; - const groupTokenObject = { - ...groupTokenConfig, - fetchGroups: (search) => { - return this.$apollo - .query({ - query: groupsAutocompleteQuery, - variables: { search }, - }) - .then(({ data }) => data.currentUser.groups.nodes); - }, - defaultGroups: [], - }; const tokens = []; // Add tokens one at a time, to allow for exclusive options @@ -176,7 +164,16 @@ export default { preloadedUsers, }); if (isFilteringByGroup || notExclusive) { - tokens.push(groupTokenObject); + tokens.push({ + ...groupTokenConfig, + fetchGroups: (search = '') => { + return this.$apollo.query({ + query: groupsAutocompleteQuery, + variables: { search }, + }); + }, + defaultGroups: [], + }); } tokens.push(pausedTokenConfig); if (isFilteringByProject || notExclusive) { diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue index cdd572cebc6759..bdd3004d5d2835 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue @@ -49,15 +49,28 @@ export default { }, fetchGroupsBySearchTerm(search) { this.loading = true; - this.fetchGroups(search) - .then((response) => { - const parentGroup = pick(response, ['id', 'name', 'fullName', 'fullPath']) || {}; - this.groups = [parentGroup, ...(response?.descendantGroups?.nodes || [])]; - }) - .catch(() => createAlert({ message: __('There was a problem fetching groups.') })) - .finally(() => { - this.loading = false; - }); + + if (this.config.fetchGroups) { + this.config + .fetchGroups(this, search) + .then((response) => { + this.groups = response.data.groups.nodes; + }) + .catch(() => createAlert({ message: __('There was a problem fetching groups.') })) + .finally(() => { + this.loading = false; + }); + } else { + this.fetchGroups(search) + .then((response) => { + const parentGroup = pick(response, ['id', 'name', 'fullName', 'fullPath']) || {}; + this.groups = [parentGroup, ...(response?.descendantGroups?.nodes || [])]; + }) + .catch(() => createAlert({ message: __('There was a problem fetching groups.') })) + .finally(() => { + this.loading = false; + }); + } }, getActiveGroup(groups, data) { if (data && groups.length) { -- GitLab From 7cfddda8fb5caea596efef0ff08b580fb980b155 Mon Sep 17 00:00:00 2001 From: Joseph Snyder Date: Thu, 3 Jul 2025 08:32:27 -0400 Subject: [PATCH 04/15] Additional fixes * Update group and project to be the same ownerPath value in GraphQL * Remove extra data in call to fetch suggestions, avoiding circluar reference * Use ownerPath as variable in query for both EE and non-EE query * Fix display of group token and ensure that the right value is used in searching --- .../ci/runner/admin_runners/admin_runners_app.vue | 3 ++- .../ci/runner/graphql/list/all_runners.query.graphql | 4 ++-- app/assets/javascripts/ci/runner/runner_search_utils.js | 3 +-- .../filtered_search_bar/tokens/group_token.vue | 9 ++++----- .../ci/runner/graphql/list/all_runners.query.graphql | 4 ++-- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue index 6b556c55b51d43..27fb4b07d771da 100644 --- a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue @@ -145,7 +145,7 @@ export default { const isFilteringByGroup = Boolean( this.search.filters.find((f) => f.type === PARAM_KEY_GROUP), ); - const notExclusive = !isFilteringByProject && !isFilteringByProject; + const notExclusive = !isFilteringByProject && !isFilteringByGroup; const tokens = []; // Add tokens one at a time, to allow for exclusive options @@ -173,6 +173,7 @@ export default { }); }, defaultGroups: [], + skipIdPrefix: true, }); } tokens.push(pausedTokenConfig); diff --git a/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql b/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql index 59ea75e119e9fe..18e26b6014fed1 100644 --- a/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql +++ b/app/assets/javascripts/ci/runner/graphql/list/all_runners.query.graphql @@ -12,7 +12,7 @@ query getAllRunners( $search: String $versionPrefix: String $creator: String - $group: String + $ownerFullPath: String $sort: CiRunnerSort ) { runners( @@ -27,7 +27,7 @@ query getAllRunners( search: $search versionPrefix: $versionPrefix creatorUsername: $creator - ownerFullPath: $group + ownerFullPath: $ownerFullPath sort: $sort ) { ...AllRunnersConnection diff --git a/app/assets/javascripts/ci/runner/runner_search_utils.js b/app/assets/javascripts/ci/runner/runner_search_utils.js index 01c2add5a6dab8..596a43886f77ec 100644 --- a/app/assets/javascripts/ci/runner/runner_search_utils.js +++ b/app/assets/javascripts/ci/runner/runner_search_utils.js @@ -247,8 +247,7 @@ export const fromSearchToVariables = ({ filterVariables.tagList = queryObj[PARAM_KEY_TAG]; [filterVariables.versionPrefix] = queryObj[PARAM_KEY_VERSION] || []; [filterVariables.creator] = queryObj[PARAM_KEY_CREATOR] || []; - [filterVariables.group] = queryObj[PARAM_KEY_GROUP] || []; - [filterVariables.project] = queryObj[PARAM_KEY_PROJECT] || []; + [filterVariables.ownerFullPath] = queryObj[PARAM_KEY_GROUP] || queryObj[PARAM_KEY_PROJECT] || []; if (queryObj[PARAM_KEY_PAUSED]) { filterVariables.paused = parseBoolean(queryObj[PARAM_KEY_PAUSED]); diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue index bdd3004d5d2835..876312699b95a9 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/group_token.vue @@ -49,10 +49,9 @@ export default { }, fetchGroupsBySearchTerm(search) { this.loading = true; - - if (this.config.fetchGroups) { + if (Object.hasOwn(this.config, 'fetchGroups')) { this.config - .fetchGroups(this, search) + .fetchGroups(search) .then((response) => { this.groups = response.data.groups.nodes; }) @@ -79,7 +78,7 @@ export default { return undefined; }, getValue(group) { - return group.fullPath; + return group.name; }, displayValue(group) { const prefix = this.config.skipIdPrefix @@ -115,7 +114,7 @@ export default { diff --git a/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js b/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js index e510d86efa0af8..d337339e4cf5d4 100644 --- a/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js +++ b/app/assets/javascripts/ci/runner/components/search_tokens/group_token_config.js @@ -8,4 +8,5 @@ export const groupTokenConfig = { type: PARAM_KEY_GROUP, token: GroupToken, operators: OPERATORS_IS, + unique: true, }; diff --git a/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js b/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js index fb4cef9c63428b..fd535aa3944be8 100644 --- a/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js +++ b/app/assets/javascripts/ci/runner/components/search_tokens/project_token_config.js @@ -8,4 +8,5 @@ export const projectTokenConfig = { type: PARAM_KEY_PROJECT, token: ProjectToken, operators: OPERATORS_IS, + unique: true, }; diff --git a/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql b/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql index ce87488b8f0520..7d55e07526dbca 100644 --- a/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql +++ b/app/assets/javascripts/ci/runner/graphql/list/all_runners_count.query.graphql @@ -6,7 +6,7 @@ query getAllRunnersCount( $search: String $versionPrefix: String $creator: String - $owner: String + $ownerFullPath: String ) { runners( paused: $paused @@ -16,7 +16,7 @@ query getAllRunnersCount( search: $search versionPrefix: $versionPrefix creatorUsername: $creator - ownerFullPath: $owner + ownerFullPath: $ownerFullPath ) { count } diff --git a/app/assets/javascripts/graphql_shared/queries/groups_autocomplete.query.graphql b/app/assets/javascripts/graphql_shared/queries/groups_autocomplete.query.graphql index 74da46e5a606b7..e34921747f3077 100644 --- a/app/assets/javascripts/graphql_shared/queries/groups_autocomplete.query.graphql +++ b/app/assets/javascripts/graphql_shared/queries/groups_autocomplete.query.graphql @@ -3,7 +3,7 @@ query groupsAutocomplete($search: String) { nodes { id name - fullName + fullPath avatarUrl } } diff --git a/app/assets/javascripts/graphql_shared/queries/projects_autocomplete.query.graphql b/app/assets/javascripts/graphql_shared/queries/projects_autocomplete.query.graphql index f306f598005f5c..ad05c67bd12aff 100644 --- a/app/assets/javascripts/graphql_shared/queries/projects_autocomplete.query.graphql +++ b/app/assets/javascripts/graphql_shared/queries/projects_autocomplete.query.graphql @@ -1,5 +1,5 @@ query projectsAutocomplete($search: String) { - projects(search: $search) { + projects(search: $search, searchNamespaces: true) { nodes { id name diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue index 915ae93108761a..02020827389dd0 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue @@ -346,6 +346,12 @@ export default { onInput(tokens) { this.$emit('onInput', this.removeQuotesEnclosure(uniqueTokens(tokens))); }, + onTokenComplete(token) { + this.$emit('token-complete', token); + }, + onTokenDestroy(token) { + this.$emit('token-destroy', token); + }, }, }; @@ -385,6 +391,8 @@ export default { @clear-history="handleClearHistory" @submit="handleFilterSubmit" @input="onInput" + @token-complete="onTokenComplete" + @token-destroy="onTokenDestroy" >