diff options
Diffstat (limited to 'app/assets/javascripts')
9 files changed, 134 insertions, 260 deletions
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index 1ceb3cb9828..e4cf5760987 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -135,7 +135,7 @@ export default { >{{ $options.i18n.newEnvironmentButtonLabel }}</gl-button > </div> - <gl-tabs content-class="gl-display-none"> + <gl-tabs :value="activeTab" content-class="gl-display-none"> <gl-tab v-for="(tab, idx) in tabs" :key="idx" diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index 280f5799503..c80839a117f 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -208,6 +208,9 @@ export default { }, ]; }, + activeTab() { + return this.tabs.findIndex(({ isActive }) => isActive) ?? 0; + }, }, /** diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue index 921af766796..051512e9a66 100644 --- a/app/assets/javascripts/issues_list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue @@ -16,7 +16,6 @@ import IssuableByEmail from '~/issuable/components/issuable_by_email.vue'; import IssuableList from '~/issuable_list/components/issuable_list_root.vue'; import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants'; import { - API_PARAM, CREATED_DESC, i18n, initialPageParams, @@ -25,7 +24,7 @@ import { PARAM_DUE_DATE, PARAM_SORT, PARAM_STATE, - RELATIVE_POSITION_DESC, + RELATIVE_POSITION_ASC, TOKEN_TYPE_ASSIGNEE, TOKEN_TYPE_AUTHOR, TOKEN_TYPE_CONFIDENTIAL, @@ -36,12 +35,12 @@ import { TOKEN_TYPE_MILESTONE, TOKEN_TYPE_WEIGHT, UPDATED_DESC, - URL_PARAM, urlSortParams, } from '~/issues_list/constants'; import { - convertToParams, + convertToApiParams, convertToSearchQuery, + convertToUrlParams, getDueDateValue, getFilterTokens, getSortKey, @@ -192,10 +191,10 @@ export default { ...this.apiFilterParams, }; }, - update: ({ project }) => project.issues.nodes, + update: ({ project }) => project?.issues.nodes ?? [], result({ data }) { - this.pageInfo = data.project.issues.pageInfo; - this.totalIssues = data.project.issues.count; + this.pageInfo = data.project?.issues.pageInfo ?? {}; + this.totalIssues = data.project?.issues.count ?? 0; this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery(); }, error(error) { @@ -215,32 +214,30 @@ export default { return this.showBulkEditSidebar || !this.issues.length; }, isManualOrdering() { - return this.sortKey === RELATIVE_POSITION_DESC; + return this.sortKey === RELATIVE_POSITION_ASC; }, isOpenTab() { return this.state === IssuableStates.Opened; }, apiFilterParams() { - return convertToParams(this.filterTokens, API_PARAM); + return convertToApiParams(this.filterTokens); }, urlFilterParams() { - return convertToParams(this.filterTokens, URL_PARAM); + return convertToUrlParams(this.filterTokens); }, searchQuery() { return convertToSearchQuery(this.filterTokens) || undefined; }, searchTokens() { - let preloadedAuthors = []; + const preloadedAuthors = []; if (gon.current_user_id) { - preloadedAuthors = [ - { - id: gon.current_user_id, - name: gon.current_user_fullname, - username: gon.current_username, - avatar_url: gon.current_user_avatar_url, - }, - ]; + preloadedAuthors.push({ + id: gon.current_user_id, + name: gon.current_user_fullname, + username: gon.current_username, + avatar_url: gon.current_user_avatar_url, + }); } const tokens = [ @@ -252,6 +249,7 @@ export default { dataType: 'user', unique: true, defaultAuthors: [], + operators: OPERATOR_IS_ONLY, fetchAuthors: this.fetchUsers, preloadedAuthors, }, @@ -280,7 +278,7 @@ export default { title: TOKEN_TITLE_LABEL, icon: 'labels', token: LabelToken, - defaultLabels: [], + defaultLabels: DEFAULT_NONE_ANY, fetchLabels: this.fetchLabels, }, ]; @@ -329,6 +327,7 @@ export default { token: EpicToken, unique: true, idProperty: 'id', + useIdValue: true, fetchEpics: this.fetchEpics, }); } @@ -346,7 +345,7 @@ export default { return tokens; }, showPaginationControls() { - return this.issues.length > 0; + return this.issues.length > 0 && (this.pageInfo.hasNextPage || this.pageInfo.hasPreviousPage); }, sortOptions() { return getSortOptions(this.hasIssueWeightsFeature, this.hasBlockedIssuesFeature); @@ -361,22 +360,12 @@ export default { ); }, urlParams() { - const filterParams = { - ...this.urlFilterParams, - }; - - if (filterParams.epic_id) { - filterParams.epic_id = encodeURIComponent(filterParams.epic_id); - } else if (filterParams['not[epic_id]']) { - filterParams['not[epic_id]'] = encodeURIComponent(filterParams['not[epic_id]']); - } - return { due_date: this.dueDateFilter, search: this.searchQuery, + sort: urlSortParams[this.sortKey], state: this.state, - ...urlSortParams[this.sortKey], - ...filterParams, + ...this.urlFilterParams, }; }, }, @@ -424,7 +413,10 @@ export default { return this.fetchWithCache(this.projectMilestonesPath, 'milestones', 'title', search, true); }, fetchIterations(search) { - return axios.get(this.projectIterationsPath, { params: { search } }); + const id = Number(search); + return !search || Number.isNaN(id) + ? axios.get(this.projectIterationsPath, { params: { search } }) + : axios.get(this.projectIterationsPath, { params: { id } }); }, fetchUsers(search) { return axios.get(this.autocompleteUsersPath, { params: { search } }); @@ -471,6 +463,7 @@ export default { this.state = state; }, handleFilter(filter) { + this.pageParams = initialPageParams; this.filterTokens = filter; }, handleNextPage() { diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js index 76006f9081d..6337ccc4926 100644 --- a/app/assets/javascripts/issues_list/constants.js +++ b/app/assets/javascripts/issues_list/constants.js @@ -128,21 +128,21 @@ export const CREATED_ASC = 'CREATED_ASC'; export const CREATED_DESC = 'CREATED_DESC'; export const DUE_DATE_ASC = 'DUE_DATE_ASC'; export const DUE_DATE_DESC = 'DUE_DATE_DESC'; +export const LABEL_PRIORITY_ASC = 'LABEL_PRIORITY_ASC'; export const LABEL_PRIORITY_DESC = 'LABEL_PRIORITY_DESC'; export const MILESTONE_DUE_ASC = 'MILESTONE_DUE_ASC'; export const MILESTONE_DUE_DESC = 'MILESTONE_DUE_DESC'; export const POPULARITY_ASC = 'POPULARITY_ASC'; export const POPULARITY_DESC = 'POPULARITY_DESC'; +export const PRIORITY_ASC = 'PRIORITY_ASC'; export const PRIORITY_DESC = 'PRIORITY_DESC'; -export const RELATIVE_POSITION_DESC = 'RELATIVE_POSITION_DESC'; +export const RELATIVE_POSITION_ASC = 'RELATIVE_POSITION_ASC'; export const UPDATED_ASC = 'UPDATED_ASC'; export const UPDATED_DESC = 'UPDATED_DESC'; export const WEIGHT_ASC = 'WEIGHT_ASC'; export const WEIGHT_DESC = 'WEIGHT_DESC'; -const SORT_ASC = 'asc'; -const SORT_DESC = 'desc'; - +const PRIORITY_ASC_SORT = 'priority_asc'; const CREATED_DATE_SORT = 'created_date'; const CREATED_ASC_SORT = 'created_asc'; const UPDATED_DESC_SORT = 'updated_desc'; @@ -150,129 +150,30 @@ const UPDATED_ASC_SORT = 'updated_asc'; const MILESTONE_SORT = 'milestone'; const MILESTONE_DUE_DESC_SORT = 'milestone_due_desc'; const DUE_DATE_DESC_SORT = 'due_date_desc'; +const LABEL_PRIORITY_ASC_SORT = 'label_priority_asc'; const POPULARITY_ASC_SORT = 'popularity_asc'; const WEIGHT_DESC_SORT = 'weight_desc'; const BLOCKING_ISSUES_DESC_SORT = 'blocking_issues_desc'; -const BLOCKING_ISSUES = 'blocking_issues'; - -export const apiSortParams = { - [PRIORITY_DESC]: { - order_by: PRIORITY, - sort: SORT_DESC, - }, - [CREATED_ASC]: { - order_by: CREATED_AT, - sort: SORT_ASC, - }, - [CREATED_DESC]: { - order_by: CREATED_AT, - sort: SORT_DESC, - }, - [UPDATED_ASC]: { - order_by: UPDATED_AT, - sort: SORT_ASC, - }, - [UPDATED_DESC]: { - order_by: UPDATED_AT, - sort: SORT_DESC, - }, - [MILESTONE_DUE_ASC]: { - order_by: MILESTONE_DUE, - sort: SORT_ASC, - }, - [MILESTONE_DUE_DESC]: { - order_by: MILESTONE_DUE, - sort: SORT_DESC, - }, - [DUE_DATE_ASC]: { - order_by: DUE_DATE, - sort: SORT_ASC, - }, - [DUE_DATE_DESC]: { - order_by: DUE_DATE, - sort: SORT_DESC, - }, - [POPULARITY_ASC]: { - order_by: POPULARITY, - sort: SORT_ASC, - }, - [POPULARITY_DESC]: { - order_by: POPULARITY, - sort: SORT_DESC, - }, - [LABEL_PRIORITY_DESC]: { - order_by: LABEL_PRIORITY, - sort: SORT_DESC, - }, - [RELATIVE_POSITION_DESC]: { - order_by: RELATIVE_POSITION, - per_page: 100, - sort: SORT_ASC, - }, - [WEIGHT_ASC]: { - order_by: WEIGHT, - sort: SORT_ASC, - }, - [WEIGHT_DESC]: { - order_by: WEIGHT, - sort: SORT_DESC, - }, - [BLOCKING_ISSUES_DESC]: { - order_by: BLOCKING_ISSUES, - sort: SORT_DESC, - }, -}; export const urlSortParams = { - [PRIORITY_DESC]: { - sort: PRIORITY, - }, - [CREATED_ASC]: { - sort: CREATED_ASC_SORT, - }, - [CREATED_DESC]: { - sort: CREATED_DATE_SORT, - }, - [UPDATED_ASC]: { - sort: UPDATED_ASC_SORT, - }, - [UPDATED_DESC]: { - sort: UPDATED_DESC_SORT, - }, - [MILESTONE_DUE_ASC]: { - sort: MILESTONE_SORT, - }, - [MILESTONE_DUE_DESC]: { - sort: MILESTONE_DUE_DESC_SORT, - }, - [DUE_DATE_ASC]: { - sort: DUE_DATE, - }, - [DUE_DATE_DESC]: { - sort: DUE_DATE_DESC_SORT, - }, - [POPULARITY_ASC]: { - sort: POPULARITY_ASC_SORT, - }, - [POPULARITY_DESC]: { - sort: POPULARITY, - }, - [LABEL_PRIORITY_DESC]: { - sort: LABEL_PRIORITY, - }, - [RELATIVE_POSITION_DESC]: { - sort: RELATIVE_POSITION, - per_page: 100, - }, - [WEIGHT_ASC]: { - sort: WEIGHT, - }, - [WEIGHT_DESC]: { - sort: WEIGHT_DESC_SORT, - }, - [BLOCKING_ISSUES_DESC]: { - sort: BLOCKING_ISSUES_DESC_SORT, - }, + [PRIORITY_ASC]: PRIORITY_ASC_SORT, + [PRIORITY_DESC]: PRIORITY, + [CREATED_ASC]: CREATED_ASC_SORT, + [CREATED_DESC]: CREATED_DATE_SORT, + [UPDATED_ASC]: UPDATED_ASC_SORT, + [UPDATED_DESC]: UPDATED_DESC_SORT, + [MILESTONE_DUE_ASC]: MILESTONE_SORT, + [MILESTONE_DUE_DESC]: MILESTONE_DUE_DESC_SORT, + [DUE_DATE_ASC]: DUE_DATE, + [DUE_DATE_DESC]: DUE_DATE_DESC_SORT, + [POPULARITY_ASC]: POPULARITY_ASC_SORT, + [POPULARITY_DESC]: POPULARITY, + [LABEL_PRIORITY_ASC]: LABEL_PRIORITY_ASC_SORT, + [LABEL_PRIORITY_DESC]: LABEL_PRIORITY, + [RELATIVE_POSITION_ASC]: RELATIVE_POSITION, + [WEIGHT_ASC]: WEIGHT, + [WEIGHT_DESC]: WEIGHT_DESC_SORT, + [BLOCKING_ISSUES_DESC]: BLOCKING_ISSUES_DESC_SORT, }; export const MAX_LIST_SIZE = 10; @@ -297,12 +198,7 @@ export const TOKEN_TYPE_WEIGHT = 'weight'; export const filters = { [TOKEN_TYPE_AUTHOR]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'author_username', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[author_username]', - }, + [NORMAL_FILTER]: 'authorUsername', }, [URL_PARAM]: { [OPERATOR_IS]: { @@ -315,13 +211,8 @@ export const filters = { }, [TOKEN_TYPE_ASSIGNEE]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'assignee_username', - [SPECIAL_FILTER]: 'assignee_id', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[assignee_username]', - }, + [NORMAL_FILTER]: 'assigneeUsernames', + [SPECIAL_FILTER]: 'assigneeId', }, [URL_PARAM]: { [OPERATOR_IS]: { @@ -336,12 +227,7 @@ export const filters = { }, [TOKEN_TYPE_MILESTONE]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'milestone', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[milestone]', - }, + [NORMAL_FILTER]: 'milestoneTitle', }, [URL_PARAM]: { [OPERATOR_IS]: { @@ -354,16 +240,13 @@ export const filters = { }, [TOKEN_TYPE_LABEL]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'labels', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[labels]', - }, + [NORMAL_FILTER]: 'labelName', + [SPECIAL_FILTER]: 'labelName', }, [URL_PARAM]: { [OPERATOR_IS]: { [NORMAL_FILTER]: 'label_name[]', + [SPECIAL_FILTER]: 'label_name[]', }, [OPERATOR_IS_NOT]: { [NORMAL_FILTER]: 'not[label_name][]', @@ -372,10 +255,8 @@ export const filters = { }, [TOKEN_TYPE_MY_REACTION]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'my_reaction_emoji', - [SPECIAL_FILTER]: 'my_reaction_emoji', - }, + [NORMAL_FILTER]: 'myReactionEmoji', + [SPECIAL_FILTER]: 'myReactionEmoji', }, [URL_PARAM]: { [OPERATOR_IS]: { @@ -386,9 +267,7 @@ export const filters = { }, [TOKEN_TYPE_CONFIDENTIAL]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'confidential', - }, + [NORMAL_FILTER]: 'confidential', }, [URL_PARAM]: { [OPERATOR_IS]: { @@ -398,33 +277,23 @@ export const filters = { }, [TOKEN_TYPE_ITERATION]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'iteration_title', - [SPECIAL_FILTER]: 'iteration_id', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[iteration_title]', - }, + [NORMAL_FILTER]: 'iterationId', + [SPECIAL_FILTER]: 'iterationWildcardId', }, [URL_PARAM]: { [OPERATOR_IS]: { - [NORMAL_FILTER]: 'iteration_title', + [NORMAL_FILTER]: 'iteration_id', [SPECIAL_FILTER]: 'iteration_id', }, [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[iteration_title]', + [NORMAL_FILTER]: 'not[iteration_id]', }, }, }, [TOKEN_TYPE_EPIC]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'epic_id', - [SPECIAL_FILTER]: 'epic_id', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[epic_id]', - }, + [NORMAL_FILTER]: 'epicId', + [SPECIAL_FILTER]: 'epicId', }, [URL_PARAM]: { [OPERATOR_IS]: { @@ -438,13 +307,8 @@ export const filters = { }, [TOKEN_TYPE_WEIGHT]: { [API_PARAM]: { - [OPERATOR_IS]: { - [NORMAL_FILTER]: 'weight', - [SPECIAL_FILTER]: 'weight', - }, - [OPERATOR_IS_NOT]: { - [NORMAL_FILTER]: 'not[weight]', - }, + [NORMAL_FILTER]: 'weight', + [SPECIAL_FILTER]: 'weight', }, [URL_PARAM]: { [OPERATOR_IS]: { diff --git a/app/assets/javascripts/issues_list/utils.js b/app/assets/javascripts/issues_list/utils.js index b5ec44198da..49f937cc453 100644 --- a/app/assets/javascripts/issues_list/utils.js +++ b/app/assets/javascripts/issues_list/utils.js @@ -1,4 +1,5 @@ import { + API_PARAM, BLOCKING_ISSUES_DESC, CREATED_ASC, CREATED_DESC, @@ -6,29 +7,36 @@ import { DUE_DATE_DESC, DUE_DATE_VALUES, filters, + LABEL_PRIORITY_ASC, LABEL_PRIORITY_DESC, MILESTONE_DUE_ASC, MILESTONE_DUE_DESC, NORMAL_FILTER, POPULARITY_ASC, POPULARITY_DESC, + PRIORITY_ASC, PRIORITY_DESC, - RELATIVE_POSITION_DESC, + RELATIVE_POSITION_ASC, SPECIAL_FILTER, SPECIAL_FILTER_VALUES, TOKEN_TYPE_ASSIGNEE, + TOKEN_TYPE_ITERATION, UPDATED_ASC, UPDATED_DESC, + URL_PARAM, urlSortParams, WEIGHT_ASC, WEIGHT_DESC, } from '~/issues_list/constants'; import { isPositiveInteger } from '~/lib/utils/number_utils'; import { __ } from '~/locale'; -import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants'; +import { + FILTERED_SEARCH_TERM, + OPERATOR_IS_NOT, +} from '~/vue_shared/components/filtered_search_bar/constants'; export const getSortKey = (sort) => - Object.keys(urlSortParams).find((key) => urlSortParams[key].sort === sort); + Object.keys(urlSortParams).find((key) => urlSortParams[key] === sort); export const getDueDateValue = (value) => (DUE_DATE_VALUES.includes(value) ? value : undefined); @@ -38,7 +46,7 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) id: 1, title: __('Priority'), sortDirection: { - ascending: PRIORITY_DESC, + ascending: PRIORITY_ASC, descending: PRIORITY_DESC, }, }, @@ -86,7 +94,7 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) id: 7, title: __('Label priority'), sortDirection: { - ascending: LABEL_PRIORITY_DESC, + ascending: LABEL_PRIORITY_ASC, descending: LABEL_PRIORITY_DESC, }, }, @@ -94,8 +102,8 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) id: 8, title: __('Manual'), sortDirection: { - ascending: RELATIVE_POSITION_DESC, - descending: RELATIVE_POSITION_DESC, + ascending: RELATIVE_POSITION_ASC, + descending: RELATIVE_POSITION_ASC, }, }, ]; @@ -128,7 +136,7 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) const tokenTypes = Object.keys(filters); const getUrlParams = (tokenType) => - Object.values(filters[tokenType].urlParam).flatMap((filterObj) => Object.values(filterObj)); + Object.values(filters[tokenType][URL_PARAM]).flatMap((filterObj) => Object.values(filterObj)); const urlParamKeys = tokenTypes.flatMap(getUrlParams); @@ -136,7 +144,7 @@ const getTokenTypeFromUrlParamKey = (urlParamKey) => tokenTypes.find((tokenType) => getUrlParams(tokenType).includes(urlParamKey)); const getOperatorFromUrlParamKey = (tokenType, urlParamKey) => - Object.entries(filters[tokenType].urlParam).find(([, filterObj]) => + Object.entries(filters[tokenType][URL_PARAM]).find(([, filterObj]) => Object.values(filterObj).includes(urlParamKey), )[0]; @@ -178,12 +186,36 @@ const getFilterType = (data, tokenType = '') => ? SPECIAL_FILTER : NORMAL_FILTER; -export const convertToParams = (filterTokens, paramType) => +const isIterationSpecialValue = (tokenType, value) => + tokenType === TOKEN_TYPE_ITERATION && SPECIAL_FILTER_VALUES.includes(value); + +export const convertToApiParams = (filterTokens) => { + const params = {}; + const not = {}; + + filterTokens + .filter((token) => token.type !== FILTERED_SEARCH_TERM) + .forEach((token) => { + const filterType = getFilterType(token.value.data, token.type); + const field = filters[token.type][API_PARAM][filterType]; + const obj = token.value.operator === OPERATOR_IS_NOT ? not : params; + const data = isIterationSpecialValue(token.type, token.value.data) + ? token.value.data.toUpperCase() + : token.value.data; + Object.assign(obj, { + [field]: obj[field] ? [obj[field], data].flat() : data, + }); + }); + + return Object.keys(not).length ? Object.assign(params, { not }) : params; +}; + +export const convertToUrlParams = (filterTokens) => filterTokens .filter((token) => token.type !== FILTERED_SEARCH_TERM) .reduce((acc, token) => { const filterType = getFilterType(token.value.data, token.type); - const param = filters[token.type][paramType][token.value.operator]?.[filterType]; + const param = filters[token.type][URL_PARAM][token.value.operator]?.[filterType]; return Object.assign(acc, { [param]: acc[param] ? [acc[param], token.value.data].flat() : token.value.data, }); diff --git a/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue b/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue index cac8fecb6b1..97856eaf256 100644 --- a/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue +++ b/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue @@ -72,7 +72,7 @@ export default { <template> <div class="gl-display-flex gl-align-items-stretch"> <div - class="gl-w-grid-size-30 gl-flex-shrink-0 gl-bg-gray-10 gl-py-3 gl-px-5" + class="gl-w-grid-size-30 gl-flex-shrink-0 gl-bg-gray-10 gl-p-3" :class="menuClass" data-testid="menu-sidebar" > @@ -81,7 +81,7 @@ export default { <keep-alive-slots v-show="activeView" :slot-key="activeView" - class="gl-w-grid-size-40 gl-overflow-hidden gl-py-3 gl-px-5" + class="gl-w-grid-size-40 gl-overflow-hidden gl-p-3" data-testid="menu-subview" data-qa-selector="menu_subview_container" > diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue index d21fa9a344a..5b05187955c 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue @@ -56,7 +56,7 @@ export default { } // Current value is a string. - const [groupPath, idProperty] = this.currentValue?.split('::&'); + const [groupPath, idProperty] = this.currentValue?.split(this.$options.separator); return this.epics.find( (epic) => epic.group_full_path === groupPath && @@ -65,6 +65,9 @@ export default { } return null; }, + displayText() { + return `${this.activeEpic?.title}${this.$options.separator}${this.activeEpic?.iid}`; + }, }, watch: { active: { @@ -103,8 +106,10 @@ export default { this.fetchEpicsBySearchTerm({ epicPath, search: data }); }, DEBOUNCE_DELAY), - getEpicDisplayText(epic) { - return `${epic.title}${this.$options.separator}${epic.iid}`; + getValue(epic) { + return this.config.useIdValue + ? String(epic[this.idProperty]) + : `${epic.group_full_path}${this.$options.separator}${epic[this.idProperty]}`; }, }, }; @@ -118,7 +123,7 @@ export default { @input="searchEpics" > <template #view="{ inputValue }"> - {{ activeEpic ? getEpicDisplayText(activeEpic) : inputValue }} + {{ activeEpic ? displayText : inputValue }} </template> <template #suggestions> <gl-filtered-search-suggestion @@ -131,11 +136,7 @@ export default { <gl-dropdown-divider v-if="defaultEpics.length" /> <gl-loading-icon v-if="loading" /> <template v-else> - <gl-filtered-search-suggestion - v-for="epic in epics" - :key="epic.id" - :value="`${epic.group_full_path}::&${epic[idProperty]}`" - > + <gl-filtered-search-suggestion v-for="epic in epics" :key="epic.id" :value="getValue(epic)"> {{ epic.title }} </gl-filtered-search-suggestion> </template> diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue index 7b6a590279a..cdb04ea79e1 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue @@ -30,7 +30,6 @@ export default { data() { return { iterations: this.config.initialIterations || [], - defaultIterations: this.config.defaultIterations || DEFAULT_ITERATIONS, loading: true, }; }, @@ -39,7 +38,10 @@ export default { return this.value.data; }, activeIteration() { - return this.iterations.find((iteration) => iteration.title === this.currentValue); + return this.iterations.find((iteration) => iteration.id === Number(this.currentValue)); + }, + defaultIterations() { + return this.config.defaultIterations || DEFAULT_ITERATIONS; }, }, watch: { @@ -99,8 +101,8 @@ export default { <template v-else> <gl-filtered-search-suggestion v-for="iteration in iterations" - :key="iteration.title" - :value="iteration.title" + :key="iteration.id" + :value="String(iteration.id)" > {{ iteration.title }} </gl-filtered-search-suggestion> diff --git a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue index 04e44aa2ed1..b85cae0c64f 100644 --- a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue +++ b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue @@ -96,9 +96,6 @@ export default { }, }, searchUsers: { - // TODO Remove error policy - // https://gitlab.com/gitlab-org/gitlab/-/issues/329750 - errorPolicy: 'all', query: searchUsers, variables() { return { @@ -111,28 +108,10 @@ export default { return !this.isEditing; }, update(data) { - // TODO Remove null filter (BE fix required) - // https://gitlab.com/gitlab-org/gitlab/-/issues/329750 return data.workspace?.users?.nodes.filter((x) => x?.user).map(({ user }) => user) || []; }, debounce: ASSIGNEES_DEBOUNCE_DELAY, - error({ graphQLErrors }) { - // TODO This error suppression is temporary (BE fix required) - // https://gitlab.com/gitlab-org/gitlab/-/issues/329750 - const isNullError = ({ message }) => { - return message === 'Cannot return null for non-nullable field GroupMember.user'; - }; - - if (graphQLErrors?.length > 0 && graphQLErrors.every(isNullError)) { - // only null-related errors exist, suppress them. - // eslint-disable-next-line no-console - console.error( - "Suppressing the error 'Cannot return null for non-nullable field GroupMember.user'. Please see https://gitlab.com/gitlab-org/gitlab/-/issues/329750", - ); - this.isSearching = false; - return; - } - + error() { this.$emit('error'); this.isSearching = false; }, |