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
c74f114e
Commit
c74f114e
authored
Jun 16, 2020
by
Florie Guibert
Committed by
Kushal Pandya
Jun 16, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Display Swimlanes Epic Title
- Fetch epics on board swimlanes - Display epic information
parent
7b4340f1
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
411 additions
and
75 deletions
+411
-75
app/assets/javascripts/boards/components/board_content.vue
app/assets/javascripts/boards/components/board_content.vue
+0
-3
app/assets/javascripts/boards/components/board_list_header.vue
...ssets/javascripts/boards/components/board_list_header.vue
+24
-29
app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
...s/javascripts/vue_shared/mixins/related_issuable_mixin.js
+3
-1
app/assets/stylesheets/components/related_items_list.scss
app/assets/stylesheets/components/related_items_list.scss
+0
-8
app/assets/stylesheets/pages/boards.scss
app/assets/stylesheets/pages/boards.scss
+12
-8
changelogs/unreleased/220195-display-epics-on-swimlanes.yml
changelogs/unreleased/220195-display-epics-on-swimlanes.yml
+5
-0
ee/app/assets/javascripts/boards/components/epic_lane.vue
ee/app/assets/javascripts/boards/components/epic_lane.vue
+63
-0
ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
.../assets/javascripts/boards/components/epics_swimlanes.vue
+7
-13
ee/app/assets/javascripts/boards/queries/group_epics.query.graphql
...sets/javascripts/boards/queries/group_epics.query.graphql
+17
-0
ee/app/assets/javascripts/boards/stores/actions.js
ee/app/assets/javascripts/boards/stores/actions.js
+33
-3
ee/app/assets/javascripts/boards/stores/mutation_types.js
ee/app/assets/javascripts/boards/stores/mutation_types.js
+1
-0
ee/app/assets/javascripts/boards/stores/mutations.js
ee/app/assets/javascripts/boards/stores/mutations.js
+4
-0
ee/app/assets/javascripts/boards/stores/state.js
ee/app/assets/javascripts/boards/stores/state.js
+1
-0
ee/app/assets/javascripts/related_items_tree/components/tree_item_body.vue
...ascripts/related_items_tree/components/tree_item_body.vue
+3
-1
ee/spec/frontend/boards/components/epic_lane_spec.js
ee/spec/frontend/boards/components/epic_lane_spec.js
+50
-0
ee/spec/frontend/boards/mock_data.js
ee/spec/frontend/boards/mock_data.js
+123
-0
ee/spec/frontend/boards/stores/mutations_spec.js
ee/spec/frontend/boards/stores/mutations_spec.js
+51
-0
ee/spec/frontend/related_items_tree/components/tree_item_body_spec.js
...tend/related_items_tree/components/tree_item_body_spec.js
+6
-4
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/boards/components/board_list_header_spec.js
spec/frontend/boards/components/board_list_header_spec.js
+5
-5
No files found.
app/assets/javascripts/boards/components/board_content.vue
View file @
c74f114e
...
@@ -75,10 +75,7 @@ export default {
...
@@ -75,10 +75,7 @@ export default {
ref=
"swimlanes"
ref=
"swimlanes"
:lists=
"lists"
:lists=
"lists"
:can-admin-list=
"canAdminList"
:can-admin-list=
"canAdminList"
:group-id=
"groupId"
:disabled=
"disabled"
:disabled=
"disabled"
:issue-link-base=
"issueLinkBase"
:root-path=
"rootPath"
:board-id=
"boardId"
:board-id=
"boardId"
/>
/>
</div>
</div>
...
...
app/assets/javascripts/boards/components/board_list_header.vue
View file @
c74f114e
...
@@ -2,7 +2,6 @@
...
@@ -2,7 +2,6 @@
import
{
import
{
GlButton
,
GlButton
,
GlButtonGroup
,
GlButtonGroup
,
GlDeprecatedButton
,
GlLabel
,
GlLabel
,
GlTooltip
,
GlTooltip
,
GlIcon
,
GlIcon
,
...
@@ -23,7 +22,6 @@ export default {
...
@@ -23,7 +22,6 @@ export default {
BoardDelete
,
BoardDelete
,
GlButtonGroup
,
GlButtonGroup
,
GlButton
,
GlButton
,
GlDeprecatedButton
,
GlLabel
,
GlLabel
,
GlTooltip
,
GlTooltip
,
GlIcon
,
GlIcon
,
...
@@ -89,9 +87,12 @@ export default {
...
@@ -89,9 +87,12 @@ export default {
return
sprintf
(
__
(
'
%{issuesSize} issues
'
),
{
issuesSize
});
return
sprintf
(
__
(
'
%{issuesSize} issues
'
),
{
issuesSize
});
},
},
c
aret
Tooltip
()
{
c
hevron
Tooltip
()
{
return
this
.
list
.
isExpanded
?
s__
(
'
Boards|Collapse
'
)
:
s__
(
'
Boards|Expand
'
);
return
this
.
list
.
isExpanded
?
s__
(
'
Boards|Collapse
'
)
:
s__
(
'
Boards|Expand
'
);
},
},
chevronIcon
()
{
return
this
.
list
.
isExpanded
?
'
chevron-right
'
:
'
chevron-down
'
;
},
isNewIssueShown
()
{
isNewIssueShown
()
{
return
this
.
listType
===
ListType
.
backlog
||
this
.
showListHeaderButton
;
return
this
.
listType
===
ListType
.
backlog
||
this
.
showListHeaderButton
;
},
},
...
@@ -160,20 +161,16 @@ export default {
...
@@ -160,20 +161,16 @@ export default {
}"
}"
class="board-title gl-m-0 gl-display-flex js-board-handle"
class="board-title gl-m-0 gl-display-flex js-board-handle"
>
>
<
div
<
gl-button
v-if=
"list.isExpandable"
v-if=
"list.isExpandable"
v-gl-tooltip
.
hover
.
bottom
v-gl-tooltip
.
hover
:aria-label=
"c
aret
Tooltip"
:aria-label=
"c
hevron
Tooltip"
:title=
"c
aret
Tooltip"
:title=
"c
hevron
Tooltip"
aria-hidden=
"true
"
:icon=
"chevronIcon
"
class=
"board-title-caret no-drag"
class=
"board-title-caret no-drag"
variant=
"link"
@
click=
"toggleExpanded"
@
click=
"toggleExpanded"
>
/>
<i
:class=
"
{ 'fa-caret-right': list.isExpanded, 'fa-caret-down': !list.isExpanded }"
class="fa fa-fw"
>
</i>
</div>
<!-- The following is only true in EE and if it is a milestone -->
<!-- The following is only true in EE and if it is a milestone -->
<span
<span
v-if=
"list.type === 'milestone' && list.milestone"
v-if=
"list.type === 'milestone' && list.milestone"
...
@@ -232,7 +229,7 @@ export default {
...
@@ -232,7 +229,7 @@ export default {
v-gl-tooltip
.
hover
.
bottom
v-gl-tooltip
.
hover
.
bottom
:class=
"
{ 'gl-display-none': !list.isExpanded }"
:class=
"
{ 'gl-display-none': !list.isExpanded }"
:aria-label="__('Delete list')"
:aria-label="__('Delete list')"
class="board-delete no-drag gl-pr-0 gl-shadow-none"
class="board-delete no-drag gl-pr-0 gl-shadow-none
gl-mr-3
"
:title="__('Delete list')"
:title="__('Delete list')"
icon="remove"
icon="remove"
size="small"
size="small"
...
@@ -263,32 +260,30 @@ export default {
...
@@ -263,32 +260,30 @@ export default {
v-if=
"isNewIssueShown || isSettingsShown"
v-if=
"isNewIssueShown || isSettingsShown"
class=
"board-list-button-group pl-2"
class=
"board-list-button-group pl-2"
>
>
<gl-
deprecated-
button
<gl-button
v-if=
"isNewIssueShown"
v-if=
"isNewIssueShown"
ref=
"newIssueBtn"
ref=
"newIssueBtn"
v-gl-tooltip
.
hover
:class=
"{
:class=
"{
'gl-display-none': !list.isExpanded,
'gl-display-none': !list.isExpanded,
}"
}"
:aria-label=
"__(`New issue`)"
:aria-label=
"__('New issue')"
:title=
"__('New issue')"
class=
"issue-count-badge-add-button no-drag"
class=
"issue-count-badge-add-button no-drag"
type=
"button
"
icon=
"plus
"
@
click=
"showNewIssueForm"
@
click=
"showNewIssueForm"
>
/>
<i
aria-hidden=
"true"
data-hidden=
"true"
class=
"fa fa-plus"
></i>
</gl-deprecated-button>
<gl-tooltip
:target=
"() => $refs.newIssueBtn"
>
{{ __('New Issue') }}
</gl-tooltip>
<gl-
deprecated-
button
<gl-button
v-if=
"isSettingsShown"
v-if=
"isSettingsShown"
ref=
"settingsBtn"
ref=
"settingsBtn"
:aria-label=
"__(`List settings`)"
v-gl-tooltip
.
hover
:aria-label=
"__('List settings')"
class=
"no-drag js-board-settings-button"
class=
"no-drag js-board-settings-button"
title=
"List settings
"
:title=
"__('List settings')
"
type=
"button
"
icon=
"settings
"
@
click=
"openSidebarSettings"
@
click=
"openSidebarSettings"
>
/>
<gl-icon
name=
"settings"
/>
</gl-deprecated-button>
<gl-tooltip
:target=
"() => $refs.settingsBtn"
>
{{ __('List settings') }}
</gl-tooltip>
<gl-tooltip
:target=
"() => $refs.settingsBtn"
>
{{ __('List settings') }}
</gl-tooltip>
</gl-button-group>
</gl-button-group>
</h3>
</h3>
...
...
app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
View file @
c74f114e
...
@@ -144,7 +144,9 @@ const mixins = {
...
@@ -144,7 +144,9 @@ const mixins = {
return
'
merge-request-status closed issue-token-state-icon-closed
'
;
return
'
merge-request-status closed issue-token-state-icon-closed
'
;
}
}
return
this
.
isOpen
?
'
issue-token-state-icon-open
'
:
'
issue-token-state-icon-closed
'
;
return
this
.
isOpen
?
'
issue-token-state-icon-open gl-text-green-500
'
:
'
issue-token-state-icon-closed gl-text-blue-500
'
;
},
},
computedLinkElementType
()
{
computedLinkElementType
()
{
return
this
.
path
.
length
>
0
?
'
a
'
:
'
span
'
;
return
this
.
path
.
length
>
0
?
'
a
'
:
'
span
'
;
...
...
app/assets/stylesheets/components/related_items_list.scss
View file @
c74f114e
...
@@ -34,14 +34,6 @@ $item-remove-button-space: 42px;
...
@@ -34,14 +34,6 @@ $item-remove-button-space: 42px;
position
:
relative
;
position
:
relative
;
line-height
:
$gl-line-height
;
line-height
:
$gl-line-height
;
.issue-token-state-icon-open
{
color
:
$green-500
;
}
.issue-token-state-icon-closed
{
color
:
$blue-500
;
}
.merge-request-status.closed
{
.merge-request-status.closed
{
color
:
$red-500
;
color
:
$red-500
;
}
}
...
...
app/assets/stylesheets/pages/boards.scss
View file @
c74f114e
...
@@ -84,17 +84,22 @@
...
@@ -84,17 +84,22 @@
.board-title-caret
{
.board-title-caret
{
cursor
:
pointer
;
cursor
:
pointer
;
border-radius
:
$border-radius-default
;
border-radius
:
$border-radius-default
;
padding
:
4px
;
line-height
:
$gl-spacing-scale-5
;
height
:
$gl-spacing-scale-5
;
&
.btn
svg
{
top
:
0
;
}
&
:hover
{
&
:hover
{
background-color
:
$gray-
dark
;
background-color
:
$gray-
50
;
transition
:
background-color
0
.1s
linear
;
transition
:
background-color
0
.1s
linear
;
}
}
}
}
&
:not
(
.is-collapsed
)
{
&
:not
(
.is-collapsed
)
{
.board-title-caret
{
.board-title-caret
{
margin
:
0
$gl-padding-4
0
-10px
;
margin
-right
:
$gl-padding-4
;
}
}
}
}
...
@@ -155,7 +160,7 @@
...
@@ -155,7 +160,7 @@
.board-inner
{
.board-inner
{
font-size
:
$issue-boards-font-size
;
font-size
:
$issue-boards-font-size
;
background
:
$gray-light
;
background
:
$gray-light
;
border
:
1px
solid
$
border-color
;
border
:
1px
solid
$
gray-100
;
}
}
.board-header
{
.board-header
{
...
@@ -186,8 +191,8 @@
...
@@ -186,8 +191,8 @@
.board-title
{
.board-title
{
align-items
:
center
;
align-items
:
center
;
font-size
:
1em
;
font-size
:
1em
;
border-bottom
:
1px
solid
$
border-color
;
border-bottom
:
1px
solid
$
gray-100
;
padding
:
$gl-padding-8
$gl-padding
;
padding
:
$gl-padding-8
;
.
js-max-issue-size
:
:
before
{
.
js-max-issue-size
:
:
before
{
content
:
'/'
;
content
:
'/'
;
...
@@ -199,7 +204,6 @@
...
@@ -199,7 +204,6 @@
}
}
.board-delete
{
.board-delete
{
margin-right
:
10px
;
color
:
$gray-darkest
;
color
:
$gray-darkest
;
background-color
:
transparent
;
background-color
:
transparent
;
outline
:
0
;
outline
:
0
;
...
@@ -247,7 +251,7 @@
...
@@ -247,7 +251,7 @@
.board-card
{
.board-card
{
background
:
$white
;
background
:
$white
;
border
:
1px
solid
$gray-
2
00
;
border
:
1px
solid
$gray-
1
00
;
box-shadow
:
0
1px
2px
$issue-boards-card-shadow
;
box-shadow
:
0
1px
2px
$issue-boards-card-shadow
;
line-height
:
$gl-padding
;
line-height
:
$gl-padding
;
list-style
:
none
;
list-style
:
none
;
...
...
changelogs/unreleased/220195-display-epics-on-swimlanes.yml
0 → 100644
View file @
c74f114e
---
title
:
Update board header icons
merge_request
:
34366
author
:
type
:
changed
ee/app/assets/javascripts/boards/components/epic_lane.vue
0 → 100644
View file @
c74f114e
<
script
>
import
{
GlIcon
,
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
export
default
{
components
:
{
GlIcon
,
},
directives
:
{
GlTooltip
:
GlTooltipDirective
,
},
props
:
{
epic
:
{
type
:
Object
,
required
:
true
,
},
},
computed
:
{
stateText
()
{
return
this
.
epic
.
state
===
'
opened
'
?
__
(
'
Opened
'
)
:
__
(
'
Closed
'
);
},
stateIconClass
()
{
return
this
.
epic
.
state
===
'
opened
'
?
'
gl-text-green-500
'
:
'
gl-text-blue-500
'
;
},
issuesCount
()
{
const
{
openedIssues
,
closedIssues
}
=
this
.
epic
.
descendantCounts
;
return
openedIssues
+
closedIssues
;
},
issuesCountTooltipText
()
{
return
sprintf
(
__
(
`%{issuesCount} issues in this group`
),
{
issuesCount
:
this
.
issuesCount
});
},
},
};
</
script
>
<
template
>
<div
class=
"board-epic-lane gl-py-5 gl-px-3 gl-display-flex gl-align-items-center"
>
<gl-icon
class=
"gl-mr-2 gl-flex-shrink-0"
:class=
"stateIconClass"
name=
"epic"
:aria-label=
"stateText"
/>
<span
v-gl-tooltip
.
hover
:title=
"epic.title"
class=
"gl-mr-3 gl-font-weight-bold gl-white-space-nowrap gl-text-overflow-ellipsis gl-overflow-hidden"
>
{{
epic
.
title
}}
</span>
<span
v-gl-tooltip
.
hover
:title=
"issuesCountTooltipText"
class=
"gl-display-flex gl-align-items-center gl-text-gray-700"
tabindex=
"0"
:aria-label=
"issuesCountTooltipText"
data-testid=
"epic-lane-issue-count"
>
<gl-icon
class=
"gl-mr-2 gl-flex-shrink-0"
name=
"issues"
aria-hidden=
"true"
/>
<span
aria-hidden=
"true"
>
{{
issuesCount
}}
</span>
</span>
</div>
</
template
>
ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
View file @
c74f114e
<
script
>
<
script
>
import
{
mapState
}
from
'
vuex
'
;
import
BoardListHeader
from
'
ee_else_ce/boards/components/board_list_header.vue
'
;
import
BoardListHeader
from
'
ee_else_ce/boards/components/board_list_header.vue
'
;
import
EpicLane
from
'
./epic_lane.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
BoardListHeader
,
BoardListHeader
,
EpicLane
,
},
},
props
:
{
props
:
{
lists
:
{
lists
:
{
...
@@ -14,14 +17,6 @@ export default {
...
@@ -14,14 +17,6 @@ export default {
type
:
Boolean
,
type
:
Boolean
,
required
:
true
,
required
:
true
,
},
},
issueLinkBase
:
{
type
:
String
,
required
:
true
,
},
rootPath
:
{
type
:
String
,
required
:
true
,
},
boardId
:
{
boardId
:
{
type
:
String
,
type
:
String
,
required
:
true
,
required
:
true
,
...
@@ -31,11 +26,9 @@ export default {
...
@@ -31,11 +26,9 @@ export default {
required
:
false
,
required
:
false
,
default
:
false
,
default
:
false
,
},
},
groupId
:
{
type
:
Number
,
required
:
false
,
default
:
null
,
},
},
computed
:
{
...
mapState
([
'
epics
'
]),
},
},
};
};
</
script
>
</
script
>
...
@@ -62,5 +55,6 @@ export default {
...
@@ -62,5 +55,6 @@ export default {
:is-swimlanes-header=
"true"
:is-swimlanes-header=
"true"
/>
/>
</div>
</div>
<epic-lane
v-for=
"epic in epics"
:key=
"epic.id"
:epic=
"epic"
/>
</div>
</div>
</
template
>
</
template
>
ee/app/assets/javascripts/boards/queries/group_epics.query.graphql
0 → 100644
View file @
c74f114e
query
groupEpics
(
$fullPath
:
ID
!)
{
group
(
fullPath
:
$fullPath
)
{
epics
(
first
:
10
)
{
nodes
{
id
iid
title
state
webUrl
descendantCounts
{
openedIssues
closedIssues
}
}
}
}
}
ee/app/assets/javascripts/boards/stores/actions.js
View file @
c74f114e
...
@@ -5,6 +5,7 @@ import * as types from './mutation_types';
...
@@ -5,6 +5,7 @@ import * as types from './mutation_types';
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
epicsSwimlanes
from
'
../queries/epics_swimlanes.query.graphql
'
;
import
epicsSwimlanes
from
'
../queries/epics_swimlanes.query.graphql
'
;
import
groupEpics
from
'
../queries/group_epics.query.graphql
'
;
const
notImplemented
=
()
=>
{
const
notImplemented
=
()
=>
{
/* eslint-disable-next-line @gitlab/require-i18n-strings */
/* eslint-disable-next-line @gitlab/require-i18n-strings */
...
@@ -32,6 +33,25 @@ const fetchEpicsSwimlanes = ({ endpoints }) => {
...
@@ -32,6 +33,25 @@ const fetchEpicsSwimlanes = ({ endpoints }) => {
});
});
};
};
const
fetchEpics
=
({
endpoints
})
=>
{
const
{
fullPath
}
=
endpoints
;
const
query
=
groupEpics
;
const
variables
=
{
fullPath
,
};
return
gqlClient
.
query
({
query
,
variables
,
})
.
then
(({
data
})
=>
{
const
{
group
}
=
data
;
return
group
?.
epics
.
nodes
||
[];
});
};
export
default
{
export
default
{
...
actionsCE
,
...
actionsCE
,
...
@@ -80,9 +100,15 @@ export default {
...
@@ -80,9 +100,15 @@ export default {
commit
(
types
.
TOGGLE_EPICS_SWIMLANES
);
commit
(
types
.
TOGGLE_EPICS_SWIMLANES
);
if
(
state
.
isShowingEpicsSwimlanes
)
{
if
(
state
.
isShowingEpicsSwimlanes
)
{
fetchEpicsSwimlanes
(
state
)
Promise
.
all
([
fetchEpicsSwimlanes
(
state
),
fetchEpics
(
state
)])
.
then
(
swimlanes
=>
{
.
then
(([
swimlanes
,
epics
])
=>
{
if
(
swimlanes
)
{
dispatch
(
'
receiveSwimlanesSuccess
'
,
swimlanes
);
dispatch
(
'
receiveSwimlanesSuccess
'
,
swimlanes
);
}
if
(
epics
)
{
dispatch
(
'
receiveEpicsSuccess
'
,
epics
);
}
})
})
.
catch
(()
=>
dispatch
(
'
receiveSwimlanesFailure
'
));
.
catch
(()
=>
dispatch
(
'
receiveSwimlanesFailure
'
));
}
}
...
@@ -95,4 +121,8 @@ export default {
...
@@ -95,4 +121,8 @@ export default {
receiveSwimlanesFailure
:
({
commit
})
=>
{
receiveSwimlanesFailure
:
({
commit
})
=>
{
commit
(
types
.
RECEIVE_SWIMLANES_FAILURE
);
commit
(
types
.
RECEIVE_SWIMLANES_FAILURE
);
},
},
receiveEpicsSuccess
:
({
commit
},
swimlanes
)
=>
{
commit
(
types
.
RECEIVE_EPICS_SUCCESS
,
swimlanes
);
},
};
};
ee/app/assets/javascripts/boards/stores/mutation_types.js
View file @
c74f114e
...
@@ -15,4 +15,5 @@ export const TOGGLE_LABELS = 'TOGGLE_LABELS';
...
@@ -15,4 +15,5 @@ export const TOGGLE_LABELS = 'TOGGLE_LABELS';
export
const
TOGGLE_EPICS_SWIMLANES
=
'
TOGGLE_EPICS_SWIMLANES
'
;
export
const
TOGGLE_EPICS_SWIMLANES
=
'
TOGGLE_EPICS_SWIMLANES
'
;
export
const
RECEIVE_SWIMLANES_SUCCESS
=
'
RECEIVE_SWIMLANES_SUCCESS
'
;
export
const
RECEIVE_SWIMLANES_SUCCESS
=
'
RECEIVE_SWIMLANES_SUCCESS
'
;
export
const
RECEIVE_SWIMLANES_FAILURE
=
'
RECEIVE_SWIMLANES_FAILURE
'
;
export
const
RECEIVE_SWIMLANES_FAILURE
=
'
RECEIVE_SWIMLANES_FAILURE
'
;
export
const
RECEIVE_EPICS_SUCCESS
=
'
RECEIVE_EPICS_SUCCESS
'
;
export
const
SET_ACTIVE_LIST_ID
=
'
SET_ACTIVE_LIST_ID
'
;
export
const
SET_ACTIVE_LIST_ID
=
'
SET_ACTIVE_LIST_ID
'
;
ee/app/assets/javascripts/boards/stores/mutations.js
View file @
c74f114e
...
@@ -81,4 +81,8 @@ export default {
...
@@ -81,4 +81,8 @@ export default {
state
.
epicsSwimlanesFetchFailure
=
true
;
state
.
epicsSwimlanesFetchFailure
=
true
;
state
.
epicsSwimlanesFetchInProgress
=
false
;
state
.
epicsSwimlanesFetchInProgress
=
false
;
},
},
[
mutationTypes
.
RECEIVE_EPICS_SUCCESS
]:
(
state
,
epics
)
=>
{
state
.
epics
=
epics
;
},
};
};
ee/app/assets/javascripts/boards/stores/state.js
View file @
c74f114e
...
@@ -7,4 +7,5 @@ export default () => ({
...
@@ -7,4 +7,5 @@ export default () => ({
epicsSwimlanesFetchInProgress
:
false
,
epicsSwimlanesFetchInProgress
:
false
,
epicsSwimlanesFetchFailure
:
false
,
epicsSwimlanesFetchFailure
:
false
,
epicsSwimlanes
:
{},
epicsSwimlanes
:
{},
epics
:
{},
});
});
ee/app/assets/javascripts/related_items_tree/components/tree_item_body.vue
View file @
c74f114e
...
@@ -83,7 +83,9 @@ export default {
...
@@ -83,7 +83,9 @@ export default {
return
this
.
item
.
type
===
ChildType
.
Epic
?
'
epic
'
:
'
issues
'
;
return
this
.
item
.
type
===
ChildType
.
Epic
?
'
epic
'
:
'
issues
'
;
},
},
stateIconClass
()
{
stateIconClass
()
{
return
this
.
isOpen
?
'
issue-token-state-icon-open
'
:
'
issue-token-state-icon-closed
'
;
return
this
.
isOpen
?
'
issue-token-state-icon-open gl-text-green-500
'
:
'
issue-token-state-icon-closed gl-text-blue-500
'
;
},
},
itemId
()
{
itemId
()
{
return
this
.
itemReference
.
split
(
this
.
item
.
pathIdSeparator
).
pop
();
return
this
.
itemReference
.
split
(
this
.
item
.
pathIdSeparator
).
pop
();
...
...
ee/spec/frontend/boards/components/epic_lane_spec.js
0 → 100644
View file @
c74f114e
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
EpicLane
from
'
ee/boards/components/epic_lane.vue
'
;
import
{
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
mockEpic
}
from
'
../mock_data
'
;
describe
(
'
EpicLane
'
,
()
=>
{
let
wrapper
;
const
defaultProps
=
{
epic
:
mockEpic
};
const
createComponent
=
(
props
=
{})
=>
{
wrapper
=
shallowMount
(
EpicLane
,
{
propsData
:
{
...
defaultProps
,
...
props
,
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
template
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
icon aria label is Opened when epic is opened
'
,
()
=>
{
expect
(
wrapper
.
find
(
GlIcon
).
attributes
(
'
aria-label
'
)).
toEqual
(
'
Opened
'
);
});
it
(
'
icon aria label is Closed when epic is closed
'
,
()
=>
{
createComponent
({
epic
:
{
...
mockEpic
,
state
:
'
closed
'
}
});
expect
(
wrapper
.
find
(
GlIcon
).
attributes
(
'
aria-label
'
)).
toEqual
(
'
Closed
'
);
});
it
(
'
displays total count of issues in epic
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
[data-testid="epic-lane-issue-count"]
'
).
text
()).
toContain
(
5
);
});
it
(
'
displays 2 icons
'
,
()
=>
{
expect
(
wrapper
.
findAll
(
GlIcon
).
length
).
toEqual
(
2
);
});
it
(
'
displays epic title
'
,
()
=>
{
expect
(
wrapper
.
text
()).
toContain
(
mockEpic
.
title
);
});
});
});
ee/spec/frontend/boards/mock_data.js
0 → 100644
View file @
c74f114e
export
const
mockSwimlanes
=
[
{
id
:
'
gid://gitlab/List/1
'
,
title
:
'
Backlog
'
,
position
:
null
,
listType
:
'
backlog
'
,
collapsed
:
false
,
label
:
null
,
maxIssueCount
:
0
,
assignee
:
null
,
milestone
:
null
,
},
{
id
:
'
gid://gitlab/List/10
'
,
title
:
'
To Do
'
,
position
:
0
,
listType
:
'
label
'
,
collapsed
:
false
,
label
:
{
id
:
'
gid://gitlab/GroupLabel/121
'
,
title
:
'
To Do
'
,
color
:
'
#F0AD4E
'
,
textColor
:
'
#FFFFFF
'
,
description
:
null
,
},
maxIssueCount
:
0
,
assignee
:
null
,
milestone
:
null
,
},
];
const
defaultDescendantCounts
=
{
openedIssues
:
0
,
closedIssues
:
0
,
};
export
const
mockEpic
=
{
id
:
1
,
iid
:
1
,
title
:
'
Epic title
'
,
state
:
'
opened
'
,
webUrl
:
'
/groups/gitlab-org/-/epics/1
'
,
descendantCounts
:
{
openedIssues
:
3
,
closedIssues
:
2
,
},
};
export
const
mockEpics
=
[
{
id
:
41
,
iid
:
2
,
description
:
null
,
title
:
'
Another marketing
'
,
group_id
:
56
,
group_name
:
'
Marketing
'
,
group_full_name
:
'
Gitlab Org / Marketing
'
,
start_date
:
'
2017-12-26
'
,
end_date
:
'
2018-03-10
'
,
web_url
:
'
/groups/gitlab-org/marketing/-/epics/2
'
,
descendantCounts
:
defaultDescendantCounts
,
hasParent
:
true
,
parent
:
{
id
:
'
40
'
,
},
},
{
id
:
40
,
iid
:
1
,
description
:
null
,
title
:
'
Marketing epic
'
,
group_id
:
56
,
group_name
:
'
Marketing
'
,
group_full_name
:
'
Gitlab Org / Marketing
'
,
start_date
:
'
2017-12-25
'
,
end_date
:
'
2018-03-09
'
,
web_url
:
'
/groups/gitlab-org/marketing/-/epics/1
'
,
descendantCounts
:
defaultDescendantCounts
,
hasParent
:
false
,
},
{
id
:
39
,
iid
:
12
,
description
:
null
,
title
:
'
Epic with end in first timeframe month
'
,
group_id
:
2
,
group_name
:
'
Gitlab Org
'
,
group_full_name
:
'
Gitlab Org
'
,
start_date
:
'
2017-04-02
'
,
end_date
:
'
2017-11-30
'
,
web_url
:
'
/groups/gitlab-org/-/epics/12
'
,
descendantCounts
:
defaultDescendantCounts
,
hasParent
:
false
,
},
{
id
:
38
,
iid
:
11
,
description
:
null
,
title
:
'
Epic with end date out of range
'
,
group_id
:
2
,
group_name
:
'
Gitlab Org
'
,
group_full_name
:
'
Gitlab Org
'
,
start_date
:
'
2018-01-15
'
,
end_date
:
'
2020-01-03
'
,
web_url
:
'
/groups/gitlab-org/-/epics/11
'
,
descendantCounts
:
defaultDescendantCounts
,
hasParent
:
false
,
},
{
id
:
37
,
iid
:
10
,
description
:
null
,
title
:
'
Epic with timeline in same month
'
,
group_id
:
2
,
group_name
:
'
Gitlab Org
'
,
group_full_name
:
'
Gitlab Org
'
,
start_date
:
'
2018-01-01
'
,
end_date
:
'
2018-01-31
'
,
web_url
:
'
/groups/gitlab-org/-/epics/10
'
,
descendantCounts
:
defaultDescendantCounts
,
hasParent
:
false
,
},
];
ee/spec/frontend/boards/stores/mutations_spec.js
View file @
c74f114e
import
mutations
from
'
ee/boards/stores/mutations
'
;
import
mutations
from
'
ee/boards/stores/mutations
'
;
import
{
inactiveListId
}
from
'
~/boards/constants
'
;
import
{
inactiveListId
}
from
'
~/boards/constants
'
;
import
{
mockSwimlanes
,
mockEpics
}
from
'
../mock_data
'
;
const
expectNotImplemented
=
action
=>
{
const
expectNotImplemented
=
action
=>
{
it
(
'
is not implemented
'
,
()
=>
{
it
(
'
is not implemented
'
,
()
=>
{
...
@@ -114,4 +115,54 @@ describe('TOGGLE_EPICS_SWIMLANES', () => {
...
@@ -114,4 +115,54 @@ describe('TOGGLE_EPICS_SWIMLANES', () => {
expect
(
state
.
isShowingEpicsSwimlanes
).
toBe
(
true
);
expect
(
state
.
isShowingEpicsSwimlanes
).
toBe
(
true
);
});
});
it
(
'
sets epicsSwimlanesFetchInProgress to true
'
,
()
=>
{
const
state
=
{
epicsSwimlanesFetchInProgress
:
false
,
};
mutations
.
TOGGLE_EPICS_SWIMLANES
(
state
);
expect
(
state
.
epicsSwimlanesFetchInProgress
).
toBe
(
true
);
});
});
describe
(
'
RECEIVE_SWIMLANES_SUCCESS
'
,
()
=>
{
it
(
'
sets epicsSwimlanesFetchInProgress to false and populates epicsSwimlanes with payload
'
,
()
=>
{
const
state
=
{
epicsSwimlanesFetchInProgress
:
true
,
epicsSwimlanes
:
{},
};
mutations
.
RECEIVE_SWIMLANES_SUCCESS
(
state
,
mockSwimlanes
);
expect
(
state
.
epicsSwimlanesFetchInProgress
).
toBe
(
false
);
expect
(
state
.
epicsSwimlanes
).
toEqual
(
mockSwimlanes
);
});
});
describe
(
'
RECEIVE_SWIMLANES_FAILURE
'
,
()
=>
{
it
(
'
sets epicsSwimlanesFetchInProgress to false and epicsSwimlanesFetchFailure to true
'
,
()
=>
{
const
state
=
{
epicsSwimlanesFetchInProgress
:
true
,
epicsSwimlanesFetchFailure
:
false
,
};
mutations
.
RECEIVE_SWIMLANES_FAILURE
(
state
);
expect
(
state
.
epicsSwimlanesFetchInProgress
).
toBe
(
false
);
expect
(
state
.
epicsSwimlanesFetchFailure
).
toBe
(
true
);
});
});
describe
(
'
RECEIVE_EPICS_SUCCESS
'
,
()
=>
{
it
(
'
populates epics with payload
'
,
()
=>
{
const
state
=
{
epics
:
{},
};
mutations
.
RECEIVE_EPICS_SUCCESS
(
state
,
mockEpics
);
expect
(
state
.
epics
).
toEqual
(
mockEpics
);
});
});
});
ee/spec/frontend/related_items_tree/components/tree_item_body_spec.js
View file @
c74f114e
...
@@ -191,23 +191,25 @@ describe('RelatedItemsTree', () => {
...
@@ -191,23 +191,25 @@ describe('RelatedItemsTree', () => {
});
});
describe
(
'
stateIconClass
'
,
()
=>
{
describe
(
'
stateIconClass
'
,
()
=>
{
it
(
'
returns string `issue-token-state-icon-open` when `item.state` value is `opened`
'
,
()
=>
{
it
(
'
returns string `issue-token-state-icon-open
gl-text-green-500
` when `item.state` value is `opened`
'
,
()
=>
{
wrapper
.
setProps
({
wrapper
.
setProps
({
item
:
{
...
mockItem
,
state
:
ChildState
.
Open
},
item
:
{
...
mockItem
,
state
:
ChildState
.
Open
},
});
});
return
wrapper
.
vm
.
$nextTick
(()
=>
{
return
wrapper
.
vm
.
$nextTick
(()
=>
{
expect
(
wrapper
.
vm
.
stateIconClass
).
toBe
(
'
issue-token-state-icon-open
'
);
expect
(
wrapper
.
vm
.
stateIconClass
).
toBe
(
'
issue-token-state-icon-open
gl-text-green-500
'
);
});
});
});
});
it
(
'
returns string `issue-token-state-icon-closed` when `item.state` value is `closed`
'
,
()
=>
{
it
(
'
returns string `issue-token-state-icon-closed
gl-text-blue-500
` when `item.state` value is `closed`
'
,
()
=>
{
wrapper
.
setProps
({
wrapper
.
setProps
({
item
:
{
...
mockItem
,
state
:
ChildState
.
Closed
},
item
:
{
...
mockItem
,
state
:
ChildState
.
Closed
},
});
});
return
wrapper
.
vm
.
$nextTick
(()
=>
{
return
wrapper
.
vm
.
$nextTick
(()
=>
{
expect
(
wrapper
.
vm
.
stateIconClass
).
toBe
(
'
issue-token-state-icon-closed
'
);
expect
(
wrapper
.
vm
.
stateIconClass
).
toBe
(
'
issue-token-state-icon-closed gl-text-blue-500
'
,
);
});
});
});
});
});
});
...
...
locale/gitlab.pot
View file @
c74f114e
...
@@ -380,6 +380,9 @@ msgstr ""
...
@@ -380,6 +380,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgstr ""
msgid "%{issuesCount} issues in this group"
msgstr ""
msgid "%{issuesSize} issues"
msgid "%{issuesSize} issues"
msgstr ""
msgstr ""
...
...
spec/frontend/boards/components/board_list_header_spec.js
View file @
c74f114e
...
@@ -107,7 +107,7 @@ describe('Board List Header Component', () => {
...
@@ -107,7 +107,7 @@ describe('Board List Header Component', () => {
createComponent
();
createComponent
();
expect
(
isCollapsed
()).
toBe
(
false
);
expect
(
isCollapsed
()).
toBe
(
false
);
wrapper
.
find
(
'
[data-testid="board-list-header"]
'
).
trigger
(
'
click
'
);
wrapper
.
find
(
'
[data-testid="board-list-header"]
'
).
vm
.
$emit
(
'
click
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
isCollapsed
()).
toBe
(
false
);
expect
(
isCollapsed
()).
toBe
(
false
);
...
@@ -118,7 +118,7 @@ describe('Board List Header Component', () => {
...
@@ -118,7 +118,7 @@ describe('Board List Header Component', () => {
createComponent
();
createComponent
();
expect
(
isExpanded
()).
toBe
(
true
);
expect
(
isExpanded
()).
toBe
(
true
);
findCaret
().
trigger
(
'
click
'
);
findCaret
().
vm
.
$emit
(
'
click
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
isCollapsed
()).
toBe
(
true
);
expect
(
isCollapsed
()).
toBe
(
true
);
...
@@ -129,7 +129,7 @@ describe('Board List Header Component', () => {
...
@@ -129,7 +129,7 @@ describe('Board List Header Component', () => {
createComponent
({
collapsed
:
true
});
createComponent
({
collapsed
:
true
});
expect
(
isCollapsed
()).
toBe
(
true
);
expect
(
isCollapsed
()).
toBe
(
true
);
findCaret
().
trigger
(
'
click
'
);
findCaret
().
vm
.
$emit
(
'
click
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
isCollapsed
()).
toBe
(
false
);
expect
(
isCollapsed
()).
toBe
(
false
);
...
@@ -142,7 +142,7 @@ describe('Board List Header Component', () => {
...
@@ -142,7 +142,7 @@ describe('Board List Header Component', () => {
createComponent
({
withLocalStorage
:
false
});
createComponent
({
withLocalStorage
:
false
});
findCaret
().
trigger
(
'
click
'
);
findCaret
().
vm
.
$emit
(
'
click
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
vm
.
list
.
update
).
toHaveBeenCalledTimes
(
1
);
expect
(
wrapper
.
vm
.
list
.
update
).
toHaveBeenCalledTimes
(
1
);
...
@@ -155,7 +155,7 @@ describe('Board List Header Component', () => {
...
@@ -155,7 +155,7 @@ describe('Board List Header Component', () => {
createComponent
();
createComponent
();
findCaret
().
trigger
(
'
click
'
);
findCaret
().
vm
.
$emit
(
'
click
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
vm
.
list
.
update
).
not
.
toHaveBeenCalled
();
expect
(
wrapper
.
vm
.
list
.
update
).
not
.
toHaveBeenCalled
();
...
...
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