Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-12-07 03:08:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-07 03:08:34 +0300
commit7e89568aa1b1c531aa34860fbd9e77d9e988b9b2 (patch)
tree9d644d947b75594d969f040ef046541c769e0dc3 /app/assets/javascripts/issues
parentf2143c9986ad7b6206b8a41cc9aeb419e543d3f5 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/issues')
-rw-r--r--app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue78
-rw-r--r--app/assets/javascripts/issues/dashboard/index.js2
-rw-r--r--app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql2
-rw-r--r--app/assets/javascripts/issues/list/components/issues_list_app.vue18
-rw-r--r--app/assets/javascripts/issues/list/constants.js20
-rw-r--r--app/assets/javascripts/issues/list/queries/get_issues.query.graphql3
6 files changed, 114 insertions, 9 deletions
diff --git a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue
index 080f1fe222c..5e2bd096534 100644
--- a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue
+++ b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue
@@ -5,9 +5,17 @@ import getIssuesQuery from 'ee_else_ce/issues/dashboard/queries/get_issues.query
import IssueCardStatistics from 'ee_else_ce/issues/list/components/issue_card_statistics.vue';
import IssueCardTimeInfo from 'ee_else_ce/issues/list/components/issue_card_time_info.vue';
import { IssuableStatus } from '~/issues/constants';
-import { PAGE_SIZE } from '~/issues/list/constants';
-import { getInitialPageParams } from '~/issues/list/utils';
+import {
+ CREATED_DESC,
+ PAGE_SIZE,
+ PARAM_STATE,
+ UPDATED_DESC,
+ urlSortParams,
+} from '~/issues/list/constants';
+import setSortPreferenceMutation from '~/issues/list/queries/set_sort_preference.mutation.graphql';
+import { getInitialPageParams, getSortKey, getSortOptions, isSortKey } from '~/issues/list/utils';
import { scrollUp } from '~/lib/utils/scroll_utils';
+import { getParameterByName } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants';
@@ -17,13 +25,10 @@ export default {
calendarButtonText: __('Subscribe to calendar'),
closed: __('CLOSED'),
closedMoved: __('CLOSED (MOVED)'),
- downvotes: __('Downvotes'),
emptyStateTitle: __('Please select at least one filter to see results'),
errorFetchingIssues: __('An error occurred while loading issues'),
- relatedMergeRequests: __('Related merge requests'),
rssButtonText: __('Subscribe to RSS feed'),
searchInputPlaceholder: __('Search or filter results...'),
- upvotes: __('Upvotes'),
},
IssuableListTabs,
components: {
@@ -39,20 +44,35 @@ export default {
inject: [
'calendarPath',
'emptyStateSvgPath',
+ 'hasBlockedIssuesFeature',
+ 'hasIssuableHealthStatusFeature',
+ 'hasIssueWeightsFeature',
'hasScopedLabelsFeature',
+ 'initialSort',
'isPublicVisibilityRestricted',
'isSignedIn',
'rssPath',
],
data() {
+ const state = getParameterByName(PARAM_STATE);
+
+ const defaultSortKey = state === IssuableStates.Closed ? UPDATED_DESC : CREATED_DESC;
+ const dashboardSortKey = getSortKey(this.initialSort);
+ const graphQLSortKey =
+ isSortKey(this.initialSort?.toUpperCase()) && this.initialSort.toUpperCase();
+
+ // The initial sort is an old enum value when it is saved on the dashboard issues page.
+ // The initial sort is a GraphQL enum value when it is saved on the Vue issues list page.
+ const sortKey = dashboardSortKey || graphQLSortKey || defaultSortKey;
+
return {
issues: [],
issuesError: null,
pageInfo: {},
pageParams: getInitialPageParams(),
searchTokens: [],
- sortOptions: [],
- state: IssuableStates.Opened,
+ sortKey,
+ state: state || IssuableStates.Opened,
};
},
apollo: {
@@ -62,6 +82,7 @@ export default {
return {
hideUsers: this.isPublicVisibilityRestricted && !this.isSignedIn,
isSignedIn: this.isSignedIn,
+ sort: this.sortKey,
state: this.state,
...this.pageParams,
};
@@ -82,6 +103,19 @@ export default {
showPaginationControls() {
return this.issues.length > 0 && (this.pageInfo.hasNextPage || this.pageInfo.hasPreviousPage);
},
+ sortOptions() {
+ return getSortOptions({
+ hasBlockedIssuesFeature: this.hasBlockedIssuesFeature,
+ hasIssuableHealthStatusFeature: this.hasIssuableHealthStatusFeature,
+ hasIssueWeightsFeature: this.hasIssueWeightsFeature,
+ });
+ },
+ urlParams() {
+ return {
+ sort: urlSortParams[this.sortKey],
+ state: this.state,
+ };
+ },
},
methods: {
getStatus(issue) {
@@ -117,6 +151,33 @@ export default {
};
scrollUp();
},
+ handleSort(sortKey) {
+ if (this.sortKey === sortKey) {
+ return;
+ }
+
+ this.pageParams = getInitialPageParams();
+ this.sortKey = sortKey;
+
+ if (this.isSignedIn) {
+ this.saveSortPreference(sortKey);
+ }
+ },
+ saveSortPreference(sortKey) {
+ this.$apollo
+ .mutate({
+ mutation: setSortPreferenceMutation,
+ variables: { input: { issuesSort: sortKey } },
+ })
+ .then(({ data }) => {
+ if (data.userPreferencesUpdate.errors.length) {
+ throw new Error(data.userPreferencesUpdate.errors);
+ }
+ })
+ .catch((error) => {
+ Sentry.captureException(error);
+ });
+ },
},
};
</script>
@@ -128,6 +189,7 @@ export default {
:has-next-page="pageInfo.hasNextPage"
:has-previous-page="pageInfo.hasPreviousPage"
:has-scoped-labels-feature="hasScopedLabelsFeature"
+ :initial-sort-by="sortKey"
:issuables="issues"
:issuables-loading="$apollo.queries.issues.loading"
namespace="dashboard"
@@ -137,11 +199,13 @@ export default {
:show-pagination-controls="showPaginationControls"
:sort-options="sortOptions"
:tabs="$options.IssuableListTabs"
+ :url-params="urlParams"
use-keyset-pagination
@click-tab="handleClickTab"
@dismiss-alert="handleDismissAlert"
@next-page="handleNextPage"
@previous-page="handlePreviousPage"
+ @sort="handleSort"
>
<template #nav-actions>
<gl-button :href="rssPath" icon="rss">
diff --git a/app/assets/javascripts/issues/dashboard/index.js b/app/assets/javascripts/issues/dashboard/index.js
index ed11a600d4c..e3e5cc614cb 100644
--- a/app/assets/javascripts/issues/dashboard/index.js
+++ b/app/assets/javascripts/issues/dashboard/index.js
@@ -20,6 +20,7 @@ export function mountIssuesDashboardApp() {
hasIssuableHealthStatusFeature,
hasIssueWeightsFeature,
hasScopedLabelsFeature,
+ initialSort,
isPublicVisibilityRestricted,
isSignedIn,
rssPath,
@@ -38,6 +39,7 @@ export function mountIssuesDashboardApp() {
hasIssuableHealthStatusFeature: parseBoolean(hasIssuableHealthStatusFeature),
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
hasScopedLabelsFeature: parseBoolean(hasScopedLabelsFeature),
+ initialSort,
isPublicVisibilityRestricted: parseBoolean(isPublicVisibilityRestricted),
isSignedIn: parseBoolean(isSignedIn),
rssPath,
diff --git a/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql b/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql
index 2e70fb1eade..6d0c7139068 100644
--- a/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql
+++ b/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql
@@ -4,6 +4,7 @@
query getDashboardIssues(
$hideUsers: Boolean = false
$isSignedIn: Boolean = false
+ $sort: IssueSort
$state: IssuableState
$afterCursor: String
$beforeCursor: String
@@ -11,6 +12,7 @@ query getDashboardIssues(
$lastPageSize: Int
) {
issues(
+ sort: $sort
state: $state
after: $afterCursor
before: $beforeCursor
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 6e0782ac866..d661ce67d88 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -23,6 +23,7 @@ import {
OPERATORS_IS_NOT,
OPERATORS_IS_NOT_OR,
OPTIONS_NONE_ANY,
+ TOKEN_TITLE_SEARCH_WITHIN,
TOKEN_TITLE_ASSIGNEE,
TOKEN_TITLE_AUTHOR,
TOKEN_TITLE_CONFIDENTIAL,
@@ -43,6 +44,7 @@ import {
TOKEN_TYPE_ORGANIZATION,
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
+ TOKEN_TYPE_SEARCH_WITHIN,
} from '~/vue_shared/components/filtered_search_bar/constants';
import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants';
@@ -305,6 +307,22 @@ export default {
const tokens = [
{
+ type: TOKEN_TYPE_SEARCH_WITHIN,
+ title: TOKEN_TITLE_SEARCH_WITHIN,
+ icon: 'search',
+ token: GlFilteredSearchToken,
+ unique: true,
+ operators: OPERATORS_IS,
+ options: [
+ { icon: 'title', value: 'TITLE', title: this.$options.i18n.titles },
+ {
+ icon: 'text-description',
+ value: 'DESCRIPTION',
+ title: this.$options.i18n.descriptions,
+ },
+ ],
+ },
+ {
type: TOKEN_TYPE_AUTHOR,
title: TOKEN_TITLE_AUTHOR,
icon: 'pencil',
diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js
index dc8adf9473f..683a5955465 100644
--- a/app/assets/javascripts/issues/list/constants.js
+++ b/app/assets/javascripts/issues/list/constants.js
@@ -22,6 +22,7 @@ import {
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
TOKEN_TYPE_WEIGHT,
+ TOKEN_TYPE_SEARCH_WITHIN,
} from '~/vue_shared/components/filtered_search_bar/constants';
import {
WORK_ITEM_TYPE_ENUM_INCIDENT,
@@ -111,6 +112,8 @@ export const i18n = {
rssLabel: __('Subscribe to RSS feed'),
searchPlaceholder: __('Search or filter results...'),
upvotes: __('Upvotes'),
+ titles: __('Titles'),
+ descriptions: __('Descriptions'),
};
export const urlSortParams = {
@@ -120,8 +123,8 @@ export const urlSortParams = {
[CREATED_DESC]: 'created_date',
[UPDATED_ASC]: 'updated_asc',
[UPDATED_DESC]: 'updated_desc',
- [CLOSED_AT_ASC]: 'closed_asc',
- [CLOSED_AT_DESC]: 'closed_desc',
+ [CLOSED_AT_ASC]: 'closed_at',
+ [CLOSED_AT_DESC]: 'closed_at_desc',
[MILESTONE_DUE_ASC]: 'milestone',
[MILESTONE_DUE_DESC]: 'milestone_due_desc',
[DUE_DATE_ASC]: 'due_date',
@@ -189,6 +192,19 @@ export const filters = {
},
},
},
+ [TOKEN_TYPE_SEARCH_WITHIN]: {
+ [API_PARAM]: {
+ [NORMAL_FILTER]: 'in',
+ },
+ [URL_PARAM]: {
+ [OPERATOR_IS]: {
+ [NORMAL_FILTER]: 'in',
+ },
+ [OPERATOR_NOT]: {
+ [NORMAL_FILTER]: 'not[in]',
+ },
+ },
+ },
[TOKEN_TYPE_ASSIGNEE]: {
[API_PARAM]: {
[NORMAL_FILTER]: 'assigneeUsernames',
diff --git a/app/assets/javascripts/issues/list/queries/get_issues.query.graphql b/app/assets/javascripts/issues/list/queries/get_issues.query.graphql
index b447289b425..ee97fb6edca 100644
--- a/app/assets/javascripts/issues/list/queries/get_issues.query.graphql
+++ b/app/assets/javascripts/issues/list/queries/get_issues.query.graphql
@@ -10,6 +10,7 @@ query getIssues(
$search: String
$sort: IssueSort
$state: IssuableState
+ $in: [IssuableSearchableField!]
$assigneeId: String
$assigneeUsernames: [String!]
$authorUsername: String
@@ -38,6 +39,7 @@ query getIssues(
search: $search
sort: $sort
state: $state
+ in: $in
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
@@ -72,6 +74,7 @@ query getIssues(
search: $search
sort: $sort
state: $state
+ in: $in
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername