Commit 15c06897 authored by Coung Ngo's avatar Coung Ngo

Add milestone wildcard filters to issues page refactor

Add ability to filter issues by milestone None, Any, Upcoming,
and Started values on the issues page refactor.

Also adds merge request count on issues card
parent b6216e88
...@@ -306,7 +306,6 @@ export default { ...@@ -306,7 +306,6 @@ export default {
icon: 'clock', icon: 'clock',
token: MilestoneToken, token: MilestoneToken,
unique: true, unique: true,
defaultMilestones: [],
fetchMilestones: this.fetchMilestones, fetchMilestones: this.fetchMilestones,
}, },
{ {
......
...@@ -5,6 +5,8 @@ import { ...@@ -5,6 +5,8 @@ import {
FILTER_ANY, FILTER_ANY,
FILTER_CURRENT, FILTER_CURRENT,
FILTER_NONE, FILTER_NONE,
FILTER_STARTED,
FILTER_UPCOMING,
OPERATOR_IS, OPERATOR_IS,
OPERATOR_IS_NOT, OPERATOR_IS_NOT,
} from '~/vue_shared/components/filtered_search_bar/constants'; } from '~/vue_shared/components/filtered_search_bar/constants';
...@@ -186,7 +188,13 @@ export const URL_PARAM = 'urlParam'; ...@@ -186,7 +188,13 @@ export const URL_PARAM = 'urlParam';
export const NORMAL_FILTER = 'normalFilter'; export const NORMAL_FILTER = 'normalFilter';
export const SPECIAL_FILTER = 'specialFilter'; export const SPECIAL_FILTER = 'specialFilter';
export const ALTERNATIVE_FILTER = 'alternativeFilter'; export const ALTERNATIVE_FILTER = 'alternativeFilter';
export const SPECIAL_FILTER_VALUES = [FILTER_NONE, FILTER_ANY, FILTER_CURRENT]; export const SPECIAL_FILTER_VALUES = [
FILTER_NONE,
FILTER_ANY,
FILTER_CURRENT,
FILTER_UPCOMING,
FILTER_STARTED,
];
export const TOKEN_TYPE_AUTHOR = 'author_username'; export const TOKEN_TYPE_AUTHOR = 'author_username';
export const TOKEN_TYPE_ASSIGNEE = 'assignee_username'; export const TOKEN_TYPE_ASSIGNEE = 'assignee_username';
...@@ -231,10 +239,12 @@ export const filters = { ...@@ -231,10 +239,12 @@ export const filters = {
[TOKEN_TYPE_MILESTONE]: { [TOKEN_TYPE_MILESTONE]: {
[API_PARAM]: { [API_PARAM]: {
[NORMAL_FILTER]: 'milestoneTitle', [NORMAL_FILTER]: 'milestoneTitle',
[SPECIAL_FILTER]: 'milestoneWildcardId',
}, },
[URL_PARAM]: { [URL_PARAM]: {
[OPERATOR_IS]: { [OPERATOR_IS]: {
[NORMAL_FILTER]: 'milestone_title', [NORMAL_FILTER]: 'milestone_title',
[SPECIAL_FILTER]: 'milestone_title',
}, },
[OPERATOR_IS_NOT]: { [OPERATOR_IS_NOT]: {
[NORMAL_FILTER]: 'not[milestone_title]', [NORMAL_FILTER]: 'not[milestone_title]',
......
...@@ -12,6 +12,7 @@ query getProjectIssues( ...@@ -12,6 +12,7 @@ query getProjectIssues(
$authorUsername: String $authorUsername: String
$labelName: [String] $labelName: [String]
$milestoneTitle: [String] $milestoneTitle: [String]
$milestoneWildcardId: MilestoneWildcardId
$not: NegatedIssueFilterInput $not: NegatedIssueFilterInput
$beforeCursor: String $beforeCursor: String
$afterCursor: String $afterCursor: String
...@@ -28,6 +29,7 @@ query getProjectIssues( ...@@ -28,6 +29,7 @@ query getProjectIssues(
authorUsername: $authorUsername authorUsername: $authorUsername
labelName: $labelName labelName: $labelName
milestoneTitle: $milestoneTitle milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
not: $not not: $not
before: $beforeCursor before: $beforeCursor
after: $afterCursor after: $afterCursor
......
...@@ -7,6 +7,7 @@ query getProjectIssuesCount( ...@@ -7,6 +7,7 @@ query getProjectIssuesCount(
$authorUsername: String $authorUsername: String
$labelName: [String] $labelName: [String]
$milestoneTitle: [String] $milestoneTitle: [String]
$milestoneWildcardId: MilestoneWildcardId
$not: NegatedIssueFilterInput $not: NegatedIssueFilterInput
) { ) {
project(fullPath: $projectPath) { project(fullPath: $projectPath) {
...@@ -18,6 +19,7 @@ query getProjectIssuesCount( ...@@ -18,6 +19,7 @@ query getProjectIssuesCount(
authorUsername: $authorUsername authorUsername: $authorUsername
labelName: $labelName labelName: $labelName
milestoneTitle: $milestoneTitle milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
not: $not not: $not
) { ) {
count count
......
...@@ -7,6 +7,7 @@ fragment IssueFragment on Issue { ...@@ -7,6 +7,7 @@ fragment IssueFragment on Issue {
downvotes downvotes
dueDate dueDate
humanTimeEstimate humanTimeEstimate
mergeRequestsCount
moved moved
title title
updatedAt updatedAt
......
...@@ -21,6 +21,7 @@ import { ...@@ -21,6 +21,7 @@ import {
SPECIAL_FILTER_VALUES, SPECIAL_FILTER_VALUES,
TOKEN_TYPE_ASSIGNEE, TOKEN_TYPE_ASSIGNEE,
TOKEN_TYPE_ITERATION, TOKEN_TYPE_ITERATION,
TOKEN_TYPE_MILESTONE,
UPDATED_ASC, UPDATED_ASC,
UPDATED_DESC, UPDATED_DESC,
URL_PARAM, URL_PARAM,
...@@ -186,8 +187,14 @@ const getFilterType = (data, tokenType = '') => ...@@ -186,8 +187,14 @@ const getFilterType = (data, tokenType = '') =>
? SPECIAL_FILTER ? SPECIAL_FILTER
: NORMAL_FILTER; : NORMAL_FILTER;
const isIterationSpecialValue = (tokenType, value) => const requiresUpperCaseValue = (tokenType, value) =>
tokenType === TOKEN_TYPE_ITERATION && SPECIAL_FILTER_VALUES.includes(value); (tokenType === TOKEN_TYPE_ITERATION || tokenType === TOKEN_TYPE_MILESTONE) &&
SPECIAL_FILTER_VALUES.includes(value);
const formatData = (token) =>
requiresUpperCaseValue(token.type, token.value.data)
? token.value.data.toUpperCase()
: token.value.data;
export const convertToApiParams = (filterTokens) => { export const convertToApiParams = (filterTokens) => {
const params = {}; const params = {};
...@@ -199,9 +206,7 @@ export const convertToApiParams = (filterTokens) => { ...@@ -199,9 +206,7 @@ export const convertToApiParams = (filterTokens) => {
const filterType = getFilterType(token.value.data, token.type); const filterType = getFilterType(token.value.data, token.type);
const field = filters[token.type][API_PARAM][filterType]; const field = filters[token.type][API_PARAM][filterType];
const obj = token.value.operator === OPERATOR_IS_NOT ? not : params; const obj = token.value.operator === OPERATOR_IS_NOT ? not : params;
const data = isIterationSpecialValue(token.type, token.value.data) const data = formatData(token);
? token.value.data.toUpperCase()
: token.value.data;
Object.assign(obj, { Object.assign(obj, {
[field]: obj[field] ? [obj[field], data].flat() : data, [field]: obj[field] ? [obj[field], data].flat() : data,
}); });
......
...@@ -7,6 +7,8 @@ export const WEIGHT_TOKEN_SUGGESTIONS_SIZE = 21; ...@@ -7,6 +7,8 @@ export const WEIGHT_TOKEN_SUGGESTIONS_SIZE = 21;
export const FILTER_NONE = 'None'; export const FILTER_NONE = 'None';
export const FILTER_ANY = 'Any'; export const FILTER_ANY = 'Any';
export const FILTER_CURRENT = 'Current'; export const FILTER_CURRENT = 'Current';
export const FILTER_UPCOMING = 'Upcoming';
export const FILTER_STARTED = 'Started';
export const OPERATOR_IS = '='; export const OPERATOR_IS = '=';
export const OPERATOR_IS_TEXT = __('is'); export const OPERATOR_IS_TEXT = __('is');
...@@ -28,8 +30,8 @@ export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([ ...@@ -28,8 +30,8 @@ export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([
export const DEFAULT_LABELS = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY]; export const DEFAULT_LABELS = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([ export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([
{ value: 'Upcoming', text: __('Upcoming') }, // eslint-disable-line @gitlab/require-i18n-strings { value: FILTER_UPCOMING, text: __(FILTER_UPCOMING) },
{ value: 'Started', text: __('Started') }, // eslint-disable-line @gitlab/require-i18n-strings { value: FILTER_STARTED, text: __(FILTER_STARTED) },
]); ]);
export const SortDirection = { export const SortDirection = {
......
...@@ -12,6 +12,7 @@ query getProjectIssues( ...@@ -12,6 +12,7 @@ query getProjectIssues(
$authorUsername: String $authorUsername: String
$labelName: [String] $labelName: [String]
$milestoneTitle: [String] $milestoneTitle: [String]
$milestoneWildcardId: MilestoneWildcardId
$epicId: String $epicId: String
$iterationId: [ID] $iterationId: [ID]
$iterationWildcardId: IterationWildcardId $iterationWildcardId: IterationWildcardId
...@@ -32,6 +33,7 @@ query getProjectIssues( ...@@ -32,6 +33,7 @@ query getProjectIssues(
authorUsername: $authorUsername authorUsername: $authorUsername
labelName: $labelName labelName: $labelName
milestoneTitle: $milestoneTitle milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
epicId: $epicId epicId: $epicId
iterationId: $iterationId iterationId: $iterationId
iterationWildcardId: $iterationWildcardId iterationWildcardId: $iterationWildcardId
......
...@@ -7,6 +7,7 @@ query getProjectIssuesCount( ...@@ -7,6 +7,7 @@ query getProjectIssuesCount(
$authorUsername: String $authorUsername: String
$labelName: [String] $labelName: [String]
$milestoneTitle: [String] $milestoneTitle: [String]
$milestoneWildcardId: MilestoneWildcardId
$epicId: String $epicId: String
$iterationId: [ID] $iterationId: [ID]
$iterationWildcardId: IterationWildcardId $iterationWildcardId: IterationWildcardId
...@@ -22,6 +23,7 @@ query getProjectIssuesCount( ...@@ -22,6 +23,7 @@ query getProjectIssuesCount(
authorUsername: $authorUsername authorUsername: $authorUsername
labelName: $labelName labelName: $labelName
milestoneTitle: $milestoneTitle milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
epicId: $epicId epicId: $epicId
iterationId: $iterationId iterationId: $iterationId
iterationWildcardId: $iterationWildcardId iterationWildcardId: $iterationWildcardId
......
...@@ -23,6 +23,7 @@ export const getIssuesQueryResponse = { ...@@ -23,6 +23,7 @@ export const getIssuesQueryResponse = {
downvotes: 2, downvotes: 2,
dueDate: '2021-05-29', dueDate: '2021-05-29',
humanTimeEstimate: null, humanTimeEstimate: null,
mergeRequestsCount: false,
moved: false, moved: false,
title: 'Issue title', title: 'Issue title',
updatedAt: '2021-05-22T04:08:01Z', updatedAt: '2021-05-22T04:08:01Z',
...@@ -108,6 +109,7 @@ export const locationSearchWithSpecialValues = [ ...@@ -108,6 +109,7 @@ export const locationSearchWithSpecialValues = [
'assignee_username=bart', 'assignee_username=bart',
'my_reaction_emoji=None', 'my_reaction_emoji=None',
'iteration_id=Current', 'iteration_id=Current',
'milestone_title=Upcoming',
'epic_id=None', 'epic_id=None',
'weight=None', 'weight=None',
].join('&'); ].join('&');
...@@ -142,6 +144,7 @@ export const filteredTokensWithSpecialValues = [ ...@@ -142,6 +144,7 @@ export const filteredTokensWithSpecialValues = [
{ type: 'assignee_username', value: { data: 'bart', operator: OPERATOR_IS } }, { type: 'assignee_username', value: { data: 'bart', operator: OPERATOR_IS } },
{ type: 'my_reaction_emoji', value: { data: 'None', operator: OPERATOR_IS } }, { type: 'my_reaction_emoji', value: { data: 'None', operator: OPERATOR_IS } },
{ type: 'iteration', value: { data: 'Current', operator: OPERATOR_IS } }, { type: 'iteration', value: { data: 'Current', operator: OPERATOR_IS } },
{ type: 'milestone', value: { data: 'Upcoming', operator: OPERATOR_IS } },
{ type: 'epic_id', value: { data: 'None', operator: OPERATOR_IS } }, { type: 'epic_id', value: { data: 'None', operator: OPERATOR_IS } },
{ type: 'weight', value: { data: 'None', operator: OPERATOR_IS } }, { type: 'weight', value: { data: 'None', operator: OPERATOR_IS } },
]; ];
...@@ -172,6 +175,7 @@ export const apiParamsWithSpecialValues = { ...@@ -172,6 +175,7 @@ export const apiParamsWithSpecialValues = {
assigneeUsernames: 'bart', assigneeUsernames: 'bart',
myReactionEmoji: 'None', myReactionEmoji: 'None',
iterationWildcardId: 'CURRENT', iterationWildcardId: 'CURRENT',
milestoneWildcardId: 'UPCOMING',
epicId: 'None', epicId: 'None',
weight: 'None', weight: 'None',
}; };
...@@ -200,6 +204,7 @@ export const urlParamsWithSpecialValues = { ...@@ -200,6 +204,7 @@ export const urlParamsWithSpecialValues = {
'assignee_username[]': 'bart', 'assignee_username[]': 'bart',
my_reaction_emoji: 'None', my_reaction_emoji: 'None',
iteration_id: 'Current', iteration_id: 'Current',
milestone_title: 'Upcoming',
epic_id: 'None', epic_id: 'None',
weight: 'None', weight: 'None',
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment