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
3c079000
Commit
3c079000
authored
Oct 14, 2021
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Consolidate labels widget architecture
- Update labels within widget
parent
54cf5455
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
190 additions
and
105 deletions
+190
-105
app/assets/javascripts/boards/components/board_content_sidebar.vue
...s/javascripts/boards/components/board_content_sidebar.vue
+9
-8
app/assets/javascripts/boards/stores/actions.js
app/assets/javascripts/boards/stores/actions.js
+32
-20
app/assets/javascripts/boards/stores/mutation_types.js
app/assets/javascripts/boards/stores/mutation_types.js
+0
-1
app/assets/javascripts/boards/stores/mutations.js
app/assets/javascripts/boards/stores/mutations.js
+0
-4
app/assets/javascripts/boards/stores/state.js
app/assets/javascripts/boards/stores/state.js
+0
-1
app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
.../javascripts/sidebar/components/labels/sidebar_labels.vue
+4
-4
app/assets/javascripts/sidebar/constants.js
app/assets/javascripts/sidebar/constants.js
+13
-0
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
...ared/components/sidebar/labels_select_widget/constants.js
+5
-0
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
...onents/sidebar/labels_select_widget/dropdown_contents.vue
+6
-3
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
...ar/labels_select_widget/dropdown_contents_create_view.vue
+12
-21
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
...ar/labels_select_widget/dropdown_contents_labels_view.vue
+0
-4
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
...nents/sidebar/labels_select_widget/labels_select_root.vue
+89
-18
ee/app/assets/javascripts/epic/components/epic_form.vue
ee/app/assets/javascripts/epic/components/epic_form.vue
+4
-3
ee/spec/features/labels_hierarchy_spec.rb
ee/spec/features/labels_hierarchy_spec.rb
+5
-6
spec/frontend/boards/stores/actions_spec.js
spec/frontend/boards/stores/actions_spec.js
+3
-10
spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
...abels_select_widget/dropdown_contents_create_view_spec.js
+4
-1
spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
...ts/sidebar/labels_select_widget/dropdown_contents_spec.js
+2
-0
spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
...s/sidebar/labels_select_widget/labels_select_root_spec.js
+1
-0
spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
...ared/components/sidebar/labels_select_widget/mock_data.js
+1
-1
No files found.
app/assets/javascripts/boards/components/board_content_sidebar.vue
View file @
3c079000
...
...
@@ -15,6 +15,7 @@ import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue
import
SidebarSubscriptionsWidget
from
'
~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
'
;
import
SidebarTodoWidget
from
'
~/sidebar/components/todo_toggle/sidebar_todo_widget.vue
'
;
import
SidebarLabelsWidget
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
import
{
LabelType
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
export
default
{
...
...
@@ -63,7 +64,7 @@ export default {
'
groupPathForActiveIssue
'
,
'
projectPathForActiveIssue
'
,
]),
...
mapState
([
'
sidebarType
'
,
'
issuableType
'
,
'
isSettingLabels
'
]),
...
mapState
([
'
sidebarType
'
,
'
issuableType
'
]),
isIssuableSidebar
()
{
return
this
.
sidebarType
===
ISSUABLE
;
},
...
...
@@ -84,7 +85,10 @@ export default {
});
},
attrWorkspacePath
()
{
return
this
.
isGroupBoard
?
this
.
groupPathForActiveIssue
:
undefined
;
return
this
.
isGroupBoard
?
this
.
groupPathForActiveIssue
:
this
.
projectPathForActiveIssue
;
},
labelType
()
{
return
this
.
isGroupBoard
?
LabelType
.
group
:
LabelType
.
project
;
},
},
methods
:
{
...
...
@@ -102,10 +106,8 @@ export default {
this
.
setActiveBoardItemLabels
({
iid
:
this
.
activeBoardItem
.
iid
,
projectPath
:
this
.
projectPathForActiveIssue
,
addLabelIds
:
input
.
map
((
label
)
=>
getIdFromGraphQLId
(
label
.
id
)),
removeLabelIds
:
this
.
activeBoardItem
.
labels
.
filter
((
label
)
=>
!
input
.
find
((
selected
)
=>
selected
.
id
===
label
.
id
))
.
map
((
label
)
=>
label
.
id
),
labelsIds
:
input
.
map
((
label
)
=>
getIdFromGraphQLId
(
label
.
id
)),
labels
:
input
,
});
},
handleLabelRemove
(
input
)
{
...
...
@@ -207,14 +209,13 @@ export default {
:full-path=
"projectPathForActiveIssue"
:allow-label-remove=
"allowLabelEdit"
:allow-multiselect=
"true"
:selected-labels=
"activeBoardItem.labels"
:labels-select-in-progress=
"isSettingLabels"
:footer-create-label-title=
"createLabelTitle"
:footer-manage-label-title=
"manageLabelTitle"
:labels-create-title=
"createLabelTitle"
:labels-filter-base-path=
"projectPathForActiveIssue"
:attr-workspace-path=
"attrWorkspacePath"
:issuable-type=
"issuableType"
:label-type=
"labelType"
@
onLabelRemove=
"handleLabelRemove"
@
updateSelectedLabels=
"handleUpdateSelectedLabels"
>
...
...
app/assets/javascripts/boards/stores/actions.js
View file @
3c079000
...
...
@@ -656,31 +656,43 @@ export default {
},
setActiveIssueLabels
:
async
({
commit
,
getters
},
input
)
=>
{
commit
(
types
.
SET_LABELS_LOADING
,
true
);
const
{
activeBoardItem
}
=
getters
;
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetLabelsMutation
,
variables
:
{
input
:
{
iid
:
input
.
iid
||
String
(
activeBoardItem
.
iid
),
addLabelIds
:
input
.
addLabelIds
??
[],
removeLabelIds
:
input
.
removeLabelIds
??
[],
projectPath
:
input
.
projectPath
,
if
(
!
gon
.
features
?.
labelsWidget
)
{
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetLabelsMutation
,
variables
:
{
input
:
{
iid
:
input
.
iid
||
String
(
activeBoardItem
.
iid
),
labelsIds
:
input
.
labelsIds
??
[],
removeLabelIds
:
input
.
removeLabelIds
??
[],
projectPath
:
input
.
projectPath
,
},
},
},
});
});
commit
(
types
.
SET_LABELS_LOADING
,
false
);
if
(
data
.
updateIssue
?.
errors
?.
length
>
0
)
{
throw
new
Error
(
data
.
updateIssue
.
errors
);
}
if
(
data
.
updateIssue
?.
errors
?.
length
>
0
)
{
throw
new
Error
(
data
.
updateIssue
.
errors
);
commit
(
types
.
UPDATE_BOARD_ITEM_BY_ID
,
{
itemId
:
data
.
updateIssue
?.
issue
?.
id
||
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
data
.
updateIssue
?.
issue
?.
labels
.
nodes
,
});
}
else
{
let
labels
=
input
?.
labels
||
[];
if
(
input
.
removeLabelIds
)
{
labels
=
activeBoardItem
.
labels
.
filter
(
(
label
)
=>
input
.
removeLabelIds
[
0
]
!==
getIdFromGraphQLId
(
label
.
id
),
);
}
commit
(
types
.
UPDATE_BOARD_ITEM_BY_ID
,
{
itemId
:
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
labels
,
});
}
commit
(
types
.
UPDATE_BOARD_ITEM_BY_ID
,
{
itemId
:
data
.
updateIssue
?.
issue
?.
id
||
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
data
.
updateIssue
.
issue
.
labels
.
nodes
,
});
},
setActiveItemSubscribed
:
async
({
commit
,
getters
,
state
},
input
)
=>
{
...
...
app/assets/javascripts/boards/stores/mutation_types.js
View file @
3c079000
...
...
@@ -28,7 +28,6 @@ export const ADD_BOARD_ITEM_TO_LIST = 'ADD_BOARD_ITEM_TO_LIST';
export
const
REMOVE_BOARD_ITEM_FROM_LIST
=
'
REMOVE_BOARD_ITEM_FROM_LIST
'
;
export
const
SET_ACTIVE_ID
=
'
SET_ACTIVE_ID
'
;
export
const
UPDATE_BOARD_ITEM_BY_ID
=
'
UPDATE_BOARD_ITEM_BY_ID
'
;
export
const
SET_LABELS_LOADING
=
'
SET_LABELS_LOADING
'
;
export
const
SET_ASSIGNEE_LOADING
=
'
SET_ASSIGNEE_LOADING
'
;
export
const
RESET_ISSUES
=
'
RESET_ISSUES
'
;
export
const
REQUEST_GROUP_PROJECTS
=
'
REQUEST_GROUP_PROJECTS
'
;
...
...
app/assets/javascripts/boards/stores/mutations.js
View file @
3c079000
...
...
@@ -195,10 +195,6 @@ export default {
Vue
.
set
(
state
.
boardItems
[
itemId
],
prop
,
value
);
},
[
mutationTypes
.
SET_LABELS_LOADING
](
state
,
isLoading
)
{
state
.
isSettingLabels
=
isLoading
;
},
[
mutationTypes
.
SET_ASSIGNEE_LOADING
](
state
,
isLoading
)
{
state
.
isSettingAssignees
=
isLoading
;
},
...
...
app/assets/javascripts/boards/stores/state.js
View file @
3c079000
...
...
@@ -12,7 +12,6 @@ export default () => ({
listsFlags
:
{},
boardItemsByListId
:
{},
backupItemsList
:
[],
isSettingLabels
:
false
,
isSettingAssignees
:
false
,
pageInfoByListId
:
{},
boardItems
:
{},
...
...
app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
View file @
3c079000
...
...
@@ -11,6 +11,7 @@ import { toLabelGid } from '~/sidebar/utils';
import
{
DropdownVariant
}
from
'
~/vue_shared/components/sidebar/labels_select_vue/constants
'
;
import
LabelsSelect
from
'
~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
'
;
import
LabelsSelectWidget
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
import
{
LabelType
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
const
mutationMap
=
{
...
...
@@ -48,6 +49,7 @@ export default {
return
{
isLabelsSelectInProgress
:
false
,
selectedLabels
:
this
.
initiallySelectedLabels
,
LabelType
,
};
},
methods
:
{
...
...
@@ -154,13 +156,11 @@ export default {
:footer-manage-label-title=
"__('Manage project labels')"
:labels-create-title=
"__('Create project label')"
:labels-filter-base-path=
"projectIssuesPath"
:labels-select-in-progress=
"isLabelsSelectInProgress"
:selected-labels=
"selectedLabels"
:variant=
"$options.variant"
:issuable-type=
"issuableType"
:attr-workspace-path=
"fullPath"
:label-type=
"LabelType.project"
data-qa-selector=
"labels_block"
@
onLabelRemove=
"handleLabelRemove"
@
updateSelectedLabels=
"handleUpdateSelectedLabels"
>
{{
__
(
'
None
'
)
}}
</labels-select-widget>
...
...
app/assets/javascripts/sidebar/constants.js
View file @
3c079000
import
updateIssueLabelsMutation
from
'
~/boards/graphql/issue_set_labels.mutation.graphql
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
DEFAULT_DEBOUNCE_AND_THROTTLE_MS
}
from
'
~/lib/utils/constants
'
;
import
epicConfidentialQuery
from
'
~/sidebar/queries/epic_confidential.query.graphql
'
;
...
...
@@ -29,6 +30,7 @@ import updateIssueConfidentialMutation from '~/sidebar/queries/update_issue_conf
import
updateIssueDueDateMutation
from
'
~/sidebar/queries/update_issue_due_date.mutation.graphql
'
;
import
updateIssueSubscriptionMutation
from
'
~/sidebar/queries/update_issue_subscription.mutation.graphql
'
;
import
mergeRequestMilestoneMutation
from
'
~/sidebar/queries/update_merge_request_milestone.mutation.graphql
'
;
import
updateMergeRequestLabelsMutation
from
'
~/sidebar/queries/update_merge_request_labels.mutation.graphql
'
;
import
updateMergeRequestSubscriptionMutation
from
'
~/sidebar/queries/update_merge_request_subscription.mutation.graphql
'
;
import
updateAlertAssigneesMutation
from
'
~/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql
'
;
import
epicLabelsQuery
from
'
~/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
'
;
...
...
@@ -120,6 +122,17 @@ export const labelsQueries = {
},
};
export
const
labelsMutations
=
{
[
IssuableType
.
Issue
]:
{
mutation
:
updateIssueLabelsMutation
,
mutationName
:
'
updateIssue
'
,
},
[
IssuableType
.
MergeRequest
]:
{
mutation
:
updateMergeRequestLabelsMutation
,
mutationName
:
'
mergeRequestSetLabels
'
,
},
};
export
const
dateTypes
=
{
start
:
'
startDate
'
,
due
:
'
dueDate
'
,
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
View file @
3c079000
...
...
@@ -5,3 +5,8 @@ export const DropdownVariant = {
Standalone
:
'
standalone
'
,
Embedded
:
'
embedded
'
,
};
export
const
LabelType
=
{
group
:
'
GroupLabel
'
,
project
:
'
ProjectLabel
'
,
};
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
View file @
3c079000
...
...
@@ -68,8 +68,11 @@ export default {
},
attrWorkspacePath
:
{
type
:
String
,
required
:
false
,
default
:
undefined
,
required
:
true
,
},
labelType
:
{
type
:
String
,
required
:
true
,
},
},
data
()
{
...
...
@@ -193,11 +196,11 @@ export default {
:is=
"dropdownContentsView"
v-model=
"localSelectedLabels"
:search-key=
"searchKey"
:selected-labels=
"selectedLabels"
:allow-multiselect=
"allowMultiselect"
:issuable-type=
"issuableType"
:full-path=
"fullPath"
:attr-workspace-path=
"attrWorkspacePath"
:label-type=
"labelType"
@
hideCreateView=
"toggleDropdownContentsCreateView"
/>
</
template
>
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
View file @
3c079000
...
...
@@ -2,10 +2,10 @@
import
{
GlTooltipDirective
,
GlButton
,
GlFormInput
,
GlLink
,
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
produce
from
'
immer
'
;
import
createFlash
from
'
~/flash
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
labelsQueries
}
from
'
~/sidebar/constants
'
;
import
createLabelMutation
from
'
./graphql/create_label.mutation.graphql
'
;
import
{
LabelType
}
from
'
./constants
'
;
const
errorMessage
=
__
(
'
Error creating label.
'
);
...
...
@@ -30,8 +30,11 @@ export default {
},
attrWorkspacePath
:
{
type
:
String
,
required
:
false
,
default
:
undefined
,
required
:
true
,
},
labelType
:
{
type
:
String
,
required
:
true
,
},
},
data
()
{
...
...
@@ -50,25 +53,13 @@ export default {
return
Object
.
keys
(
colorsMap
).
map
((
color
)
=>
({
[
color
]:
colorsMap
[
color
]
}));
},
mutationVariables
()
{
if
(
this
.
issuableType
===
IssuableType
.
Epic
)
{
return
{
title
:
this
.
labelTitle
,
color
:
this
.
selectedColor
,
groupPath
:
this
.
fullPath
,
};
}
const
attributePath
=
this
.
labelType
===
LabelType
.
group
?
'
groupPath
'
:
'
projectPath
'
;
return
this
.
attrWorkspacePath
!==
undefined
?
{
title
:
this
.
labelTitle
,
color
:
this
.
selectedColor
,
groupPath
:
this
.
attrWorkspacePath
,
}
:
{
title
:
this
.
labelTitle
,
color
:
this
.
selectedColor
,
projectPath
:
this
.
fullPath
,
};
return
{
title
:
this
.
labelTitle
,
color
:
this
.
selectedColor
,
[
attributePath
]:
this
.
attrWorkspacePath
,
};
},
},
methods
:
{
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
View file @
3c079000
...
...
@@ -19,10 +19,6 @@ export default {
prop
:
'
localSelectedLabels
'
,
},
props
:
{
selectedLabels
:
{
type
:
Array
,
required
:
true
,
},
allowMultiselect
:
{
type
:
Boolean
,
required
:
true
,
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
View file @
3c079000
<
script
>
import
{
MutationOperationMode
}
from
'
~/graphql_shared/utils
'
;
import
createFlash
from
'
~/flash
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
__
}
from
'
~/locale
'
;
import
SidebarEditableItem
from
'
~/sidebar/components/sidebar_editable_item.vue
'
;
import
{
labelsQueries
}
from
'
~/sidebar/constants
'
;
import
{
labelsQueries
,
labelsMutations
}
from
'
~/sidebar/constants
'
;
import
{
DropdownVariant
}
from
'
./constants
'
;
import
DropdownContents
from
'
./dropdown_contents.vue
'
;
import
DropdownValue
from
'
./dropdown_value.vue
'
;
...
...
@@ -50,16 +52,6 @@ export default {
required
:
false
,
default
:
DropdownVariant
.
Sidebar
,
},
selectedLabels
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
labelsSelectInProgress
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
labelsFilterBasePath
:
{
type
:
String
,
required
:
false
,
...
...
@@ -106,14 +98,18 @@ export default {
},
attrWorkspacePath
:
{
type
:
String
,
required
:
false
,
default
:
undefined
,
required
:
true
,
},
labelType
:
{
type
:
String
,
required
:
true
,
},
},
data
()
{
return
{
contentIsOnViewport
:
true
,
issuableLabels
:
[],
labelsSelectInProgress
:
false
,
};
},
computed
:
{
...
...
@@ -136,7 +132,9 @@ export default {
};
},
update
(
data
)
{
return
data
.
workspace
?.
issuable
?.
labels
.
nodes
||
[];
const
labels
=
data
.
workspace
?.
issuable
?.
labels
.
nodes
||
[];
this
.
selected
=
labels
;
return
labels
;
},
error
()
{
createFlash
({
message
:
__
(
'
Error fetching labels.
'
)
});
...
...
@@ -145,6 +143,10 @@ export default {
},
methods
:
{
handleDropdownClose
(
labels
)
{
if
(
this
.
iid
!==
''
)
{
this
.
updateSelectedLabels
(
this
.
getUpdateVariables
(
labels
));
}
this
.
$emit
(
'
updateSelectedLabels
'
,
labels
);
this
.
collapseEditableItem
();
},
...
...
@@ -154,6 +156,72 @@ export default {
handleCollapsedValueClick
()
{
this
.
$emit
(
'
toggleCollapse
'
);
},
getUpdateVariables
(
labels
)
{
let
labelIds
=
[];
labelIds
=
labels
.
map
(({
id
})
=>
id
);
switch
(
this
.
issuableType
)
{
case
IssuableType
.
Issue
:
return
{
iid
:
this
.
iid
,
projectPath
:
this
.
fullPath
,
labelIds
,
};
case
IssuableType
.
MergeRequest
:
return
{
iid
:
this
.
iid
,
labelIds
,
operationMode
:
MutationOperationMode
.
Replace
,
projectPath
:
this
.
fullPath
,
};
default
:
return
{};
}
},
updateSelectedLabels
(
inputVariables
)
{
this
.
labelsSelectInProgress
=
true
;
this
.
$apollo
.
mutate
({
mutation
:
labelsMutations
[
this
.
issuableType
].
mutation
,
variables
:
{
input
:
inputVariables
},
})
.
then
(({
data
})
=>
{
const
{
mutationName
}
=
labelsMutations
[
this
.
issuableType
];
if
(
data
[
mutationName
]?.
errors
?.
length
)
{
throw
new
Error
();
}
})
.
catch
(()
=>
createFlash
({
message
:
__
(
'
An error occurred while updating labels.
'
)
}))
.
finally
(()
=>
{
this
.
labelsSelectInProgress
=
false
;
});
},
getRemoveVariables
(
labelId
)
{
switch
(
this
.
issuableType
)
{
case
IssuableType
.
Issue
:
return
{
iid
:
this
.
iid
,
projectPath
:
this
.
fullPath
,
removeLabelIds
:
[
labelId
],
};
case
IssuableType
.
MergeRequest
:
return
{
iid
:
this
.
iid
,
labelIds
:
[
labelId
],
operationMode
:
MutationOperationMode
.
Remove
,
projectPath
:
this
.
fullPath
,
};
default
:
return
{};
}
},
handleLabelRemove
(
labelId
)
{
this
.
updateSelectedLabels
(
this
.
getRemoveVariables
(
labelId
));
this
.
$emit
(
'
onLabelRemove
'
,
labelId
);
},
isDropdownVariantSidebar
,
isDropdownVariantStandalone
,
isDropdownVariantEmbedded
,
...
...
@@ -188,7 +256,7 @@ export default {
:allow-label-remove=
"allowLabelRemove"
:labels-filter-base-path=
"labelsFilterBasePath"
:labels-filter-param=
"labelsFilterParam"
@
onLabelRemove=
"
$emit('onLabelRemove', $event)
"
@
onLabelRemove=
"
handleLabelRemove
"
>
<slot></slot>
</dropdown-value>
...
...
@@ -201,7 +269,7 @@ export default {
:labels-filter-base-path=
"labelsFilterBasePath"
:labels-filter-param=
"labelsFilterParam"
class=
"gl-mb-2"
@
onLabelRemove=
"
$emit('onLabelRemove', $event)
"
@
onLabelRemove=
"
handleLabelRemove
"
>
<slot></slot>
</dropdown-value>
...
...
@@ -212,12 +280,13 @@ export default {
:footer-create-label-title=
"footerCreateLabelTitle"
:footer-manage-label-title=
"footerManageLabelTitle"
:labels-create-title=
"labelsCreateTitle"
:selected-labels=
"
selected
Labels"
:selected-labels=
"
issuable
Labels"
:variant=
"variant"
:issuable-type=
"issuableType"
:is-visible=
"edit"
:full-path=
"fullPath"
:attr-workspace-path=
"attrWorkspacePath"
:label-type=
"labelType"
@
setLabels=
"handleDropdownClose"
@
closeDropdown=
"collapseEditableItem"
/>
...
...
@@ -233,10 +302,12 @@ export default {
:footer-create-label-title=
"footerCreateLabelTitle"
:footer-manage-label-title=
"footerManageLabelTitle"
:labels-create-title=
"labelsCreateTitle"
:selected-labels=
"
selected
Labels"
:selected-labels=
"
issuable
Labels"
:variant=
"variant"
:issuable-type=
"issuableType"
:full-path=
"fullPath"
:attr-workspace-path=
"attrWorkspacePath"
:label-type=
"labelType"
@
setLabels=
"handleDropdownClose"
/>
</div>
...
...
ee/app/assets/javascripts/epic/components/epic_form.vue
View file @
3c079000
...
...
@@ -14,6 +14,7 @@ import { s__ } from '~/locale';
import
MarkdownField
from
'
~/vue_shared/components/markdown/field.vue
'
;
import
LabelsSelectVue
from
'
~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
'
;
import
LabelsSelectWidget
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
import
{
LabelType
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
createEpic
from
'
../queries/createEpic.mutation.graphql
'
;
...
...
@@ -31,7 +32,6 @@ export default {
},
mixins
:
[
glFeatureFlagMixin
()],
inject
:
[
'
iid
'
,
'
groupPath
'
,
'
groupEpicsPath
'
,
'
labelsFetchPath
'
,
...
...
@@ -48,6 +48,7 @@ export default {
startDateFixed
:
null
,
dueDateFixed
:
null
,
loading
:
false
,
LabelType
,
};
},
computed
:
{
...
...
@@ -190,13 +191,13 @@ export default {
<labels-select-widget
v-if=
"glFeatures.labelsWidget"
class=
"block labels js-labels-block"
:iid=
"iid"
:full-path=
"groupPath"
:allow-label-create=
"true"
:allow-multiselect=
"true"
:allow-scoped-labels=
"false"
:labels-filter-base-path=
"groupEpicsPath"
:selected-labels=
"labels"
:attr-workspace-path=
"groupPath"
:label-type=
"LabelType.group"
issuable-type=
"epic"
variant=
"embedded"
data-qa-selector=
"labels_block"
...
...
ee/spec/features/labels_hierarchy_spec.rb
View file @
3c079000
...
...
@@ -11,12 +11,11 @@ RSpec.describe 'Labels Hierarchy', :js do
let!
(
:grandparent_group_label
)
{
create
(
:group_label
,
group:
grandparent
,
title:
'Label_1'
)
}
let!
(
:parent_group_label
)
{
create
(
:group_label
,
group:
parent
,
title:
'Label_2'
)
}
let!
(
:child_group_label
)
{
create
(
:group_label
,
group:
child
,
title:
'Label_3'
)
}
let!
(
:project_label_1
)
{
create
(
:label
,
project:
project_1
,
title:
'Label_4'
)
}
let!
(
:project_label_1
)
{
create
(
:label
,
project:
project_1
,
title:
'Label_3'
)
}
let!
(
:labeled_issue_1
)
{
create
(
:labeled_issue
,
project:
project_1
,
labels:
[
grandparent_group_label
,
parent_group_label
,
child_group_label
])
}
let!
(
:labeled_issue_1
)
{
create
(
:labeled_issue
,
project:
project_1
,
labels:
[
grandparent_group_label
,
parent_group_label
])
}
let!
(
:labeled_issue_2
)
{
create
(
:labeled_issue
,
project:
project_1
,
labels:
[
grandparent_group_label
,
parent_group_label
])
}
let!
(
:labeled_issue_3
)
{
create
(
:labeled_issue
,
project:
project_1
,
labels:
[
grandparent_group_label
,
parent_group_label
,
child_group_label
,
project_label_1
])
}
let!
(
:labeled_issue_3
)
{
create
(
:labeled_issue
,
project:
project_1
,
labels:
[
grandparent_group_label
,
parent_group_label
,
project_label_1
])
}
let!
(
:not_labeled
)
{
create
(
:issue
,
project:
project_1
)
}
before
do
...
...
@@ -26,8 +25,8 @@ RSpec.describe 'Labels Hierarchy', :js do
end
shared_examples
'filter for scoped boards'
do
|
project
=
false
|
it
'scopes board to ancestor and
descendant
labels'
do
labels
=
[
grandparent_group_label
,
parent_group_label
,
child_group_label
]
it
'scopes board to ancestor and
current group
labels'
do
labels
=
[
grandparent_group_label
,
parent_group_label
]
labels
.
push
(
project_label_1
)
if
project
labels
.
each
do
|
label
|
...
...
spec/frontend/boards/stores/actions_spec.js
View file @
3c079000
...
...
@@ -1572,12 +1572,13 @@ describe('setActiveIssueLabels', () => {
const
getters
=
{
activeBoardItem
:
mockIssue
};
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
input
=
{
addLabel
Ids
:
testLabelIds
,
labels
Ids
:
testLabelIds
,
removeLabelIds
:
[],
projectPath
:
'
h/b
'
,
labels
,
};
it
(
'
should assign labels on success
, and sets loading state for labels
'
,
(
done
)
=>
{
it
(
'
should assign labels on success
'
,
(
done
)
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateIssue
:
{
issue
:
{
labels
:
{
nodes
:
labels
}
}
}
}
});
...
...
@@ -1593,14 +1594,6 @@ describe('setActiveIssueLabels', () => {
input
,
{
...
state
,
...
getters
},
[
{
type
:
types
.
SET_LABELS_LOADING
,
payload
:
true
,
},
{
type
:
types
.
SET_LABELS_LOADING
,
payload
:
false
,
},
{
type
:
types
.
UPDATE_BOARD_ITEM_BY_ID
,
payload
,
...
...
spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
View file @
3c079000
...
...
@@ -51,6 +51,7 @@ describe('DropdownContentsCreateView', () => {
const
createComponent
=
({
mutationHandler
=
createLabelSuccessHandler
,
issuableType
=
IssuableType
.
Issue
,
labelType
=
'
ProjectLabel
'
,
}
=
{})
=>
{
const
mockApollo
=
createMockApollo
([[
createLabelMutation
,
mutationHandler
]]);
mockApollo
.
clients
.
defaultClient
.
cache
.
writeQuery
({
...
...
@@ -68,6 +69,8 @@ describe('DropdownContentsCreateView', () => {
propsData
:
{
issuableType
,
fullPath
:
''
,
attrWorkspacePath
:
''
,
labelType
,
},
});
};
...
...
@@ -174,7 +177,7 @@ describe('DropdownContentsCreateView', () => {
});
it
(
'
calls a mutation with `groupPath` variable on the epic
'
,
()
=>
{
createComponent
({
issuableType
:
IssuableType
.
Epic
});
createComponent
({
issuableType
:
IssuableType
.
Epic
,
labelType
:
'
GroupLabel
'
});
fillLabelAttributes
();
findCreateButton
().
vm
.
$emit
(
'
click
'
);
...
...
spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
View file @
3c079000
...
...
@@ -41,6 +41,8 @@ describe('DropdownContent', () => {
variant
:
'
sidebar
'
,
issuableType
:
'
issue
'
,
fullPath
:
'
test
'
,
labelType
:
'
ProjectLabel
'
,
attrWorkspacePath
:
'
path
'
,
...
props
,
},
data
()
{
...
...
spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
View file @
3c079000
...
...
@@ -41,6 +41,7 @@ describe('LabelsSelectRoot', () => {
propsData
:
{
...
config
,
issuableType
:
IssuableType
.
Issue
,
labelType
:
'
ProjectLabel
'
,
},
stubs
:
{
SidebarEditableItem
,
...
...
spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
View file @
3c079000
...
...
@@ -40,12 +40,12 @@ export const mockConfig = {
labelsListTitle
:
'
Assign labels
'
,
labelsCreateTitle
:
'
Create label
'
,
variant
:
'
sidebar
'
,
selectedLabels
:
[
mockRegularLabel
,
mockScopedLabel
],
labelsSelectInProgress
:
false
,
labelsFilterBasePath
:
'
/gitlab-org/my-project/issues
'
,
labelsFilterParam
:
'
label_name
'
,
footerCreateLabelTitle
:
'
create
'
,
footerManageLabelTitle
:
'
manage
'
,
attrWorkspacePath
:
'
test
'
,
};
export
const
mockSuggestedColors
=
{
...
...
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