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
12676b0e
Commit
12676b0e
authored
Apr 30, 2021
by
Coung Ngo
Committed by
Jacques Erasmus
Apr 30, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix minor UX issues with "group by" within Iteration Report
parent
13b260da
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
79 additions
and
68 deletions
+79
-68
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
...omponents/sidebar/labels_select_vue/dropdown_contents.vue
+5
-7
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
...debar/labels_select_vue/dropdown_contents_labels_view.vue
+7
-6
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue
...hared/components/sidebar/labels_select_vue/label_item.vue
+6
-6
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
...mponents/sidebar/labels_select_vue/labels_select_root.vue
+3
-3
ee/app/assets/javascripts/iterations/components/iteration_report_issues.vue
...scripts/iterations/components/iteration_report_issues.vue
+10
-3
ee/app/assets/javascripts/iterations/components/iteration_report_tabs.vue
...vascripts/iterations/components/iteration_report_tabs.vue
+4
-4
ee/app/assets/stylesheets/pages/issuable_form.scss
ee/app/assets/stylesheets/pages/issuable_form.scss
+0
-1
ee/changelogs/unreleased/299238-fix-minor-ux-issues-with-group-by-within-iteration-report.yml
...minor-ux-issues-with-group-by-within-iteration-report.yml
+5
-0
ee/spec/frontend/iterations/components/iteration_report_issues_spec.js
...end/iterations/components/iteration_report_issues_spec.js
+4
-4
spec/features/issues/resource_label_events_spec.rb
spec/features/issues/resource_label_events_spec.rb
+1
-1
spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
...nents/sidebar/labels_select_vue/dropdown_contents_spec.js
+12
-5
spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
...ents/sidebar/labels_select_vue/labels_select_root_spec.js
+22
-28
No files found.
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
View file @
12676b0e
<
script
>
import
{
mapState
}
from
'
vuex
'
;
import
{
map
Getters
,
map
State
}
from
'
vuex
'
;
import
DropdownContentsCreateView
from
'
./dropdown_contents_create_view.vue
'
;
import
DropdownContentsLabelsView
from
'
./dropdown_contents_labels_view.vue
'
;
...
...
@@ -18,6 +18,7 @@ export default {
},
computed
:
{
...
mapState
([
'
showDropdownContentsCreateView
'
]),
...
mapGetters
([
'
isDropdownVariantSidebar
'
]),
dropdownContentsView
()
{
if
(
this
.
showDropdownContentsCreateView
)
{
return
'
dropdown-contents-create-view
'
;
...
...
@@ -25,11 +26,8 @@ export default {
return
'
dropdown-contents-labels-view
'
;
},
directionStyle
()
{
if
(
this
.
renderOnTop
)
{
return
{
bottom
:
'
100%
'
};
}
return
{};
const
bottom
=
this
.
isDropdownVariantSidebar
?
'
3rem
'
:
'
2rem
'
;
return
this
.
renderOnTop
?
{
bottom
}
:
{};
},
},
};
...
...
@@ -37,7 +35,7 @@ export default {
<
template
>
<div
class=
"labels-select-dropdown-contents
w-100 mt-1 mb-3 py-2 rounded-top rounded-bottom position
-absolute"
class=
"labels-select-dropdown-contents
gl-w-full gl-my-2 gl-py-3 gl-rounded-base gl
-absolute"
data-qa-selector=
"labels_dropdown_content"
:style=
"directionStyle"
>
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
View file @
12676b0e
...
...
@@ -83,12 +83,13 @@ export default {
const
highlightedLabel
=
this
.
$refs
.
labelsListContainer
.
querySelector
(
'
.is-focused
'
);
if
(
highlightedLabel
)
{
const
rect
=
highlightedLabel
.
getBoundingClientRect
();
if
(
rect
.
bottom
>
this
.
$refs
.
labelsListContainer
.
clientHeight
)
{
highlightedLabel
.
scrollIntoView
(
false
);
}
if
(
rect
.
top
<
0
)
{
highlightedLabel
.
scrollIntoView
();
const
container
=
this
.
$refs
.
labelsListContainer
.
getBoundingClientRect
();
const
label
=
highlightedLabel
.
getBoundingClientRect
();
if
(
label
.
bottom
>
container
.
bottom
)
{
this
.
$refs
.
labelsListContainer
.
scrollTop
+=
label
.
bottom
-
container
.
bottom
;
}
else
if
(
label
.
top
<
container
.
top
)
{
this
.
$refs
.
labelsListContainer
.
scrollTop
-=
container
.
top
-
label
.
top
;
}
}
},
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue
View file @
12676b0e
...
...
@@ -22,7 +22,7 @@ export default {
const
{
label
,
highlight
,
isLabelSet
}
=
props
;
const
labelColorBox
=
h
(
'
span
'
,
{
class
:
'
dropdown-label-box
'
,
class
:
'
dropdown-label-box
gl-flex-shrink-0 gl-top-0 gl-mr-3
'
,
style
:
{
backgroundColor
:
label
.
color
,
},
...
...
@@ -33,7 +33,7 @@ export default {
const
checkedIcon
=
h
(
GlIcon
,
{
class
:
{
'
mr-2 align-self-center
'
:
true
,
'
gl-mr-3 gl-flex-shrink-0
'
:
true
,
hidden
:
!
isLabelSet
,
},
props
:
{
...
...
@@ -43,7 +43,7 @@ export default {
const
noIcon
=
h
(
'
span
'
,
{
class
:
{
'
mr-3 pr-2
'
:
true
,
'
gl-mr-5 gl-pr-3
'
:
true
,
hidden
:
isLabelSet
,
},
attrs
:
{
...
...
@@ -56,7 +56,7 @@ export default {
const
labelLink
=
h
(
GlLink
,
{
class
:
'
d-flex align-items-baseline text-break-word label-item
'
,
class
:
'
gl-display-flex gl-align-items-center label-item gl-text-black-normal
'
,
on
:
{
click
:
()
=>
{
listeners
.
clickLabel
(
label
);
...
...
@@ -70,8 +70,8 @@ export default {
'
li
'
,
{
class
:
{
'
d
-block
'
:
true
,
'
text-left
'
:
true
,
'
gl-display
-block
'
:
true
,
'
gl-
text-left
'
:
true
,
'
is-focused
'
:
highlight
,
},
},
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
View file @
12676b0e
...
...
@@ -268,7 +268,7 @@ export default {
this
.
$emit
(
'
toggleCollapse
'
);
},
setContentIsOnViewport
(
showDropdownContents
)
{
if
(
!
this
.
isDropdownVariantEmbedded
||
!
showDropdownContents
)
{
if
(
!
showDropdownContents
)
{
this
.
contentIsOnViewport
=
true
;
return
;
...
...
@@ -276,8 +276,7 @@ export default {
this
.
$nextTick
(()
=>
{
if
(
this
.
$refs
.
dropdownContents
)
{
const
offset
=
{
top
:
100
};
this
.
contentIsOnViewport
=
isInViewport
(
this
.
$refs
.
dropdownContents
.
$el
,
offset
);
this
.
contentIsOnViewport
=
isInViewport
(
this
.
$refs
.
dropdownContents
.
$el
);
}
});
},
...
...
@@ -313,6 +312,7 @@ export default {
<dropdown-contents
v-show=
"dropdownButtonVisible && showDropdownContents"
ref=
"dropdownContents"
:render-on-top=
"!contentIsOnViewport"
/>
</
template
>
<
template
v-if=
"isDropdownVariantStandalone || isDropdownVariantEmbedded"
>
...
...
ee/app/assets/javascripts/iterations/components/iteration_report_issues.vue
View file @
12676b0e
...
...
@@ -6,8 +6,8 @@ import {
GlButton
,
GlLabel
,
GlLink
,
GlLoadingIcon
,
GlPagination
,
GlSkeletonLoader
,
GlTable
,
GlTooltipDirective
,
}
from
'
@gitlab/ui
'
;
...
...
@@ -18,12 +18,15 @@ import { Namespace } from '../constants';
import
iterationIssuesQuery
from
'
../queries/iteration_issues.query.graphql
'
;
import
iterationIssuesWithLabelFilterQuery
from
'
../queries/iteration_issues_with_label_filter.query.graphql
'
;
const
skeletonLoaderLimit
=
5
;
const
states
=
{
opened
:
'
opened
'
,
closed
:
'
closed
'
,
};
export
default
{
skeletonLoaderLimit
,
fields
:
[
{
key
:
'
title
'
,
...
...
@@ -50,8 +53,8 @@ export default {
GlButton
,
GlLabel
,
GlLink
,
GlLoadingIcon
,
GlPagination
,
GlSkeletonLoader
,
GlTable
,
},
directives
:
{
...
...
@@ -252,7 +255,11 @@ export default {
</gl-badge>
</div>
<gl-loading-icon
v-show=
"$apollo.queries.issues.loading"
class=
"gl-my-9"
size=
"md"
/>
<div
v-show=
"$apollo.queries.issues.loading"
>
<div
v-for=
"n in $options.skeletonLoaderLimit"
:key=
"n"
class=
"gl-mx-5 gl-my-6"
>
<gl-skeleton-loader
/>
</div>
</div>
<gl-table
v-show=
"shouldShowTable"
:items=
"issues.list"
...
...
ee/app/assets/javascripts/iterations/components/iteration_report_tabs.vue
View file @
12676b0e
...
...
@@ -135,8 +135,8 @@ export default {
<gl-tabs>
<gl-tab
title=
"Issues"
>
<template
#title
>
<span>
{{
__
(
'
Issues
'
)
}}
</span
><gl-badge
class=
"gl-ml-2"
variant=
"neutral
"
>
{{
issueCount
}}
</gl-badge>
{{
__
(
'
Issues
'
)
}}
<gl-badge
class=
"gl-ml-2"
size=
"sm"
variant=
"muted
"
>
{{
issueCount
}}
</gl-badge>
</
template
>
<div
class=
"card gl-bg-gray-10 gl-display-flex gl-flex-direction-row gl-flex-wrap gl-px-4"
>
...
...
@@ -153,9 +153,9 @@ export default {
<div
v-if=
"shouldShowFilterByLabel"
class=
"gl-display-flex gl-align-items-center gl-flex-basis-half gl-
white-space-nowrap gl-
my-3"
class=
"gl-display-flex gl-align-items-center gl-flex-basis-half gl-my-3"
>
<label
class=
"gl-mb-0 gl-mr-2"
>
{{ __('Filter by label') }}
</label>
<label
class=
"gl-
white-space-nowrap gl-
mb-0 gl-mr-2"
>
{{ __('Filter by label') }}
</label>
<labels-select
:allow-label-create=
"false"
:allow-label-edit=
"true"
...
...
ee/app/assets/stylesheets/pages/issuable_form.scss
View file @
12676b0e
...
...
@@ -32,7 +32,6 @@
width
:
300px
!
important
;
min-height
:
none
;
max-height
:
none
;
margin-bottom
:
$gl-spacing-scale-6
!
important
;
a
:not
(
.btn
)
{
@include
gl-reset-color
;
...
...
ee/changelogs/unreleased/299238-fix-minor-ux-issues-with-group-by-within-iteration-report.yml
0 → 100644
View file @
12676b0e
---
title
:
Fix minor UX issues with "group by" within iteration report
merge_request
:
59522
author
:
type
:
fixed
ee/spec/frontend/iterations/components/iteration_report_issues_spec.js
View file @
12676b0e
...
...
@@ -4,8 +4,8 @@ import {
GlBadge
,
GlButton
,
GlLabel
,
GlLoadingIcon
,
GlPagination
,
GlSkeletonLoader
,
GlTable
,
}
from
'
@gitlab/ui
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
...
...
@@ -31,7 +31,7 @@ describe('Iterations report issues', () => {
const
findGlBadge
=
()
=>
wrapper
.
findComponent
(
GlBadge
);
const
findGlButton
=
()
=>
wrapper
.
findComponent
(
GlButton
);
const
findGlLabel
=
()
=>
wrapper
.
findComponent
(
GlLabel
);
const
findGl
LoadingIcon
=
()
=>
wrapper
.
findComponent
(
GlLoadingIcon
);
const
findGl
SkeletonLoader
=
()
=>
wrapper
.
findComponent
(
GlSkeletonLoader
);
const
findGlPagination
=
()
=>
wrapper
.
findComponent
(
GlPagination
);
const
findGlTable
=
()
=>
wrapper
.
findComponent
(
GlTable
);
...
...
@@ -64,14 +64,14 @@ describe('Iterations report issues', () => {
loading
:
true
,
});
expect
(
findGl
LoadingIcon
().
exists
()).
toBe
(
true
);
expect
(
findGl
SkeletonLoader
().
exists
()).
toBe
(
true
);
expect
(
findGlTable
().
isVisible
()).
toBe
(
false
);
});
it
(
'
shows iterations list when not loading
'
,
()
=>
{
mountComponent
({
loading
:
false
,
mountFunction
:
mount
});
expect
(
findGl
LoadingIcon
().
isVisible
()).
toBe
(
false
);
expect
(
findGl
SkeletonLoader
().
isVisible
()).
toBe
(
false
);
expect
(
findGlTable
().
exists
()).
toBe
(
true
);
expect
(
wrapper
.
text
()).
toContain
(
'
No issues found
'
);
});
...
...
spec/features/issues/resource_label_events_spec.rb
View file @
12676b0e
...
...
@@ -40,7 +40,7 @@ RSpec.describe 'List issue resource label events', :js do
labels
.
each
{
|
label
|
click_link
label
}
click_on
'Edit'
send_keys
(
:escape
)
wait_for_requests
end
end
...
...
spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
View file @
12676b0e
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
{
DropdownVariant
}
from
'
~/vue_shared/components/sidebar/labels_select_vue/constants
'
;
import
DropdownContents
from
'
~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
'
;
import
labelsSelectModule
from
'
~/vue_shared/components/sidebar/labels_select_vue/store
'
;
import
{
mockConfig
}
from
'
./mock_data
'
;
...
...
@@ -50,13 +50,20 @@ describe('DropdownContent', () => {
describe
(
'
template
'
,
()
=>
{
it
(
'
renders component container element with class `labels-select-dropdown-contents` and no styles
'
,
()
=>
{
expect
(
wrapper
.
attributes
(
'
class
'
)).
toContain
(
'
labels-select-dropdown-contents
'
);
expect
(
wrapper
.
attributes
(
'
style
'
)).
toBe
(
undefined
);
expect
(
wrapper
.
attributes
(
'
style
'
)).
toBe
Undefined
(
);
});
it
(
'
renders component container element with styles when `renderOnTop` is true
'
,
()
=>
{
wrapper
=
createComponent
(
mockConfig
,
{
renderOnTop
:
true
});
describe
(
'
when `renderOnTop` is true
'
,
()
=>
{
it
.
each
`
variant | expected
${
DropdownVariant
.
Sidebar
}
|
${
'
bottom: 3rem
'
}
${
DropdownVariant
.
Standalone
}
|
${
'
bottom: 2rem
'
}
${
DropdownVariant
.
Embedded
}
|
${
'
bottom: 2rem
'
}
`
(
'
renders upward for $variant variant
'
,
({
variant
,
expected
})
=>
{
wrapper
=
createComponent
({
...
mockConfig
,
variant
},
{
renderOnTop
:
true
});
expect
(
wrapper
.
attributes
(
'
style
'
)).
toContain
(
'
bottom: 100%
'
);
expect
(
wrapper
.
attributes
(
'
style
'
)).
toContain
(
expected
);
});
});
});
});
spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
View file @
12676b0e
...
...
@@ -3,6 +3,7 @@ import Vuex from 'vuex';
import
{
isInViewport
}
from
'
~/lib/utils/common_utils
'
;
import
DropdownValueCollapsed
from
'
~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
'
;
import
{
DropdownVariant
}
from
'
~/vue_shared/components/sidebar/labels_select_vue/constants
'
;
import
DropdownButton
from
'
~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
'
;
import
DropdownContents
from
'
~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
'
;
import
DropdownTitle
from
'
~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
'
;
...
...
@@ -190,40 +191,33 @@ describe('LabelsSelectRoot', () => {
});
describe
(
'
sets content direction based on viewport
'
,
()
=>
{
it
(
'
does not set direction when `state.variant` is not "embedded"
'
,
async
()
=>
{
createComponent
();
wrapper
.
vm
.
$store
.
dispatch
(
'
toggleDropdownContents
'
);
wrapper
.
vm
.
setContentIsOnViewport
(
wrapper
.
vm
.
$store
.
state
);
await
wrapper
.
vm
.
$nextTick
;
expect
(
wrapper
.
find
(
DropdownContents
).
props
(
'
renderOnTop
'
)).
toBe
(
false
);
});
describe
(
'
when `state.variant` is "embedded"
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
...
mockConfig
,
variant
:
'
embedded
'
});
wrapper
.
vm
.
$store
.
dispatch
(
'
toggleDropdownContents
'
);
});
describe
.
each
(
Object
.
values
(
DropdownVariant
))(
'
when labels variant is "%s"
'
,
({
variant
})
=>
{
beforeEach
(()
=>
{
createComponent
({
...
mockConfig
,
variant
});
wrapper
.
vm
.
$store
.
dispatch
(
'
toggleDropdownContents
'
);
});
it
(
'
set direction when out of viewport
'
,
()
=>
{
isInViewport
.
mockImplementation
(()
=>
false
);
wrapper
.
vm
.
setContentIsOnViewport
(
wrapper
.
vm
.
$store
.
state
);
it
(
'
set direction when out of viewport
'
,
()
=>
{
isInViewport
.
mockImplementation
(()
=>
false
);
wrapper
.
vm
.
setContentIsOnViewport
(
wrapper
.
vm
.
$store
.
state
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
DropdownContents
).
props
(
'
renderOnTop
'
)).
toBe
(
true
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
DropdownContents
).
props
(
'
renderOnTop
'
)).
toBe
(
true
);
});
});
});
it
(
'
does not set direction when inside of viewport
'
,
()
=>
{
isInViewport
.
mockImplementation
(()
=>
true
);
wrapper
.
vm
.
setContentIsOnViewport
(
wrapper
.
vm
.
$store
.
state
);
it
(
'
does not set direction when inside of viewport
'
,
()
=>
{
isInViewport
.
mockImplementation
(()
=>
true
);
wrapper
.
vm
.
setContentIsOnViewport
(
wrapper
.
vm
.
$store
.
state
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
DropdownContents
).
props
(
'
renderOnTop
'
)).
toBe
(
false
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
DropdownContents
).
props
(
'
renderOnTop
'
)).
toBe
(
false
);
});
});
}
);
}
);
}
,
);
});
});
...
...
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