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>2020-09-21 15:09:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-21 15:09:34 +0300
commit79850719759d6fe1b0682fd27573d479c9013f03 (patch)
treebc0466515aca2c2db339cfe8e44d3c148804d304 /app/assets/javascripts/incidents
parentd05604c95aeed1e8bbf63abc0b363cb921f0996a (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/incidents')
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue158
-rw-r--r--app/assets/javascripts/incidents/constants.js3
-rw-r--r--app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql15
-rw-r--r--app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql6
-rw-r--r--app/assets/javascripts/incidents/list.js6
5 files changed, 164 insertions, 24 deletions
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 670c42cbdac..9d86c551af3 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -8,7 +8,6 @@ import {
GlAvatar,
GlTooltipDirective,
GlButton,
- GlSearchBoxByType,
GlIcon,
GlPagination,
GlTabs,
@@ -16,16 +15,25 @@ import {
GlBadge,
GlEmptyState,
} from '@gitlab/ui';
-import { debounce } from 'lodash';
+import Api from '~/api';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
-import { s__ } from '~/locale';
-import { mergeUrlParams, joinPaths, visitUrl } from '~/lib/utils/url_utility';
+import { s__, __ } from '~/locale';
+import { urlParamsToObject } from '~/lib/utils/common_utils';
+import {
+ visitUrl,
+ mergeUrlParams,
+ joinPaths,
+ updateHistory,
+ setUrlParams,
+} from '~/lib/utils/url_utility';
import getIncidents from '../graphql/queries/get_incidents.query.graphql';
import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
-import { I18N, DEFAULT_PAGE_SIZE, INCIDENT_SEARCH_DELAY, INCIDENT_STATUS_TABS } from '../constants';
+import { I18N, DEFAULT_PAGE_SIZE, INCIDENT_STATUS_TABS } from '../constants';
const TH_TEST_ID = { 'data-testid': 'incident-management-created-at-sort' };
const tdClass =
@@ -82,7 +90,6 @@ export default {
GlAvatar,
GlButton,
TimeAgoTooltip,
- GlSearchBoxByType,
GlIcon,
GlPagination,
GlTabs,
@@ -91,6 +98,7 @@ export default {
GlBadge,
GlEmptyState,
SeverityToken,
+ FilteredSearchBar,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -103,6 +111,9 @@ export default {
'issuePath',
'publishedAvailable',
'emptyListSvgPath',
+ 'textQuery',
+ 'authorUsernamesQuery',
+ 'assigneeUsernamesQuery',
],
apollo: {
incidents: {
@@ -118,6 +129,8 @@ export default {
lastPageSize: this.pagination.lastPageSize,
prevPageCursor: this.pagination.prevPageCursor,
nextPageCursor: this.pagination.nextPageCursor,
+ authorUsername: this.authorUsername,
+ assigneeUsernames: this.assigneeUsernames,
};
},
update({ project: { issues: { nodes = [], pageInfo = {} } = {} } = {} }) {
@@ -135,6 +148,8 @@ export default {
variables() {
return {
searchTerm: this.searchTerm,
+ authorUsername: this.authorUsername,
+ assigneeUsernames: this.assigneeUsernames,
projectPath: this.projectPath,
issueTypes: ['INCIDENT'],
};
@@ -149,7 +164,7 @@ export default {
errored: false,
isErrorAlertDismissed: false,
redirecting: false,
- searchTerm: '',
+ searchTerm: this.textQuery,
pagination: initialPaginationState,
incidents: {},
sort: 'created_desc',
@@ -157,6 +172,9 @@ export default {
sortDesc: true,
statusFilter: '',
filteredByStatus: '',
+ authorUsername: this.authorUsernamesQuery,
+ assigneeUsernames: this.assigneeUsernamesQuery,
+ filterParams: {},
};
},
computed: {
@@ -242,14 +260,57 @@ export default {
btnText: createIncidentBtnLabel,
};
},
+ filteredSearchTokens() {
+ return [
+ {
+ type: 'author_username',
+ icon: 'user',
+ title: __('Author'),
+ unique: true,
+ symbol: '@',
+ token: AuthorToken,
+ operators: [{ value: '=', description: __('is'), default: 'true' }],
+ fetchPath: this.projectPath,
+ fetchAuthors: Api.projectUsers.bind(Api),
+ },
+ {
+ type: 'assignee_username',
+ icon: 'user',
+ title: __('Assignees'),
+ unique: true,
+ symbol: '@',
+ token: AuthorToken,
+ operators: [{ value: '=', description: __('is'), default: 'true' }],
+ fetchPath: this.projectPath,
+ fetchAuthors: Api.projectUsers.bind(Api),
+ },
+ ];
+ },
+ filteredSearchValue() {
+ const value = [];
+
+ if (this.authorUsername) {
+ value.push({
+ type: 'author_username',
+ value: { data: this.authorUsername },
+ });
+ }
+
+ if (this.assigneeUsernames) {
+ value.push({
+ type: 'assignee_username',
+ value: { data: this.assigneeUsernames },
+ });
+ }
+
+ if (this.searchTerm) {
+ value.push(this.searchTerm);
+ }
+
+ return value;
+ },
},
methods: {
- onInputChange: debounce(function debounceSearch(input) {
- const trimmedInput = input.trim();
- if (trimmedInput !== this.searchTerm) {
- this.searchTerm = trimmedInput;
- }
- }, INCIDENT_SEARCH_DELAY),
filterIncidentsByStatus(tabIndex) {
const { filters, status } = this.$options.statusTabs[tabIndex];
this.statusFilter = filters;
@@ -292,6 +353,61 @@ export default {
getSeverity(severity) {
return INCIDENT_SEVERITY[severity];
},
+ handleFilterIncidents(filters) {
+ const filterParams = { authorUsername: '', assigneeUsername: [], search: '' };
+
+ filters.forEach(filter => {
+ if (typeof filter === 'object') {
+ switch (filter.type) {
+ case 'author_username':
+ filterParams.authorUsername = filter.value.data;
+ break;
+ case 'assignee_username':
+ filterParams.assigneeUsername.push(filter.value.data);
+ break;
+ case 'filtered-search-term':
+ if (filter.value.data !== '') filterParams.search = filter.value.data;
+ break;
+ default:
+ break;
+ }
+ }
+ });
+
+ this.filterParams = filterParams;
+ this.updateUrl();
+ this.searchTerm = filterParams?.search;
+ this.authorUsername = filterParams?.authorUsername;
+ this.assigneeUsernames = filterParams?.assigneeUsername;
+ },
+ updateUrl() {
+ const queryParams = urlParamsToObject(window.location.search);
+ const { authorUsername, assigneeUsername, search } = this.filterParams || {};
+
+ if (authorUsername) {
+ queryParams.author_username = authorUsername;
+ } else {
+ delete queryParams.author_username;
+ }
+
+ if (assigneeUsername) {
+ queryParams.assignee_username = assigneeUsername;
+ } else {
+ delete queryParams.assignee_username;
+ }
+
+ if (search) {
+ queryParams.search = search;
+ } else {
+ delete queryParams.search;
+ }
+
+ updateHistory({
+ url: setUrlParams(queryParams, window.location.href, true),
+ title: document.title,
+ replace: true,
+ });
+ },
},
};
</script>
@@ -331,12 +447,16 @@ export default {
</gl-button>
</div>
- <div class="gl-bg-gray-10 gl-p-5 gl-border-b-solid gl-border-b-1 gl-border-gray-100">
- <gl-search-box-by-type
- :value="searchTerm"
- class="gl-bg-white"
- :placeholder="$options.i18n.searchPlaceholder"
- @input="onInputChange"
+ <div class="filtered-search-wrapper">
+ <filtered-search-bar
+ :namespace="projectPath"
+ :search-input-placeholder="$options.i18n.searchPlaceholder"
+ :tokens="filteredSearchTokens"
+ :initial-filter-value="filteredSearchValue"
+ initial-sortby="created_desc"
+ recent-searches-storage-key="incidents"
+ class="row-content-block"
+ @onFilter="handleFilterIncidents"
/>
</div>
diff --git a/app/assets/javascripts/incidents/constants.js b/app/assets/javascripts/incidents/constants.js
index 289b36d9848..01a7b1b124f 100644
--- a/app/assets/javascripts/incidents/constants.js
+++ b/app/assets/javascripts/incidents/constants.js
@@ -6,7 +6,7 @@ export const I18N = {
unassigned: s__('IncidentManagement|Unassigned'),
createIncidentBtnLabel: s__('IncidentManagement|Create incident'),
unPublished: s__('IncidentManagement|Unpublished'),
- searchPlaceholder: __('Search results…'),
+ searchPlaceholder: __('Search or filter results…'),
emptyState: {
title: s__('IncidentManagement|Display your incidents in a dedicated view'),
emptyClosedTabTitle: s__('IncidentManagement|There are no closed incidents'),
@@ -34,5 +34,4 @@ export const INCIDENT_STATUS_TABS = [
},
];
-export const INCIDENT_SEARCH_DELAY = 300;
export const DEFAULT_PAGE_SIZE = 20;
diff --git a/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql
index 0b784b104a8..1346b3e6fff 100644
--- a/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql
+++ b/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql
@@ -1,6 +1,17 @@
-query getIncidentsCountByStatus($searchTerm: String, $projectPath: ID!, $issueTypes: [IssueType!]) {
+query getIncidentsCountByStatus(
+ $searchTerm: String
+ $projectPath: ID!
+ $issueTypes: [IssueType!]
+ $authorUsername: String = ""
+ $assigneeUsernames: [String!] = []
+) {
project(fullPath: $projectPath) {
- issueStatusCounts(search: $searchTerm, types: $issueTypes) {
+ issueStatusCounts(
+ search: $searchTerm
+ types: $issueTypes
+ authorUsername: $authorUsername
+ assigneeUsername: $assigneeUsernames
+ ) {
all
opened
closed
diff --git a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
index dab130835e2..27834b9dec4 100644
--- a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
+++ b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
@@ -9,7 +9,9 @@ query getIncidents(
$lastPageSize: Int
$prevPageCursor: String = ""
$nextPageCursor: String = ""
- $searchTerm: String
+ $searchTerm: String = ""
+ $authorUsername: String = ""
+ $assigneeUsernames: [String!] = []
) {
project(fullPath: $projectPath) {
issues(
@@ -17,6 +19,8 @@ query getIncidents(
types: $issueTypes
sort: $sort
state: $status
+ authorUsername: $authorUsername
+ assigneeUsername: $assigneeUsernames
first: $firstPageSize
last: $lastPageSize
after: $nextPageCursor
diff --git a/app/assets/javascripts/incidents/list.js b/app/assets/javascripts/incidents/list.js
index 7505d07449c..aeec4a258b9 100644
--- a/app/assets/javascripts/incidents/list.js
+++ b/app/assets/javascripts/incidents/list.js
@@ -16,6 +16,9 @@ export default () => {
issuePath,
publishedAvailable,
emptyListSvgPath,
+ textQuery,
+ authorUsernamesQuery,
+ assigneeUsernamesQuery,
} = domEl.dataset;
const apolloProvider = new VueApollo({
@@ -32,6 +35,9 @@ export default () => {
issuePath,
publishedAvailable,
emptyListSvgPath,
+ textQuery,
+ authorUsernamesQuery,
+ assigneeUsernamesQuery,
},
apolloProvider,
components: {