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
614610c5
Commit
614610c5
authored
Mar 05, 2021
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Epic Boards - Update board scope
Update labels in epic board scope
parent
7912ce21
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
289 additions
and
21 deletions
+289
-21
app/assets/javascripts/boards/components/board_form.vue
app/assets/javascripts/boards/components/board_form.vue
+9
-4
app/assets/javascripts/boards/components/config_toggle.vue
app/assets/javascripts/boards/components/config_toggle.vue
+4
-3
app/assets/javascripts/boards/config_toggle.js
app/assets/javascripts/boards/config_toggle.js
+1
-1
app/assets/javascripts/boards/stores/getters.js
app/assets/javascripts/boards/stores/getters.js
+5
-1
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+5
-1
app/helpers/application_helper.rb
app/helpers/application_helper.rb
+1
-0
ee/app/assets/javascripts/boards/components/board_form.vue
ee/app/assets/javascripts/boards/components/board_form.vue
+16
-4
ee/app/assets/javascripts/boards/components/board_scope.vue
ee/app/assets/javascripts/boards/components/board_scope.vue
+6
-0
ee/app/assets/javascripts/boards/graphql/epic_board_update.mutation.graphql
...scripts/boards/graphql/epic_board_update.mutation.graphql
+9
-0
ee/app/assets/javascripts/boards/graphql/lists_epics.query.graphql
...sets/javascripts/boards/graphql/lists_epics.query.graphql
+2
-1
ee/app/assets/javascripts/boards/stores/actions.js
ee/app/assets/javascripts/boards/stores/actions.js
+6
-3
ee/app/assets/javascripts/epic_boards/index.js
ee/app/assets/javascripts/epic_boards/index.js
+15
-1
ee/app/models/boards/epic_board.rb
ee/app/models/boards/epic_board.rb
+1
-1
ee/spec/features/epic_boards/epic_boards_spec.rb
ee/spec/features/epic_boards/epic_boards_spec.rb
+99
-0
ee/spec/frontend/boards/components/board_form_spec.js
ee/spec/frontend/boards/components/board_form_spec.js
+46
-0
ee/spec/frontend/boards/components/board_scope_spec.js
ee/spec/frontend/boards/components/board_scope_spec.js
+18
-1
ee/spec/frontend/boards/stores/getters_spec.js
ee/spec/frontend/boards/stores/getters_spec.js
+18
-0
spec/frontend/boards/stores/getters_spec.js
spec/frontend/boards/stores/getters_spec.js
+28
-0
No files found.
app/assets/javascripts/boards/components/board_form.vue
View file @
614610c5
...
@@ -107,7 +107,7 @@ export default {
...
@@ -107,7 +107,7 @@ export default {
};
};
},
},
computed
:
{
computed
:
{
...
mapGetters
([
'
is
Epic
Board
'
,
'
isGroupBoard
'
,
'
isProjectBoard
'
]),
...
mapGetters
([
'
is
Issue
Board
'
,
'
isGroupBoard
'
,
'
isProjectBoard
'
]),
isNewForm
()
{
isNewForm
()
{
return
this
.
currentPage
===
formType
.
new
;
return
this
.
currentPage
===
formType
.
new
;
},
},
...
@@ -182,7 +182,7 @@ export default {
...
@@ -182,7 +182,7 @@ export default {
groupPath
:
this
.
isGroupBoard
?
this
.
fullPath
:
undefined
,
groupPath
:
this
.
isGroupBoard
?
this
.
fullPath
:
undefined
,
};
};
},
},
b
oardScopeMutationVariables
()
{
issueB
oardScopeMutationVariables
()
{
/* eslint-disable @gitlab/require-i18n-strings */
/* eslint-disable @gitlab/require-i18n-strings */
return
{
return
{
weight
:
this
.
board
.
weight
,
weight
:
this
.
board
.
weight
,
...
@@ -193,13 +193,18 @@ export default {
...
@@ -193,13 +193,18 @@ export default {
this
.
board
.
milestone
?.
id
||
this
.
board
.
milestone
?.
id
===
0
this
.
board
.
milestone
?.
id
||
this
.
board
.
milestone
?.
id
===
0
?
convertToGraphQLId
(
'
Milestone
'
,
this
.
board
.
milestone
.
id
)
?
convertToGraphQLId
(
'
Milestone
'
,
this
.
board
.
milestone
.
id
)
:
null
,
:
null
,
labelIds
:
this
.
board
.
labels
.
map
(
fullLabelId
),
iterationId
:
this
.
board
.
iteration_id
iterationId
:
this
.
board
.
iteration_id
?
convertToGraphQLId
(
'
Iteration
'
,
this
.
board
.
iteration_id
)
?
convertToGraphQLId
(
'
Iteration
'
,
this
.
board
.
iteration_id
)
:
null
,
:
null
,
};
};
/* eslint-enable @gitlab/require-i18n-strings */
/* eslint-enable @gitlab/require-i18n-strings */
},
},
boardScopeMutationVariables
()
{
return
{
labelIds
:
this
.
board
.
labels
.
map
(
fullLabelId
),
...(
this
.
isIssueBoard
&&
this
.
issueBoardScopeMutationVariables
),
};
},
mutationVariables
()
{
mutationVariables
()
{
return
{
return
{
...
this
.
baseMutationVariables
,
...
this
.
baseMutationVariables
,
...
@@ -324,7 +329,7 @@ export default {
...
@@ -324,7 +329,7 @@ export default {
/>
/>
<board-scope
<board-scope
v-if=
"scopedIssueBoardFeatureEnabled
&& !isEpicBoard
"
v-if=
"scopedIssueBoardFeatureEnabled"
:collapse-scope=
"isNewForm"
:collapse-scope=
"isNewForm"
:board=
"board"
:board=
"board"
:can-admin-board=
"canAdminBoard"
:can-admin-board=
"canAdminBoard"
...
...
app/assets/javascripts/boards/components/config_toggle.vue
View file @
614610c5
...
@@ -15,7 +15,8 @@ export default {
...
@@ -15,7 +15,8 @@ export default {
props
:
{
props
:
{
boardsStore
:
{
boardsStore
:
{
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
false
,
default
:
undefined
,
},
},
canAdminList
:
{
canAdminList
:
{
type
:
Boolean
,
type
:
Boolean
,
...
@@ -28,7 +29,7 @@ export default {
...
@@ -28,7 +29,7 @@ export default {
},
},
data
()
{
data
()
{
return
{
return
{
state
:
this
.
boardsStore
.
state
,
state
:
this
.
boardsStore
?
this
.
boardsStore
.
state
:
{}
,
};
};
},
},
computed
:
{
computed
:
{
...
@@ -42,7 +43,7 @@ export default {
...
@@ -42,7 +43,7 @@ export default {
methods
:
{
methods
:
{
showPage
()
{
showPage
()
{
eventHub
.
$emit
(
'
showBoardModal
'
,
formType
.
edit
);
eventHub
.
$emit
(
'
showBoardModal
'
,
formType
.
edit
);
return
this
.
boardsStore
.
showPage
(
formType
.
edit
)
;
return
this
.
boardsStore
?
this
.
boardsStore
.
showPage
(
formType
.
edit
)
:
null
;
},
},
},
},
};
};
...
...
app/assets/javascripts/boards/config_toggle.js
View file @
614610c5
...
@@ -2,7 +2,7 @@ import Vue from 'vue';
...
@@ -2,7 +2,7 @@ import Vue from 'vue';
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
ConfigToggle
from
'
./components/config_toggle.vue
'
;
import
ConfigToggle
from
'
./components/config_toggle.vue
'
;
export
default
(
boardsStore
)
=>
{
export
default
(
boardsStore
=
undefined
)
=>
{
const
el
=
document
.
querySelector
(
'
.js-board-config
'
);
const
el
=
document
.
querySelector
(
'
.js-board-config
'
);
if
(
!
el
)
{
if
(
!
el
)
{
...
...
app/assets/javascripts/boards/stores/getters.js
View file @
614610c5
import
{
find
}
from
'
lodash
'
;
import
{
find
}
from
'
lodash
'
;
import
{
BoardType
,
inactiveId
}
from
'
../constants
'
;
import
{
BoardType
,
inactiveId
,
issuableTypes
}
from
'
../constants
'
;
export
default
{
export
default
{
isGroupBoard
:
(
state
)
=>
state
.
boardType
===
BoardType
.
group
,
isGroupBoard
:
(
state
)
=>
state
.
boardType
===
BoardType
.
group
,
...
@@ -44,6 +44,10 @@ export default {
...
@@ -44,6 +44,10 @@ export default {
return
find
(
state
.
boardLists
,
(
l
)
=>
l
.
title
===
title
);
return
find
(
state
.
boardLists
,
(
l
)
=>
l
.
title
===
title
);
},
},
isIssueBoard
:
(
state
)
=>
{
return
state
.
issuableType
===
issuableTypes
.
issue
;
},
isEpicBoard
:
()
=>
{
isEpicBoard
:
()
=>
{
return
false
;
return
false
;
},
},
...
...
app/assets/javascripts/labels_select.js
View file @
614610c5
...
@@ -313,7 +313,11 @@ export default class LabelsSelect {
...
@@ -313,7 +313,11 @@ export default class LabelsSelect {
return
;
return
;
}
}
if
(
$
(
'
html
'
).
hasClass
(
'
issue-boards-page
'
))
{
if
(
$
(
'
html
'
)
.
attr
(
'
class
'
)
.
match
(
/issue-boards-page|epic-boards-page/
)
)
{
return
;
return
;
}
}
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
...
...
app/helpers/application_helper.rb
View file @
614610c5
...
@@ -281,6 +281,7 @@ module ApplicationHelper
...
@@ -281,6 +281,7 @@ module ApplicationHelper
def
page_class
def
page_class
class_names
=
[]
class_names
=
[]
class_names
<<
'issue-boards-page gl-overflow-auto'
if
current_controller?
(
:boards
)
class_names
<<
'issue-boards-page gl-overflow-auto'
if
current_controller?
(
:boards
)
class_names
<<
'epic-boards-page'
if
current_controller?
(
:epic_boards
)
class_names
<<
'environment-logs-page'
if
current_controller?
(
:logs
)
class_names
<<
'environment-logs-page'
if
current_controller?
(
:logs
)
class_names
<<
'with-performance-bar'
if
performance_bar_enabled?
class_names
<<
'with-performance-bar'
if
performance_bar_enabled?
class_names
<<
system_message_class
class_names
<<
system_message_class
...
...
ee/app/assets/javascripts/boards/components/board_form.vue
View file @
614610c5
...
@@ -4,7 +4,9 @@
...
@@ -4,7 +4,9 @@
/* eslint-disable @gitlab/no-runtime-template-compiler */
/* eslint-disable @gitlab/no-runtime-template-compiler */
import
{
mapGetters
}
from
'
vuex
'
;
import
{
mapGetters
}
from
'
vuex
'
;
import
BoardFormFoss
from
'
~/boards/components/board_form.vue
'
;
import
BoardFormFoss
from
'
~/boards/components/board_form.vue
'
;
import
{
fullEpicBoardId
}
from
'
../boards_util
'
;
import
createEpicBoardMutation
from
'
../graphql/epic_board_create.mutation.graphql
'
;
import
createEpicBoardMutation
from
'
../graphql/epic_board_create.mutation.graphql
'
;
import
updateEpicBoardMutation
from
'
../graphql/epic_board_update.mutation.graphql
'
;
export
default
{
export
default
{
extends
:
BoardFormFoss
,
extends
:
BoardFormFoss
,
...
@@ -13,11 +15,16 @@ export default {
...
@@ -13,11 +15,16 @@ export default {
epicBoardCreateQuery
()
{
epicBoardCreateQuery
()
{
return
createEpicBoardMutation
;
return
createEpicBoardMutation
;
},
},
currentEpicBoardMutation
()
{
return
this
.
board
.
id
?
updateEpicBoardMutation
:
createEpicBoardMutation
;
},
mutationVariables
()
{
mutationVariables
()
{
// TODO: Epic board scope will be added in a future iteration: https://gitlab.com/gitlab-org/gitlab/-/issues/231389
const
{
board
}
=
this
;
return
{
return
{
...
this
.
baseMutationVariables
,
...
this
.
baseMutationVariables
,
...(
this
.
scopedIssueBoardFeatureEnabled
&&
!
this
.
isEpicBoard
...(
board
.
id
&&
this
.
isEpicBoard
&&
{
id
:
fullEpicBoardId
(
board
.
id
)
}),
...(
this
.
scopedIssueBoardFeatureEnabled
||
this
.
isEpicBoard
?
this
.
boardScopeMutationVariables
?
this
.
boardScopeMutationVariables
:
{}),
:
{}),
};
};
...
@@ -27,9 +34,12 @@ export default {
...
@@ -27,9 +34,12 @@ export default {
epicBoardCreateResponse
(
data
)
{
epicBoardCreateResponse
(
data
)
{
return
data
.
epicBoardCreate
.
epicBoard
.
webPath
;
return
data
.
epicBoardCreate
.
epicBoard
.
webPath
;
},
},
epicBoardUpdateResponse
(
data
)
{
return
data
.
epicBoardUpdate
.
epicBoard
.
webPath
;
},
async
createOrUpdateBoard
()
{
async
createOrUpdateBoard
()
{
const
response
=
await
this
.
$apollo
.
mutate
({
const
response
=
await
this
.
$apollo
.
mutate
({
mutation
:
this
.
isEpicBoard
?
this
.
epicBoardCreateQuery
:
this
.
currentMutation
,
mutation
:
this
.
isEpicBoard
?
this
.
currentEpicBoardMutation
:
this
.
currentMutation
,
variables
:
{
input
:
this
.
mutationVariables
},
variables
:
{
input
:
this
.
mutationVariables
},
});
});
...
@@ -39,7 +49,9 @@ export default {
...
@@ -39,7 +49,9 @@ export default {
:
this
.
boardCreateResponse
(
response
.
data
);
:
this
.
boardCreateResponse
(
response
.
data
);
}
}
return
this
.
boardUpdateResponse
(
response
.
data
);
return
this
.
isEpicBoard
?
this
.
epicBoardUpdateResponse
(
response
.
data
)
:
this
.
boardUpdateResponse
(
response
.
data
);
},
},
},
},
};
};
...
...
ee/app/assets/javascripts/boards/components/board_scope.vue
View file @
614610c5
<
script
>
<
script
>
import
{
mapGetters
}
from
'
vuex
'
;
import
ListLabel
from
'
~/boards/models/label
'
;
import
ListLabel
from
'
~/boards/models/label
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
BoardLabelsSelect
from
'
~/vue_shared/components/sidebar/labels_select/base.vue
'
;
import
BoardLabelsSelect
from
'
~/vue_shared/components/sidebar/labels_select/base.vue
'
;
...
@@ -66,6 +67,7 @@ export default {
...
@@ -66,6 +67,7 @@ export default {
},
},
computed
:
{
computed
:
{
...
mapGetters
([
'
isIssueBoard
'
]),
expandButtonText
()
{
expandButtonText
()
{
return
this
.
expanded
?
__
(
'
Collapse
'
)
:
__
(
'
Expand
'
);
return
this
.
expanded
?
__
(
'
Collapse
'
)
:
__
(
'
Expand
'
);
},
},
...
@@ -110,6 +112,7 @@ export default {
...
@@ -110,6 +112,7 @@ export default {
</p>
</p>
<div
v-if=
"!collapseScope || expanded"
>
<div
v-if=
"!collapseScope || expanded"
>
<board-milestone-select
<board-milestone-select
v-if=
"isIssueBoard"
:board=
"board"
:board=
"board"
:group-id=
"groupId"
:group-id=
"groupId"
:project-id=
"projectId"
:project-id=
"projectId"
...
@@ -117,6 +120,7 @@ export default {
...
@@ -117,6 +120,7 @@ export default {
/>
/>
<board-scope-current-iteration
<board-scope-current-iteration
v-if=
"isIssueBoard"
:can-admin-board=
"canAdminBoard"
:can-admin-board=
"canAdminBoard"
:iteration-id=
"board.iteration_id"
:iteration-id=
"board.iteration_id"
@
set-iteration=
"$emit('set-iteration', $event)"
@
set-iteration=
"$emit('set-iteration', $event)"
...
@@ -136,6 +140,7 @@ export default {
...
@@ -136,6 +140,7 @@ export default {
>
>
<assignee-select
<assignee-select
v-if=
"isIssueBoard"
:board=
"board"
:board=
"board"
:selected=
"board.assignee"
:selected=
"board.assignee"
:can-edit=
"canAdminBoard"
:can-edit=
"canAdminBoard"
...
@@ -150,6 +155,7 @@ export default {
...
@@ -150,6 +155,7 @@ export default {
<!-- eslint-disable vue/no-mutating-props -->
<!-- eslint-disable vue/no-mutating-props -->
<board-weight-select
<board-weight-select
v-if=
"isIssueBoard"
v-model=
"board.weight"
v-model=
"board.weight"
:board=
"board"
:board=
"board"
:weights=
"weights"
:weights=
"weights"
...
...
ee/app/assets/javascripts/boards/graphql/epic_board_update.mutation.graphql
0 → 100644
View file @
614610c5
mutation
updateEpicBoard
(
$input
:
EpicBoardUpdateInput
!)
{
epicBoardUpdate
(
input
:
$input
)
{
epicBoard
{
id
webPath
}
errors
}
}
ee/app/assets/javascripts/boards/graphql/lists_epics.query.graphql
View file @
614610c5
...
@@ -5,6 +5,7 @@ query ListEpics(
...
@@ -5,6 +5,7 @@ query ListEpics(
$fullPath
:
ID
!
$fullPath
:
ID
!
$boardId
:
BoardsEpicBoardID
!
$boardId
:
BoardsEpicBoardID
!
$id
:
BoardsEpicListID
$id
:
BoardsEpicListID
$filters
:
EpicFilters
$after
:
String
$after
:
String
$first
:
Int
$first
:
Int
)
{
)
{
...
@@ -13,7 +14,7 @@ query ListEpics(
...
@@ -13,7 +14,7 @@ query ListEpics(
lists
(
id
:
$id
)
{
lists
(
id
:
$id
)
{
nodes
{
nodes
{
id
id
epics
(
first
:
$first
,
after
:
$after
)
{
epics
(
first
:
$first
,
after
:
$after
,
filters
:
$filters
)
{
edges
{
edges
{
node
{
node
{
...
EpicNode
...
EpicNode
...
...
ee/app/assets/javascripts/boards/stores/actions.js
View file @
614610c5
...
@@ -115,7 +115,7 @@ const fetchAndFormatListEpics = (state, extraVariables) => {
...
@@ -115,7 +115,7 @@ const fetchAndFormatListEpics = (state, extraVariables) => {
export
default
{
export
default
{
...
actionsCE
,
...
actionsCE
,
setFilters
:
({
commit
,
dispatch
},
filters
)
=>
{
setFilters
:
({
commit
,
dispatch
,
getters
},
filters
)
=>
{
const
filterParams
=
pick
(
filters
,
[
const
filterParams
=
pick
(
filters
,
[
'
assigneeUsername
'
,
'
assigneeUsername
'
,
'
authorUsername
'
,
'
authorUsername
'
,
...
@@ -128,7 +128,10 @@ export default {
...
@@ -128,7 +128,10 @@ export default {
'
weight
'
,
'
weight
'
,
]);
]);
filterParams
.
not
=
transformNotFilters
(
filters
);
// Temporarily disabled until negated filters are supported for epic boards
if
(
!
getters
.
isEpicBoard
)
{
filterParams
.
not
=
transformNotFilters
(
filters
);
}
if
(
filters
.
groupBy
===
GroupByParamType
.
epic
)
{
if
(
filters
.
groupBy
===
GroupByParamType
.
epic
)
{
dispatch
(
'
setEpicSwimlanes
'
);
dispatch
(
'
setEpicSwimlanes
'
);
...
@@ -140,7 +143,7 @@ export default {
...
@@ -140,7 +143,7 @@ export default {
}
else
if
(
filterParams
.
epicId
)
{
}
else
if
(
filterParams
.
epicId
)
{
filterParams
.
epicId
=
fullEpicId
(
filterParams
.
epicId
);
filterParams
.
epicId
=
fullEpicId
(
filterParams
.
epicId
);
}
}
if
(
filterParams
.
not
.
epicId
)
{
if
(
!
getters
.
isEpicBoard
&&
filterParams
.
not
.
epicId
)
{
filterParams
.
not
.
epicId
=
fullEpicId
(
filterParams
.
not
.
epicId
);
filterParams
.
not
.
epicId
=
fullEpicId
(
filterParams
.
not
.
epicId
);
}
}
...
...
ee/app/assets/javascripts/epic_boards/index.js
View file @
614610c5
...
@@ -4,14 +4,16 @@
...
@@ -4,14 +4,16 @@
/* eslint-disable @gitlab/no-runtime-template-compiler */
/* eslint-disable @gitlab/no-runtime-template-compiler */
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
{
mapActions
}
from
'
vuex
'
;
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
transformBoardConfig
}
from
'
ee_component/boards/boards_util
'
;
import
BoardSidebar
from
'
ee_component/boards/components/board_sidebar
'
;
import
BoardSidebar
from
'
ee_component/boards/components/board_sidebar
'
;
import
toggleLabels
from
'
ee_component/boards/toggle_labels
'
;
import
toggleLabels
from
'
ee_component/boards/toggle_labels
'
;
import
BoardAddNewColumnTrigger
from
'
~/boards/components/board_add_new_column_trigger.vue
'
;
import
BoardAddNewColumnTrigger
from
'
~/boards/components/board_add_new_column_trigger.vue
'
;
import
BoardContent
from
'
~/boards/components/board_content.vue
'
;
import
BoardContent
from
'
~/boards/components/board_content.vue
'
;
import
BoardAddIssuesModal
from
'
~/boards/components/modal/index.vue
'
;
import
BoardAddIssuesModal
from
'
~/boards/components/modal/index.vue
'
;
import
boardConfigToggle
from
'
~/boards/config_toggle
'
;
import
{
issuableTypes
}
from
'
~/boards/constants
'
;
import
{
issuableTypes
}
from
'
~/boards/constants
'
;
import
mountMultipleBoardsSwitcher
from
'
~/boards/mount_multiple_boards_switcher
'
;
import
mountMultipleBoardsSwitcher
from
'
~/boards/mount_multiple_boards_switcher
'
;
import
store
from
'
~/boards/stores
'
;
import
store
from
'
~/boards/stores
'
;
...
@@ -19,6 +21,7 @@ import createDefaultClient from '~/lib/graphql';
...
@@ -19,6 +21,7 @@ import createDefaultClient from '~/lib/graphql';
import
'
~/boards/filters/due_date_filters
'
;
import
'
~/boards/filters/due_date_filters
'
;
import
{
NavigationType
,
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
NavigationType
,
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
updateHistory
}
from
'
~/lib/utils/url_utility
'
;
Vue
.
use
(
VueApollo
);
Vue
.
use
(
VueApollo
);
...
@@ -87,6 +90,9 @@ export default () => {
...
@@ -87,6 +90,9 @@ export default () => {
detailIssueVisible
:
false
,
detailIssueVisible
:
false
,
};
};
},
},
computed
:
{
...
mapState
([
'
boardConfig
'
]),
},
created
()
{
created
()
{
this
.
setInitialBoardData
({
this
.
setInitialBoardData
({
boardId
:
$boardApp
.
dataset
.
boardId
,
boardId
:
$boardApp
.
dataset
.
boardId
,
...
@@ -110,6 +116,13 @@ export default () => {
...
@@ -110,6 +116,13 @@ export default () => {
});
});
},
},
mounted
()
{
mounted
()
{
const
boardConfigPath
=
transformBoardConfig
(
this
.
boardConfig
);
if
(
boardConfigPath
!==
''
)
{
const
filterPath
=
window
.
location
.
search
?
`
${
window
.
location
.
search
}
&`
:
'
?
'
;
updateHistory
({
url
:
`
${
filterPath
}${
transformBoardConfig
(
this
.
boardConfig
)}
`
,
});
}
this
.
performSearch
();
this
.
performSearch
();
},
},
methods
:
{
methods
:
{
...
@@ -136,6 +149,7 @@ export default () => {
...
@@ -136,6 +149,7 @@ export default () => {
}
}
toggleLabels
();
toggleLabels
();
boardConfigToggle
();
mountMultipleBoardsSwitcher
({
mountMultipleBoardsSwitcher
({
fullPath
:
$boardApp
.
dataset
.
fullPath
,
fullPath
:
$boardApp
.
dataset
.
fullPath
,
...
...
ee/app/models/boards/epic_board.rb
View file @
614610c5
...
@@ -33,7 +33,7 @@ module Boards
...
@@ -33,7 +33,7 @@ module Boards
end
end
def
scoped?
def
scoped?
false
labels
.
any?
end
end
def
milestone_id
def
milestone_id
...
...
ee/spec/features/epic_boards/epic_boards_spec.rb
View file @
614610c5
...
@@ -20,6 +20,9 @@ RSpec.describe 'epic boards', :js do
...
@@ -20,6 +20,9 @@ RSpec.describe 'epic boards', :js do
let_it_be
(
:epic2
)
{
create
(
:epic
,
group:
group
,
title:
'Epic2'
)
}
let_it_be
(
:epic2
)
{
create
(
:epic
,
group:
group
,
title:
'Epic2'
)
}
let_it_be
(
:epic3
)
{
create
(
:epic
,
group:
group
,
labels:
[
label2
],
title:
'Epic3'
)
}
let_it_be
(
:epic3
)
{
create
(
:epic
,
group:
group
,
labels:
[
label2
],
title:
'Epic3'
)
}
let
(
:edit_board
)
{
find
(
'.btn'
,
text:
'Edit board'
)
}
let
(
:view_scope
)
{
find
(
'.btn'
,
text:
'View scope'
)
}
context
'display epics in board'
do
context
'display epics in board'
do
before
do
before
do
stub_licensed_features
(
epics:
true
)
stub_licensed_features
(
epics:
true
)
...
@@ -103,6 +106,23 @@ RSpec.describe 'epic boards', :js do
...
@@ -103,6 +106,23 @@ RSpec.describe 'epic boards', :js do
it
"shows 'Create list' button"
do
it
"shows 'Create list' button"
do
expect
(
page
).
to
have_selector
(
'[data-testid="boards-create-list"]'
)
expect
(
page
).
to
have_selector
(
'[data-testid="boards-create-list"]'
)
end
end
it
'creates board filtering by one label'
do
create_board_label
(
label
.
title
)
expect
(
page
).
to
have_selector
(
'.board-card'
,
count:
1
)
end
it
'adds label to board scope and filters epics'
do
label_title
=
label
.
title
update_board_label
(
label_title
)
expect
(
page
).
to
have_selector
(
'.board-card'
,
count:
1
)
expect
(
page
).
to
have_content
(
'Epic1'
)
expect
(
page
).
not_to
have_content
(
'Epic2'
)
expect
(
page
).
not_to
have_content
(
'Epic3'
)
end
end
end
context
'when user cannot admin epic boards'
do
context
'when user cannot admin epic boards'
do
...
@@ -116,6 +136,19 @@ RSpec.describe 'epic boards', :js do
...
@@ -116,6 +136,19 @@ RSpec.describe 'epic boards', :js do
it
"does not show 'Create list'"
do
it
"does not show 'Create list'"
do
expect
(
page
).
not_to
have_selector
(
'[data-testid="boards-create-list"]'
)
expect
(
page
).
not_to
have_selector
(
'[data-testid="boards-create-list"]'
)
end
end
it
'can view board scope'
do
view_scope
.
click
page
.
within
(
'.modal'
)
do
expect
(
find
(
'.modal-header'
)).
to
have_content
(
'Board scope'
)
expect
(
page
).
not_to
have_content
(
'Board name'
)
expect
(
page
).
not_to
have_link
(
'Edit'
)
expect
(
page
).
not_to
have_button
(
'Edit'
)
expect
(
page
).
not_to
have_button
(
'Save'
)
expect
(
page
).
not_to
have_button
(
'Cancel'
)
end
end
end
end
def
visit_epic_boards_page
def
visit_epic_boards_page
...
@@ -139,4 +172,70 @@ RSpec.describe 'epic boards', :js do
...
@@ -139,4 +172,70 @@ RSpec.describe 'epic boards', :js do
list_to_index:
list_to_index
,
list_to_index:
list_to_index
,
perform_drop:
perform_drop
)
perform_drop:
perform_drop
)
end
end
def
click_value
(
filter
,
value
)
page
.
within
(
".
#{
filter
}
"
)
do
click_button
'Edit'
if
value
.
is_a?
(
Array
)
value
.
each
{
|
value
|
click_link
value
}
else
click_link
value
end
end
end
def
click_on_create_new_board
page
.
within
'.js-boards-selector'
do
find
(
'.dropdown-menu-toggle'
).
click
wait_for_requests
click_button
'Create new board'
end
end
def
create_board_label
(
label_title
)
create_board_scope
(
'labels'
,
label_title
)
end
def
create_board_scope
(
filter
,
value
)
click_on_create_new_board
find
(
'#board-new-name'
).
set
'test'
click_button
'Expand'
click_value
(
filter
,
value
)
click_on_board_modal
click_button
'Create board'
wait_for_requests
expect
(
page
).
not_to
have_selector
(
'.board-list-loading'
)
end
def
update_board_scope
(
filter
,
value
)
edit_board
.
click
click_value
(
filter
,
value
)
click_on_board_modal
click_button
'Save changes'
wait_for_requests
expect
(
page
).
not_to
have_selector
(
'.board-list-loading'
)
end
def
update_board_label
(
label_title
)
update_board_scope
(
'labels'
,
label_title
)
end
# Click on modal to make sure the dropdown is closed (e.g. label scenario)
#
def
click_on_board_modal
find
(
'.board-config-modal .modal-content'
).
click
end
end
end
ee/spec/frontend/boards/components/board_form_spec.js
View file @
614610c5
...
@@ -4,6 +4,7 @@ import Vuex from 'vuex';
...
@@ -4,6 +4,7 @@ import Vuex from 'vuex';
import
BoardForm
from
'
ee/boards/components/board_form.vue
'
;
import
BoardForm
from
'
ee/boards/components/board_form.vue
'
;
import
createEpicBoardMutation
from
'
ee/boards/graphql/epic_board_create.mutation.graphql
'
;
import
createEpicBoardMutation
from
'
ee/boards/graphql/epic_board_create.mutation.graphql
'
;
import
updateEpicBoardMutation
from
'
ee/boards/graphql/epic_board_update.mutation.graphql
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
...
@@ -55,6 +56,7 @@ describe('BoardForm', () => {
...
@@ -55,6 +56,7 @@ describe('BoardForm', () => {
const
createStore
=
()
=>
{
const
createStore
=
()
=>
{
return
new
Vuex
.
Store
({
return
new
Vuex
.
Store
({
getters
:
{
getters
:
{
isIssueBoard
:
()
=>
false
,
isEpicBoard
:
()
=>
true
,
isEpicBoard
:
()
=>
true
,
isGroupBoard
:
()
=>
true
,
isGroupBoard
:
()
=>
true
,
isProjectBoard
:
()
=>
false
,
isProjectBoard
:
()
=>
false
,
...
@@ -181,4 +183,48 @@ describe('BoardForm', () => {
...
@@ -181,4 +183,48 @@ describe('BoardForm', () => {
});
});
});
});
});
});
describe
(
'
when editing an epic board
'
,
()
=>
{
it
(
'
calls GraphQL mutation with correct parameters
'
,
async
()
=>
{
mutate
=
jest
.
fn
().
mockResolvedValue
({
data
:
{
epicBoardUpdate
:
{
epicBoard
:
{
id
:
'
gid://gitlab/Boards::EpicBoard/321
'
,
webPath
:
'
test-path
'
},
},
},
});
window
.
location
=
new
URL
(
'
https://test/boards/1
'
);
createComponent
({
canAdminBoard
:
true
,
currentPage
:
formType
.
edit
});
findInput
().
trigger
(
'
keyup.enter
'
,
{
metaKey
:
true
});
await
waitForPromises
();
expect
(
mutate
).
toHaveBeenCalledWith
({
mutation
:
updateEpicBoardMutation
,
variables
:
{
input
:
expect
.
objectContaining
({
id
:
`gid://gitlab/Boards::EpicBoard/
${
currentBoard
.
id
}
`
,
}),
},
});
await
waitForPromises
();
expect
(
visitUrl
).
toHaveBeenCalledWith
(
'
test-path
'
);
});
it
(
'
shows an error flash if GraphQL mutation fails
'
,
async
()
=>
{
mutate
=
jest
.
fn
().
mockRejectedValue
(
'
Houston, we have a problem
'
);
createComponent
({
canAdminBoard
:
true
,
currentPage
:
formType
.
edit
});
findInput
().
trigger
(
'
keyup.enter
'
,
{
metaKey
:
true
});
await
waitForPromises
();
expect
(
mutate
).
toHaveBeenCalled
();
await
waitForPromises
();
expect
(
visitUrl
).
not
.
toHaveBeenCalled
();
expect
(
createFlash
).
toHaveBeenCalled
();
});
});
});
});
ee/spec/frontend/boards/components/board_scope_spec.js
View file @
614610c5
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
,
mount
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
BoardScope
from
'
ee/boards/components/board_scope.vue
'
;
import
BoardScope
from
'
ee/boards/components/board_scope.vue
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
describe
(
'
BoardScope
'
,
()
=>
{
describe
(
'
BoardScope
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
let
vm
;
let
vm
;
...
@@ -18,8 +22,21 @@ describe('BoardScope', () => {
...
@@ -18,8 +22,21 @@ describe('BoardScope', () => {
labelsWebUrl
:
`
${
TEST_HOST
}
/-/labels`
,
labelsWebUrl
:
`
${
TEST_HOST
}
/-/labels`
,
};
};
const
createStore
=
()
=>
{
return
new
Vuex
.
Store
({
getters
:
{
isIssueBoard
:
()
=>
true
,
isEpicBoard
:
()
=>
false
,
},
});
};
const
store
=
createStore
();
wrapper
=
mount
(
BoardScope
,
{
wrapper
=
mount
(
BoardScope
,
{
localVue
,
propsData
,
propsData
,
store
,
});
});
({
vm
}
=
wrapper
);
({
vm
}
=
wrapper
);
...
...
ee/spec/frontend/boards/stores/getters_spec.js
View file @
614610c5
...
@@ -122,4 +122,22 @@ describe('EE Boards Store Getters', () => {
...
@@ -122,4 +122,22 @@ describe('EE Boards Store Getters', () => {
).
toBeUndefined
();
).
toBeUndefined
();
});
});
});
});
describe
(
'
isEpicBoard
'
,
()
=>
{
it
(
'
returns true when issuableType on state is epic
'
,
()
=>
{
const
state
=
{
issuableType
:
'
epic
'
,
};
expect
(
getters
.
isEpicBoard
(
state
)).
toBe
(
true
);
});
it
(
'
returns false when issuableType on state is not epic
'
,
()
=>
{
const
state
=
{
issuableType
:
'
issue
'
,
};
expect
(
getters
.
isEpicBoard
(
state
)).
toBe
(
false
);
});
});
});
});
spec/frontend/boards/stores/getters_spec.js
View file @
614610c5
...
@@ -177,4 +177,32 @@ describe('Boards - Getters', () => {
...
@@ -177,4 +177,32 @@ describe('Boards - Getters', () => {
expect(getters.activeGroupProjects(state)).toEqual([mockGroupProject1]);
expect(getters.activeGroupProjects(state)).toEqual([mockGroupProject1]);
});
});
});
});
describe('isIssueBoard', () => {
it('returns true when issuableType on state is issue', () => {
const state = {
issuableType: 'issue',
};
expect(getters.isIssueBoard(state)).toBe(true);
});
it('returns false when issuableType on state is not issue', () => {
const state = {
issuableType: 'epic',
};
expect(getters.isIssueBoard(state)).toBe(false);
});
});
describe('isEpicBoard', () => {
afterEach(() => {
window.gon = { features: {} };
});
it('returns false', () => {
expect(getters.isEpicBoard()).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