Skip to content

Commit deba779

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent 747345d commit deba779

File tree

78 files changed

+1662
-323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1662
-323
lines changed

.rubocop_todo/rspec/feature_category.yml

-1
Original file line numberDiff line numberDiff line change
@@ -4187,7 +4187,6 @@ RSpec/FeatureCategory:
41874187
- 'spec/views/shared/_label_row.html.haml_spec.rb'
41884188
- 'spec/views/shared/_milestones_sort_dropdown.html.haml_spec.rb'
41894189
- 'spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb'
4190-
- 'spec/views/shared/groups/_dropdown.html.haml_spec.rb'
41914190
- 'spec/views/shared/issuable/_sidebar.html.haml_spec.rb'
41924191
- 'spec/views/shared/milestones/_issuable.html.haml_spec.rb'
41934192
- 'spec/views/shared/milestones/_issuables.html.haml_spec.rb'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<script>
2+
import FilteredSearchAndSort from '~/groups_projects/components/filtered_search_and_sort.vue';
3+
import {
4+
FILTERED_SEARCH_NAMESPACE,
5+
FILTERED_SEARCH_TERM_KEY,
6+
SORT_DIRECTION_ASC,
7+
SORT_DIRECTION_DESC,
8+
SORT_OPTION_CREATED_DATE,
9+
SORT_OPTIONS,
10+
} from '~/admin/groups/constants';
11+
import { RECENT_SEARCHES_STORAGE_KEY_GROUPS } from '~/filtered_search/recent_searches_storage_keys';
12+
import { objectToQuery, queryToObject, visitUrl } from '~/lib/utils/url_utility';
13+
14+
export default {
15+
components: {
16+
FilteredSearchAndSort,
17+
},
18+
computed: {
19+
defaultSortOption() {
20+
return SORT_OPTION_CREATED_DATE;
21+
},
22+
defaultSortBy() {
23+
return `${this.defaultSortOption.value}_${SORT_DIRECTION_DESC}`;
24+
},
25+
queryAsObject() {
26+
return queryToObject(document.location.search);
27+
},
28+
queryAsObjectWithoutPagination() {
29+
const { page, ...queryAsObject } = this.queryAsObject;
30+
return queryAsObject;
31+
},
32+
sortByQuery() {
33+
return this.queryAsObject.sort;
34+
},
35+
sortBy() {
36+
return this.sortByQuery || this.defaultSortBy;
37+
},
38+
sortOptions() {
39+
return SORT_OPTIONS;
40+
},
41+
activeSortOption() {
42+
return (
43+
this.sortOptions.find((option) => this.sortBy.includes(option.value)) ||
44+
this.defaultSortOption
45+
);
46+
},
47+
isAscending() {
48+
return this.sortBy.endsWith(SORT_DIRECTION_ASC);
49+
},
50+
},
51+
methods: {
52+
visitUrlWithQueryObject(queryObject) {
53+
return visitUrl(`?${objectToQuery(queryObject)}`);
54+
},
55+
onSortChange(sortBy, isAscending) {
56+
const sort = `${sortBy}_${isAscending ? SORT_DIRECTION_ASC : SORT_DIRECTION_DESC}`;
57+
this.visitUrlWithQueryObject({ ...this.queryAsObjectWithoutPagination, sort });
58+
},
59+
onSortDirectionChange(isAscending) {
60+
this.onSortChange(this.activeSortOption.value, isAscending);
61+
},
62+
onSortByChange(sortBy) {
63+
this.onSortChange(sortBy, this.isAscending);
64+
},
65+
onFilter(filtersQuery) {
66+
const queryObject = { ...filtersQuery };
67+
68+
if (this.sortByQuery) {
69+
queryObject.sort = this.sortByQuery;
70+
}
71+
72+
this.visitUrlWithQueryObject(queryObject);
73+
},
74+
},
75+
filteredSearch: {
76+
recentSearchesStorageKey: RECENT_SEARCHES_STORAGE_KEY_GROUPS,
77+
namespace: FILTERED_SEARCH_NAMESPACE,
78+
termKey: FILTERED_SEARCH_TERM_KEY,
79+
tokens: [],
80+
},
81+
};
82+
</script>
83+
84+
<template>
85+
<div class="gl-mb-4" data-testid="admin-groups-filtered-search-and-sort">
86+
<filtered-search-and-sort
87+
:filtered-search-namespace="$options.filteredSearch.namespace"
88+
:filtered-search-tokens="$options.filteredSearch.tokens"
89+
:filtered-search-term-key="$options.filteredSearch.termKey"
90+
:filtered-search-recent-searches-storage-key="
91+
$options.filteredSearch.recentSearchesStorageKey
92+
"
93+
:is-ascending="isAscending"
94+
:sort-options="sortOptions"
95+
:active-sort-option="activeSortOption"
96+
:filtered-search-query="queryAsObject"
97+
@filter="onFilter"
98+
@sort-direction-change="onSortDirectionChange"
99+
@sort-by-change="onSortByChange"
100+
/>
101+
</div>
102+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { __ } from '~/locale';
2+
3+
export const FILTERED_SEARCH_NAMESPACE = 'admin-groups';
4+
export const FILTERED_SEARCH_TERM_KEY = 'name';
5+
6+
export const SORT_DIRECTION_ASC = 'asc';
7+
export const SORT_DIRECTION_DESC = 'desc';
8+
9+
const NAME = 'name';
10+
const CREATED = 'created';
11+
const LATEST_ACTIVITY = 'latest_activity';
12+
const STORAGE_SIZE = 'storage_size';
13+
14+
export const SORT_OPTION_NAME = {
15+
text: __('Name'),
16+
value: NAME,
17+
};
18+
19+
export const SORT_OPTION_CREATED_DATE = {
20+
text: __('Created date'),
21+
value: CREATED,
22+
};
23+
24+
export const SORT_OPTION_UPDATED_DATE = {
25+
text: __('Updated date'),
26+
value: LATEST_ACTIVITY,
27+
};
28+
29+
export const SORT_OPTION_STORAGE_SIZE = {
30+
text: __('Storage size'),
31+
value: STORAGE_SIZE,
32+
};
33+
34+
export const SORT_OPTIONS = [
35+
SORT_OPTION_NAME,
36+
SORT_OPTION_CREATED_DATE,
37+
SORT_OPTION_UPDATED_DATE,
38+
SORT_OPTION_STORAGE_SIZE,
39+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Vue from 'vue';
2+
import FilteredSearchAndSort from './components/filtered_search_and_sort.vue';
3+
4+
export const initAdminGroupsFilteredSearchAndSort = () => {
5+
const el = document.getElementById('js-admin-groups-filtered-search-and-sort');
6+
7+
if (!el) return false;
8+
9+
return new Vue({
10+
el,
11+
name: 'AdminGroupsFilteredSearchAndSort',
12+
render(createElement) {
13+
return createElement(FilteredSearchAndSort);
14+
},
15+
});
16+
};

app/assets/javascripts/ci/runner/components/registration/gke_node_pool_group.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ export default {
199199
<code>&lt;name&gt;_&lt;type(optional)&gt;</code>
200200
</template>
201201
<template #example>
202-
<code>ubuntu</code>
202+
<code>ubuntu_containerd</code>
203203
</template>
204204
<!-- eslint-enable @gitlab/vue-require-i18n-strings -->
205205
</gl-sprintf>

app/assets/javascripts/merge_request_dashboard/components/app.vue

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script>
22
import { GlButton, GlIcon, GlAlert, GlTabs, GlTab, GlLink } from '@gitlab/ui';
3+
import TabTitle from './tab_title.vue';
34
import MergeRequestsQuery from './merge_requests_query.vue';
45
import CollapsibleSection from './collapsible_section.vue';
56
import MergeRequest from './merge_request.vue';
@@ -12,6 +13,7 @@ export default {
1213
GlTabs,
1314
GlTab,
1415
GlLink,
16+
TabTitle,
1517
MergeRequestsQuery,
1618
CollapsibleSection,
1719
MergeRequest,
@@ -33,6 +35,11 @@ export default {
3335
this.currentTab = key;
3436
this.$router.push({ path: key || '/' });
3537
},
38+
queriesForTab(tab) {
39+
return tab.lists
40+
.filter((l) => !l.hideCount)
41+
.map((list) => ({ query: list.query, variables: list.variables }));
42+
},
3643
},
3744
};
3845
</script>
@@ -43,22 +50,24 @@ export default {
4350
<gl-tab
4451
v-for="tab in tabs"
4552
:key="tab.title"
46-
:title="tab.title"
4753
:active="tab.key === currentTab"
4854
lazy
4955
@click="clickTab(tab)"
5056
>
57+
<template #title>
58+
<tab-title :title="tab.title" :queries="queriesForTab(tab)" :tab-key="tab.key" />
59+
</template>
5160
<merge-requests-query
5261
v-for="(list, i) in tab.lists"
5362
:key="`list_${i}`"
5463
:query="list.query"
5564
:variables="list.variables"
65+
:hide-count="list.hideCount"
5666
:class="{ 'gl-mb-4': i !== tab.lists.length - 1 }"
5767
>
5868
<template #default="{ mergeRequests, count, hasNextPage, loadMore, loading, error }">
5969
<collapsible-section
6070
:count="count"
61-
:loading="loading || error"
6271
:title="list.title"
6372
:help-content="list.helpContent"
6473
>

app/assets/javascripts/merge_request_dashboard/components/collapsible_section.vue

+8-8
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ export default {
2525
required: false,
2626
default: null,
2727
},
28-
loading: {
29-
type: Boolean,
30-
required: false,
31-
default: false,
32-
},
3328
},
3429
data() {
3530
return {
@@ -86,9 +81,14 @@ export default {
8681
@click="toggleOpen"
8782
/>
8883
{{ title }}
89-
<gl-badge v-if="!loading || count" class="gl-ml-1" variant="neutral" size="sm">{{
90-
count
91-
}}</gl-badge>
84+
<gl-badge
85+
v-if="count !== null"
86+
class="gl-ml-1"
87+
variant="neutral"
88+
size="sm"
89+
data-testid="merge-request-list-count"
90+
>{{ count }}</gl-badge
91+
>
9292
<gl-button
9393
v-gl-tooltip
9494
:title="helpContent"

app/assets/javascripts/merge_request_dashboard/components/merge_requests_query.vue

+12-15
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
<script>
2-
import reviewerQuery from '../queries/reviewer.query.graphql';
3-
import reviewerCountQuery from '../queries/reviewer_count.query.graphql';
4-
import assigneeQuery from '../queries/assignee.query.graphql';
5-
import assigneeCountQuery from '../queries/assignee_count.query.graphql';
6-
import assigneeOrReviewerQuery from '../queries/assignee_or_reviewer.query.graphql';
7-
import assigneeOrReviewerCountQuery from '../queries/assignee_or_reviewer_count.query.graphql';
2+
import { QUERIES } from '../constants';
83
94
const PER_PAGE = 20;
105
11-
const QUERIES = {
12-
reviewRequestedMergeRequests: { dataQuery: reviewerQuery, countQuery: reviewerCountQuery },
13-
assignedMergeRequests: { dataQuery: assigneeQuery, countQuery: assigneeCountQuery },
14-
assigneeOrReviewerMergeRequests: {
15-
dataQuery: assigneeOrReviewerQuery,
16-
countQuery: assigneeOrReviewerCountQuery,
17-
},
18-
};
19-
206
export default {
217
apollo: {
228
mergeRequests: {
@@ -37,6 +23,9 @@ export default {
3723
},
3824
},
3925
count: {
26+
context: {
27+
batchKey: 'MergeRequestListsCounts',
28+
},
4029
query() {
4130
return QUERIES[this.query].countQuery;
4231
},
@@ -49,6 +38,9 @@ export default {
4938
perPage: PER_PAGE,
5039
};
5140
},
41+
skip() {
42+
return this.hideCount;
43+
},
5244
},
5345
},
5446
props: {
@@ -60,6 +52,11 @@ export default {
6052
type: Object,
6153
required: true,
6254
},
55+
hideCount: {
56+
type: Boolean,
57+
required: false,
58+
default: false,
59+
},
6360
},
6461
data() {
6562
return {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<script>
2+
import { GlBadge } from '@gitlab/ui';
3+
import { QUERIES } from '../constants';
4+
5+
export default {
6+
components: { GlBadge },
7+
props: {
8+
title: {
9+
type: String,
10+
required: true,
11+
},
12+
queries: {
13+
type: Array,
14+
required: true,
15+
},
16+
tabKey: {
17+
type: String,
18+
required: true,
19+
},
20+
},
21+
data() {
22+
return {
23+
loading: true,
24+
count: 0,
25+
};
26+
},
27+
async mounted() {
28+
this.fetchAllCounts();
29+
},
30+
methods: {
31+
async fetchAllCounts() {
32+
const counts = await Promise.all(
33+
this.queries.map(({ query, variables }) => this.fetchCount({ query, variables })),
34+
);
35+
36+
this.count = counts.reduce((acc, { data }) => acc + data.currentUser.mergeRequests.count, 0);
37+
this.loading = false;
38+
},
39+
fetchCount({ query, variables }) {
40+
return this.$apollo.query({
41+
query: QUERIES[query].countQuery,
42+
variables,
43+
context: { batchKey: `MergeRequestTabsCounts_${this.tabKey}` },
44+
});
45+
},
46+
},
47+
};
48+
</script>
49+
50+
<template>
51+
<span>
52+
{{ title }}
53+
<gl-badge class="gl-tab-counter-badge" data-testid="tab-count">{{
54+
loading ? '-' : count
55+
}}</gl-badge>
56+
</span>
57+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import reviewerQuery from './queries/reviewer.query.graphql';
2+
import reviewerCountQuery from './queries/reviewer_count.query.graphql';
3+
import assigneeQuery from './queries/assignee.query.graphql';
4+
import assigneeCountQuery from './queries/assignee_count.query.graphql';
5+
import assigneeOrReviewerQuery from './queries/assignee_or_reviewer.query.graphql';
6+
import assigneeOrReviewerCountQuery from './queries/assignee_or_reviewer_count.query.graphql';
7+
8+
export const QUERIES = {
9+
reviewRequestedMergeRequests: { dataQuery: reviewerQuery, countQuery: reviewerCountQuery },
10+
assignedMergeRequests: { dataQuery: assigneeQuery, countQuery: assigneeCountQuery },
11+
assigneeOrReviewerMergeRequests: {
12+
dataQuery: assigneeOrReviewerQuery,
13+
countQuery: assigneeOrReviewerCountQuery,
14+
},
15+
};
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
import initConfirmDanger from '~/init_confirm_danger';
2+
import { initAdminGroupsFilteredSearchAndSort } from '~/admin/groups/index';
23

34
initConfirmDanger();
5+
initAdminGroupsFilteredSearchAndSort();

0 commit comments

Comments
 (0)