Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
bdd3c8d2
Commit
bdd3c8d2
authored
May 14, 2021
by
Eulyeon Ko
Committed by
Nathan Friend
May 14, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Correctly fetch labels in GraphQL boards sidebar [RUN-AS-IF-FOSS]
parent
cbd76096
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
251 additions
and
66 deletions
+251
-66
app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
...boards/components/sidebar/board_sidebar_labels_select.vue
+37
-2
app/assets/javascripts/boards/index.js
app/assets/javascripts/boards/index.js
+0
-1
ee/changelogs/unreleased/330479-graphql-issue-board-uses-a-wrong-labels-endpoint.yml
...0479-graphql-issue-board-uses-a-wrong-labels-endpoint.yml
+5
-0
ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_labels_spec.rb
...s/boards/swimlanes/epics_swimlanes_sidebar_labels_spec.rb
+39
-0
ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_spec.rb
...features/boards/swimlanes/epics_swimlanes_sidebar_spec.rb
+2
-9
ee/spec/support/helpers/board_helpers.rb
ee/spec/support/helpers/board_helpers.rb
+11
-0
spec/features/boards/sidebar_labels_in_namespaces_spec.rb
spec/features/boards/sidebar_labels_in_namespaces_spec.rb
+34
-0
spec/features/boards/sub_group_project_spec.rb
spec/features/boards/sub_group_project_spec.rb
+0
-46
spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
...ds/components/sidebar/board_sidebar_labels_select_spec.js
+26
-6
spec/frontend/boards/mock_data.js
spec/frontend/boards/mock_data.js
+4
-2
spec/support/helpers/board_helpers.rb
spec/support/helpers/board_helpers.rb
+16
-0
spec/support/shared_examples/features/board_sidebar_labels_examples.rb
...shared_examples/features/board_sidebar_labels_examples.rb
+77
-0
No files found.
app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
View file @
bdd3c8d2
<
script
>
import
{
GlLabel
}
from
'
@gitlab/ui
'
;
import
{
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
Api
from
'
~/api
'
;
import
BoardEditableItem
from
'
~/boards/components/sidebar/board_editable_item.vue
'
;
import
createFlash
from
'
~/flash
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
isScopedLabel
}
from
'
~/lib/utils/common_utils
'
;
import
{
mergeUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
{
__
}
from
'
~/locale
'
;
import
LabelsSelect
from
'
~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
'
;
...
...
@@ -14,7 +16,13 @@ export default {
LabelsSelect
,
GlLabel
,
},
inject
:
[
'
labelsFetchPath
'
,
'
labelsManagePath
'
,
'
labelsFilterBasePath
'
],
inject
:
{
labelsFetchPath
:
{
default
:
null
,
},
labelsManagePath
:
{},
labelsFilterBasePath
:
{},
},
data
()
{
return
{
loading
:
false
,
...
...
@@ -38,6 +46,32 @@ export default {
scoped
:
isScopedLabel
(
label
),
}));
},
fetchPath
()
{
/*
Labels fetched in epic boards are always group-level labels
and the correct path are passed from the backend (injected through labelsFetchPath)
For issue boards, we should always include project-level labels and use a different endpoint.
(it requires knowing the project path of a selected issue.)
Note 1. that we will be using GraphQL to fetch labels when we create a labels select widget.
And this component will be removed _wholesale_ https://gitlab.com/gitlab-org/gitlab/-/issues/300653.
Note 2. Moreover, 'fetchPath' needs to be used as a key for 'labels-select' component to force updates.
'labels-select' has its own vuex store and initializes the passed props as states
and these states aren't reactively bound to the passed props.
*/
const
projectLabelsFetchPath
=
mergeUrlParams
(
{
include_ancestor_groups
:
true
},
Api
.
buildUrl
(
Api
.
projectLabelsPath
).
replace
(
'
:namespace_path/:project_path
'
,
this
.
projectPathForActiveIssue
,
),
);
return
this
.
labelsFetchPath
||
projectLabelsFetchPath
;
},
},
methods
:
{
...
mapActions
([
'
setActiveBoardItemLabels
'
]),
...
...
@@ -100,12 +134,13 @@ export default {
<
template
#default=
"{ edit }"
>
<labels-select
ref=
"labelsSelect"
:key=
"fetchPath"
:allow-label-edit=
"false"
:allow-label-create=
"false"
:allow-multiselect=
"true"
:allow-scoped-labels=
"true"
:selected-labels=
"selectedLabels"
:labels-fetch-path=
"
labelsF
etchPath"
:labels-fetch-path=
"
f
etchPath"
:labels-manage-path=
"labelsManagePath"
:labels-filter-base-path=
"labelsFilterBasePath"
:labels-list-title=
"__('Select label')"
...
...
app/assets/javascripts/boards/index.js
View file @
bdd3c8d2
...
...
@@ -97,7 +97,6 @@ export default () => {
currentUserId
:
gon
.
current_user_id
||
null
,
canUpdate
:
parseBoolean
(
$boardApp
.
dataset
.
canUpdate
),
canAdminList
:
parseBoolean
(
$boardApp
.
dataset
.
canAdminList
),
labelsFetchPath
:
$boardApp
.
dataset
.
labelsFetchPath
,
labelsManagePath
:
$boardApp
.
dataset
.
labelsManagePath
,
labelsFilterBasePath
:
$boardApp
.
dataset
.
labelsFilterBasePath
,
timeTrackingLimitToHours
:
parseBoolean
(
$boardApp
.
dataset
.
timeTrackingLimitToHours
),
...
...
ee/changelogs/unreleased/330479-graphql-issue-board-uses-a-wrong-labels-endpoint.yml
0 → 100644
View file @
bdd3c8d2
---
title
:
Display labels from sub groups and projects when using epics swimlanes
merge_request
:
61423
author
:
type
:
fixed
ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_labels_spec.rb
0 → 100644
View file @
bdd3c8d2
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Issue boards sidebar labels using epic swimlanes'
,
:js
do
include
BoardHelpers
include_context
'labels from nested groups and projects'
before
do
stub_licensed_features
(
epics:
true
,
swimlanes:
true
)
end
let
(
:card
)
{
find
(
"[data-testid='board-lane-unassigned-issues']"
).
first
(
"[data-testid='board_card']"
)
}
context
'group boards'
do
context
'in the top-level group board'
do
let_it_be
(
:group_board
)
{
create
(
:board
,
group:
group
)
}
let_it_be
(
:board_list
)
{
create
(
:backlog_list
,
board:
group_board
)
}
before
do
load_board
group_board_path
(
group
,
group_board
)
load_epic_swimlanes
end
context
'selecting an issue from a direct descendant project'
do
let_it_be
(
:project_issue
)
{
create
(
:issue
,
project:
project
)
}
include_examples
'an issue from a direct descendant project is selected'
end
context
"selecting an issue from a subgroup's project"
do
let_it_be
(
:subproject_issue
)
{
create
(
:issue
,
project:
subproject
)
}
include_examples
"an issue from a subgroup's project is selected"
end
end
end
end
ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_spec.rb
View file @
bdd3c8d2
...
...
@@ -3,6 +3,8 @@
require
'spec_helper'
RSpec
.
describe
'epics swimlanes sidebar'
,
:js
do
include
BoardHelpers
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:group
)
{
create
(
:group
,
:public
)
}
let_it_be
(
:project
,
reload:
true
)
{
create
(
:project
,
:public
,
group:
group
)
}
...
...
@@ -48,15 +50,6 @@ RSpec.describe 'epics swimlanes sidebar', :js do
it_behaves_like
'issue boards sidebar EE'
end
def
load_epic_swimlanes
page
.
within
(
'.board-swimlanes-toggle-wrapper'
)
do
page
.
find
(
'.dropdown-toggle'
).
click
page
.
find
(
'.dropdown-item'
,
text:
'Epic'
).
click
end
wait_for_requests
end
def
first_card
find
(
"[data-testid='board-lane-unassigned-issues']"
).
first
(
"[data-testid='board_card']"
)
end
...
...
ee/spec/support/helpers/board_helpers.rb
0 → 100644
View file @
bdd3c8d2
# frozen_string_literal: true
module
BoardHelpers
def
load_epic_swimlanes
page
.
within
(
'.board-swimlanes-toggle-wrapper'
)
do
page
.
find
(
'.dropdown-toggle'
).
click
page
.
find
(
'.dropdown-item'
,
text:
'Epic'
).
click
end
wait_for_requests
end
end
spec/features/boards/sidebar_labels_in_namespaces_spec.rb
0 → 100644
View file @
bdd3c8d2
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Issue boards sidebar labels select'
,
:js
do
include
BoardHelpers
include_context
'labels from nested groups and projects'
let
(
:card
)
{
find
(
'.board:nth-child(1)'
).
first
(
'[data-testid="board_card"]'
)
}
context
'group boards'
do
context
'in the top-level group board'
do
let_it_be
(
:group_board
)
{
create
(
:board
,
group:
group
)
}
let_it_be
(
:board_list
)
{
create
(
:backlog_list
,
board:
group_board
)
}
before
do
load_board
group_board_path
(
group
,
group_board
)
end
context
'selecting an issue from a direct descendant project'
do
let_it_be
(
:project_issue
)
{
create
(
:issue
,
project:
project
)
}
include_examples
'an issue from a direct descendant project is selected'
end
context
"selecting an issue from a subgroup's project"
do
let_it_be
(
:subproject_issue
)
{
create
(
:issue
,
project:
subproject
)
}
include_examples
"an issue from a subgroup's project is selected"
end
end
end
end
spec/features/boards/sub_group_project_spec.rb
deleted
100644 → 0
View file @
cbd76096
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Sub-group project issue boards'
,
:js
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:nested_group_1
)
{
create
(
:group
,
parent:
group
)
}
let
(
:project
)
{
create
(
:project
,
group:
nested_group_1
)
}
let
(
:board
)
{
create
(
:board
,
project:
project
)
}
let
(
:label
)
{
create
(
:label
,
project:
project
)
}
let
(
:user
)
{
create
(
:user
)
}
let!
(
:list1
)
{
create
(
:list
,
board:
board
,
label:
label
,
position:
0
)
}
let!
(
:issue
)
{
create
(
:labeled_issue
,
project:
project
,
labels:
[
label
])
}
before
do
project
.
add_maintainer
(
user
)
sign_in
(
user
)
visit
project_board_path
(
project
,
board
)
wait_for_requests
end
# TODO https://gitlab.com/gitlab-org/gitlab/-/issues/324290
xit
'creates new label from sidebar'
do
find
(
'.board-card'
).
click
page
.
within
'.labels'
do
click_link
'Edit'
click_link
'Create project label'
end
page
.
within
'.dropdown-new-label'
do
fill_in
'new_label_name'
,
with:
'test label'
first
(
'.suggest-colors-dropdown a'
).
click
click_button
'Create'
wait_for_requests
end
page
.
within
'.labels'
do
expect
(
page
).
to
have_link
'test label'
end
end
end
spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
View file @
bdd3c8d2
import
{
GlLabel
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
labels
as
TEST_LABELS
,
mockIssue
as
TEST_ISSUE
}
from
'
jest/boards/mock_data
'
;
import
{
labels
as
TEST_LABELS
,
mockIssue
as
TEST_ISSUE
,
mockIssueFullPath
as
TEST_ISSUE_FULLPATH
,
}
from
'
jest/boards/mock_data
'
;
import
BoardEditableItem
from
'
~/boards/components/sidebar/board_editable_item.vue
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
{
createStore
}
from
'
~/boards/stores
'
;
...
...
@@ -23,7 +27,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
wrapper
=
null
;
});
const
createWrapper
=
({
labels
=
[]
}
=
{})
=>
{
const
createWrapper
=
({
labels
=
[]
,
providedValues
=
{}
}
=
{})
=>
{
store
=
createStore
();
store
.
state
.
boardItems
=
{
[
TEST_ISSUE
.
id
]:
{
...
TEST_ISSUE
,
labels
}
};
store
.
state
.
activeId
=
TEST_ISSUE
.
id
;
...
...
@@ -32,9 +36,9 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
store
,
provide
:
{
canUpdate
:
true
,
labelsFetchPath
:
TEST_HOST
,
labelsManagePath
:
TEST_HOST
,
labelsFilterBasePath
:
TEST_HOST
,
...
providedValues
,
},
stubs
:
{
BoardEditableItem
,
...
...
@@ -48,6 +52,22 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
wrapper
.
findAll
(
GlLabel
).
wrappers
.
map
((
item
)
=>
item
.
props
(
'
title
'
));
const
findCollapsed
=
()
=>
wrapper
.
find
(
'
[data-testid="collapsed-content"]
'
);
describe
(
'
when labelsFetchPath is provided
'
,
()
=>
{
it
(
'
uses injected labels fetch path
'
,
()
=>
{
createWrapper
({
providedValues
:
{
labelsFetchPath
:
'
foobar
'
}
});
expect
(
findLabelsSelect
().
props
(
'
labelsFetchPath
'
)).
toEqual
(
'
foobar
'
);
});
});
it
(
'
uses the default project label endpoint
'
,
()
=>
{
createWrapper
();
expect
(
findLabelsSelect
().
props
(
'
labelsFetchPath
'
)).
toEqual
(
`/
${
TEST_ISSUE_FULLPATH
}
/-/labels?include_ancestor_groups=true`
,
);
});
it
(
'
renders "None" when no labels are selected
'
,
()
=>
{
createWrapper
();
...
...
@@ -78,7 +98,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
it
(
'
commits change to the server
'
,
()
=>
{
expect
(
wrapper
.
vm
.
setActiveBoardItemLabels
).
toHaveBeenCalledWith
({
addLabelIds
:
TEST_LABELS
.
map
((
label
)
=>
label
.
id
),
projectPath
:
'
gitlab-org/test-subgroup/gitlab-test
'
,
projectPath
:
TEST_ISSUE_FULLPATH
,
removeLabelIds
:
[],
});
});
...
...
@@ -103,7 +123,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
expect
(
wrapper
.
vm
.
setActiveBoardItemLabels
).
toHaveBeenCalledWith
({
addLabelIds
:
[
5
,
7
],
removeLabelIds
:
[
6
],
projectPath
:
'
gitlab-org/test-subgroup/gitlab-test
'
,
projectPath
:
TEST_ISSUE_FULLPATH
,
});
});
});
...
...
@@ -122,7 +142,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
expect
(
wrapper
.
vm
.
setActiveBoardItemLabels
).
toHaveBeenCalledWith
({
removeLabelIds
:
[
getIdFromGraphQLId
(
testLabel
.
id
)],
projectPath
:
'
gitlab-org/test-subgroup/gitlab-test
'
,
projectPath
:
TEST_ISSUE_FULLPATH
,
});
});
});
...
...
spec/frontend/boards/mock_data.js
View file @
bdd3c8d2
...
...
@@ -151,6 +151,8 @@ export const rawIssue = {
},
};
export
const
mockIssueFullPath
=
'
gitlab-org/test-subgroup/gitlab-test
'
;
export
const
mockIssue
=
{
id
:
'
gid://gitlab/Issue/436
'
,
iid
:
'
27
'
,
...
...
@@ -159,8 +161,8 @@ export const mockIssue = {
timeEstimate
:
0
,
weight
:
null
,
confidential
:
false
,
referencePath
:
'
gitlab-org/test-subgroup/gitlab-test#27
'
,
path
:
'
/gitlab-org/test-subgroup/gitlab-test/-/issues/27
'
,
referencePath
:
`
${
mockIssueFullPath
}
#27`
,
path
:
`/
${
mockIssueFullPath
}
/-/issues/27`
,
assignees
,
labels
:
[
{
...
...
spec/support/helpers/board_helpers.rb
View file @
bdd3c8d2
...
...
@@ -7,4 +7,20 @@ module BoardHelpers
wait_for_requests
end
end
def
load_board
(
board_path
)
visit
board_path
wait_for_requests
end
def
click_card_and_edit_label
click_card
(
card
)
page
.
within
(
labels_select
)
do
click_button
'Edit'
wait_for_requests
end
end
end
spec/support/shared_examples/features/board_sidebar_labels_examples.rb
0 → 100644
View file @
bdd3c8d2
# frozen_string_literal: true
RSpec
.
shared_context
'labels from nested groups and projects'
do
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:group_label
)
{
create
(
:group_label
,
group:
group
,
name:
'Group label'
)
}
let_it_be
(
:project
)
{
create
(
:project
,
group:
group
)
}
let_it_be
(
:project_label
)
{
create
(
:label
,
project:
project
,
name:
'Project label'
)
}
let_it_be
(
:subgroup
)
{
create
(
:group
,
parent:
group
)
}
let_it_be
(
:subgroup_label
)
{
create
(
:group_label
,
group:
subgroup
,
name:
'Subgroup label'
)
}
let_it_be
(
:subproject
)
{
create
(
:project
,
group:
subgroup
)
}
let_it_be
(
:subproject_label
)
{
create
(
:label
,
project:
subproject
,
name:
'Subproject label'
)
}
let_it_be
(
:subgroup2
)
{
create
(
:group
,
parent:
group
)
}
let_it_be
(
:subgroup2_label
)
{
create
(
:group_label
,
group:
subgroup2
,
name:
'Subgroup2 label'
)
}
let_it_be
(
:maintainer
)
{
create
(
:user
)
}
let
(
:labels_select
)
{
find
(
"[data-testid='sidebar-labels']"
)
}
let
(
:labels_dropdown
)
{
labels_select
.
find
(
'[data-testid="dropdown-content"]'
)}
before
do
group
.
add_maintainer
(
maintainer
)
sign_in
(
maintainer
)
end
end
RSpec
.
shared_examples
"an issue from a subgroup's project is selected"
do
context
'when editing labels'
do
before
do
click_card_and_edit_label
end
it
'displays the label from the top-level group'
do
expect
(
labels_dropdown
).
to
have_content
(
group_label
.
name
)
end
it
'displays the label from the subgroup'
do
expect
(
labels_dropdown
).
to
have_content
(
subgroup_label
.
name
)
end
it
'displays the label from the project'
do
expect
(
labels_dropdown
).
to
have_content
(
subproject_label
.
name
)
end
it
"does not display labels from the subgroup's siblings (project or group)"
do
aggregate_failures
do
expect
(
labels_dropdown
).
not_to
have_content
(
project_label
.
name
)
expect
(
labels_dropdown
).
not_to
have_content
(
subgroup2_label
.
name
)
end
end
end
end
RSpec
.
shared_examples
'an issue from a direct descendant project is selected'
do
context
'when editing labels'
do
before
do
click_card_and_edit_label
end
it
'displays the label from the top-level group'
do
expect
(
labels_dropdown
).
to
have_content
(
group_label
.
name
)
end
it
'displays the label from the project'
do
expect
(
labels_dropdown
).
to
have_content
(
project_label
.
name
)
end
it
"does not display labels from the project's siblings or their descendents"
do
aggregate_failures
do
expect
(
labels_dropdown
).
not_to
have_content
(
subgroup_label
.
name
)
expect
(
labels_dropdown
).
not_to
have_content
(
subproject_label
.
name
)
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment