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
59d29e78
Commit
59d29e78
authored
Sep 28, 2017
by
Simon Knox
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'issue-board-edit-modal' into edit-board
parents
58565ac5
605c9059
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
420 additions
and
371 deletions
+420
-371
app/assets/javascripts/boards/components/board_form.vue
app/assets/javascripts/boards/components/board_form.vue
+44
-52
app/assets/javascripts/boards/components/board_new_issue.js
app/assets/javascripts/boards/components/board_new_issue.js
+1
-0
app/assets/javascripts/boards/components/form_block.vue
app/assets/javascripts/boards/components/form_block.vue
+1
-34
app/assets/javascripts/boards/components/labels_select.vue
app/assets/javascripts/boards/components/labels_select.vue
+118
-0
app/assets/javascripts/boards/components/milestone_select.vue
...assets/javascripts/boards/components/milestone_select.vue
+42
-13
app/assets/javascripts/boards/components/weight_select.vue
app/assets/javascripts/boards/components/weight_select.vue
+117
-0
app/assets/javascripts/boards/services/board_service.js
app/assets/javascripts/boards/services/board_service.js
+0
-11
app/assets/javascripts/boards/stores/boards_store.js
app/assets/javascripts/boards/stores/boards_store.js
+22
-2
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+17
-0
app/assets/javascripts/users_select.js
app/assets/javascripts/users_select.js
+2
-0
app/assets/stylesheets/framework/modal.scss
app/assets/stylesheets/framework/modal.scss
+1
-3
spec/ee/spec/features/boards/user_configures_board.rb
spec/ee/spec/features/boards/user_configures_board.rb
+52
-0
spec/features/boards/board_with_milestone_spec.rb
spec/features/boards/board_with_milestone_spec.rb
+0
-232
spec/features/boards/multiple_boards_spec.rb
spec/features/boards/multiple_boards_spec.rb
+1
-20
spec/javascripts/boards/milestone_select_spec.js
spec/javascripts/boards/milestone_select_spec.js
+2
-4
No files found.
app/assets/javascripts/boards/components/board_form.vue
View file @
59d29e78
...
...
@@ -13,6 +13,7 @@
</p>
<form
v-else
class=
"js-board-config-modal"
>
<div
v-if=
"!readonly"
...
...
@@ -52,9 +53,6 @@
<!-- TODO: if current_board_parent.issue_board_milestone_available?(current_user) -->
<form-block
title=
"Milestone"
defaultText=
"Any milestone"
:canEdit=
"canAdminBoard"
>
<div
v-if=
"board.milestone"
...
...
@@ -65,31 +63,21 @@
<board-milestone-select
:board=
"board"
:milestone-path=
"milestonePath"
v-model=
"board.milestone_id"
>
</board-milestone-select>
</form-block>
<form-block
title=
"Labels"
defaultText=
"Any label"
:canEdit=
"canAdminBoard"
>
</form-block>
<form-block
title=
"Assignee"
defaultText=
"Any assignee"
:fieldName=
"'board_filter[assignee]'"
:canEdit=
"canAdminBoard"
>
v-model=
"board.milestone_id"
title=
"Milestone"
defaultText=
"Any milestone"
:canEdit=
"canAdminBoard"
/>
</form-block>
<form-block
title=
"Author"
defaultText=
"Any author"
:fieldName=
"'board_filter[author]'"
:canEdit=
"canAdminBoard"
>
<form-block>
<board-labels-select
:board=
"board"
title=
"Labels"
defaultText=
"Any label"
:canEdit=
"canAdminBoard"
:labelsPath=
"labelsPath"
/>
</form-block>
<form-block
...
...
@@ -98,6 +86,13 @@
:fieldName=
"'board_filter[weight]'"
:canEdit=
"canAdminBoard"
>
<board-weight-select
:board=
"board"
v-model=
"board.weight"
title=
"Weight"
defaultText=
"Any weight"
:canEdit=
"canAdminBoard"
/>
</form-block>
</div>
</form>
...
...
@@ -115,6 +110,8 @@ import Vue from 'vue';
import
PopupDialog
from
'
~/vue_shared/components/popup_dialog.vue
'
;
import
FormBlock
from
'
./form_block.vue
'
;
import
BoardMilestoneSelect
from
'
./milestone_select.vue
'
;
import
BoardWeightSelect
from
'
./weight_select.vue
'
;
import
BoardLabelsSelect
from
'
./labels_select.vue
'
;
window
.
gl
=
window
.
gl
||
{};
window
.
gl
.
issueBoards
=
window
.
gl
.
issueBoards
||
{};
...
...
@@ -127,6 +124,11 @@ export default Vue.extend({
type
:
String
,
required
:
true
,
},
labelsPath
:
{
type
:
String
,
required
:
false
,
default
:
'
/root/my-rails/labels.json
'
,
},
canAdminBoard
:
{
type
:
Boolean
,
required
:
true
,
...
...
@@ -134,10 +136,7 @@ export default Vue.extend({
},
data
()
{
return
{
board
:
{
id
:
false
,
name
:
''
,
},
board
:
Store
.
boardConfig
,
expanded
:
false
,
issue
:
{},
currentBoard
:
Store
.
state
.
currentBoard
,
...
...
@@ -148,13 +147,26 @@ export default Vue.extend({
},
components
:
{
BoardMilestoneSelect
,
BoardLabelsSelect
,
BoardWeightSelect
,
PopupDialog
,
FormBlock
,
},
mounted
()
{
if
(
this
.
currentBoard
&&
Object
.
keys
(
this
.
currentBoard
).
length
&&
this
.
currentPage
!==
'
new
'
)
{
this
.
board
=
Vue
.
util
.
extend
({},
this
.
currentBoard
);
Store
.
updateBoardConfig
(
this
.
currentBoard
);
}
else
{
Store
.
updateBoardConfig
({
name
:
''
,
id
:
false
,
label_ids
:
[],
});
}
if
(
!
this
.
board
.
labels
)
{
this
.
board
.
labels
=
[];
}
if
(
this
.
$refs
.
name
)
{
this
.
$refs
.
name
.
focus
();
}
...
...
@@ -199,7 +211,7 @@ export default Vue.extend({
return
false
;
},
expandButtonText
()
{
return
this
.
expanded
?
'
Collapse
'
:
'
Expand
'
return
this
.
expanded
?
'
Collapse
'
:
'
Expand
'
;
},
collapseScope
()
{
return
this
.
currentPage
===
'
new
'
;
...
...
@@ -212,19 +224,6 @@ export default Vue.extend({
refreshPage
()
{
location
.
href
=
location
.
pathname
;
},
loadMilestones
(
e
)
{
this
.
milestoneDropdownOpen
=
!
this
.
milestoneDropdownOpen
;
BoardService
.
loadMilestones
.
call
(
this
);
if
(
this
.
milestoneDropdownOpen
)
{
this
.
$nextTick
(()
=>
{
const
milestoneDropdown
=
this
.
$refs
.
milestoneDropdown
;
const
rect
=
e
.
target
.
getBoundingClientRect
();
milestoneDropdown
.
style
.
width
=
`
${
rect
.
width
}
px`
;
});
}
},
submit
()
{
gl
.
boardService
.
createBoard
(
this
.
board
)
.
then
(
resp
=>
resp
.
json
())
...
...
@@ -252,13 +251,6 @@ export default Vue.extend({
cancel
()
{
Store
.
state
.
currentPage
=
''
;
},
selectMilestone
(
milestone
)
{
this
.
milestoneDropdownOpen
=
false
;
this
.
board
.
milestone_id
=
milestone
.
id
;
this
.
board
.
milestone
=
{
title
:
milestone
.
title
,
};
},
},
});
</
script
>
app/assets/javascripts/boards/components/board_new_issue.js
View file @
59d29e78
...
...
@@ -42,6 +42,7 @@ export default {
this
.
error
=
false
;
// TODO: add board labels
const
labels
=
this
.
list
.
label
?
[
this
.
list
.
label
]
:
[];
const
issue
=
new
ListIssue
({
title
:
this
.
title
,
...
...
app/assets/javascripts/boards/components/form_block.vue
View file @
59d29e78
<
template
>
<div
class=
"list-item"
>
<div
class=
"media"
>
<label
class=
"label-light media-body"
>
{{
title
}}
</label>
<a
v-if=
"canEdit"
class=
"edit-link"
href=
"#"
@
click.prevent=
"toggleEditing"
>
Edit
</a>
</div>
<slot></slot>
<div>
<slot
name=
"currentValue"
>
{{
defaultText
}}
</slot>
</div>
</div>
</
template
>
...
...
@@ -25,23 +9,6 @@ import eventHub from '../eventhub';
export
default
{
props
:
{
defaultText
:
{
type
:
String
,
required
:
true
,
},
title
:
{
type
:
String
,
required
:
true
,
},
fieldName
:
{
type
:
String
,
required
:
false
,
},
canEdit
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
}
},
data
()
{
return
{
...
...
@@ -54,4 +21,4 @@ export default {
},
},
};
</
script
>
\ No newline at end of file
</
script
>
app/assets/javascripts/boards/components/labels_select.vue
0 → 100644
View file @
59d29e78
<
template
>
<div
class=
"block labels"
>
<div
class=
"title append-bottom-10"
>
Labels
<i
aria-hidden=
"true"
class=
"fa fa-spinner fa-spin block-loading"
data-hidden=
"true"
style=
"display: none;"
></i>
<a
class=
"edit-link pull-right"
href=
"#"
>
Edit
</a>
</div>
<div
class=
"value issuable-show-labels"
>
<span
v-if=
"board.labels.length === 0"
class=
"no-value"
>
Any label
</span>
<a
href=
"#"
v-for=
"label in board.labels"
:key=
"label.id"
>
<span
class=
"label color-label has-tooltip"
:style=
"`background-color: $
{label.color}; color: ${label.textColor};`"
title=""
>
{{
label
.
title
}}
</span>
</a>
</div>
<div
class=
"selectbox"
style=
"display: none"
>
<div
class=
"dropdown"
>
<button
class=
"dropdown-menu-toggle wide js-label-select js-multiselect js-board-config-modal"
data-field-name=
"issue[label_names][]"
v-bind:data-labels=
"labelsPath"
data-toggle=
"dropdown"
type=
"button"
>
<span
class=
"dropdown-toggle-text"
>
Label
</span>
<i
aria-hidden=
"true"
class=
"fa fa-chevron-down"
data-hidden=
"true"
></i>
</button>
<div
class=
"dropdown-menu dropdown-select dropdown-menu-paging dropdown-menu-labels dropdown-menu-selectable"
>
<div
class=
"dropdown-input"
>
<input
autocomplete=
"off"
class=
"dropdown-input-field"
id=
""
placeholder=
"Search"
type=
"search"
value=
""
>
<i
aria-hidden=
"true"
class=
"fa fa-search dropdown-input-search"
data-hidden=
"true"
></i>
<i
aria-hidden=
"true"
class=
"fa fa-times dropdown-input-clear js-dropdown-input-clear"
data-hidden=
"true"
role=
"button"
></i>
</div>
<div
class=
"dropdown-content"
></div>
<div
class=
"dropdown-loading"
>
<i
aria-hidden=
"true"
class=
"fa fa-spinner fa-spin"
data-hidden=
"true"
></i>
</div>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
/* global LabelsSelect */
import
loadingIcon
from
'
~/vue_shared/components/loading_icon.vue
'
;
import
eventHub
from
'
../eventhub
'
;
export
default
{
props
:
{
board
:
{
type
:
Object
,
required
:
true
,
},
labelsPath
:
{
type
:
String
,
required
:
true
,
},
value
:
{
type
:
Array
,
required
:
false
,
},
defaultText
:
{
type
:
String
,
required
:
true
,
},
title
:
{
type
:
String
,
required
:
true
,
},
canEdit
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
components
:
{
loadingIcon
,
},
data
()
{
return
{
isOpen
:
false
,
loading
:
true
,
};
},
mounted
()
{
new
LabelsSelect
();
},
methods
:
{
open
()
{
this
.
isOpen
=
true
;
},
close
()
{
this
.
isOpen
=
false
;
},
toggle
()
{
this
.
isOpen
=
!
this
.
isOpen
;
},
},
};
</
script
>
app/assets/javascripts/boards/components/milestone_select.vue
View file @
59d29e78
<
template
>
<div
class=
"dropdown"
:class=
"
{ open: isOpen }">
<div
class=
"media"
>
<label
class=
"label-light media-body"
>
{{
title
}}
</label>
<a
v-if=
"canEdit"
class=
"edit-link"
href=
"#"
@
click.prevent=
"toggle"
>
Edit
</a>
</div>
<div
class=
"dropdown-menu dropdown-menu-wide"
>
<div
class=
"dropdown-input"
>
<input
ref=
"search"
class=
"dropdown-input-field"
type=
"search"
placeholder=
"Search milestones"
>
<i
aria-hidden=
"true"
data-hidden=
"true"
class=
"fa fa-search dropdown-input-search"
></i>
</div>
<ul
ref=
"list"
>
...
...
@@ -47,6 +50,9 @@
</li>
</ul>
</div>
<div>
{{
milestoneTitle
}}
</div>
</div>
</
template
>
...
...
@@ -71,10 +77,28 @@ export default {
type
:
Number
,
required
:
false
,
},
defaultText
:
{
type
:
String
,
required
:
true
,
},
title
:
{
type
:
String
,
required
:
true
,
},
canEdit
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
components
:
{
loadingIcon
,
},
computed
:
{
milestoneTitle
()
{
return
this
.
board
.
milestone
?
this
.
board
.
milestone
.
title
:
this
.
defaultText
;
},
},
data
()
{
return
{
isOpen
:
false
,
...
...
@@ -84,13 +108,18 @@ export default {
};
},
mounted
()
{
BoardService
.
loadMilestones
.
call
(
this
).
then
(()
=>
this
.
loading
=
false
);
this
.
$http
.
get
(
this
.
milestonePath
)
.
then
(
resp
=>
resp
.
json
())
.
then
((
data
)
=>
{
this
.
milestones
=
data
;
this
.
loading
=
false
;
})
.
catch
(()
=>
{
this
.
loading
=
false
;
});
eventHub
.
$on
(
'
open
'
,
this
.
open
);
eventHub
.
$on
(
'
close
'
,
this
.
close
);
eventHub
.
$on
(
'
toggle
'
,
this
.
toggle
);
this
.
$nextTick
(()
=>
{
this
.
$refs
.
search
.
focus
();
});
},
beforeDestroy
()
{
eventHub
.
$off
(
'
open
'
,
this
.
open
);
...
...
@@ -99,7 +128,7 @@ export default {
},
methods
:
{
selectMilestone
(
milestone
)
{
this
.
board
.
milestone
=
milestone
;
this
.
$set
(
this
.
board
,
'
milestone
'
,
milestone
)
;
this
.
$emit
(
'
input
'
,
milestone
.
id
);
this
.
close
();
},
...
...
app/assets/javascripts/boards/components/weight_select.vue
0 → 100644
View file @
59d29e78
<
template
>
<div
class=
"dropdown"
:class=
"
{ open: isOpen }">
<div
class=
"media"
>
<label
class=
"label-light media-body"
>
{{
title
}}
</label>
<a
v-if=
"canEdit"
class=
"edit-link"
href=
"#"
@
click.prevent=
"toggle"
>
Edit
</a>
</div>
<div
class=
"dropdown-menu dropdown-menu-wide"
>
<ul
ref=
"list"
>
<li>
<a
href=
"#"
@
click.prevent.stop=
"selectWeight(0)"
>
<i
class=
"fa fa-check"
v-if=
"0 === value"
></i>
No weight
</a>
</li>
<li
v-for=
"weight in weights"
:key=
"weight.id"
>
<a
href=
"#"
@
click.prevent.stop=
"selectWeight(weight)"
>
<i
class=
"fa fa-check"
v-if=
"weight === value"
></i>
{{
weight
}}
</a>
</li>
</ul>
</div>
<div>
{{
weight
}}
</div>
</div>
</
template
>
<
script
>
/* global BoardService */
import
loadingIcon
from
'
~/vue_shared/components/loading_icon.vue
'
;
import
eventHub
from
'
../eventhub
'
;
export
default
{
props
:
{
board
:
{
type
:
Object
,
required
:
true
,
},
value
:
{
type
:
Number
,
required
:
false
,
},
defaultText
:
{
type
:
String
,
required
:
true
,
},
title
:
{
type
:
String
,
required
:
true
,
},
canEdit
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
components
:
{
loadingIcon
,
},
computed
:
{
weight
()
{
if
(
parseInt
(
this
.
board
.
weight
,
10
)
===
0
)
{
return
'
No weight
'
;
}
return
this
.
board
.
weight
||
'
Any weight
'
;
},
},
data
()
{
return
{
isOpen
:
false
,
// TODO: use Issue.weight_options from backend
weights
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
],
};
},
methods
:
{
selectWeight
(
weight
)
{
this
.
$set
(
this
.
board
,
'
weight
'
,
weight
);
// this.$emit('input', weight);
this
.
close
();
},
open
()
{
this
.
isOpen
=
true
;
},
close
()
{
this
.
isOpen
=
false
;
},
toggle
()
{
this
.
isOpen
=
!
this
.
isOpen
;
},
},
};
</
script
>
app/assets/javascripts/boards/services/board_service.js
View file @
59d29e78
...
...
@@ -99,17 +99,6 @@ class BoardService {
return
this
.
issues
.
bulkUpdate
(
data
);
}
static
loadMilestones
(
path
)
{
this
.
loading
=
true
;
return
this
.
$http
.
get
(
this
.
milestonePath
)
.
then
(
resp
=>
resp
.
json
())
.
then
((
data
)
=>
{
this
.
milestones
=
data
;
this
.
loading
=
false
;
});
}
}
window
.
BoardService
=
BoardService
;
app/assets/javascripts/boards/stores/boards_store.js
View file @
59d29e78
...
...
@@ -19,7 +19,12 @@ gl.issueBoards.BoardsStore = {
reload
:
false
,
},
detail
:
{
issue
:
{}
issue
:
{},
},
boardConfig
:
{
id
:
false
,
name
:
''
,
labels
:
[],
},
moving
:
{
issue
:
{},
...
...
@@ -28,7 +33,9 @@ gl.issueBoards.BoardsStore = {
create
()
{
this
.
state
.
lists
=
[];
this
.
filter
.
path
=
getUrlParamsArray
().
join
(
'
&
'
);
this
.
detail
=
{
issue
:
{}
};
this
.
detail
=
{
issue
:
{},
};
},
createNewListDropdownData
()
{
this
.
state
.
currentBoard
=
{};
...
...
@@ -39,6 +46,19 @@ gl.issueBoards.BoardsStore = {
this
.
state
.
reload
=
false
;
this
.
state
.
currentPage
=
page
;
},
updateBoardConfig
({
name
,
id
,
milestone
,
milestone_id
,
labels
=
[],
})
{
this
.
boardConfig
.
name
=
name
;
this
.
boardConfig
.
milestone
=
milestone
;
this
.
boardConfig
.
milestone_id
=
milestone_id
;
this
.
boardConfig
.
id
=
id
;
this
.
boardConfig
.
labels
=
labels
;
},
addList
(
listObj
,
defaultAvatar
)
{
const
list
=
new
List
(
listObj
,
defaultAvatar
);
this
.
state
.
lists
.
push
(
list
);
...
...
app/assets/javascripts/labels_select.js
View file @
59d29e78
...
...
@@ -390,6 +390,23 @@ import DropdownUtils from './filtered_search/dropdown_utils';
.
then
(
fadeOutLoader
)
.
catch
(
fadeOutLoader
);
}
else
if
(
$dropdown
.
hasClass
(
'
js-board-config-modal
'
))
{
if
(
$el
.
hasClass
(
'
is-active
'
))
{
gl
.
issueBoards
.
BoardsStore
.
boardConfig
.
labels
.
push
(
new
ListLabel
({
id
:
label
.
id
,
title
:
label
.
title
,
color
:
label
.
color
[
0
],
textColor
:
'
#fff
'
}));
}
else
{
let
labels
=
gl
.
issueBoards
.
BoardsStore
.
boardConfig
.
labels
;
labels
=
labels
.
filter
(
function
(
selectedLabel
)
{
return
selectedLabel
.
id
!==
label
.
id
;
});
gl
.
issueBoards
.
BoardsStore
.
boardConfig
.
labels
=
labels
;
}
}
else
{
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
...
...
app/assets/javascripts/users_select.js
View file @
59d29e78
...
...
@@ -442,6 +442,8 @@ function UsersSelect(currentUser, els) {
}
if
(
$el
.
closest
(
'
.add-issues-modal
'
).
length
)
{
gl
.
issueBoards
.
ModalStore
.
store
.
filter
[
$dropdown
.
data
(
'
field-name
'
)]
=
user
.
id
;
}
else
if
(
$el
.
closest
(
'
js-board-config-modal
'
).
length
)
{
gl
.
issueBoards
.
BoardsStore
.
boardConfig
.
authorId
=
user
.
id
;
}
else
if
(
$dropdown
.
hasClass
(
'
js-filter-submit
'
)
&&
(
isIssueIndex
||
isMRIndex
))
{
return
Issuable
.
filterResults
(
$dropdown
.
closest
(
'
form
'
));
}
else
if
(
$dropdown
.
hasClass
(
'
js-filter-submit
'
))
{
...
...
app/assets/stylesheets/framework/modal.scss
View file @
59d29e78
...
...
@@ -54,9 +54,7 @@ body.modal-open {
}
.modal.popup-dialog
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
display
:
block
;
@media
(
min-width
:
$screen-md-min
)
{
.modal-dialog
{
...
...
spec/ee/spec/features/boards/user_configures_board.rb
0 → 100644
View file @
59d29e78
require
'rails_helper'
describe
'issue board config'
,
:js
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let!
(
:planning
)
{
create
(
:label
,
project:
project
,
name:
'Planning'
)
}
let!
(
:board
)
{
create
(
:board
,
project:
project
)
}
before
do
stub_licensed_features
(
multiple_issue_boards:
true
)
end
context
'user with edit permissions'
do
before
do
project
.
team
<<
[
user
,
:master
]
login_as
(
user
)
visit
project_boards_path
(
project
)
wait_for_requests
end
it
'edits board'
do
click_button
'Edit board'
page
.
within
(
'.popup-dialog'
)
do
fill_in
'board-new-name'
,
with:
'Testing'
click_button
'Save'
end
expect
(
'.dropdown-menu-toggle'
,
text:
'Testing'
).
to
exist
end
end
context
'user without edit permissions'
do
before
do
visit
project_boards_path
(
project
)
wait_for_requests
end
it
'shows board scope'
do
click_button
'View scope'
page
.
within
(
'.popup-dialog'
)
do
expect
(
page
).
not_to
have_link
(
'Edit'
)
expect
(
page
).
not_to
have_button
(
'Edit'
)
expect
(
page
).
not_to
have_button
(
'Save'
)
end
end
end
end
\ No newline at end of file
spec/features/boards/board_with_milestone_spec.rb
deleted
100644 → 0
View file @
58565ac5
require
'rails_helper'
describe
'Board with milestone'
,
:js
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let!
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
let!
(
:issue
)
{
create
(
:closed_issue
,
project:
project
)
}
let!
(
:issue_milestone
)
{
create
(
:closed_issue
,
project:
project
,
milestone:
milestone
)
}
before
do
allow_any_instance_of
(
ApplicationHelper
).
to
receive
(
:collapsed_sidebar?
).
and_return
(
true
)
project
.
team
<<
[
user
,
:master
]
sign_in
(
user
)
end
context
'with the feature enabled'
do
before
do
stub_licensed_features
(
scoped_issue_board:
true
)
end
context
'new board'
do
before
do
visit
project_boards_path
(
project
)
end
it
'creates board with milestone'
do
create_board_with_milestone
expect
(
find
(
'.tokens-container'
)).
to
have_content
(
milestone
.
title
)
wait_for_requests
find
(
'.card'
,
match: :first
)
expect
(
all
(
'.board'
).
last
).
to
have_selector
(
'.card'
,
count:
1
)
end
end
context
'update board'
do
let!
(
:milestone_two
)
{
create
(
:milestone
,
project:
project
)
}
let!
(
:board
)
{
create
(
:board
,
project:
project
,
milestone:
milestone
)
}
before
do
visit
project_boards_path
(
project
)
end
it
'defaults milestone filter'
do
page
.
within
'#js-multiple-boards-switcher'
do
find
(
'.dropdown-menu-toggle'
).
click
wait_for_requests
click_link
board
.
name
end
expect
(
find
(
'.tokens-container'
)).
to
have_content
(
milestone
.
title
)
find
(
'.card'
,
match: :first
)
expect
(
all
(
'.board'
).
last
).
to
have_selector
(
'.card'
,
count:
1
)
end
it
'sets board to any milestone'
do
update_board_milestone
(
'Any Milestone'
)
expect
(
page
).
not_to
have_css
(
'.js-visual-token'
)
expect
(
find
(
'.tokens-container'
)).
not_to
have_content
(
milestone
.
title
)
find
(
'.card'
,
match: :first
)
expect
(
page
).
to
have_selector
(
'.board'
,
count:
3
)
expect
(
all
(
'.board'
).
last
).
to
have_selector
(
'.card'
,
count:
2
)
end
it
'sets board to upcoming milestone'
do
update_board_milestone
(
'Upcoming'
)
expect
(
find
(
'.tokens-container'
)).
not_to
have_content
(
milestone
.
title
)
find
(
'.board'
,
match: :first
)
expect
(
all
(
'.board'
)[
1
]).
to
have_selector
(
'.card'
,
count:
0
)
end
it
'does not allow milestone in filter to be editted'
do
find
(
'.filtered-search'
).
native
.
send_keys
(
:backspace
)
page
.
within
(
'.tokens-container'
)
do
expect
(
page
).
to
have_selector
(
'.value'
)
end
end
it
'does not render milestone in hint dropdown'
do
find
(
'.filtered-search'
).
click
page
.
within
(
'#js-dropdown-hint'
)
do
expect
(
page
).
not_to
have_button
(
'Milestone'
)
end
end
end
context
'removing issue from board'
do
let
(
:label
)
{
create
(
:label
,
project:
project
)
}
let!
(
:issue
)
{
create
(
:labeled_issue
,
project:
project
,
labels:
[
label
],
milestone:
milestone
)
}
let!
(
:board
)
{
create
(
:board
,
project:
project
,
milestone:
milestone
)
}
let!
(
:list
)
{
create
(
:list
,
board:
board
,
label:
label
,
position:
0
)
}
before
do
visit
project_boards_path
(
project
)
end
it
'removes issues milestone when removing from the board'
do
wait_for_requests
first
(
'.card .card-number'
).
click
click_button
(
'Remove from board'
)
wait_for_requests
expect
(
issue
.
reload
.
milestone
).
to
be_nil
end
end
context
'new issues'
do
let
(
:label
)
{
create
(
:label
,
project:
project
)
}
let!
(
:list1
)
{
create
(
:list
,
board:
board
,
label:
label
,
position:
0
)
}
let!
(
:board
)
{
create
(
:board
,
project:
project
,
milestone:
milestone
)
}
let!
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
before
do
visit
project_boards_path
(
project
)
end
it
'creates new issue with boards milestone'
do
wait_for_requests
page
.
within
(
first
(
'.board'
))
do
find
(
'.btn-default'
).
click
find
(
'.form-control'
).
set
(
'testing new issue with milestone'
)
click_button
(
'Submit issue'
)
wait_for_requests
click_link
(
'testing new issue with milestone'
)
end
expect
(
page
).
to
have_content
(
milestone
.
title
)
end
it
'updates issue with milestone from add issues modal'
do
wait_for_requests
click_button
'Add issues'
page
.
within
(
'.add-issues-modal'
)
do
card
=
find
(
'.card'
,
:first
)
expect
(
page
).
to
have_selector
(
'.card'
,
count:
1
)
card
.
click
click_button
'Add 1 issue'
end
click_link
(
issue
.
title
)
expect
(
page
).
to
have_content
(
milestone
.
title
)
end
end
end
context
'with the feature disabled'
do
before
do
stub_licensed_features
(
scoped_issue_board:
false
)
visit
project_boards_path
(
project
)
end
it
"doesn't show the input when creating a board"
do
page
.
within
'#js-multiple-boards-switcher'
do
find
(
'.dropdown-menu-toggle'
).
click
click_link
'Create new board'
# To make sure the form is shown
expect
(
page
).
to
have_selector
(
'#board-new-name'
)
expect
(
page
).
not_to
have_button
(
'Milestone'
)
end
end
it
"doesn't show the option to edit the milestone"
do
page
.
within
'#js-multiple-boards-switcher'
do
find
(
'.dropdown-menu-toggle'
).
click
# To make sure the dropdown is open
expect
(
page
).
to
have_link
(
'Edit board name'
)
expect
(
page
).
not_to
have_link
(
'Edit board milestone'
)
end
end
end
def
create_board_with_milestone
page
.
within
'#js-multiple-boards-switcher'
do
find
(
'.dropdown-menu-toggle'
).
click
click_link
'Create new board'
find
(
'#board-new-name'
).
set
'test'
find
(
'button'
,
text:
'Any Milestone'
).
trigger
(
'click'
)
find
(
'a'
,
text:
milestone
.
title
).
trigger
(
'click'
)
click_button
'Create'
end
end
def
update_board_milestone
(
milestone_title
)
page
.
within
'#js-multiple-boards-switcher'
do
find
(
'.dropdown-menu-toggle'
).
click
click_link
'Edit board milestone'
click_link
milestone_title
click_button
'Save'
end
end
end
spec/features/boards/multiple_boards_spec.rb
View file @
59d29e78
...
...
@@ -67,24 +67,6 @@ describe 'Multiple Issue Boards', :js do
expect
(
page
).
to
have_button
(
'This is a new board'
)
end
it
'edits board name'
do
click_button
board
.
name
page
.
within
(
'.dropdown-menu'
)
do
click_link
'Edit board name'
fill_in
'board-new-name'
,
with:
'Testing'
click_button
'Save'
end
wait_for_requests
page
.
within
(
'.dropdown-menu'
)
do
expect
(
page
).
to
have_content
(
'Testing'
)
end
end
it
'deletes board'
do
click_button
board
.
name
...
...
@@ -156,7 +138,6 @@ describe 'Multiple Issue Boards', :js do
page
.
within
(
'.dropdown-menu'
)
do
expect
(
page
).
not_to
have_content
(
'Create new board'
)
expect
(
page
).
not_to
have_content
(
'Edit board name'
)
expect
(
page
).
not_to
have_content
(
'Delete board'
)
end
end
...
...
@@ -178,7 +159,7 @@ describe 'Multiple Issue Boards', :js do
click_button
board
.
name
page
.
within
(
'.dropdown-menu'
)
do
expect
(
page
).
to
have_content
(
'Edit board
name
'
)
expect
(
page
).
to
have_content
(
'Edit board'
)
expect
(
page
).
not_to
have_content
(
'Create new board'
)
expect
(
page
).
not_to
have_content
(
'Delete board'
)
end
...
...
spec/javascripts/boards/milestone_select_spec.js
View file @
59d29e78
...
...
@@ -4,7 +4,7 @@
/* global mockBoardService */
import
Vue
from
'
vue
'
;
import
milestoneSelect
from
'
~/boards/components/milestone_select
'
;
import
MilestoneSelect
from
'
~/boards/components/milestone_select.vue
'
;
import
'
~/boards/services/board_service
'
;
import
'
~/boards/stores/boards_store
'
;
import
'
./mock_data
'
;
...
...
@@ -14,8 +14,6 @@ describe('Milestone select component', () => {
let
vm
;
beforeEach
(()
=>
{
const
MilestoneComp
=
Vue
.
extend
(
milestoneSelect
);
Vue
.
http
.
interceptors
.
push
(
boardsMockInterceptor
);
gl
.
boardService
=
mockBoardService
();
gl
.
issueBoards
.
BoardsStore
.
create
();
...
...
@@ -24,7 +22,7 @@ describe('Milestone select component', () => {
vm
.
board
.
milestone_id
=
milestone
.
id
;
});
vm
=
new
Milestone
Comp
({
vm
=
new
Milestone
Select
({
propsData
:
{
board
:
boardObj
,
milestonePath
:
'
/test/issue-boards/milestones.json
'
,
...
...
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