diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-07 03:08:34 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-07 03:08:34 +0300 |
commit | 7e89568aa1b1c531aa34860fbd9e77d9e988b9b2 (patch) | |
tree | 9d644d947b75594d969f040ef046541c769e0dc3 /app/assets/javascripts/issues | |
parent | f2143c9986ad7b6206b8a41cc9aeb419e543d3f5 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/issues')
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 |