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
4e53ae6c
Commit
4e53ae6c
authored
Dec 01, 2021
by
Florie Guibert
Committed by
Natalia Tepluhina
Dec 01, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up labels_widget feature flag
parent
a9a8dd14
Changes
32
Show whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
140 additions
and
658 deletions
+140
-658
app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
...ets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+6
-0
app/assets/javascripts/boards/components/board_content_sidebar.vue
...s/javascripts/boards/components/board_content_sidebar.vue
+0
-4
app/assets/javascripts/boards/stores/actions.js
app/assets/javascripts/boards/stores/actions.js
+0
-28
app/assets/javascripts/right_sidebar.js
app/assets/javascripts/right_sidebar.js
+0
-9
app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
.../javascripts/sidebar/components/labels/sidebar_labels.vue
+1
-153
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
...nents/sidebar/labels_select_widget/labels_select_root.vue
+2
-1
app/controllers/groups/boards_controller.rb
app/controllers/groups/boards_controller.rb
+0
-1
app/controllers/projects/boards_controller.rb
app/controllers/projects/boards_controller.rb
+0
-1
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+0
-1
app/controllers/projects/merge_requests_controller.rb
app/controllers/projects/merge_requests_controller.rb
+0
-1
config/feature_flags/development/labels_widget.yml
config/feature_flags/development/labels_widget.yml
+0
-8
ee/app/assets/javascripts/behaviors/shortcuts/shortcuts_epic.js
.../assets/javascripts/behaviors/shortcuts/shortcuts_epic.js
+2
-12
ee/app/assets/javascripts/boards/components/epic_board_content_sidebar.vue
...ascripts/boards/components/epic_board_content_sidebar.vue
+0
-4
ee/app/assets/javascripts/boards/graphql/update_epic_labels.mutation.graphql
...cripts/boards/graphql/update_epic_labels.mutation.graphql
+0
-16
ee/app/assets/javascripts/boards/stores/actions.js
ee/app/assets/javascripts/boards/stores/actions.js
+1
-28
ee/app/assets/javascripts/epic/components/epic_form.vue
ee/app/assets/javascripts/epic/components/epic_form.vue
+2
-45
ee/app/assets/javascripts/epic/components/epic_sidebar.vue
ee/app/assets/javascripts/epic/components/epic_sidebar.vue
+0
-9
ee/app/controllers/groups/epic_boards_controller.rb
ee/app/controllers/groups/epic_boards_controller.rb
+0
-3
ee/app/controllers/groups/epics_controller.rb
ee/app/controllers/groups/epics_controller.rb
+0
-1
ee/spec/frontend/boards/components/__snapshots__/board_content_sidebar_spec.js.snap
...mponents/__snapshots__/board_content_sidebar_spec.js.snap
+22
-2
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
.../frontend/boards/components/board_content_sidebar_spec.js
+5
-1
ee/spec/frontend/boards/components/epic_board_content_sidebar_spec.js
...tend/boards/components/epic_board_content_sidebar_spec.js
+6
-3
ee/spec/frontend/boards/stores/actions_spec.js
ee/spec/frontend/boards/stores/actions_spec.js
+21
-71
ee/spec/frontend/epic/components/epic_form_spec.js
ee/spec/frontend/epic/components/epic_form_spec.js
+5
-3
qa/qa/page/component/issuable/sidebar.rb
qa/qa/page/component/issuable/sidebar.rb
+0
-9
qa/qa/specs/features/ee/browser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb
...ser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb
+0
-5
spec/features/issues/user_edits_issue_spec.rb
spec/features/issues/user_edits_issue_spec.rb
+1
-2
spec/features/labels_hierarchy_spec.rb
spec/features/labels_hierarchy_spec.rb
+4
-6
spec/frontend/boards/components/board_content_sidebar_spec.js
.../frontend/boards/components/board_content_sidebar_spec.js
+6
-3
spec/frontend/boards/stores/actions_spec.js
spec/frontend/boards/stores/actions_spec.js
+20
-70
spec/frontend/sidebar/sidebar_labels_spec.js
spec/frontend/sidebar/sidebar_labels_spec.js
+28
-153
spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
...s/sidebar/labels_select_widget/labels_select_root_spec.js
+8
-5
No files found.
app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
View file @
4e53ae6c
...
@@ -3,6 +3,7 @@ import Mousetrap from 'mousetrap';
...
@@ -3,6 +3,7 @@ import Mousetrap from 'mousetrap';
import
{
clickCopyToClipboardButton
}
from
'
~/behaviors/copy_to_clipboard
'
;
import
{
clickCopyToClipboardButton
}
from
'
~/behaviors/copy_to_clipboard
'
;
import
{
getSelectedFragment
}
from
'
~/lib/utils/common_utils
'
;
import
{
getSelectedFragment
}
from
'
~/lib/utils/common_utils
'
;
import
{
isElementVisible
}
from
'
~/lib/utils/dom_utils
'
;
import
{
isElementVisible
}
from
'
~/lib/utils/dom_utils
'
;
import
{
DEBOUNCE_DROPDOWN_DELAY
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
Sidebar
from
'
../../right_sidebar
'
;
import
Sidebar
from
'
../../right_sidebar
'
;
import
{
CopyAsGFM
}
from
'
../markdown/copy_as_gfm
'
;
import
{
CopyAsGFM
}
from
'
../markdown/copy_as_gfm
'
;
import
{
import
{
...
@@ -114,6 +115,11 @@ export default class ShortcutsIssuable extends Shortcuts {
...
@@ -114,6 +115,11 @@ export default class ShortcutsIssuable extends Shortcuts {
static
openSidebarDropdown
(
name
)
{
static
openSidebarDropdown
(
name
)
{
Sidebar
.
instance
.
openDropdown
(
name
);
Sidebar
.
instance
.
openDropdown
(
name
);
// Wait for the sidebar to trigger('click') open
// so it doesn't cause our dropdown to close preemptively
setTimeout
(()
=>
{
document
.
querySelector
(
`.block.
${
name
}
.shortcut-sidebar-dropdown-toggle`
).
click
();
},
DEBOUNCE_DROPDOWN_DELAY
);
return
false
;
return
false
;
}
}
...
...
app/assets/javascripts/boards/components/board_content_sidebar.vue
View file @
4e53ae6c
...
@@ -4,7 +4,6 @@ import { MountingPortal } from 'portal-vue';
...
@@ -4,7 +4,6 @@ import { MountingPortal } from 'portal-vue';
import
{
mapState
,
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
{
mapState
,
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
SidebarDropdownWidget
from
'
ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
SidebarDropdownWidget
from
'
ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
BoardSidebarTimeTracker
from
'
~/boards/components/sidebar/board_sidebar_time_tracker.vue
'
;
import
BoardSidebarTimeTracker
from
'
~/boards/components/sidebar/board_sidebar_time_tracker.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
...
@@ -26,7 +25,6 @@ export default {
...
@@ -26,7 +25,6 @@ export default {
SidebarDateWidget
,
SidebarDateWidget
,
SidebarConfidentialityWidget
,
SidebarConfidentialityWidget
,
BoardSidebarTimeTracker
,
BoardSidebarTimeTracker
,
BoardSidebarLabelsSelect
,
SidebarLabelsWidget
,
SidebarLabelsWidget
,
SidebarSubscriptionsWidget
,
SidebarSubscriptionsWidget
,
SidebarDropdownWidget
,
SidebarDropdownWidget
,
...
@@ -210,7 +208,6 @@ export default {
...
@@ -210,7 +208,6 @@ export default {
data-testid=
"sidebar-due-date"
data-testid=
"sidebar-due-date"
/>
/>
<sidebar-labels-widget
<sidebar-labels-widget
v-if=
"glFeatures.labelsWidget"
class=
"block labels"
class=
"block labels"
data-testid=
"sidebar-labels"
data-testid=
"sidebar-labels"
:iid=
"activeBoardItem.iid"
:iid=
"activeBoardItem.iid"
...
@@ -230,7 +227,6 @@ export default {
...
@@ -230,7 +227,6 @@ export default {
>
>
{{ __('None') }}
{{ __('None') }}
</sidebar-labels-widget>
</sidebar-labels-widget>
<board-sidebar-labels-select
v-else
class=
"block labels"
/>
<sidebar-weight-widget
<sidebar-weight-widget
v-if=
"weightFeatureAvailable"
v-if=
"weightFeatureAvailable"
:iid=
"activeBoardItem.iid"
:iid=
"activeBoardItem.iid"
...
...
app/assets/javascripts/boards/stores/actions.js
View file @
4e53ae6c
...
@@ -39,7 +39,6 @@ import boardLabelsQuery from '../graphql/board_labels.query.graphql';
...
@@ -39,7 +39,6 @@ import boardLabelsQuery from '../graphql/board_labels.query.graphql';
import
groupBoardMilestonesQuery
from
'
../graphql/group_board_milestones.query.graphql
'
;
import
groupBoardMilestonesQuery
from
'
../graphql/group_board_milestones.query.graphql
'
;
import
groupProjectsQuery
from
'
../graphql/group_projects.query.graphql
'
;
import
groupProjectsQuery
from
'
../graphql/group_projects.query.graphql
'
;
import
issueCreateMutation
from
'
../graphql/issue_create.mutation.graphql
'
;
import
issueCreateMutation
from
'
../graphql/issue_create.mutation.graphql
'
;
import
issueSetLabelsMutation
from
'
../graphql/issue_set_labels.mutation.graphql
'
;
import
listsIssuesQuery
from
'
../graphql/lists_issues.query.graphql
'
;
import
listsIssuesQuery
from
'
../graphql/lists_issues.query.graphql
'
;
import
projectBoardMilestonesQuery
from
'
../graphql/project_board_milestones.query.graphql
'
;
import
projectBoardMilestonesQuery
from
'
../graphql/project_board_milestones.query.graphql
'
;
...
@@ -609,33 +608,6 @@ export default {
...
@@ -609,33 +608,6 @@ export default {
setActiveIssueLabels
:
async
({
commit
,
getters
},
input
)
=>
{
setActiveIssueLabels
:
async
({
commit
,
getters
},
input
)
=>
{
const
{
activeBoardItem
}
=
getters
;
const
{
activeBoardItem
}
=
getters
;
if
(
!
gon
.
features
?.
labelsWidget
)
{
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetLabelsMutation
,
variables
:
{
input
:
{
iid
:
input
.
iid
||
String
(
activeBoardItem
.
iid
),
labelIds
:
input
.
labelsId
??
undefined
,
addLabelIds
:
input
.
addLabelIds
??
[],
removeLabelIds
:
input
.
removeLabelIds
??
[],
projectPath
:
input
.
projectPath
,
},
},
});
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
,
});
return
;
}
let
labels
=
input
?.
labels
||
[];
let
labels
=
input
?.
labels
||
[];
if
(
input
.
removeLabelIds
)
{
if
(
input
.
removeLabelIds
)
{
labels
=
activeBoardItem
.
labels
.
filter
(
labels
=
activeBoardItem
.
labels
.
filter
(
...
...
app/assets/javascripts/right_sidebar.js
View file @
4e53ae6c
...
@@ -3,7 +3,6 @@
...
@@ -3,7 +3,6 @@
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
Cookies
from
'
js-cookie
'
;
import
Cookies
from
'
js-cookie
'
;
import
{
hide
,
fixTitle
}
from
'
~/tooltips
'
;
import
{
hide
,
fixTitle
}
from
'
~/tooltips
'
;
import
{
DEBOUNCE_DROPDOWN_DELAY
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
createFlash
from
'
./flash
'
;
import
createFlash
from
'
./flash
'
;
import
axios
from
'
./lib/utils/axios_utils
'
;
import
axios
from
'
./lib/utils/axios_utils
'
;
import
{
sprintf
,
s__
,
__
}
from
'
./locale
'
;
import
{
sprintf
,
s__
,
__
}
from
'
./locale
'
;
...
@@ -127,14 +126,6 @@ Sidebar.prototype.openDropdown = function (blockOrName) {
...
@@ -127,14 +126,6 @@ Sidebar.prototype.openDropdown = function (blockOrName) {
this
.
setCollapseAfterUpdate
(
$block
);
this
.
setCollapseAfterUpdate
(
$block
);
this
.
toggleSidebar
(
'
open
'
);
this
.
toggleSidebar
(
'
open
'
);
}
}
// Wait for the sidebar to trigger('click') open
// so it doesn't cause our dropdown to close preemptively
setTimeout
(()
=>
{
if
(
!
gon
.
features
?.
labelsWidget
&&
!
$block
.
hasClass
(
'
labels-select-wrapper
'
))
{
$block
.
find
(
'
.js-sidebar-dropdown-toggle
'
).
trigger
(
'
click
'
);
}
},
DEBOUNCE_DROPDOWN_DELAY
);
};
};
Sidebar
.
prototype
.
setCollapseAfterUpdate
=
function
(
$block
)
{
Sidebar
.
prototype
.
setCollapseAfterUpdate
=
function
(
$block
)
{
...
...
app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
View file @
4e53ae6c
<
script
>
<
script
>
import
$
from
'
jquery
'
;
import
{
camelCase
,
difference
,
union
}
from
'
lodash
'
;
import
updateIssueLabelsMutation
from
'
~/boards/graphql/issue_set_labels.mutation.graphql
'
;
import
createFlash
from
'
~/flash
'
;
import
{
getIdFromGraphQLId
,
MutationOperationMode
}
from
'
~/graphql_shared/utils
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
__
}
from
'
~/locale
'
;
import
updateMergeRequestLabelsMutation
from
'
~/sidebar/queries/update_merge_request_labels.mutation.graphql
'
;
import
{
toLabelGid
}
from
'
~/sidebar/utils
'
;
import
{
DropdownVariant
}
from
'
~/vue_shared/components/sidebar/labels_select_vue/constants
'
;
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
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
{
LabelType
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
const
mutationMap
=
{
[
IssuableType
.
Issue
]:
{
mutation
:
updateIssueLabelsMutation
,
mutationName
:
'
updateIssue
'
,
},
[
IssuableType
.
MergeRequest
]:
{
mutation
:
updateMergeRequestLabelsMutation
,
mutationName
:
'
mergeRequestSetLabels
'
,
},
};
export
default
{
export
default
{
components
:
{
components
:
{
LabelsSelect
,
LabelsSelectWidget
,
LabelsSelectWidget
,
},
},
variant
:
DropdownVariant
.
Sidebar
,
variant
:
DropdownVariant
.
Sidebar
,
mixins
:
[
glFeatureFlagMixin
()],
inject
:
[
'
allowLabelEdit
'
,
'
iid
'
,
'
fullPath
'
,
'
issuableType
'
,
'
projectIssuesPath
'
],
inject
:
[
'
allowLabelCreate
'
,
'
allowLabelEdit
'
,
'
allowScopedLabels
'
,
'
iid
'
,
'
fullPath
'
,
'
initiallySelectedLabels
'
,
'
issuableType
'
,
'
labelsFetchPath
'
,
'
labelsManagePath
'
,
'
projectIssuesPath
'
,
'
projectPath
'
,
],
data
()
{
data
()
{
return
{
return
{
isLabelsSelectInProgress
:
false
,
selectedLabels
:
this
.
initiallySelectedLabels
,
LabelType
,
LabelType
,
};
};
},
},
methods
:
{
handleDropdownClose
()
{
$
(
this
.
$el
).
trigger
(
'
hidden.gl.dropdown
'
);
},
getUpdateVariables
(
labels
)
{
let
labelIds
=
[];
if
(
this
.
glFeatures
.
labelsWidget
)
{
labelIds
=
labels
.
map
(({
id
})
=>
toLabelGid
(
id
));
}
else
{
const
currentLabelIds
=
this
.
selectedLabels
.
map
((
label
)
=>
label
.
id
);
const
userAddedLabelIds
=
labels
.
filter
((
label
)
=>
label
.
set
).
map
((
label
)
=>
label
.
id
);
const
userRemovedLabelIds
=
labels
.
filter
((
label
)
=>
!
label
.
set
).
map
((
label
)
=>
label
.
id
);
labelIds
=
difference
(
union
(
currentLabelIds
,
userAddedLabelIds
),
userRemovedLabelIds
).
map
(
toLabelGid
,
);
}
switch
(
this
.
issuableType
)
{
case
IssuableType
.
Issue
:
return
{
iid
:
this
.
iid
,
projectPath
:
this
.
projectPath
,
labelIds
,
};
case
IssuableType
.
MergeRequest
:
return
{
iid
:
this
.
iid
,
labelIds
,
operationMode
:
MutationOperationMode
.
Replace
,
projectPath
:
this
.
projectPath
,
};
default
:
return
{};
}
},
handleUpdateSelectedLabels
(
dropdownLabels
)
{
this
.
updateSelectedLabels
(
this
.
getUpdateVariables
(
dropdownLabels
));
},
getRemoveVariables
(
labelId
)
{
switch
(
this
.
issuableType
)
{
case
IssuableType
.
Issue
:
return
{
iid
:
this
.
iid
,
projectPath
:
this
.
projectPath
,
removeLabelIds
:
[
labelId
],
};
case
IssuableType
.
MergeRequest
:
return
{
iid
:
this
.
iid
,
labelIds
:
[
toLabelGid
(
labelId
)],
operationMode
:
MutationOperationMode
.
Remove
,
projectPath
:
this
.
projectPath
,
};
default
:
return
{};
}
},
handleLabelRemove
(
labelId
)
{
this
.
updateSelectedLabels
(
this
.
getRemoveVariables
(
labelId
));
},
updateSelectedLabels
(
inputVariables
)
{
this
.
isLabelsSelectInProgress
=
true
;
this
.
$apollo
.
mutate
({
mutation
:
mutationMap
[
this
.
issuableType
].
mutation
,
variables
:
{
input
:
inputVariables
},
})
.
then
(({
data
})
=>
{
const
{
mutationName
}
=
mutationMap
[
this
.
issuableType
];
if
(
data
[
mutationName
]?.
errors
?.
length
)
{
throw
new
Error
();
}
const
issuableType
=
camelCase
(
this
.
issuableType
);
this
.
selectedLabels
=
data
[
mutationName
]?.[
issuableType
]?.
labels
?.
nodes
?.
map
((
label
)
=>
({
...
label
,
id
:
getIdFromGraphQLId
(
label
.
id
),
}));
})
.
catch
(()
=>
createFlash
({
message
:
__
(
'
An error occurred while updating labels.
'
)
}))
.
finally
(()
=>
{
this
.
isLabelsSelectInProgress
=
false
;
});
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<labels-select-widget
<labels-select-widget
v-if=
"glFeatures.labelsWidget"
class=
"block labels js-labels-block"
class=
"block labels js-labels-block"
:iid=
"iid"
:iid=
"iid"
:full-path=
"fullPath"
:full-path=
"fullPath"
...
@@ -165,28 +37,4 @@ export default {
...
@@ -165,28 +37,4 @@ export default {
>
>
{{
__
(
'
None
'
)
}}
{{
__
(
'
None
'
)
}}
</labels-select-widget>
</labels-select-widget>
<labels-select
v-else
class=
"block labels js-labels-block"
:allow-label-remove=
"allowLabelEdit"
:allow-label-create=
"allowLabelCreate"
:allow-label-edit=
"allowLabelEdit"
:allow-multiselect=
"true"
:allow-scoped-labels=
"allowScopedLabels"
:footer-create-label-title=
"__('Create project label')"
:footer-manage-label-title=
"__('Manage project labels')"
:labels-create-title=
"__('Create project label')"
:labels-fetch-path=
"labelsFetchPath"
:labels-filter-base-path=
"projectIssuesPath"
:labels-manage-path=
"labelsManagePath"
:labels-select-in-progress=
"isLabelsSelectInProgress"
:selected-labels=
"selectedLabels"
:variant=
"$options.sidebar"
data-qa-selector=
"labels_block"
@
onDropdownClose=
"handleDropdownClose"
@
onLabelRemove=
"handleLabelRemove"
@
updateSelectedLabels=
"handleUpdateSelectedLabels"
>
{{
__
(
'
None
'
)
}}
</labels-select>
</
template
>
</
template
>
app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
View file @
4e53ae6c
...
@@ -231,9 +231,10 @@ export default {
...
@@ -231,9 +231,10 @@ export default {
throw
new
Error
();
throw
new
Error
();
}
}
this
.
issuableLabels
=
data
[
mutationName
]?.[
this
.
issuableType
]?.
labels
?.
nodes
;
this
.
$emit
(
'
updateSelectedLabels
'
,
{
this
.
$emit
(
'
updateSelectedLabels
'
,
{
id
:
data
[
mutationName
]?.[
this
.
issuableType
]?.
id
,
id
:
data
[
mutationName
]?.[
this
.
issuableType
]?.
id
,
labels
:
data
[
mutationName
]?.[
this
.
issuableType
]?.
labels
?.
node
s
,
labels
:
this
.
issuableLabel
s
,
});
});
})
})
.
catch
((
error
)
=>
.
catch
((
error
)
=>
...
...
app/controllers/groups/boards_controller.rb
View file @
4e53ae6c
...
@@ -11,7 +11,6 @@ class Groups::BoardsController < Groups::ApplicationController
...
@@ -11,7 +11,6 @@ class Groups::BoardsController < Groups::ApplicationController
push_frontend_feature_flag
(
:board_multi_select
,
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:board_multi_select
,
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:swimlanes_buffered_rendering
,
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:swimlanes_buffered_rendering
,
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:iteration_cadences
,
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:iteration_cadences
,
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:labels_widget
,
group
,
default_enabled: :yaml
)
experiment
(
:prominent_create_board_btn
,
subject:
current_user
)
do
|
e
|
experiment
(
:prominent_create_board_btn
,
subject:
current_user
)
do
|
e
|
e
.
use
{
}
e
.
use
{
}
e
.
try
{
}
e
.
try
{
}
...
...
app/controllers/projects/boards_controller.rb
View file @
4e53ae6c
...
@@ -11,7 +11,6 @@ class Projects::BoardsController < Projects::ApplicationController
...
@@ -11,7 +11,6 @@ class Projects::BoardsController < Projects::ApplicationController
push_frontend_feature_flag
(
:issue_boards_filtered_search
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:issue_boards_filtered_search
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:board_multi_select
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:board_multi_select
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:iteration_cadences
,
project
&
.
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:iteration_cadences
,
project
&
.
group
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:labels_widget
,
project
,
default_enabled: :yaml
)
experiment
(
:prominent_create_board_btn
,
subject:
current_user
)
do
|
e
|
experiment
(
:prominent_create_board_btn
,
subject:
current_user
)
do
|
e
|
e
.
use
{
}
e
.
use
{
}
e
.
try
{
}
e
.
try
{
}
...
...
app/controllers/projects/issues_controller.rb
View file @
4e53ae6c
...
@@ -51,7 +51,6 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -51,7 +51,6 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag
(
:real_time_issue_sidebar
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:real_time_issue_sidebar
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:confidential_notes
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:confidential_notes
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:issue_assignees_widget
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:issue_assignees_widget
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:labels_widget
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:paginated_issue_discussions
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:paginated_issue_discussions
,
@project
,
default_enabled: :yaml
)
experiment
(
:invite_members_in_comment
,
namespace:
@project
.
root_ancestor
)
do
|
experiment_instance
|
experiment
(
:invite_members_in_comment
,
namespace:
@project
.
root_ancestor
)
do
|
experiment_instance
|
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
4e53ae6c
...
@@ -42,7 +42,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
...
@@ -42,7 +42,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag
(
:restructured_mr_widget
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:restructured_mr_widget
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:mr_changes_fluid_layout
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:mr_changes_fluid_layout
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:mr_attention_requests
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:mr_attention_requests
,
project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:labels_widget
,
project
,
default_enabled: :yaml
)
# Usage data feature flags
# Usage data feature flags
push_frontend_feature_flag
(
:users_expanding_widgets_usage_data
,
@project
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:users_expanding_widgets_usage_data
,
@project
,
default_enabled: :yaml
)
...
...
config/feature_flags/development/labels_widget.yml
deleted
100644 → 0
View file @
a9a8dd14
---
name
:
labels_widget
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62898
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/issues/332327
milestone
:
'
14.0'
type
:
development
group
:
group::project management
default_enabled
:
false
ee/app/assets/javascripts/behaviors/shortcuts/shortcuts_epic.js
View file @
4e53ae6c
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
Cookies
from
'
js-cookie
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
{
import
{
keysFor
,
keysFor
,
...
@@ -8,7 +7,6 @@ import {
...
@@ -8,7 +7,6 @@ import {
ISSUABLE_EDIT_DESCRIPTION
,
ISSUABLE_EDIT_DESCRIPTION
,
}
from
'
~/behaviors/shortcuts/keybindings
'
;
}
from
'
~/behaviors/shortcuts/keybindings
'
;
import
ShortcutsIssuable
from
'
~/behaviors/shortcuts/shortcuts_issuable
'
;
import
ShortcutsIssuable
from
'
~/behaviors/shortcuts/shortcuts_issuable
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
export
default
class
ShortcutsEpic
extends
ShortcutsIssuable
{
export
default
class
ShortcutsEpic
extends
ShortcutsIssuable
{
constructor
()
{
constructor
()
{
...
@@ -23,15 +21,7 @@ export default class ShortcutsEpic extends ShortcutsIssuable {
...
@@ -23,15 +21,7 @@ export default class ShortcutsEpic extends ShortcutsIssuable {
Mousetrap
.
bind
(
keysFor
(
ISSUABLE_EDIT_DESCRIPTION
),
ShortcutsIssuable
.
editIssue
);
Mousetrap
.
bind
(
keysFor
(
ISSUABLE_EDIT_DESCRIPTION
),
ShortcutsIssuable
.
editIssue
);
}
}
static
openSidebarDropdown
(
$block
)
{
static
openSidebarDropdown
()
{
if
(
gon
.
features
?.
labelsWidget
)
{
document
.
dispatchEvent
(
new
Event
(
'
toggleSidebarRevealLabelsDropdown
'
));
document
.
dispatchEvent
(
new
Event
(
'
toggleSidebarRevealLabelsDropdown
'
));
return
;
}
if
(
parseBoolean
(
Cookies
.
get
(
'
collapsed_gutter
'
)))
{
document
.
dispatchEvent
(
new
Event
(
'
toggleSidebarRevealLabelsDropdown
'
));
}
else
{
$block
.
find
(
'
.js-sidebar-dropdown-toggle
'
).
get
(
0
).
dispatchEvent
(
new
Event
(
'
click
'
));
}
}
}
}
}
ee/app/assets/javascripts/boards/components/epic_board_content_sidebar.vue
View file @
4e53ae6c
...
@@ -3,7 +3,6 @@ import { GlDrawer } from '@gitlab/ui';
...
@@ -3,7 +3,6 @@ import { GlDrawer } from '@gitlab/ui';
import
{
MountingPortal
}
from
'
portal-vue
'
;
import
{
MountingPortal
}
from
'
portal-vue
'
;
import
{
mapState
,
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
{
mapState
,
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
SidebarAncestorsWidget
from
'
ee_component/sidebar/components/ancestors_tree/sidebar_ancestors_widget.vue
'
;
import
SidebarAncestorsWidget
from
'
ee_component/sidebar/components/ancestors_tree/sidebar_ancestors_widget.vue
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
...
@@ -19,7 +18,6 @@ export default {
...
@@ -19,7 +18,6 @@ export default {
components
:
{
components
:
{
GlDrawer
,
GlDrawer
,
SidebarTodoWidget
,
SidebarTodoWidget
,
BoardSidebarLabelsSelect
,
BoardSidebarTitle
,
BoardSidebarTitle
,
SidebarLabelsWidget
,
SidebarLabelsWidget
,
SidebarConfidentialityWidget
,
SidebarConfidentialityWidget
,
...
@@ -113,7 +111,6 @@ export default {
...
@@ -113,7 +111,6 @@ export default {
:can-inherit=
"true"
:can-inherit=
"true"
/>
/>
<sidebar-labels-widget
<sidebar-labels-widget
v-if=
"glFeatures.labelsWidget"
class=
"block labels"
class=
"block labels"
data-testid=
"sidebar-labels"
data-testid=
"sidebar-labels"
:iid=
"activeBoardItem.iid"
:iid=
"activeBoardItem.iid"
...
@@ -130,7 +127,6 @@ export default {
...
@@ -130,7 +127,6 @@ export default {
>
>
{{
__
(
'
None
'
)
}}
{{
__
(
'
None
'
)
}}
</sidebar-labels-widget>
</sidebar-labels-widget>
<board-sidebar-labels-select
v-else
class=
"labels"
/>
<sidebar-confidentiality-widget
<sidebar-confidentiality-widget
:iid=
"activeBoardItem.iid"
:iid=
"activeBoardItem.iid"
:full-path=
"fullPath"
:full-path=
"fullPath"
...
...
ee/app/assets/javascripts/boards/graphql/update_epic_labels.mutation.graphql
deleted
100644 → 0
View file @
a9a8dd14
mutation
updateBoardEpicLabels
(
$input
:
UpdateEpicInput
!)
{
updateEpic
(
input
:
$input
)
{
epic
{
id
labels
{
nodes
{
id
title
color
description
}
}
}
errors
}
}
ee/app/assets/javascripts/boards/stores/actions.js
View file @
4e53ae6c
...
@@ -36,7 +36,6 @@ import listUpdateLimitMetricsMutation from '../graphql/list_update_limit_metrics
...
@@ -36,7 +36,6 @@ import listUpdateLimitMetricsMutation from '../graphql/list_update_limit_metrics
import
listsEpicsQuery
from
'
../graphql/lists_epics.query.graphql
'
;
import
listsEpicsQuery
from
'
../graphql/lists_epics.query.graphql
'
;
import
subGroupsQuery
from
'
../graphql/sub_groups.query.graphql
'
;
import
subGroupsQuery
from
'
../graphql/sub_groups.query.graphql
'
;
import
updateBoardEpicUserPreferencesMutation
from
'
../graphql/update_board_epic_user_preferences.mutation.graphql
'
;
import
updateBoardEpicUserPreferencesMutation
from
'
../graphql/update_board_epic_user_preferences.mutation.graphql
'
;
import
updateEpicLabelsMutation
from
'
../graphql/update_epic_labels.mutation.graphql
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
*
as
types
from
'
./mutation_types
'
;
...
@@ -631,35 +630,9 @@ export default {
...
@@ -631,35 +630,9 @@ export default {
}
}
},
},
setActiveEpicLabels
:
async
({
commit
,
getters
,
state
},
input
)
=>
{
setActiveEpicLabels
:
async
({
commit
,
getters
},
input
)
=>
{
const
{
activeBoardItem
}
=
getters
;
const
{
activeBoardItem
}
=
getters
;
if
(
!
gon
.
features
?.
labelsWidget
)
{
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
updateEpicLabelsMutation
,
variables
:
{
input
:
{
iid
:
String
(
activeBoardItem
.
iid
),
addLabelIds
:
input
.
addLabelIds
??
[],
removeLabelIds
:
input
.
removeLabelIds
??
[],
groupPath
:
state
.
fullPath
,
},
},
});
if
(
data
.
updateEpic
?.
errors
?.
length
>
0
)
{
throw
new
Error
(
data
.
updateEpic
.
errors
);
}
commit
(
typesCE
.
UPDATE_BOARD_ITEM_BY_ID
,
{
itemId
:
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
data
.
updateEpic
.
epic
.
labels
.
nodes
,
});
return
;
}
let
labels
=
input
?.
labels
||
[];
let
labels
=
input
?.
labels
||
[];
if
(
input
.
removeLabelIds
)
{
if
(
input
.
removeLabelIds
)
{
labels
=
activeBoardItem
.
labels
.
filter
(
labels
=
activeBoardItem
.
labels
.
filter
(
...
...
ee/app/assets/javascripts/epic/components/epic_form.vue
View file @
4e53ae6c
...
@@ -13,10 +13,8 @@ import { formatDate } from '~/lib/utils/datetime_utility';
...
@@ -13,10 +13,8 @@ import { formatDate } from '~/lib/utils/datetime_utility';
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
MarkdownField
from
'
~/vue_shared/components/markdown/field.vue
'
;
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
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
{
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
'
;
import
createEpic
from
'
../queries/createEpic.mutation.graphql
'
;
export
default
{
export
default
{
...
@@ -28,18 +26,9 @@ export default {
...
@@ -28,18 +26,9 @@ export default {
GlFormInput
,
GlFormInput
,
GlFormGroup
,
GlFormGroup
,
MarkdownField
,
MarkdownField
,
LabelsSelectVue
,
LabelsSelectWidget
,
LabelsSelectWidget
,
},
},
mixins
:
[
glFeatureFlagMixin
()],
inject
:
[
'
groupPath
'
,
'
groupEpicsPath
'
,
'
markdownPreviewPath
'
,
'
markdownDocsPath
'
],
inject
:
[
'
groupPath
'
,
'
groupEpicsPath
'
,
'
labelsFetchPath
'
,
'
labelsManagePath
'
,
'
markdownPreviewPath
'
,
'
markdownDocsPath
'
,
],
data
()
{
data
()
{
return
{
return
{
title
:
''
,
title
:
''
,
...
@@ -113,20 +102,7 @@ export default {
...
@@ -113,20 +102,7 @@ export default {
this
.
startDateFixed
=
val
;
this
.
startDateFixed
=
val
;
},
},
handleUpdateSelectedLabels
(
labels
)
{
handleUpdateSelectedLabels
(
labels
)
{
if
(
this
.
glFeatures
.
labelsWidget
)
{
this
.
labels
=
labels
.
map
((
label
)
=>
({
...
label
,
id
:
getIdFromGraphQLId
(
label
.
id
)
}));
this
.
labels
=
labels
.
map
((
label
)
=>
({
...
label
,
id
:
getIdFromGraphQLId
(
label
.
id
)
}));
return
;
}
const
ids
=
[];
const
allLabels
=
[...
labels
,
...
this
.
labels
];
this
.
labels
=
allLabels
.
filter
((
label
)
=>
{
const
exists
=
ids
.
includes
(
label
.
id
);
ids
.
push
(
label
.
id
);
return
!
exists
&&
label
.
set
;
});
},
},
},
},
};
};
...
@@ -190,7 +166,6 @@ export default {
...
@@ -190,7 +166,6 @@ export default {
<hr
/>
<hr
/>
<gl-form-group
:label=
"__('Labels')"
>
<gl-form-group
:label=
"__('Labels')"
>
<labels-select-widget
<labels-select-widget
v-if=
"glFeatures.labelsWidget"
class=
"block labels js-labels-block"
class=
"block labels js-labels-block"
:full-path=
"groupPath"
:full-path=
"groupPath"
:allow-label-create=
"true"
:allow-label-create=
"true"
...
@@ -207,24 +182,6 @@ export default {
...
@@ -207,24 +182,6 @@ export default {
>
>
{{ __('None') }}
{{ __('None') }}
</labels-select-widget>
</labels-select-widget>
<labels-select-vue
v-else
:allow-label-edit=
"false"
:allow-label-create=
"true"
:allow-multiselect=
"true"
:allow-scoped-labels=
"false"
:selected-labels=
"labels"
:labels-fetch-path=
"labelsFetchPath"
:labels-manage-path=
"labelsManagePath"
:labels-filter-base-path=
"groupEpicsPath"
:labels-list-title=
"__('Select label')"
:dropdown-button-text=
"__('Choose labels')"
variant=
"embedded"
class=
"block labels js-labels-block"
@
updateSelectedLabels=
"handleUpdateSelectedLabels"
>
{{ __('None') }}
</labels-select-vue>
</gl-form-group>
</gl-form-group>
<gl-form-group
:label=
"__('Start date')"
:description=
"$options.i18n.epicDatesHint"
>
<gl-form-group
:label=
"__('Start date')"
:description=
"$options.i18n.epicDatesHint"
>
<div
class=
"gl-display-inline-block gl-mr-2"
>
<div
class=
"gl-display-inline-block gl-mr-2"
>
...
...
ee/app/assets/javascripts/epic/components/epic_sidebar.vue
View file @
4e53ae6c
...
@@ -22,7 +22,6 @@ import { dateTypes } from '../constants';
...
@@ -22,7 +22,6 @@ import { dateTypes } from '../constants';
import
epicUtils
from
'
../utils/epic_utils
'
;
import
epicUtils
from
'
../utils/epic_utils
'
;
import
SidebarDatePicker
from
'
./sidebar_items/sidebar_date_picker.vue
'
;
import
SidebarDatePicker
from
'
./sidebar_items/sidebar_date_picker.vue
'
;
import
SidebarHeader
from
'
./sidebar_items/sidebar_header.vue
'
;
import
SidebarHeader
from
'
./sidebar_items/sidebar_header.vue
'
;
import
SidebarLabels
from
'
./sidebar_items/sidebar_labels.vue
'
;
export
default
{
export
default
{
dateTypes
,
dateTypes
,
...
@@ -30,7 +29,6 @@ export default {
...
@@ -30,7 +29,6 @@ export default {
SidebarHeader
,
SidebarHeader
,
SidebarDatePicker
,
SidebarDatePicker
,
SidebarDatePickerCollapsed
,
SidebarDatePickerCollapsed
,
SidebarLabels
,
SidebarAncestorsWidget
,
SidebarAncestorsWidget
,
SidebarParticipantsWidget
,
SidebarParticipantsWidget
,
SidebarConfidentialityWidget
,
SidebarConfidentialityWidget
,
...
@@ -239,7 +237,6 @@ export default {
...
@@ -239,7 +237,6 @@ export default {
@
toggleCollapse=
"toggleSidebar(
{ sidebarCollapsed })"
@
toggleCollapse=
"toggleSidebar(
{ sidebarCollapsed })"
/>
/>
<labels-select-widget
<labels-select-widget
v-if=
"glFeatures.labelsWidget"
class=
"block labels js-labels-block"
class=
"block labels js-labels-block"
:iid=
"String(iid)"
:iid=
"String(iid)"
:full-path=
"fullPath"
:full-path=
"fullPath"
...
@@ -256,12 +253,6 @@ export default {
...
@@ -256,12 +253,6 @@ export default {
>
>
{{
__
(
'
None
'
)
}}
{{
__
(
'
None
'
)
}}
</labels-select-widget>
</labels-select-widget>
<sidebar-labels
v-else
:can-update=
"canUpdate"
:sidebar-collapsed=
"sidebarCollapsed"
data-testid=
"labels-select"
/>
<sidebar-confidentiality-widget
<sidebar-confidentiality-widget
:iid=
"String(iid)"
:iid=
"String(iid)"
:full-path=
"fullPath"
:full-path=
"fullPath"
...
...
ee/app/controllers/groups/epic_boards_controller.rb
View file @
4e53ae6c
...
@@ -8,9 +8,6 @@ class Groups::EpicBoardsController < Groups::ApplicationController
...
@@ -8,9 +8,6 @@ class Groups::EpicBoardsController < Groups::ApplicationController
before_action
:redirect_to_recent_board
,
only:
[
:index
]
before_action
:redirect_to_recent_board
,
only:
[
:index
]
before_action
:assign_endpoint_vars
before_action
:assign_endpoint_vars
before_action
do
push_frontend_feature_flag
(
:labels_widget
,
group
,
default_enabled: :yaml
)
end
track_redis_hll_event
:index
,
:show
,
name:
'g_project_management_users_viewing_epic_boards'
track_redis_hll_event
:index
,
:show
,
name:
'g_project_management_users_viewing_epic_boards'
...
...
ee/app/controllers/groups/epics_controller.rb
View file @
4e53ae6c
...
@@ -23,7 +23,6 @@ class Groups::EpicsController < Groups::ApplicationController
...
@@ -23,7 +23,6 @@ class Groups::EpicsController < Groups::ApplicationController
before_action
do
before_action
do
push_frontend_feature_flag
(
:vue_epics_list
,
@group
,
type: :development
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:vue_epics_list
,
@group
,
type: :development
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:improved_emoji_picker
,
@group
,
type: :development
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:improved_emoji_picker
,
@group
,
type: :development
,
default_enabled: :yaml
)
push_frontend_feature_flag
(
:labels_widget
,
@group
,
default_enabled: :yaml
)
end
end
feature_category
:portfolio_management
feature_category
:portfolio_management
...
...
ee/spec/frontend/boards/components/__snapshots__/board_content_sidebar_spec.js.snap
View file @
4e53ae6c
...
@@ -69,9 +69,29 @@ exports[`ee/BoardContentSidebar matches the snapshot 1`] = `
...
@@ -69,9 +69,29 @@ exports[`ee/BoardContentSidebar matches the snapshot 1`] = `
issuabletype="issue"
issuabletype="issue"
/>
/>
<boardsidebarlabelsselect-stub
<sidebarlabelswidget-stub
allowmultiselect="true"
attrworkspacepath="gitlab-org/gitlab-test"
class="block labels"
class="block labels"
/>
data-testid="sidebar-labels"
dropdownbuttontext="Label"
footercreatelabeltitle="Create project label"
footermanagelabeltitle="Manage project labels"
fullpath="gitlab-org/gitlab-test"
iid="27"
issuabletype="issue"
labelcreatetype="project"
labelscreatetitle="Create project label"
labelsfilterbasepath=""
labelsfilterparam="label_name"
labelslisttitle="Assign labels"
variant="sidebar"
workspacetype="project"
>
None
</sidebarlabelswidget-stub>
<sidebarweightwidget-stub
<sidebarweightwidget-stub
full-path="gitlab-org/gitlab-test"
full-path="gitlab-org/gitlab-test"
...
...
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
View file @
4e53ae6c
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
Vuex
from
'
vuex
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
BoardContentSidebar
from
'
~/boards/components/board_content_sidebar.vue
'
;
import
BoardContentSidebar
from
'
~/boards/components/board_content_sidebar.vue
'
;
import
{
ISSUABLE
,
issuableTypes
}
from
'
~/boards/constants
'
;
import
{
ISSUABLE
,
issuableTypes
}
from
'
~/boards/constants
'
;
import
{
mockIssue
,
mockIssueGroupPath
,
mockIssueProjectPath
}
from
'
../mock_data
'
;
import
{
mockIssue
,
mockIssueGroupPath
,
mockIssueProjectPath
}
from
'
../mock_data
'
;
Vue
.
use
(
Vuex
);
describe
(
'
ee/BoardContentSidebar
'
,
()
=>
{
describe
(
'
ee/BoardContentSidebar
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
let
store
;
let
store
;
...
@@ -25,6 +28,7 @@ describe('ee/BoardContentSidebar', () => {
...
@@ -25,6 +28,7 @@ describe('ee/BoardContentSidebar', () => {
projectPathForActiveIssue
:
()
=>
mockIssueProjectPath
,
projectPathForActiveIssue
:
()
=>
mockIssueProjectPath
,
groupPathForActiveIssue
:
()
=>
mockIssueGroupPath
,
groupPathForActiveIssue
:
()
=>
mockIssueGroupPath
,
isSidebarOpen
:
()
=>
true
,
isSidebarOpen
:
()
=>
true
,
isGroupBoard
:
()
=>
false
,
...
mockGetters
,
...
mockGetters
,
},
},
actions
:
mockActions
,
actions
:
mockActions
,
...
@@ -69,7 +73,7 @@ describe('ee/BoardContentSidebar', () => {
...
@@ -69,7 +73,7 @@ describe('ee/BoardContentSidebar', () => {
BoardEditableItem
:
true
,
BoardEditableItem
:
true
,
BoardSidebarTitle
:
true
,
BoardSidebarTitle
:
true
,
BoardSidebarTimeTracker
:
true
,
BoardSidebarTimeTracker
:
true
,
BoardSidebarLabelsSelec
t
:
true
,
SidebarLabelsWidge
t
:
true
,
SidebarAssigneesWidget
:
true
,
SidebarAssigneesWidget
:
true
,
SidebarConfidentialityWidget
:
true
,
SidebarConfidentialityWidget
:
true
,
SidebarDateWidget
:
true
,
SidebarDateWidget
:
true
,
...
...
ee/spec/frontend/boards/components/epic_board_content_sidebar_spec.js
View file @
4e53ae6c
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
MountingPortal
}
from
'
portal-vue
'
;
import
{
MountingPortal
}
from
'
portal-vue
'
;
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
Vuex
from
'
vuex
'
;
import
EpicBoardContentSidebar
from
'
ee_component/boards/components/epic_board_content_sidebar.vue
'
;
import
EpicBoardContentSidebar
from
'
ee_component/boards/components/epic_board_content_sidebar.vue
'
;
import
SidebarAncestorsWidget
from
'
ee_component/sidebar/components/ancestors_tree/sidebar_ancestors_widget.vue
'
;
import
SidebarAncestorsWidget
from
'
ee_component/sidebar/components/ancestors_tree/sidebar_ancestors_widget.vue
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
SidebarConfidentialityWidget
from
'
~/sidebar/components/confidential/sidebar_confidentiality_widget.vue
'
;
import
SidebarConfidentialityWidget
from
'
~/sidebar/components/confidential/sidebar_confidentiality_widget.vue
'
;
...
@@ -13,8 +13,11 @@ import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue
...
@@ -13,8 +13,11 @@ import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue
import
SidebarParticipantsWidget
from
'
~/sidebar/components/participants/sidebar_participants_widget.vue
'
;
import
SidebarParticipantsWidget
from
'
~/sidebar/components/participants/sidebar_participants_widget.vue
'
;
import
SidebarSubscriptionsWidget
from
'
~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
'
;
import
SidebarSubscriptionsWidget
from
'
~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
'
;
import
SidebarTodoWidget
from
'
~/sidebar/components/todo_toggle/sidebar_todo_widget.vue
'
;
import
SidebarTodoWidget
from
'
~/sidebar/components/todo_toggle/sidebar_todo_widget.vue
'
;
import
LabelsSelectWidget
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
import
{
mockFormattedBoardEpic
}
from
'
../mock_data
'
;
import
{
mockFormattedBoardEpic
}
from
'
../mock_data
'
;
Vue
.
use
(
Vuex
);
describe
(
'
EpicBoardContentSidebar
'
,
()
=>
{
describe
(
'
EpicBoardContentSidebar
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
let
store
;
let
store
;
...
@@ -95,8 +98,8 @@ describe('EpicBoardContentSidebar', () => {
...
@@ -95,8 +98,8 @@ describe('EpicBoardContentSidebar', () => {
);
);
});
});
it
(
'
renders
BoardSidebarLabelsSelec
t
'
,
()
=>
{
it
(
'
renders
LabelsSelectWidge
t
'
,
()
=>
{
expect
(
wrapper
.
findComponent
(
BoardSidebarLabelsSelec
t
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
findComponent
(
LabelsSelectWidge
t
).
exists
()).
toBe
(
true
);
});
});
it
(
'
renders BoardSidebarTitle
'
,
()
=>
{
it
(
'
renders BoardSidebarTitle
'
,
()
=>
{
...
...
ee/spec/frontend/boards/stores/actions_spec.js
View file @
4e53ae6c
...
@@ -1340,7 +1340,7 @@ describe('setSelectedGroup', () => {
...
@@ -1340,7 +1340,7 @@ describe('setSelectedGroup', () => {
describe
(
'
setActiveEpicLabels
'
,
()
=>
{
describe
(
'
setActiveEpicLabels
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockEpic
.
id
]:
mockEpic
}
};
const
state
=
{
boardItems
:
{
[
mockEpic
.
id
]:
mockEpic
}
};
const
getters
=
{
activeBoardItem
:
mockEpic
};
const
getters
=
{
activeBoardItem
:
{
...
mockEpic
,
labels
}
};
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
input
=
{
const
input
=
{
addLabelIds
:
testLabelIds
,
addLabelIds
:
testLabelIds
,
...
@@ -1348,55 +1348,6 @@ describe('setActiveEpicLabels', () => {
...
@@ -1348,55 +1348,6 @@ describe('setActiveEpicLabels', () => {
groupPath
:
'
h/b
'
,
groupPath
:
'
h/b
'
,
};
};
it
(
'
should assign labels on success
'
,
(
done
)
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateEpic
:
{
epic
:
{
labels
:
{
nodes
:
labels
}
}
}
}
});
const
payload
=
{
itemId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
labels
,
};
testAction
(
actions
.
setActiveEpicLabels
,
input
,
{
...
state
,
...
getters
},
[
{
type
:
typesCE
.
UPDATE_BOARD_ITEM_BY_ID
,
payload
,
},
],
[],
done
,
);
});
it
(
'
throws error if fails
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateEpic
:
{
errors
:
[
'
failed mutation
'
]
}
}
});
await
expect
(
actions
.
setActiveEpicLabels
({
getters
},
input
)).
rejects
.
toThrow
(
Error
);
});
describe
(
'
labels_widget FF on
'
,
()
=>
{
beforeEach
(()
=>
{
window
.
gon
=
{
features
:
{
labelsWidget
:
true
},
};
getters
.
activeBoardItem
=
{
...
mockIssue
,
labels
};
});
afterEach
(()
=>
{
window
.
gon
=
{
features
:
{},
};
});
it
(
'
should assign labels
'
,
()
=>
{
it
(
'
should assign labels
'
,
()
=>
{
const
payload
=
{
const
payload
=
{
itemId
:
getters
.
activeBoardItem
.
id
,
itemId
:
getters
.
activeBoardItem
.
id
,
...
@@ -1438,5 +1389,4 @@ describe('setActiveEpicLabels', () => {
...
@@ -1438,5 +1389,4 @@ describe('setActiveEpicLabels', () => {
[],
[],
);
);
});
});
});
});
});
ee/spec/frontend/epic/components/epic_form_spec.js
View file @
4e53ae6c
...
@@ -6,7 +6,7 @@ import EpicForm from 'ee/epic/components/epic_form.vue';
...
@@ -6,7 +6,7 @@ import EpicForm from 'ee/epic/components/epic_form.vue';
import
createEpic
from
'
ee/epic/queries/createEpic.mutation.graphql
'
;
import
createEpic
from
'
ee/epic/queries/createEpic.mutation.graphql
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
LabelsSelect
Vue
from
'
~/vue_shared/components/sidebar/labels_select_vue
/labels_select_root.vue
'
;
import
LabelsSelect
Widget
from
'
~/vue_shared/components/sidebar/labels_select_widget
/labels_select_root.vue
'
;
jest
.
mock
(
'
~/lib/utils/url_utility
'
,
()
=>
({
jest
.
mock
(
'
~/lib/utils/url_utility
'
,
()
=>
({
visitUrl
:
jest
.
fn
(),
visitUrl
:
jest
.
fn
(),
...
@@ -48,7 +48,7 @@ describe('ee/epic/components/epic_form.vue', () => {
...
@@ -48,7 +48,7 @@ describe('ee/epic/components/epic_form.vue', () => {
});
});
const
findForm
=
()
=>
wrapper
.
find
(
GlForm
);
const
findForm
=
()
=>
wrapper
.
find
(
GlForm
);
const
findLabels
=
()
=>
wrapper
.
find
(
LabelsSelect
Vue
);
const
findLabels
=
()
=>
wrapper
.
find
(
LabelsSelect
Widget
);
const
findTitle
=
()
=>
wrapper
.
find
(
'
[data-testid="epic-title"]
'
);
const
findTitle
=
()
=>
wrapper
.
find
(
'
[data-testid="epic-title"]
'
);
const
findDescription
=
()
=>
wrapper
.
find
(
'
[data-testid="epic-description"]
'
);
const
findDescription
=
()
=>
wrapper
.
find
(
'
[data-testid="epic-description"]
'
);
const
findConfidentialityCheck
=
()
=>
wrapper
.
find
(
'
[data-testid="epic-confidentiality"]
'
);
const
findConfidentialityCheck
=
()
=>
wrapper
.
find
(
'
[data-testid="epic-confidentiality"]
'
);
...
@@ -113,7 +113,9 @@ describe('ee/epic/components/epic_form.vue', () => {
...
@@ -113,7 +113,9 @@ describe('ee/epic/components/epic_form.vue', () => {
findTitle
().
vm
.
$emit
(
'
input
'
,
title
);
findTitle
().
vm
.
$emit
(
'
input
'
,
title
);
findDescription
().
setValue
(
description
);
findDescription
().
setValue
(
description
);
findConfidentialityCheck
().
vm
.
$emit
(
'
input
'
,
confidential
);
findConfidentialityCheck
().
vm
.
$emit
(
'
input
'
,
confidential
);
findLabels
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
[{
id
:
1
,
set
:
1
}]);
findLabels
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
{
labels
:
[{
id
:
'
gid://gitlab/GroupLabel/1
'
}],
});
// Make sure the submitted values for start and due dates are date strings without timezone info.
// Make sure the submitted values for start and due dates are date strings without timezone info.
// (Datepicker emits a Date object but the submitted value must be a date string).
// (Datepicker emits a Date object but the submitted value must be a date string).
...
...
qa/qa/page/component/issuable/sidebar.rb
View file @
4e53ae6c
...
@@ -124,15 +124,6 @@ module QA
...
@@ -124,15 +124,6 @@ module QA
click_element
(
:more_assignees_link
)
click_element
(
:more_assignees_link
)
end
end
# When the labels_widget feature flag is enabled, wait until the labels widget appears
def
wait_for_labels_widget_feature_flag
Support
::
Retrier
.
retry_until
(
max_duration:
60
,
reload_page:
page
,
retry_on_exception:
true
,
sleep_interval:
5
)
do
within_element
(
:labels_block
)
do
find_element
(
:edit_link
)
end
end
end
private
private
def
wait_assignees_block_finish_loading
def
wait_assignees_block_finish_loading
...
...
qa/qa/specs/features/ee/browser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb
View file @
4e53ae6c
...
@@ -19,8 +19,6 @@ module QA
...
@@ -19,8 +19,6 @@ module QA
end
end
before
do
before
do
Runtime
::
Feature
.
enable
(
:labels_widget
,
project:
issue
.
project
)
Flow
::
Login
.
sign_in
Flow
::
Login
.
sign_in
[
[
...
@@ -43,9 +41,6 @@ module QA
...
@@ -43,9 +41,6 @@ module QA
testcase:
'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1181'
testcase:
'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1181'
)
do
)
do
Page
::
Project
::
Issue
::
Show
.
perform
do
|
show
|
Page
::
Project
::
Issue
::
Show
.
perform
do
|
show
|
# TODO: Remove this method when the `Runtime::Feature.enable` method call is removed
show
.
wait_for_labels_widget_feature_flag
show
.
select_labels
(
show
.
select_labels
(
[
[
new_label_same_scope
,
new_label_same_scope
,
...
...
spec/features/issues/user_edits_issue_spec.rb
View file @
4e53ae6c
...
@@ -15,7 +15,6 @@ RSpec.describe "Issues > User edits issue", :js do
...
@@ -15,7 +15,6 @@ RSpec.describe "Issues > User edits issue", :js do
context
'with authorized user'
do
context
'with authorized user'
do
before
do
before
do
stub_feature_flags
(
labels_widget:
false
)
project
.
add_developer
(
user
)
project
.
add_developer
(
user
)
project_with_milestones
.
add_developer
(
user
)
project_with_milestones
.
add_developer
(
user
)
sign_in
(
user
)
sign_in
(
user
)
...
@@ -151,7 +150,7 @@ RSpec.describe "Issues > User edits issue", :js do
...
@@ -151,7 +150,7 @@ RSpec.describe "Issues > User edits issue", :js do
page
.
within
'.block.labels'
do
page
.
within
'.block.labels'
do
# Remove `verisimilitude` label
# Remove `verisimilitude` label
within
'.gl-label'
do
within
'.gl-label'
do
click_button
click_button
'Remove label'
end
end
expect
(
page
).
to
have_text
(
'syzygy'
)
expect
(
page
).
to
have_text
(
'syzygy'
)
...
...
spec/features/labels_hierarchy_spec.rb
View file @
4e53ae6c
...
@@ -17,7 +17,6 @@ RSpec.describe 'Labels Hierarchy', :js do
...
@@ -17,7 +17,6 @@ RSpec.describe 'Labels Hierarchy', :js do
let!
(
:project_label_1
)
{
create
(
:label
,
project:
project_1
,
title:
'Label_4'
)
}
let!
(
:project_label_1
)
{
create
(
:label
,
project:
project_1
,
title:
'Label_4'
)
}
before
do
before
do
stub_feature_flags
(
labels_widget:
false
)
grandparent
.
add_owner
(
user
)
grandparent
.
add_owner
(
user
)
sign_in
(
user
)
sign_in
(
user
)
...
@@ -28,13 +27,12 @@ RSpec.describe 'Labels Hierarchy', :js do
...
@@ -28,13 +27,12 @@ RSpec.describe 'Labels Hierarchy', :js do
[
grandparent_group_label
,
parent_group_label
,
project_label_1
].
each
do
|
label
|
[
grandparent_group_label
,
parent_group_label
,
project_label_1
].
each
do
|
label
|
page
.
within
(
'.block.labels'
)
do
page
.
within
(
'.block.labels'
)
do
click_on
'Edit'
click_on
'Edit'
end
wait_for_requests
wait_for_requests
find
(
'a.label-item'
,
text:
label
.
title
).
click
click_on
label
.
title
wait_for_requests
click_on
'Close'
click_on
'Close'
end
wait_for_requests
wait_for_requests
...
...
spec/frontend/boards/components/board_content_sidebar_spec.js
View file @
4e53ae6c
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
MountingPortal
}
from
'
portal-vue
'
;
import
{
MountingPortal
}
from
'
portal-vue
'
;
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
Vuex
from
'
vuex
'
;
import
SidebarDropdownWidget
from
'
ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
SidebarDropdownWidget
from
'
ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
BoardContentSidebar
from
'
~/boards/components/board_content_sidebar.vue
'
;
import
BoardContentSidebar
from
'
~/boards/components/board_content_sidebar.vue
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
BoardSidebarTitle
from
'
~/boards/components/sidebar/board_sidebar_title.vue
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
SidebarDateWidget
from
'
~/sidebar/components/date/sidebar_date_widget.vue
'
;
import
SidebarDateWidget
from
'
~/sidebar/components/date/sidebar_date_widget.vue
'
;
import
SidebarSubscriptionsWidget
from
'
~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
'
;
import
SidebarSubscriptionsWidget
from
'
~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
'
;
import
SidebarTodoWidget
from
'
~/sidebar/components/todo_toggle/sidebar_todo_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
{
mockActiveIssue
,
mockIssue
,
mockIssueGroupPath
,
mockIssueProjectPath
}
from
'
../mock_data
'
;
import
{
mockActiveIssue
,
mockIssue
,
mockIssueGroupPath
,
mockIssueProjectPath
}
from
'
../mock_data
'
;
Vue
.
use
(
Vuex
);
describe
(
'
BoardContentSidebar
'
,
()
=>
{
describe
(
'
BoardContentSidebar
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
let
store
;
let
store
;
...
@@ -32,6 +34,7 @@ describe('BoardContentSidebar', () => {
...
@@ -32,6 +34,7 @@ describe('BoardContentSidebar', () => {
groupPathForActiveIssue
:
()
=>
mockIssueGroupPath
,
groupPathForActiveIssue
:
()
=>
mockIssueGroupPath
,
projectPathForActiveIssue
:
()
=>
mockIssueProjectPath
,
projectPathForActiveIssue
:
()
=>
mockIssueProjectPath
,
isSidebarOpen
:
()
=>
true
,
isSidebarOpen
:
()
=>
true
,
isGroupBoard
:
()
=>
false
,
...
mockGetters
,
...
mockGetters
,
},
},
actions
:
mockActions
,
actions
:
mockActions
,
...
@@ -115,8 +118,8 @@ describe('BoardContentSidebar', () => {
...
@@ -115,8 +118,8 @@ describe('BoardContentSidebar', () => {
expect
(
wrapper
.
findComponent
(
SidebarTodoWidget
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
findComponent
(
SidebarTodoWidget
).
exists
()).
toBe
(
true
);
});
});
it
(
'
renders
BoardSidebarLabelsSelec
t
'
,
()
=>
{
it
(
'
renders
SidebarLabelsWidge
t
'
,
()
=>
{
expect
(
wrapper
.
findComponent
(
BoardSidebarLabelsSelec
t
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
findComponent
(
SidebarLabelsWidge
t
).
exists
()).
toBe
(
true
);
});
});
it
(
'
renders BoardSidebarTitle
'
,
()
=>
{
it
(
'
renders BoardSidebarTitle
'
,
()
=>
{
...
...
spec/frontend/boards/stores/actions_spec.js
View file @
4e53ae6c
...
@@ -1570,7 +1570,7 @@ describe('addListNewIssue', () => {
...
@@ -1570,7 +1570,7 @@ describe('addListNewIssue', () => {
describe
(
'
setActiveIssueLabels
'
,
()
=>
{
describe
(
'
setActiveIssueLabels
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
getters
=
{
activeBoardItem
:
mockIssue
};
const
getters
=
{
activeBoardItem
:
{
...
mockIssue
,
labels
}
};
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
input
=
{
const
input
=
{
labelIds
:
testLabelIds
,
labelIds
:
testLabelIds
,
...
@@ -1579,55 +1579,6 @@ describe('setActiveIssueLabels', () => {
...
@@ -1579,55 +1579,6 @@ describe('setActiveIssueLabels', () => {
labels
,
labels
,
};
};
it
(
'
should assign labels on success
'
,
(
done
)
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateIssue
:
{
issue
:
{
labels
:
{
nodes
:
labels
}
}
}
}
});
const
payload
=
{
itemId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
labels
,
};
testAction
(
actions
.
setActiveIssueLabels
,
input
,
{
...
state
,
...
getters
},
[
{
type
:
types
.
UPDATE_BOARD_ITEM_BY_ID
,
payload
,
},
],
[],
done
,
);
});
it
(
'
throws error if fails
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateIssue
:
{
errors
:
[
'
failed mutation
'
]
}
}
});
await
expect
(
actions
.
setActiveIssueLabels
({
getters
},
input
)).
rejects
.
toThrow
(
Error
);
});
describe
(
'
labels_widget FF on
'
,
()
=>
{
beforeEach
(()
=>
{
window
.
gon
=
{
features
:
{
labelsWidget
:
true
},
};
getters
.
activeBoardItem
=
{
...
mockIssue
,
labels
};
});
afterEach
(()
=>
{
window
.
gon
=
{
features
:
{},
};
});
it
(
'
should assign labels
'
,
()
=>
{
it
(
'
should assign labels
'
,
()
=>
{
const
payload
=
{
const
payload
=
{
itemId
:
getters
.
activeBoardItem
.
id
,
itemId
:
getters
.
activeBoardItem
.
id
,
...
@@ -1669,7 +1620,6 @@ describe('setActiveIssueLabels', () => {
...
@@ -1669,7 +1620,6 @@ describe('setActiveIssueLabels', () => {
[],
[],
);
);
});
});
});
});
});
describe
(
'
setActiveItemSubscribed
'
,
()
=>
{
describe
(
'
setActiveItemSubscribed
'
,
()
=>
{
...
...
spec/frontend/sidebar/sidebar_labels_spec.js
View file @
4e53ae6c
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
mockLabels
,
mockRegularLabel
,
}
from
'
jest/vue_shared/components/sidebar/labels_select_vue/mock_data
'
;
import
updateIssueLabelsMutation
from
'
~/boards/graphql/issue_set_labels.mutation.graphql
'
;
import
{
MutationOperationMode
}
from
'
~/graphql_shared/utils
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
SidebarLabels
from
'
~/sidebar/components/labels/sidebar_labels.vue
'
;
import
SidebarLabels
from
'
~/sidebar/components/labels/sidebar_labels.vue
'
;
import
updateMergeRequestLabelsMutation
from
'
~/sidebar/queries/update_merge_request_labels.mutation.graphql
'
;
import
{
import
{
toLabelGid
}
from
'
~/sidebar/utils
'
;
DropdownVariant
,
import
{
DropdownVariant
}
from
'
~/vue_shared/components/sidebar/labels_select_vue/constants
'
;
LabelType
,
import
LabelsSelect
from
'
~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
'
;
}
from
'
~/vue_shared/components/sidebar/labels_select_widget/constants
'
;
import
LabelsSelect
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
describe
(
'
sidebar labels
'
,
()
=>
{
describe
(
'
sidebar labels
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
const
defaultProps
=
{
const
defaultProps
=
{
allowLabelCreate
:
true
,
allowLabelEdit
:
true
,
allowLabelEdit
:
true
,
allowScopedLabels
:
true
,
canEdit
:
true
,
iid
:
'
1
'
,
iid
:
'
1
'
,
initiallySelectedLabels
:
mockLabels
,
issuableType
:
'
issue
'
,
issuableType
:
'
issue
'
,
labelsFetchPath
:
'
/gitlab-org/gitlab-test/-/labels.json?include_ancestor_groups=true
'
,
labelsManagePath
:
'
/gitlab-org/gitlab-test/-/labels
'
,
projectIssuesPath
:
'
/gitlab-org/gitlab-test/-/issues
'
,
projectIssuesPath
:
'
/gitlab-org/gitlab-test/-/issues
'
,
projectPath
:
'
gitlab-org/gitlab-test
'
,
fullPath
:
'
gitlab-org/gitlab-test
'
,
fullPath
:
'
gitlab-org/gitlab-test
'
,
};
};
const
$apollo
=
{
mutate
:
jest
.
fn
().
mockResolvedValue
(),
};
const
userUpdatedLabels
=
[
{
...
mockRegularLabel
,
set
:
false
,
},
{
id
:
40
,
title
:
'
Security
'
,
color
:
'
#ddd
'
,
text_color
:
'
#fff
'
,
set
:
true
,
},
{
id
:
55
,
title
:
'
Tooling
'
,
color
:
'
#ddd
'
,
text_color
:
'
#fff
'
,
set
:
false
,
},
];
const
findLabelsSelect
=
()
=>
wrapper
.
find
(
LabelsSelect
);
const
findLabelsSelect
=
()
=>
wrapper
.
find
(
LabelsSelect
);
const
mountComponent
=
(
props
=
{})
=>
{
const
mountComponent
=
(
props
=
{})
=>
{
...
@@ -63,9 +25,6 @@ describe('sidebar labels', () => {
...
@@ -63,9 +25,6 @@ describe('sidebar labels', () => {
...
defaultProps
,
...
defaultProps
,
...
props
,
...
props
,
},
},
mocks
:
{
$apollo
,
},
});
});
};
};
...
@@ -75,116 +34,32 @@ describe('sidebar labels', () => {
...
@@ -75,116 +34,32 @@ describe('sidebar labels', () => {
});
});
describe
(
'
LabelsSelect props
'
,
()
=>
{
describe
(
'
LabelsSelect props
'
,
()
=>
{
describe
.
each
`
issuableType
${
'
issue
'
}
${
'
merge_request
'
}
`
(
'
issuableType $issuableType
'
,
({
issuableType
})
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mountComponent
(
);
mountComponent
({
issuableType
}
);
});
});
it
(
'
are as expected
'
,
()
=>
{
it
(
'
has expected props
'
,
()
=>
{
expect
(
findLabelsSelect
().
props
()).
toMatchObject
({
expect
(
findLabelsSelect
().
props
()).
toMatchObject
({
allowLabelCreate
:
defaultProps
.
allowLabelCreate
,
iid
:
defaultProps
.
iid
,
allowLabelEdit
:
defaultProps
.
allowLabelEdit
,
fullPath
:
defaultProps
.
fullPath
,
allowLabelRemove
:
defaultProps
.
allowLabelEdit
,
allowMultiselect
:
true
,
allowMultiselect
:
true
,
allowScopedLabels
:
defaultProps
.
allowScopedLabels
,
footerCreateLabelTitle
:
'
Create project label
'
,
footerCreateLabelTitle
:
'
Create project label
'
,
footerManageLabelTitle
:
'
Manage project labels
'
,
footerManageLabelTitle
:
'
Manage project labels
'
,
labelsCreateTitle
:
'
Create project label
'
,
labelsCreateTitle
:
'
Create project label
'
,
labelsFetchPath
:
defaultProps
.
labelsFetchPath
,
labelsFilterBasePath
:
defaultProps
.
projectIssuesPath
,
labelsFilterBasePath
:
defaultProps
.
projectIssuesPath
,
labelsManagePath
:
defaultProps
.
labelsManagePath
,
labelsSelectInProgress
:
false
,
selectedLabels
:
defaultProps
.
initiallySelectedLabels
,
variant
:
DropdownVariant
.
Sidebar
,
variant
:
DropdownVariant
.
Sidebar
,
issuableType
,
workspaceType
:
'
project
'
,
attrWorkspacePath
:
defaultProps
.
fullPath
,
labelCreateType
:
LabelType
.
project
,
});
});
});
});
});
});
describe
(
'
when type is issue
'
,
()
=>
{
beforeEach
(()
=>
{
mountComponent
({
issuableType
:
IssuableType
.
Issue
});
});
describe
(
'
when labels are updated
'
,
()
=>
{
it
(
'
invokes a mutation
'
,
()
=>
{
findLabelsSelect
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
userUpdatedLabels
);
const
expected
=
{
mutation
:
updateIssueLabelsMutation
,
variables
:
{
input
:
{
iid
:
defaultProps
.
iid
,
projectPath
:
defaultProps
.
projectPath
,
labelIds
:
[
toLabelGid
(
29
),
toLabelGid
(
28
),
toLabelGid
(
27
),
toLabelGid
(
40
)],
},
},
};
expect
(
$apollo
.
mutate
).
toHaveBeenCalledWith
(
expected
);
});
});
describe
(
'
when label `x` is clicked
'
,
()
=>
{
it
(
'
invokes a mutation
'
,
()
=>
{
findLabelsSelect
().
vm
.
$emit
(
'
onLabelRemove
'
,
27
);
const
expected
=
{
mutation
:
updateIssueLabelsMutation
,
variables
:
{
input
:
{
iid
:
defaultProps
.
iid
,
projectPath
:
defaultProps
.
projectPath
,
removeLabelIds
:
[
27
],
},
},
};
expect
(
$apollo
.
mutate
).
toHaveBeenCalledWith
(
expected
);
});
});
});
describe
(
'
when type is merge_request
'
,
()
=>
{
beforeEach
(()
=>
{
mountComponent
({
issuableType
:
IssuableType
.
MergeRequest
});
});
describe
(
'
when labels are updated
'
,
()
=>
{
it
(
'
invokes a mutation
'
,
()
=>
{
findLabelsSelect
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
userUpdatedLabels
);
const
expected
=
{
mutation
:
updateMergeRequestLabelsMutation
,
variables
:
{
input
:
{
iid
:
defaultProps
.
iid
,
labelIds
:
[
toLabelGid
(
29
),
toLabelGid
(
28
),
toLabelGid
(
27
),
toLabelGid
(
40
)],
operationMode
:
MutationOperationMode
.
Replace
,
projectPath
:
defaultProps
.
projectPath
,
},
},
};
expect
(
$apollo
.
mutate
).
toHaveBeenCalledWith
(
expected
);
});
});
describe
(
'
when label `x` is clicked
'
,
()
=>
{
it
(
'
invokes a mutation
'
,
()
=>
{
findLabelsSelect
().
vm
.
$emit
(
'
onLabelRemove
'
,
27
);
const
expected
=
{
mutation
:
updateMergeRequestLabelsMutation
,
variables
:
{
input
:
{
iid
:
defaultProps
.
iid
,
labelIds
:
[
toLabelGid
(
27
)],
operationMode
:
MutationOperationMode
.
Remove
,
projectPath
:
defaultProps
.
projectPath
,
},
},
};
expect
(
$apollo
.
mutate
).
toHaveBeenCalledWith
(
expected
);
});
});
});
});
});
});
spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
View file @
4e53ae6c
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
nextTick
}
from
'
vue
'
;
import
Vue
,
{
nextTick
}
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
...
@@ -8,14 +8,14 @@ import { IssuableType } from '~/issue_show/constants';
...
@@ -8,14 +8,14 @@ import { IssuableType } from '~/issue_show/constants';
import
SidebarEditableItem
from
'
~/sidebar/components/sidebar_editable_item.vue
'
;
import
SidebarEditableItem
from
'
~/sidebar/components/sidebar_editable_item.vue
'
;
import
DropdownContents
from
'
~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
'
;
import
DropdownContents
from
'
~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
'
;
import
DropdownValue
from
'
~/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
'
;
import
DropdownValue
from
'
~/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
'
;
import
DropdownValueCollapsed
from
'
~/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue
'
;
import
issueLabelsQuery
from
'
~/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
'
;
import
issueLabelsQuery
from
'
~/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
'
;
import
LabelsSelectRoot
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
import
LabelsSelectRoot
from
'
~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
'
;
import
{
mockConfig
,
issuableLabelsQueryResponse
}
from
'
./mock_data
'
;
import
{
mockConfig
,
issuableLabelsQueryResponse
}
from
'
./mock_data
'
;
jest
.
mock
(
'
~/flash
'
);
jest
.
mock
(
'
~/flash
'
);
const
localVue
=
createLocalVue
();
Vue
.
use
(
VueApollo
);
localVue
.
use
(
VueApollo
);
const
successfulQueryHandler
=
jest
.
fn
().
mockResolvedValue
(
issuableLabelsQueryResponse
);
const
successfulQueryHandler
=
jest
.
fn
().
mockResolvedValue
(
issuableLabelsQueryResponse
);
const
errorQueryHandler
=
jest
.
fn
().
mockRejectedValue
(
'
Houston, we have a problem
'
);
const
errorQueryHandler
=
jest
.
fn
().
mockRejectedValue
(
'
Houston, we have a problem
'
);
...
@@ -25,6 +25,7 @@ describe('LabelsSelectRoot', () => {
...
@@ -25,6 +25,7 @@ describe('LabelsSelectRoot', () => {
const
findSidebarEditableItem
=
()
=>
wrapper
.
findComponent
(
SidebarEditableItem
);
const
findSidebarEditableItem
=
()
=>
wrapper
.
findComponent
(
SidebarEditableItem
);
const
findDropdownValue
=
()
=>
wrapper
.
findComponent
(
DropdownValue
);
const
findDropdownValue
=
()
=>
wrapper
.
findComponent
(
DropdownValue
);
const
findDropdownValueCollapsed
=
()
=>
wrapper
.
findComponent
(
DropdownValueCollapsed
);
const
findDropdownContents
=
()
=>
wrapper
.
findComponent
(
DropdownContents
);
const
findDropdownContents
=
()
=>
wrapper
.
findComponent
(
DropdownContents
);
const
createComponent
=
({
const
createComponent
=
({
...
@@ -37,7 +38,6 @@ describe('LabelsSelectRoot', () => {
...
@@ -37,7 +38,6 @@ describe('LabelsSelectRoot', () => {
wrapper
=
shallowMount
(
LabelsSelectRoot
,
{
wrapper
=
shallowMount
(
LabelsSelectRoot
,
{
slots
,
slots
,
apolloProvider
:
mockApollo
,
apolloProvider
:
mockApollo
,
localVue
,
propsData
:
{
propsData
:
{
...
config
,
...
config
,
issuableType
:
IssuableType
.
Issue
,
issuableType
:
IssuableType
.
Issue
,
...
@@ -107,6 +107,9 @@ describe('LabelsSelectRoot', () => {
...
@@ -107,6 +107,9 @@ describe('LabelsSelectRoot', () => {
expect
(
findDropdownValue
().
props
(
'
selectedLabels
'
)).
toEqual
(
expect
(
findDropdownValue
().
props
(
'
selectedLabels
'
)).
toEqual
(
issuableLabelsQueryResponse
.
data
.
workspace
.
issuable
.
labels
.
nodes
,
issuableLabelsQueryResponse
.
data
.
workspace
.
issuable
.
labels
.
nodes
,
);
);
expect
(
findDropdownValueCollapsed
().
props
(
'
labels
'
)).
toEqual
(
issuableLabelsQueryResponse
.
data
.
workspace
.
issuable
.
labels
.
nodes
,
);
});
});
it
(
'
emits `onLabelRemove` event on dropdown value label remove event
'
,
()
=>
{
it
(
'
emits `onLabelRemove` event on dropdown value label remove event
'
,
()
=>
{
...
...
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