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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
39a27b7c
Commit
39a27b7c
authored
Jun 06, 2019
by
Kushal Pandya
Committed by
Phil Hughes
Jun 06, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CE Backport: Show tree within Epic containing child Epics and Issues
parent
4bb63a8c
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
242 additions
and
4 deletions
+242
-4
app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
...scripts/vue_shared/components/droplab_dropdown_button.vue
+89
-0
app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
...vascripts/vue_shared/components/issue/issue_assignees.vue
+11
-2
app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
...vascripts/vue_shared/components/issue/issue_milestone.vue
+6
-2
spec/frontend/vue_shared/droplab_dropdown_button_spec.js
spec/frontend/vue_shared/droplab_dropdown_button_spec.js
+136
-0
No files found.
app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
0 → 100644
View file @
39a27b7c
<
script
>
import
{
GlButton
}
from
'
@gitlab/ui
'
;
import
Icon
from
'
./icon.vue
'
;
export
default
{
components
:
{
Icon
,
GlButton
,
},
props
:
{
size
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
primaryButtonClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
dropdownClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
actions
:
{
type
:
Array
,
required
:
true
,
},
defaultAction
:
{
type
:
Number
,
required
:
true
,
},
},
data
()
{
return
{
selectedAction
:
this
.
defaultAction
,
};
},
computed
:
{
selectedActionTitle
()
{
return
this
.
actions
[
this
.
selectedAction
].
title
;
},
buttonSizeClass
()
{
return
`btn-
${
this
.
size
}
`
;
},
},
methods
:
{
handlePrimaryActionClick
()
{
this
.
$emit
(
'
onActionClick
'
,
this
.
actions
[
this
.
selectedAction
]);
},
handleActionClick
(
selectedAction
)
{
this
.
selectedAction
=
selectedAction
;
this
.
$emit
(
'
onActionSelect
'
,
selectedAction
);
},
},
};
</
script
>
<
template
>
<div
class=
"btn-group droplab-dropdown comment-type-dropdown"
>
<gl-button
:class=
"primaryButtonClass"
:size=
"size"
@
click.prevent=
"handlePrimaryActionClick"
>
{{
selectedActionTitle
}}
</gl-button>
<button
:class=
"buttonSizeClass"
type=
"button"
class=
"btn dropdown-toggle pl-2 pr-2"
data-display=
"static"
data-toggle=
"dropdown"
>
<icon
name=
"arrow-down"
aria-label=
"toggle dropdown"
/>
</button>
<ul
:class=
"dropdownClass"
class=
"dropdown-menu dropdown-open-top"
>
<template
v-for=
"(action, index) in actions"
>
<li
:key=
"index"
:class=
"
{ 'droplab-item-selected': selectedAction === index }">
<gl-button
class=
"btn-transparent"
@
click.prevent=
"handleActionClick(index)"
>
<i
aria-hidden=
"true"
class=
"fa fa-check icon"
>
</i>
<div
class=
"description"
>
<strong>
{{
action
.
title
}}
</strong>
<p>
{{
action
.
description
}}
</p>
</div>
</gl-button>
</li>
<li
v-if=
"index === 0"
:key=
"`$
{index}-separator`" class="divider droplab-item-ignore">
</li>
</
template
>
</ul>
</div>
</template>
app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
View file @
39a27b7c
...
...
@@ -62,6 +62,15 @@ export default {
assigneeName
:
assignee
.
name
,
});
},
// This method is for backward compat
// since Graph query would return camelCase
// props while Rails would return snake_case
webUrl
(
assignee
)
{
return
assignee
.
web_url
||
assignee
.
webUrl
;
},
avatarUrl
(
assignee
)
{
return
assignee
.
avatar_url
||
assignee
.
avatarUrl
;
},
},
};
</
script
>
...
...
@@ -70,9 +79,9 @@ export default {
<user-avatar-link
v-for=
"assignee in assigneesToShow"
:key=
"assignee.id"
:link-href=
"
assignee.web_url
"
:link-href=
"
webUrl(assignee)
"
:img-alt=
"avatarUrlTitle(assignee)"
:img-src=
"a
ssignee.avatar_url
"
:img-src=
"a
vatarUrl(assignee)
"
:img-size=
"24"
class=
"js-no-trigger"
tooltip-placement=
"bottom"
...
...
app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
View file @
39a27b7c
...
...
@@ -19,10 +19,14 @@ export default {
},
computed
:
{
milestoneDue
()
{
return
this
.
milestone
.
due_date
?
parsePikadayDate
(
this
.
milestone
.
due_date
)
:
null
;
const
dueDate
=
this
.
milestone
.
due_date
||
this
.
milestone
.
dueDate
;
return
dueDate
?
parsePikadayDate
(
dueDate
)
:
null
;
},
milestoneStart
()
{
return
this
.
milestone
.
start_date
?
parsePikadayDate
(
this
.
milestone
.
start_date
)
:
null
;
const
startDate
=
this
.
milestone
.
start_date
||
this
.
milestone
.
startDate
;
return
startDate
?
parsePikadayDate
(
startDate
)
:
null
;
},
isMilestoneStarted
()
{
if
(
!
this
.
milestoneStart
)
{
...
...
spec/frontend/vue_shared/droplab_dropdown_button_spec.js
0 → 100644
View file @
39a27b7c
import
{
mount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
DroplabDropdownButton
from
'
~/vue_shared/components/droplab_dropdown_button.vue
'
;
const
mockActions
=
[
{
title
:
'
Foo
'
,
description
:
'
Some foo action
'
,
},
{
title
:
'
Bar
'
,
description
:
'
Some bar action
'
,
},
];
const
createComponent
=
({
size
=
''
,
dropdownClass
=
''
,
actions
=
mockActions
,
defaultAction
=
0
,
})
=>
{
const
localVue
=
createLocalVue
();
return
mount
(
DroplabDropdownButton
,
{
localVue
,
propsData
:
{
size
,
dropdownClass
,
actions
,
defaultAction
,
},
});
};
describe
(
'
DroplabDropdownButton
'
,
()
=>
{
let
wrapper
;
beforeEach
(()
=>
{
wrapper
=
createComponent
({});
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
data
'
,
()
=>
{
it
(
'
contains `selectedAction` representing value of `defaultAction` prop
'
,
()
=>
{
expect
(
wrapper
.
vm
.
selectedAction
).
toBe
(
0
);
});
});
describe
(
'
computed
'
,
()
=>
{
describe
(
'
selectedActionTitle
'
,
()
=>
{
it
(
'
returns string containing title of selected action
'
,
()
=>
{
wrapper
.
setData
({
selectedAction
:
0
});
expect
(
wrapper
.
vm
.
selectedActionTitle
).
toBe
(
mockActions
[
0
].
title
);
wrapper
.
setData
({
selectedAction
:
1
});
expect
(
wrapper
.
vm
.
selectedActionTitle
).
toBe
(
mockActions
[
1
].
title
);
});
});
describe
(
'
buttonSizeClass
'
,
()
=>
{
it
(
'
returns string containing button sizing class based on `size` prop
'
,
done
=>
{
const
wrapperWithSize
=
createComponent
({
size
:
'
sm
'
,
});
wrapperWithSize
.
vm
.
$nextTick
(()
=>
{
expect
(
wrapperWithSize
.
vm
.
buttonSizeClass
).
toBe
(
'
btn-sm
'
);
done
();
wrapperWithSize
.
destroy
();
});
});
});
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
handlePrimaryActionClick
'
,
()
=>
{
it
(
'
emits `onActionClick` event on component with selectedAction object as param
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
$emit
'
);
wrapper
.
setData
({
selectedAction
:
0
});
wrapper
.
vm
.
handlePrimaryActionClick
();
expect
(
wrapper
.
vm
.
$emit
).
toHaveBeenCalledWith
(
'
onActionClick
'
,
mockActions
[
0
]);
});
});
describe
(
'
handleActionClick
'
,
()
=>
{
it
(
'
emits `onActionSelect` event on component with selectedAction index as param
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
$emit
'
);
wrapper
.
vm
.
handleActionClick
(
1
);
expect
(
wrapper
.
vm
.
$emit
).
toHaveBeenCalledWith
(
'
onActionSelect
'
,
1
);
});
});
});
describe
(
'
template
'
,
()
=>
{
it
(
'
renders default action button
'
,
()
=>
{
const
defaultButton
=
wrapper
.
findAll
(
'
.btn
'
).
at
(
0
);
expect
(
defaultButton
.
text
()).
toBe
(
mockActions
[
0
].
title
);
});
it
(
'
renders dropdown button
'
,
()
=>
{
const
dropdownButton
=
wrapper
.
findAll
(
'
.dropdown-toggle
'
).
at
(
0
);
expect
(
dropdownButton
.
isVisible
()).
toBe
(
true
);
});
it
(
'
renders dropdown actions
'
,
()
=>
{
const
dropdownActions
=
wrapper
.
findAll
(
'
.dropdown-menu li button
'
);
Array
(
dropdownActions
.
length
)
.
fill
()
.
forEach
((
_
,
index
)
=>
{
const
actionContent
=
dropdownActions
.
at
(
index
).
find
(
'
.description
'
);
expect
(
actionContent
.
find
(
'
strong
'
).
text
()).
toBe
(
mockActions
[
index
].
title
);
expect
(
actionContent
.
find
(
'
p
'
).
text
()).
toBe
(
mockActions
[
index
].
description
);
});
});
it
(
'
renders divider between dropdown actions
'
,
()
=>
{
const
dropdownDivider
=
wrapper
.
find
(
'
.dropdown-menu .divider
'
);
expect
(
dropdownDivider
.
isVisible
()).
toBe
(
true
);
});
});
});
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