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
02d8146f
Commit
02d8146f
authored
Oct 07, 2020
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Swimlanes - Add list to board
Store lists by id on VueX state
parent
18b27142
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
314 additions
and
125 deletions
+314
-125
app/assets/javascripts/boards/boards_util.js
app/assets/javascripts/boards/boards_util.js
+21
-0
app/assets/javascripts/boards/components/board_content.vue
app/assets/javascripts/boards/components/board_content.vue
+5
-2
app/assets/javascripts/boards/components/board_settings_sidebar.vue
.../javascripts/boards/components/board_settings_sidebar.vue
+1
-1
app/assets/javascripts/boards/components/new_list_dropdown.js
...assets/javascripts/boards/components/new_list_dropdown.js
+22
-10
app/assets/javascripts/boards/queries/board_list_create.mutation.graphql
...scripts/boards/queries/board_list_create.mutation.graphql
+17
-3
app/assets/javascripts/boards/stores/actions.js
app/assets/javascripts/boards/stores/actions.js
+32
-33
app/assets/javascripts/boards/stores/getters.js
app/assets/javascripts/boards/stores/getters.js
+13
-0
app/assets/javascripts/boards/stores/mutation_types.js
app/assets/javascripts/boards/stores/mutation_types.js
+1
-0
app/assets/javascripts/boards/stores/mutations.js
app/assets/javascripts/boards/stores/mutations.js
+17
-19
app/assets/javascripts/boards/stores/state.js
app/assets/javascripts/boards/stores/state.js
+1
-1
app/serializers/label_entity.rb
app/serializers/label_entity.rb
+1
-1
app/serializers/label_serializer.rb
app/serializers/label_serializer.rb
+1
-1
ee/app/assets/javascripts/boards/boards_util.js
ee/app/assets/javascripts/boards/boards_util.js
+10
-0
ee/app/assets/javascripts/boards/components/assignees_list_selector.js
.../javascripts/boards/components/assignees_list_selector.js
+0
-0
ee/app/assets/javascripts/boards/components/boards_list_selector/index.js
...vascripts/boards/components/boards_list_selector/index.js
+26
-9
ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
.../assets/javascripts/boards/components/epics_swimlanes.vue
+3
-1
ee/app/assets/javascripts/boards/components/new_list_dropdown.js
...assets/javascripts/boards/components/new_list_dropdown.js
+4
-4
ee/app/assets/javascripts/boards/stores/actions.js
ee/app/assets/javascripts/boards/stores/actions.js
+8
-7
ee/app/assets/javascripts/boards/stores/getters.js
ee/app/assets/javascripts/boards/stores/getters.js
+7
-0
ee/app/assets/javascripts/boards/stores/mutations.js
ee/app/assets/javascripts/boards/stores/mutations.js
+2
-2
ee/spec/frontend/boards/components/board_list_selector/board_list_selector_spec.js
...omponents/board_list_selector/board_list_selector_spec.js
+24
-2
ee/spec/frontend/boards/stores/mutations_spec.js
ee/spec/frontend/boards/stores/mutations_spec.js
+8
-5
locale/gitlab.pot
locale/gitlab.pot
+3
-3
spec/frontend/boards/stores/actions_spec.js
spec/frontend/boards/stores/actions_spec.js
+17
-3
spec/frontend/boards/stores/getters_spec.js
spec/frontend/boards/stores/getters_spec.js
+29
-1
spec/frontend/boards/stores/mutations_spec.js
spec/frontend/boards/stores/mutations_spec.js
+39
-16
spec/serializers/label_serializer_spec.rb
spec/serializers/label_serializer_spec.rb
+2
-1
No files found.
app/assets/javascripts/boards/boards_util.js
View file @
02d8146f
...
@@ -2,11 +2,24 @@ import { sortBy } from 'lodash';
...
@@ -2,11 +2,24 @@ import { sortBy } from 'lodash';
import
ListIssue
from
'
ee_else_ce/boards/models/issue
'
;
import
ListIssue
from
'
ee_else_ce/boards/models/issue
'
;
import
{
ListType
}
from
'
./constants
'
;
import
{
ListType
}
from
'
./constants
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
export
function
getMilestone
()
{
export
function
getMilestone
()
{
return
null
;
return
null
;
}
}
export
function
formatBoardLists
(
lists
)
{
const
formattedLists
=
lists
.
nodes
.
map
(
list
=>
boardsStore
.
updateListPosition
({
...
list
,
doNotFetchIssues
:
true
}),
);
return
formattedLists
.
reduce
((
map
,
list
)
=>
{
return
{
...
map
,
[
list
.
id
]:
list
,
};
},
{});
}
export
function
formatIssue
(
issue
)
{
export
function
formatIssue
(
issue
)
{
return
new
ListIssue
({
return
new
ListIssue
({
...
issue
,
...
issue
,
...
@@ -62,6 +75,13 @@ export function fullBoardId(boardId) {
...
@@ -62,6 +75,13 @@ export function fullBoardId(boardId) {
return
`gid://gitlab/Board/
${
boardId
}
`
;
return
`gid://gitlab/Board/
${
boardId
}
`
;
}
}
export
function
fullLabelId
(
label
)
{
if
(
label
.
project_id
!==
null
)
{
return
`gid://gitlab/ProjectLabel/
${
label
.
id
}
`
;
}
return
`gid://gitlab/GroupLabel/
${
label
.
id
}
`
;
}
export
function
moveIssueListHelper
(
issue
,
fromList
,
toList
)
{
export
function
moveIssueListHelper
(
issue
,
fromList
,
toList
)
{
if
(
toList
.
type
===
ListType
.
label
)
{
if
(
toList
.
type
===
ListType
.
label
)
{
issue
.
addLabel
(
toList
.
label
);
issue
.
addLabel
(
toList
.
label
);
...
@@ -85,4 +105,5 @@ export default {
...
@@ -85,4 +105,5 @@ export default {
formatIssue
,
formatIssue
,
formatListIssues
,
formatListIssues
,
fullBoardId
,
fullBoardId
,
fullLabelId
,
};
};
app/assets/javascripts/boards/components/board_content.vue
View file @
02d8146f
<
script
>
<
script
>
import
{
mapState
,
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
{
mapState
,
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
{
sortBy
}
from
'
lodash
'
;
import
BoardColumn
from
'
ee_else_ce/boards/components/board_column.vue
'
;
import
BoardColumn
from
'
ee_else_ce/boards/components/board_column.vue
'
;
import
{
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
GlAlert
}
from
'
@gitlab/ui
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
...
@@ -30,7 +31,9 @@ export default {
...
@@ -30,7 +31,9 @@ export default {
...
mapState
([
'
boardLists
'
,
'
error
'
]),
...
mapState
([
'
boardLists
'
,
'
error
'
]),
...
mapGetters
([
'
isSwimlanesOn
'
]),
...
mapGetters
([
'
isSwimlanesOn
'
]),
boardListsToUse
()
{
boardListsToUse
()
{
return
this
.
glFeatures
.
graphqlBoardLists
?
this
.
boardLists
:
this
.
lists
;
const
lists
=
this
.
glFeatures
.
graphqlBoardLists
||
this
.
isSwimlanesOn
?
this
.
boardLists
:
this
.
lists
;
return
sortBy
([...
Object
.
values
(
lists
)],
'
position
'
);
},
},
},
},
mounted
()
{
mounted
()
{
...
@@ -68,7 +71,7 @@ export default {
...
@@ -68,7 +71,7 @@ export default {
<template
v-else
>
<template
v-else
>
<epics-swimlanes
<epics-swimlanes
ref=
"swimlanes"
ref=
"swimlanes"
:lists=
"boardLists"
:lists=
"boardLists
ToUse
"
:can-admin-list=
"canAdminList"
:can-admin-list=
"canAdminList"
:disabled=
"disabled"
:disabled=
"disabled"
/>
/>
...
...
app/assets/javascripts/boards/components/board_settings_sidebar.vue
View file @
02d8146f
...
@@ -34,7 +34,7 @@ export default {
...
@@ -34,7 +34,7 @@ export default {
referencing a List Model class. Reactivity only applies to plain JS objects
referencing a List Model class. Reactivity only applies to plain JS objects
*/
*/
if
(
this
.
glFeatures
.
graphqlBoardLists
)
{
if
(
this
.
glFeatures
.
graphqlBoardLists
)
{
return
this
.
boardLists
.
find
(({
id
})
=>
id
===
this
.
activeId
)
;
return
this
.
boardLists
[
this
.
activeId
]
;
}
}
return
boardsStore
.
state
.
lists
.
find
(({
id
})
=>
id
===
this
.
activeId
);
return
boardsStore
.
state
.
lists
.
find
(({
id
})
=>
id
===
this
.
activeId
);
},
},
...
...
app/assets/javascripts/boards/components/new_list_dropdown.js
View file @
02d8146f
...
@@ -6,8 +6,14 @@ import axios from '~/lib/utils/axios_utils';
...
@@ -6,8 +6,14 @@ import axios from '~/lib/utils/axios_utils';
import
{
deprecatedCreateFlash
as
flash
}
from
'
~/flash
'
;
import
{
deprecatedCreateFlash
as
flash
}
from
'
~/flash
'
;
import
CreateLabelDropdown
from
'
../../create_label
'
;
import
CreateLabelDropdown
from
'
../../create_label
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
{
fullLabelId
}
from
'
../boards_util
'
;
import
store
from
'
~/boards/stores
'
;
import
initDeprecatedJQueryDropdown
from
'
~/deprecated_jquery_dropdown
'
;
import
initDeprecatedJQueryDropdown
from
'
~/deprecated_jquery_dropdown
'
;
function
shouldCreateListGraphQL
(
label
)
{
return
store
.
getters
.
shouldUseGraphQL
&&
!
store
.
getters
.
getListByLabelId
(
fullLabelId
(
label
));
}
$
(
document
)
$
(
document
)
.
off
(
'
created.label
'
)
.
off
(
'
created.label
'
)
.
on
(
'
created.label
'
,
(
e
,
label
,
addNewList
)
=>
{
.
on
(
'
created.label
'
,
(
e
,
label
,
addNewList
)
=>
{
...
@@ -15,16 +21,20 @@ $(document)
...
@@ -15,16 +21,20 @@ $(document)
return
;
return
;
}
}
boardsStore
.
new
({
if
(
shouldCreateListGraphQL
(
label
))
{
title
:
label
.
title
,
store
.
dispatch
(
'
createList
'
,
{
labelId
:
fullLabelId
(
label
)
});
position
:
boardsStore
.
state
.
lists
.
length
-
2
,
}
else
{
list_type
:
'
label
'
,
boardsStore
.
new
({
label
:
{
id
:
label
.
id
,
title
:
label
.
title
,
title
:
label
.
title
,
color
:
label
.
color
,
position
:
boardsStore
.
state
.
lists
.
length
-
2
,
},
list_type
:
'
label
'
,
});
label
:
{
id
:
label
.
id
,
title
:
label
.
title
,
color
:
label
.
color
,
},
});
}
});
});
export
default
function
initNewListDropdown
()
{
export
default
function
initNewListDropdown
()
{
...
@@ -74,7 +84,9 @@ export default function initNewListDropdown() {
...
@@ -74,7 +84,9 @@ export default function initNewListDropdown() {
const
label
=
options
.
selectedObj
;
const
label
=
options
.
selectedObj
;
e
.
preventDefault
();
e
.
preventDefault
();
if
(
!
boardsStore
.
findListByLabelId
(
label
.
id
))
{
if
(
shouldCreateListGraphQL
(
label
))
{
store
.
dispatch
(
'
createList
'
,
{
labelId
:
fullLabelId
(
label
)
});
}
else
if
(
!
boardsStore
.
findListByLabelId
(
label
.
id
))
{
boardsStore
.
new
({
boardsStore
.
new
({
title
:
label
.
title
,
title
:
label
.
title
,
position
:
boardsStore
.
state
.
lists
.
length
-
2
,
position
:
boardsStore
.
state
.
lists
.
length
-
2
,
...
...
app/assets/javascripts/boards/queries/board_list_create.mutation.graphql
View file @
02d8146f
#import "
.
/board_list.fragment.graphql"
#import "
ee_else_ce/boards/queries
/board_list.fragment.graphql"
mutation
CreateBoardList
(
$boardId
:
BoardID
!,
$backlog
:
Boolean
)
{
mutation
CreateBoardList
(
boardListCreate
(
input
:
{
boardId
:
$boardId
,
backlog
:
$backlog
})
{
$boardId
:
BoardID
!
$backlog
:
Boolean
$labelId
:
LabelID
$milestoneId
:
MilestoneID
$assigneeId
:
UserID
)
{
boardListCreate
(
input
:
{
boardId
:
$boardId
backlog
:
$backlog
labelId
:
$labelId
milestoneId
:
$milestoneId
assigneeId
:
$assigneeId
}
)
{
list
{
list
{
...
BoardListFragment
...
BoardListFragment
}
}
...
...
app/assets/javascripts/boards/stores/actions.js
View file @
02d8146f
import
Cookies
from
'
js-cookie
'
;
import
Cookies
from
'
js-cookie
'
;
import
{
sortBy
,
pick
}
from
'
lodash
'
;
import
{
pick
}
from
'
lodash
'
;
import
createFlash
from
'
~/flash
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
createGqClient
,
{
fetchPolicies
}
from
'
~/lib/graphql
'
;
import
createGqClient
,
{
fetchPolicies
}
from
'
~/lib/graphql
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
BoardType
,
ListType
,
inactiveId
}
from
'
~/boards/constants
'
;
import
{
BoardType
,
ListType
,
inactiveId
}
from
'
~/boards/constants
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
{
formatListIssues
,
fullBoardId
,
formatListsPageInfo
}
from
'
../boards_util
'
;
import
{
formatBoardLists
,
formatListIssues
,
fullBoardId
,
formatListsPageInfo
,
}
from
'
../boards_util
'
;
import
boardStore
from
'
~/boards/stores/boards_store
'
;
import
boardStore
from
'
~/boards/stores/boards_store
'
;
import
listsIssuesQuery
from
'
../queries/lists_issues.query.graphql
'
;
import
listsIssuesQuery
from
'
../queries/lists_issues.query.graphql
'
;
...
@@ -71,38 +75,29 @@ export default {
...
@@ -71,38 +75,29 @@ export default {
variables
,
variables
,
})
})
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
let
{
lists
}
=
data
[
boardType
]?.
board
;
const
{
lists
}
=
data
[
boardType
]?.
board
;
// Temporarily using positioning logic from boardStore
commit
(
types
.
RECEIVE_BOARD_LISTS_SUCCESS
,
formatBoardLists
(
lists
));
lists
=
lists
.
nodes
.
map
(
list
=>
boardStore
.
updateListPosition
({
...
list
,
doNotFetchIssues
:
true
,
}),
);
commit
(
types
.
RECEIVE_BOARD_LISTS_SUCCESS
,
sortBy
(
lists
,
'
position
'
));
// Backlog list needs to be created if it doesn't exist
// Backlog list needs to be created if it doesn't exist
if
(
!
lists
.
find
(
l
=>
l
.
t
ype
===
ListType
.
backlog
))
{
if
(
!
lists
.
nodes
.
find
(
l
=>
l
.
listT
ype
===
ListType
.
backlog
))
{
dispatch
(
'
createList
'
,
{
backlog
:
true
});
dispatch
(
'
createList
'
,
{
backlog
:
true
});
}
}
dispatch
(
'
showWelcomeList
'
);
dispatch
(
'
showWelcomeList
'
);
})
})
.
catch
(()
=>
{
.
catch
(()
=>
commit
(
types
.
RECEIVE_BOARD_LISTS_FAILURE
));
createFlash
(
__
(
'
An error occurred while fetching the board lists. Please reload the page.
'
),
);
});
},
},
// This action only supports backlog list creation at this stage
createList
:
({
state
,
commit
,
dispatch
},
{
backlog
,
labelId
,
milestoneId
,
assigneeId
})
=>
{
// Future iterations will add the ability to create other list types
createList
:
({
state
,
commit
,
dispatch
},
{
backlog
=
false
})
=>
{
const
{
boardId
}
=
state
.
endpoints
;
const
{
boardId
}
=
state
.
endpoints
;
gqlClient
gqlClient
.
mutate
({
.
mutate
({
mutation
:
createBoardListMutation
,
mutation
:
createBoardListMutation
,
variables
:
{
variables
:
{
boardId
:
fullBoardId
(
boardId
),
boardId
:
fullBoardId
(
boardId
),
backlog
,
backlog
,
labelId
,
milestoneId
,
assigneeId
,
},
},
})
})
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
...
@@ -113,16 +108,15 @@ export default {
...
@@ -113,16 +108,15 @@ export default {
dispatch
(
'
addList
'
,
list
);
dispatch
(
'
addList
'
,
list
);
}
}
})
})
.
catch
(()
=>
{
.
catch
(()
=>
commit
(
types
.
CREATE_LIST_FAILURE
));
commit
(
types
.
CREATE_LIST_FAILURE
);
});
},
},
addList
:
({
state
,
commit
},
list
)
=>
{
addList
:
({
commit
},
list
)
=>
{
const
lists
=
state
.
boardLists
;
// Temporarily using positioning logic from boardStore
// Temporarily using positioning logic from boardStore
lists
.
push
(
boardStore
.
updateListPosition
({
...
list
,
doNotFetchIssues
:
true
}));
commit
(
commit
(
types
.
RECEIVE_BOARD_LISTS_SUCCESS
,
sortBy
(
lists
,
'
position
'
));
types
.
RECEIVE_ADD_LIST_SUCCESS
,
boardStore
.
updateListPosition
({
...
list
,
doNotFetchIssues
:
true
}),
);
},
},
showWelcomeList
:
({
state
,
dispatch
})
=>
{
showWelcomeList
:
({
state
,
dispatch
})
=>
{
...
@@ -130,7 +124,9 @@ export default {
...
@@ -130,7 +124,9 @@ export default {
return
;
return
;
}
}
if
(
if
(
state
.
boardLists
.
find
(
list
=>
list
.
type
!==
ListType
.
backlog
&&
list
.
type
!==
ListType
.
closed
)
Object
.
entries
(
state
.
boardLists
).
find
(
([,
list
])
=>
list
.
type
!==
ListType
.
backlog
&&
list
.
type
!==
ListType
.
closed
,
)
)
{
)
{
return
;
return
;
}
}
...
@@ -152,13 +148,16 @@ export default {
...
@@ -152,13 +148,16 @@ export default {
notImplemented
();
notImplemented
();
},
},
moveList
:
({
state
,
commit
,
dispatch
},
{
listId
,
newIndex
,
adjustmentValue
})
=>
{
moveList
:
(
{
state
,
commit
,
dispatch
},
{
listId
,
replacedListId
,
newIndex
,
adjustmentValue
},
)
=>
{
const
{
boardLists
}
=
state
;
const
{
boardLists
}
=
state
;
const
backupList
=
[...
boardLists
]
;
const
backupList
=
{
...
boardLists
}
;
const
movedList
=
boardLists
.
find
(({
id
})
=>
id
===
listId
)
;
const
movedList
=
boardLists
[
listId
]
;
const
newPosition
=
newIndex
-
1
;
const
newPosition
=
newIndex
-
1
;
const
listAtNewIndex
=
boardLists
[
newIndex
];
const
listAtNewIndex
=
boardLists
[
replacedListId
];
movedList
.
position
=
newPosition
;
movedList
.
position
=
newPosition
;
listAtNewIndex
.
position
+=
adjustmentValue
;
listAtNewIndex
.
position
+=
adjustmentValue
;
...
...
app/assets/javascripts/boards/stores/getters.js
View file @
02d8146f
import
{
find
}
from
'
lodash
'
;
import
{
inactiveId
}
from
'
../constants
'
;
import
{
inactiveId
}
from
'
../constants
'
;
export
default
{
export
default
{
...
@@ -22,4 +23,16 @@ export default {
...
@@ -22,4 +23,16 @@ export default {
getActiveIssue
:
state
=>
{
getActiveIssue
:
state
=>
{
return
state
.
issues
[
state
.
activeId
]
||
{};
return
state
.
issues
[
state
.
activeId
]
||
{};
},
},
getListByLabelId
:
state
=>
labelId
=>
{
return
find
(
state
.
boardLists
,
l
=>
l
.
label
?.
id
===
labelId
);
},
getListByTitle
:
state
=>
title
=>
{
return
find
(
state
.
boardLists
,
l
=>
l
.
title
===
title
);
},
shouldUseGraphQL
:
()
=>
{
return
gon
?.
features
?.
graphqlBoardLists
;
},
};
};
app/assets/javascripts/boards/stores/mutation_types.js
View file @
02d8146f
...
@@ -3,6 +3,7 @@ export const SET_FILTERS = 'SET_FILTERS';
...
@@ -3,6 +3,7 @@ export const SET_FILTERS = 'SET_FILTERS';
export
const
CREATE_LIST_SUCCESS
=
'
CREATE_LIST_SUCCESS
'
;
export
const
CREATE_LIST_SUCCESS
=
'
CREATE_LIST_SUCCESS
'
;
export
const
CREATE_LIST_FAILURE
=
'
CREATE_LIST_FAILURE
'
;
export
const
CREATE_LIST_FAILURE
=
'
CREATE_LIST_FAILURE
'
;
export
const
RECEIVE_BOARD_LISTS_SUCCESS
=
'
RECEIVE_BOARD_LISTS_SUCCESS
'
;
export
const
RECEIVE_BOARD_LISTS_SUCCESS
=
'
RECEIVE_BOARD_LISTS_SUCCESS
'
;
export
const
RECEIVE_BOARD_LISTS_FAILURE
=
'
RECEIVE_BOARD_LISTS_FAILURE
'
;
export
const
SHOW_PROMOTION_LIST
=
'
SHOW_PROMOTION_LIST
'
;
export
const
SHOW_PROMOTION_LIST
=
'
SHOW_PROMOTION_LIST
'
;
export
const
REQUEST_ADD_LIST
=
'
REQUEST_ADD_LIST
'
;
export
const
REQUEST_ADD_LIST
=
'
REQUEST_ADD_LIST
'
;
export
const
RECEIVE_ADD_LIST_SUCCESS
=
'
RECEIVE_ADD_LIST_SUCCESS
'
;
export
const
RECEIVE_ADD_LIST_SUCCESS
=
'
RECEIVE_ADD_LIST_SUCCESS
'
;
...
...
app/assets/javascripts/boards/stores/mutations.js
View file @
02d8146f
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
{
sortBy
,
pull
,
union
}
from
'
lodash
'
;
import
{
pull
,
union
}
from
'
lodash
'
;
import
{
formatIssue
,
moveIssueListHelper
}
from
'
../boards_util
'
;
import
{
formatIssue
,
moveIssueListHelper
}
from
'
../boards_util
'
;
import
*
as
mutationTypes
from
'
./mutation_types
'
;
import
*
as
mutationTypes
from
'
./mutation_types
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
...
@@ -10,16 +10,10 @@ const notImplemented = () => {
...
@@ -10,16 +10,10 @@ const notImplemented = () => {
throw
new
Error
(
'
Not implemented!
'
);
throw
new
Error
(
'
Not implemented!
'
);
};
};
const
getListById
=
({
state
,
listId
})
=>
{
const
listIndex
=
state
.
boardLists
.
findIndex
(
l
=>
l
.
id
===
listId
);
const
list
=
state
.
boardLists
[
listIndex
];
return
{
listIndex
,
list
};
};
export
const
removeIssueFromList
=
({
state
,
listId
,
issueId
})
=>
{
export
const
removeIssueFromList
=
({
state
,
listId
,
issueId
})
=>
{
Vue
.
set
(
state
.
issuesByListId
,
listId
,
pull
(
state
.
issuesByListId
[
listId
],
issueId
));
Vue
.
set
(
state
.
issuesByListId
,
listId
,
pull
(
state
.
issuesByListId
[
listId
],
issueId
));
const
{
listIndex
,
list
}
=
getListById
({
state
,
listId
})
;
const
list
=
state
.
boardLists
[
listId
]
;
Vue
.
set
(
state
.
boardLists
,
listI
ndex
,
{
...
list
,
issuesSize
:
list
.
issuesSize
-
1
});
Vue
.
set
(
state
.
boardLists
,
listI
d
,
{
...
list
,
issuesSize
:
list
.
issuesSize
-
1
});
};
};
export
const
addIssueToList
=
({
state
,
listId
,
issueId
,
moveBeforeId
,
moveAfterId
,
atIndex
})
=>
{
export
const
addIssueToList
=
({
state
,
listId
,
issueId
,
moveBeforeId
,
moveAfterId
,
atIndex
})
=>
{
...
@@ -32,8 +26,8 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter
...
@@ -32,8 +26,8 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter
}
}
listIssues
.
splice
(
newIndex
,
0
,
issueId
);
listIssues
.
splice
(
newIndex
,
0
,
issueId
);
Vue
.
set
(
state
.
issuesByListId
,
listId
,
listIssues
);
Vue
.
set
(
state
.
issuesByListId
,
listId
,
listIssues
);
const
{
listIndex
,
list
}
=
getListById
({
state
,
listId
})
;
const
list
=
state
.
boardLists
[
listId
]
;
Vue
.
set
(
state
.
boardLists
,
listI
ndex
,
{
...
list
,
issuesSize
:
list
.
issuesSize
+
1
});
Vue
.
set
(
state
.
boardLists
,
listI
d
,
{
...
list
,
issuesSize
:
list
.
issuesSize
+
1
});
};
};
export
default
{
export
default
{
...
@@ -49,6 +43,12 @@ export default {
...
@@ -49,6 +43,12 @@ export default {
state
.
boardLists
=
lists
;
state
.
boardLists
=
lists
;
},
},
[
mutationTypes
.
RECEIVE_BOARD_LISTS_FAILURE
]:
state
=>
{
state
.
error
=
s__
(
'
Boards|An error occurred while fetching the board lists. Please reload the page.
'
,
);
},
[
mutationTypes
.
SET_ACTIVE_ID
](
state
,
{
id
,
sidebarType
})
{
[
mutationTypes
.
SET_ACTIVE_ID
](
state
,
{
id
,
sidebarType
})
{
state
.
activeId
=
id
;
state
.
activeId
=
id
;
state
.
sidebarType
=
sidebarType
;
state
.
sidebarType
=
sidebarType
;
...
@@ -66,8 +66,8 @@ export default {
...
@@ -66,8 +66,8 @@ export default {
notImplemented
();
notImplemented
();
},
},
[
mutationTypes
.
RECEIVE_ADD_LIST_SUCCESS
]:
()
=>
{
[
mutationTypes
.
RECEIVE_ADD_LIST_SUCCESS
]:
(
state
,
list
)
=>
{
notImplemented
(
);
Vue
.
set
(
state
.
boardLists
,
list
.
id
,
list
);
},
},
[
mutationTypes
.
RECEIVE_ADD_LIST_ERROR
]:
()
=>
{
[
mutationTypes
.
RECEIVE_ADD_LIST_ERROR
]:
()
=>
{
...
@@ -76,10 +76,8 @@ export default {
...
@@ -76,10 +76,8 @@ export default {
[
mutationTypes
.
MOVE_LIST
]:
(
state
,
{
movedList
,
listAtNewIndex
})
=>
{
[
mutationTypes
.
MOVE_LIST
]:
(
state
,
{
movedList
,
listAtNewIndex
})
=>
{
const
{
boardLists
}
=
state
;
const
{
boardLists
}
=
state
;
const
movedListIndex
=
state
.
boardLists
.
findIndex
(
l
=>
l
.
id
===
movedList
.
id
);
Vue
.
set
(
boardLists
,
movedList
.
id
,
movedList
);
Vue
.
set
(
boardLists
,
movedListIndex
,
movedList
);
Vue
.
set
(
boardLists
,
listAtNewIndex
.
id
,
listAtNewIndex
);
Vue
.
set
(
boardLists
,
movedListIndex
.
position
+
1
,
listAtNewIndex
);
Vue
.
set
(
state
,
'
boardLists
'
,
sortBy
(
boardLists
,
'
position
'
));
},
},
[
mutationTypes
.
UPDATE_LIST_FAILURE
]:
(
state
,
backupList
)
=>
{
[
mutationTypes
.
UPDATE_LIST_FAILURE
]:
(
state
,
backupList
)
=>
{
...
@@ -156,8 +154,8 @@ export default {
...
@@ -156,8 +154,8 @@ export default {
state
,
state
,
{
originalIssue
,
fromListId
,
toListId
,
moveBeforeId
,
moveAfterId
},
{
originalIssue
,
fromListId
,
toListId
,
moveBeforeId
,
moveAfterId
},
)
=>
{
)
=>
{
const
fromList
=
state
.
boardLists
.
find
(
l
=>
l
.
id
===
fromListId
)
;
const
fromList
=
state
.
boardLists
[
fromListId
]
;
const
toList
=
state
.
boardLists
.
find
(
l
=>
l
.
id
===
toListId
)
;
const
toList
=
state
.
boardLists
[
toListId
]
;
const
issue
=
moveIssueListHelper
(
originalIssue
,
fromList
,
toList
);
const
issue
=
moveIssueListHelper
(
originalIssue
,
fromList
,
toList
);
Vue
.
set
(
state
.
issues
,
issue
.
id
,
issue
);
Vue
.
set
(
state
.
issues
,
issue
.
id
,
issue
);
...
...
app/assets/javascripts/boards/stores/state.js
View file @
02d8146f
...
@@ -8,7 +8,7 @@ export default () => ({
...
@@ -8,7 +8,7 @@ export default () => ({
isShowingLabels
:
true
,
isShowingLabels
:
true
,
activeId
:
inactiveId
,
activeId
:
inactiveId
,
sidebarType
:
''
,
sidebarType
:
''
,
boardLists
:
[]
,
boardLists
:
{}
,
listsFlags
:
{},
listsFlags
:
{},
issuesByListId
:
{},
issuesByListId
:
{},
pageInfoByListId
:
{},
pageInfoByListId
:
{},
...
...
app/serializers/label_entity.rb
View file @
02d8146f
...
@@ -7,7 +7,7 @@ class LabelEntity < Grape::Entity
...
@@ -7,7 +7,7 @@ class LabelEntity < Grape::Entity
expose
:color
expose
:color
expose
:description
expose
:description
expose
:group_id
expose
:group_id
expose
:project_id
expose
:project_id
,
if:
->
(
label
,
_
)
{
!
label
.
is_a?
(
GlobalLabel
)
}
expose
:template
expose
:template
expose
:text_color
expose
:text_color
expose
:created_at
expose
:created_at
...
...
app/serializers/label_serializer.rb
View file @
02d8146f
...
@@ -4,6 +4,6 @@ class LabelSerializer < BaseSerializer
...
@@ -4,6 +4,6 @@ class LabelSerializer < BaseSerializer
entity
LabelEntity
entity
LabelEntity
def
represent_appearance
(
resource
)
def
represent_appearance
(
resource
)
represent
(
resource
,
{
only:
[
:id
,
:title
,
:color
,
:text_color
]
})
represent
(
resource
,
{
only:
[
:id
,
:title
,
:color
,
:text_color
,
:project_id
]
})
end
end
end
end
ee/app/assets/javascripts/boards/boards_util.js
View file @
02d8146f
...
@@ -6,7 +6,17 @@ export function fullEpicId(epicId) {
...
@@ -6,7 +6,17 @@ export function fullEpicId(epicId) {
return
`gid://gitlab/Epic/
${
epicId
}
`
;
return
`gid://gitlab/Epic/
${
epicId
}
`
;
}
}
export
function
fullMilestoneId
(
milestoneId
)
{
return
`gid://gitlab/Milestone/
${
milestoneId
}
`
;
}
export
function
fullUserId
(
userId
)
{
return
`gid://gitlab/User/
${
userId
}
`
;
}
export
default
{
export
default
{
getMilestone
,
getMilestone
,
fullEpicId
,
fullEpicId
,
fullMilestoneId
,
fullUserId
,
};
};
ee/app/assets/javascripts/boards/components/assignees_list_slector.js
→
ee/app/assets/javascripts/boards/components/assignees_list_s
e
lector.js
View file @
02d8146f
File moved
ee/app/assets/javascripts/boards/components/boards_list_selector/index.js
View file @
02d8146f
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
import
vuexStore
from
'
~/boards/stores
'
;
import
ListContainer
from
'
./list_container.vue
'
;
import
ListContainer
from
'
./list_container.vue
'
;
import
{
fullMilestoneId
,
fullUserId
}
from
'
../../boards_util
'
;
export
default
Vue
.
extend
({
export
default
Vue
.
extend
({
components
:
{
components
:
{
...
@@ -20,6 +22,7 @@ export default Vue.extend({
...
@@ -20,6 +22,7 @@ export default Vue.extend({
return
{
return
{
loading
:
true
,
loading
:
true
,
store
:
boardsStore
,
store
:
boardsStore
,
vuexStore
,
};
};
},
},
mounted
()
{
mounted
()
{
...
@@ -46,19 +49,33 @@ export default Vue.extend({
...
@@ -46,19 +49,33 @@ export default Vue.extend({
return
foundName
||
username
.
indexOf
(
query
)
>
-
1
;
return
foundName
||
username
.
indexOf
(
query
)
>
-
1
;
});
});
},
},
handleItemClick
(
item
)
{
prepareListObject
(
item
)
{
if
(
!
this
.
store
.
findList
(
'
title
'
,
item
.
name
))
{
const
list
=
{
const
list
=
{
title
:
item
.
name
,
title
:
item
.
name
,
position
:
this
.
store
.
state
.
lists
.
length
-
2
,
position
:
this
.
store
.
state
.
lists
.
length
-
2
,
list_type
:
this
.
listType
,
list_type
:
this
.
listType
,
};
};
if
(
this
.
listType
===
'
milestones
'
)
{
list
.
milestone
=
item
;
}
else
if
(
this
.
listType
===
'
assignees
'
)
{
list
.
user
=
item
;
}
return
list
;
},
handleItemClick
(
item
)
{
if
(
this
.
vuexStore
.
getters
.
shouldUseGraphQL
&&
!
this
.
vuexStore
.
getters
.
getListByTitle
(
item
.
title
)
)
{
if
(
this
.
listType
===
'
milestones
'
)
{
if
(
this
.
listType
===
'
milestones
'
)
{
list
.
milestone
=
item
;
this
.
vuexStore
.
dispatch
(
'
createList
'
,
{
milestoneId
:
fullMilestoneId
(
item
.
id
)
})
;
}
else
if
(
this
.
listType
===
'
assignees
'
)
{
}
else
if
(
this
.
listType
===
'
assignees
'
)
{
list
.
user
=
item
;
this
.
vuexStore
.
dispatch
(
'
createList
'
,
{
assigneeId
:
fullUserId
(
item
.
id
)
})
;
}
}
}
else
if
(
!
this
.
store
.
findList
(
'
title
'
,
item
.
title
))
{
const
list
=
this
.
prepareListObject
(
item
);
this
.
store
.
new
(
list
);
this
.
store
.
new
(
list
);
}
}
...
...
ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
View file @
02d8146f
...
@@ -73,11 +73,13 @@ export default {
...
@@ -73,11 +73,13 @@ export default {
methods
:
{
methods
:
{
...
mapActions
([
'
moveList
'
,
'
fetchIssuesForList
'
]),
...
mapActions
([
'
moveList
'
,
'
fetchIssuesForList
'
]),
handleDragOnEnd
(
params
)
{
handleDragOnEnd
(
params
)
{
const
{
newIndex
,
oldIndex
,
item
}
=
params
;
const
{
newIndex
,
oldIndex
,
item
,
to
}
=
params
;
const
{
listId
}
=
item
.
dataset
;
const
{
listId
}
=
item
.
dataset
;
const
replacedListId
=
to
.
children
[
newIndex
].
dataset
.
listId
;
this
.
moveList
({
this
.
moveList
({
listId
,
listId
,
replacedListId
,
newIndex
,
newIndex
,
adjustmentValue
:
newIndex
<
oldIndex
?
1
:
-
1
,
adjustmentValue
:
newIndex
<
oldIndex
?
1
:
-
1
,
});
});
...
...
ee/app/assets/javascripts/boards/components/new_list_dropdown.js
View file @
02d8146f
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
initNewListDropdown
from
'
~/boards/components/new_list_dropdown
'
;
import
initNewListDropdown
from
'
~/boards/components/new_list_dropdown
'
;
import
AssigneeList
from
'
./assignees_list_slector
'
;
import
AssigneeList
from
'
./assignees_list_s
e
lector
'
;
import
MilestoneList
from
'
./milestone_list_selector
'
;
import
MilestoneList
from
'
./milestone_list_selector
'
;
const
handleDropdownHide
=
e
=>
{
const
handleDropdownHide
=
e
=>
{
...
@@ -12,7 +12,7 @@ const handleDropdownHide = e => {
...
@@ -12,7 +12,7 @@ const handleDropdownHide = e => {
};
};
let
assigneeList
;
let
assigneeList
;
let
milstoneList
;
let
mil
e
stoneList
;
const
handleDropdownTabClick
=
e
=>
{
const
handleDropdownTabClick
=
e
=>
{
const
$addListEl
=
$
(
'
#js-add-list
'
);
const
$addListEl
=
$
(
'
#js-add-list
'
);
...
@@ -21,8 +21,8 @@ const handleDropdownTabClick = e => {
...
@@ -21,8 +21,8 @@ const handleDropdownTabClick = e => {
assigneeList
=
AssigneeList
();
assigneeList
=
AssigneeList
();
}
}
if
(
e
.
target
.
dataset
.
action
===
'
tab-milestones
'
&&
!
milstoneList
)
{
if
(
e
.
target
.
dataset
.
action
===
'
tab-milestones
'
&&
!
mil
e
stoneList
)
{
milstoneList
=
MilestoneList
();
mil
e
stoneList
=
MilestoneList
();
}
}
};
};
...
...
ee/app/assets/javascripts/boards/stores/actions.js
View file @
02d8146f
import
{
sortBy
,
pick
}
from
'
lodash
'
;
import
{
pick
}
from
'
lodash
'
;
import
Cookies
from
'
js-cookie
'
;
import
Cookies
from
'
js-cookie
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
...
@@ -10,7 +10,12 @@ import { EpicFilterType } from '../constants';
...
@@ -10,7 +10,12 @@ import { EpicFilterType } from '../constants';
import
boardsStoreEE
from
'
./boards_store_ee
'
;
import
boardsStoreEE
from
'
./boards_store_ee
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
{
fullEpicId
}
from
'
../boards_util
'
;
import
{
fullEpicId
}
from
'
../boards_util
'
;
import
{
formatListIssues
,
formatListsPageInfo
,
fullBoardId
}
from
'
~/boards/boards_util
'
;
import
{
formatBoardLists
,
formatListIssues
,
formatListsPageInfo
,
fullBoardId
,
}
from
'
~/boards/boards_util
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
eventHub
from
'
~/boards/eventhub
'
;
import
eventHub
from
'
~/boards/eventhub
'
;
...
@@ -112,11 +117,7 @@ export default {
...
@@ -112,11 +117,7 @@ export default {
commit
(
types
.
RECEIVE_EPICS_SUCCESS
,
epicsFormatted
);
commit
(
types
.
RECEIVE_EPICS_SUCCESS
,
epicsFormatted
);
}
else
{
}
else
{
if
(
lists
)
{
if
(
lists
)
{
let
boardLists
=
lists
.
nodes
.
map
(
list
=>
commit
(
types
.
RECEIVE_BOARD_LISTS_SUCCESS
,
formatBoardLists
(
lists
));
boardsStore
.
updateListPosition
({
...
list
,
doNotFetchIssues
:
true
}),
);
boardLists
=
sortBy
([...
boardLists
],
'
position
'
);
commit
(
types
.
RECEIVE_BOARD_LISTS_SUCCESS
,
boardLists
);
}
}
if
(
epicsFormatted
)
{
if
(
epicsFormatted
)
{
...
...
ee/app/assets/javascripts/boards/stores/getters.js
View file @
02d8146f
...
@@ -14,4 +14,11 @@ export default {
...
@@ -14,4 +14,11 @@ export default {
getEpicById
:
state
=>
epicId
=>
{
getEpicById
:
state
=>
epicId
=>
{
return
state
.
epics
.
find
(
epic
=>
epic
.
id
===
epicId
);
return
state
.
epics
.
find
(
epic
=>
epic
.
id
===
epicId
);
},
},
shouldUseGraphQL
:
state
=>
{
return
(
(
gon
?.
features
?.
boardsWithSwimlanes
&&
state
.
isShowingEpicsSwimlanes
)
||
gon
?.
features
?.
graphqlBoardLists
);
},
};
};
ee/app/assets/javascripts/boards/stores/mutations.js
View file @
02d8146f
...
@@ -141,8 +141,8 @@ export default {
...
@@ -141,8 +141,8 @@ export default {
state
,
state
,
{
originalIssue
,
fromListId
,
toListId
,
moveBeforeId
,
moveAfterId
,
epicId
},
{
originalIssue
,
fromListId
,
toListId
,
moveBeforeId
,
moveAfterId
,
epicId
},
)
=>
{
)
=>
{
const
fromList
=
state
.
boardLists
.
find
(
l
=>
l
.
id
===
fromListId
)
;
const
fromList
=
state
.
boardLists
[
fromListId
]
;
const
toList
=
state
.
boardLists
.
find
(
l
=>
l
.
id
===
toListId
)
;
const
toList
=
state
.
boardLists
[
toListId
]
;
const
issue
=
moveIssueListHelper
(
originalIssue
,
fromList
,
toList
);
const
issue
=
moveIssueListHelper
(
originalIssue
,
fromList
,
toList
);
...
...
ee/spec/frontend/boards/components/board_list_selector/board_list_selector_spec.js
View file @
02d8146f
...
@@ -7,8 +7,15 @@ import { mockAssigneesList } from 'jest/boards/mock_data';
...
@@ -7,8 +7,15 @@ import { mockAssigneesList } from 'jest/boards/mock_data';
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
import
boardsStore
from
'
~/boards/stores/boards_store
'
;
import
{
createStore
}
from
'
~/boards/stores
'
;
describe
(
'
BoardListSelector
'
,
()
=>
{
describe
(
'
BoardListSelector
'
,
()
=>
{
global
.
gon
.
features
=
{
...(
global
.
gon
.
features
||
{}),
boardsWithSwimlanes
:
false
,
graphqlBoardLists
:
false
,
};
const
dummyEndpoint
=
`
${
TEST_HOST
}
/users.json`
;
const
dummyEndpoint
=
`
${
TEST_HOST
}
/users.json`
;
const
createComponent
=
()
=>
const
createComponent
=
()
=>
...
@@ -28,6 +35,7 @@ describe('BoardListSelector', () => {
...
@@ -28,6 +35,7 @@ describe('BoardListSelector', () => {
setFixtures
(
'
<div class="flash-container"></div>
'
);
setFixtures
(
'
<div class="flash-container"></div>
'
);
vm
=
createComponent
();
vm
=
createComponent
();
vm
.
vuexStore
=
createStore
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -86,8 +94,8 @@ describe('BoardListSelector', () => {
...
@@ -86,8 +94,8 @@ describe('BoardListSelector', () => {
});
});
describe
(
'
handleItemClick
'
,
()
=>
{
describe
(
'
handleItemClick
'
,
()
=>
{
it
(
'
creates new list in a store instance
'
,
()
=>
{
it
(
'
graphqlBoardLists FF off -
creates new list in a store instance
'
,
()
=>
{
jest
.
spyOn
(
vm
.
store
,
'
new
'
).
mock
Implementation
(()
=>
{});
jest
.
spyOn
(
vm
.
store
,
'
new
'
).
mock
ReturnValue
(
{});
const
assignee
=
mockAssigneesList
[
0
];
const
assignee
=
mockAssigneesList
[
0
];
expect
(
vm
.
store
.
findList
(
'
title
'
,
assignee
.
name
)).
not
.
toBeDefined
();
expect
(
vm
.
store
.
findList
(
'
title
'
,
assignee
.
name
)).
not
.
toBeDefined
();
...
@@ -95,6 +103,20 @@ describe('BoardListSelector', () => {
...
@@ -95,6 +103,20 @@ describe('BoardListSelector', () => {
expect
(
vm
.
store
.
new
).
toHaveBeenCalledWith
(
expect
.
any
(
Object
));
expect
(
vm
.
store
.
new
).
toHaveBeenCalledWith
(
expect
.
any
(
Object
));
});
});
it
(
'
graphqlBoardLists FF on - creates new list in a store instance
'
,
()
=>
{
global
.
gon
.
features
.
graphqlBoardLists
=
true
;
jest
.
spyOn
(
vm
.
vuexStore
,
'
dispatch
'
).
mockReturnValue
({});
const
assignee
=
mockAssigneesList
[
0
];
expect
(
vm
.
vuexStore
.
getters
.
getListByTitle
(
assignee
.
name
)).
not
.
toBeDefined
();
vm
.
handleItemClick
(
assignee
);
expect
(
vm
.
vuexStore
.
dispatch
).
toHaveBeenCalledWith
(
'
createList
'
,
{
assigneeId
:
'
gid://gitlab/User/2
'
,
});
});
});
});
});
});
});
});
ee/spec/frontend/boards/stores/mutations_spec.js
View file @
02d8146f
import
mutations
from
'
ee/boards/stores/mutations
'
;
import
mutations
from
'
ee/boards/stores/mutations
'
;
import
{
import
{
mockLists
,
mockIssue
,
mockIssue
,
mockIssue2
,
mockIssue2
,
mockEpics
,
mockEpics
,
...
@@ -18,10 +17,15 @@ const expectNotImplemented = action => {
...
@@ -18,10 +17,15 @@ const expectNotImplemented = action => {
const
epicId
=
mockEpic
.
id
;
const
epicId
=
mockEpic
.
id
;
const
initialBoardListsState
=
{
'
gid://gitlab/List/1
'
:
mockListsWithModel
[
0
],
'
gid://gitlab/List/2
'
:
mockListsWithModel
[
1
],
};
let
state
=
{
let
state
=
{
issuesByListId
:
{},
issuesByListId
:
{},
issues
:
{},
issues
:
{},
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
epicsFlags
:
{
epicsFlags
:
{
[
epicId
]:
{
isLoading
:
true
},
[
epicId
]:
{
isLoading
:
true
},
},
},
...
@@ -182,10 +186,10 @@ describe('RECEIVE_BOARD_LISTS_SUCCESS', () => {
...
@@ -182,10 +186,10 @@ describe('RECEIVE_BOARD_LISTS_SUCCESS', () => {
boardLists
:
{},
boardLists
:
{},
};
};
mutations
.
RECEIVE_BOARD_LISTS_SUCCESS
(
state
,
mockLists
);
mutations
.
RECEIVE_BOARD_LISTS_SUCCESS
(
state
,
initialBoardListsState
);
expect
(
state
.
epicsSwimlanesFetchInProgress
).
toBe
(
false
);
expect
(
state
.
epicsSwimlanesFetchInProgress
).
toBe
(
false
);
expect
(
state
.
boardLists
).
toEqual
(
mockLists
);
expect
(
state
.
boardLists
).
toEqual
(
initialBoardListsState
);
});
});
});
});
...
@@ -273,7 +277,6 @@ describe('MOVE_ISSUE', () => {
...
@@ -273,7 +277,6 @@ describe('MOVE_ISSUE', () => {
state
=
{
state
=
{
...
state
,
...
state
,
issuesByListId
:
listIssues
,
issuesByListId
:
listIssues
,
boardLists
:
mockListsWithModel
,
issues
,
issues
,
};
};
});
});
...
...
locale/gitlab.pot
View file @
02d8146f
...
@@ -2851,9 +2851,6 @@ msgstr ""
...
@@ -2851,9 +2851,6 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
msgstr ""
msgid "An error occurred while fetching the board lists. Please reload the page."
msgstr ""
msgid "An error occurred while fetching the board lists. Please try again."
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
msgstr ""
...
@@ -4185,6 +4182,9 @@ msgstr ""
...
@@ -4185,6 +4182,9 @@ msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
msgstr ""
msgstr ""
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
msgstr ""
msgstr ""
...
...
spec/frontend/boards/stores/actions_spec.js
View file @
02d8146f
...
@@ -177,16 +177,26 @@ describe('createList', () => {
...
@@ -177,16 +177,26 @@ describe('createList', () => {
describe
(
'
moveList
'
,
()
=>
{
describe
(
'
moveList
'
,
()
=>
{
it
(
'
should commit MOVE_LIST mutation and dispatch updateList action
'
,
done
=>
{
it
(
'
should commit MOVE_LIST mutation and dispatch updateList action
'
,
done
=>
{
const
initialBoardListsState
=
{
'
gid://gitlab/List/1
'
:
mockListsWithModel
[
0
],
'
gid://gitlab/List/2
'
:
mockListsWithModel
[
1
],
};
const
state
=
{
const
state
=
{
endpoints
:
{
fullPath
:
'
gitlab-org
'
,
boardId
:
'
1
'
},
endpoints
:
{
fullPath
:
'
gitlab-org
'
,
boardId
:
'
1
'
},
boardType
:
'
group
'
,
boardType
:
'
group
'
,
disabled
:
false
,
disabled
:
false
,
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
};
};
testAction
(
testAction
(
actions
.
moveList
,
actions
.
moveList
,
{
listId
:
'
gid://gitlab/List/1
'
,
newIndex
:
1
,
adjustmentValue
:
1
},
{
listId
:
'
gid://gitlab/List/1
'
,
replacedListId
:
'
gid://gitlab/List/2
'
,
newIndex
:
1
,
adjustmentValue
:
1
,
},
state
,
state
,
[
[
{
{
...
@@ -197,7 +207,11 @@ describe('moveList', () => {
...
@@ -197,7 +207,11 @@ describe('moveList', () => {
[
[
{
{
type
:
'
updateList
'
,
type
:
'
updateList
'
,
payload
:
{
listId
:
'
gid://gitlab/List/1
'
,
position
:
0
,
backupList
:
mockListsWithModel
},
payload
:
{
listId
:
'
gid://gitlab/List/1
'
,
position
:
0
,
backupList
:
initialBoardListsState
,
},
},
},
],
],
done
,
done
,
...
...
spec/frontend/boards/stores/getters_spec.js
View file @
02d8146f
import
getters
from
'
~/boards/stores/getters
'
;
import
getters
from
'
~/boards/stores/getters
'
;
import
{
inactiveId
}
from
'
~/boards/constants
'
;
import
{
inactiveId
}
from
'
~/boards/constants
'
;
import
{
mockIssue
,
mockIssue2
,
mockIssues
,
mockIssuesByListId
,
issues
}
from
'
../mock_data
'
;
import
{
mockIssue
,
mockIssue2
,
mockIssues
,
mockIssuesByListId
,
issues
,
mockListsWithModel
,
}
from
'
../mock_data
'
;
describe
(
'
Boards - Getters
'
,
()
=>
{
describe
(
'
Boards - Getters
'
,
()
=>
{
describe
(
'
getLabelToggleState
'
,
()
=>
{
describe
(
'
getLabelToggleState
'
,
()
=>
{
...
@@ -130,4 +137,25 @@ describe('Boards - Getters', () => {
...
@@ -130,4 +137,25 @@ describe('Boards - Getters', () => {
);
);
});
});
});
});
const boardsState = {
boardLists: {
'gid://gitlab/List/1': mockListsWithModel[0],
'gid://gitlab/List/2': mockListsWithModel[1],
},
};
describe('getListByLabelId', () => {
it('returns list for a given label id', () => {
expect(getters.getListByLabelId(boardsState)('gid://gitlab/GroupLabel/121')).toEqual(
mockListsWithModel[1],
);
});
});
describe('getListByTitle', () => {
it('returns list for a given list title', () => {
expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockListsWithModel[1]);
});
});
});
});
spec/frontend/boards/stores/mutations_spec.js
View file @
02d8146f
...
@@ -2,8 +2,6 @@ import mutations from '~/boards/stores/mutations';
...
@@ -2,8 +2,6 @@ import mutations from '~/boards/stores/mutations';
import
*
as
types
from
'
~/boards/stores/mutation_types
'
;
import
*
as
types
from
'
~/boards/stores/mutation_types
'
;
import
defaultState
from
'
~/boards/stores/state
'
;
import
defaultState
from
'
~/boards/stores/state
'
;
import
{
import
{
listObj
,
listObjDuplicate
,
mockListsWithModel
,
mockListsWithModel
,
mockLists
,
mockLists
,
rawIssue
,
rawIssue
,
...
@@ -22,6 +20,11 @@ const expectNotImplemented = action => {
...
@@ -22,6 +20,11 @@ const expectNotImplemented = action => {
describe
(
'
Board Store Mutations
'
,
()
=>
{
describe
(
'
Board Store Mutations
'
,
()
=>
{
let
state
;
let
state
;
const
initialBoardListsState
=
{
'
gid://gitlab/List/1
'
:
mockListsWithModel
[
0
],
'
gid://gitlab/List/2
'
:
mockListsWithModel
[
1
],
};
beforeEach
(()
=>
{
beforeEach
(()
=>
{
state
=
defaultState
();
state
=
defaultState
();
});
});
...
@@ -56,11 +59,19 @@ describe('Board Store Mutations', () => {
...
@@ -56,11 +59,19 @@ describe('Board Store Mutations', () => {
describe
(
'
RECEIVE_BOARD_LISTS_SUCCESS
'
,
()
=>
{
describe
(
'
RECEIVE_BOARD_LISTS_SUCCESS
'
,
()
=>
{
it
(
'
Should set boardLists to state
'
,
()
=>
{
it
(
'
Should set boardLists to state
'
,
()
=>
{
const
lists
=
[
listObj
,
listObjDuplicate
];
mutations
[
types
.
RECEIVE_BOARD_LISTS_SUCCESS
](
state
,
initialBoardListsState
);
expect
(
state
.
boardLists
).
toEqual
(
initialBoardListsState
);
});
});
mutations
[
types
.
RECEIVE_BOARD_LISTS_SUCCESS
](
state
,
lists
);
describe
(
'
RECEIVE_BOARD_LISTS_FAILURE
'
,
()
=>
{
it
(
'
Should set error in state
'
,
()
=>
{
mutations
[
types
.
RECEIVE_BOARD_LISTS_FAILURE
](
state
);
expect
(
state
.
boardLists
).
toEqual
(
lists
);
expect
(
state
.
error
).
toEqual
(
'
An error occurred while fetching the board lists. Please reload the page.
'
,
);
});
});
});
});
...
@@ -95,7 +106,13 @@ describe('Board Store Mutations', () => {
...
@@ -95,7 +106,13 @@ describe('Board Store Mutations', () => {
});
});
describe
(
'
RECEIVE_ADD_LIST_SUCCESS
'
,
()
=>
{
describe
(
'
RECEIVE_ADD_LIST_SUCCESS
'
,
()
=>
{
expectNotImplemented
(
mutations
.
RECEIVE_ADD_LIST_SUCCESS
);
it
(
'
adds list to boardLists state
'
,
()
=>
{
mutations
.
RECEIVE_ADD_LIST_SUCCESS
(
state
,
mockListsWithModel
[
0
]);
expect
(
state
.
boardLists
).
toEqual
({
[
mockListsWithModel
[
0
].
id
]:
mockListsWithModel
[
0
],
});
});
});
});
describe
(
'
RECEIVE_ADD_LIST_ERROR
'
,
()
=>
{
describe
(
'
RECEIVE_ADD_LIST_ERROR
'
,
()
=>
{
...
@@ -106,7 +123,7 @@ describe('Board Store Mutations', () => {
...
@@ -106,7 +123,7 @@ describe('Board Store Mutations', () => {
it
(
'
updates boardLists state with reordered lists
'
,
()
=>
{
it
(
'
updates boardLists state with reordered lists
'
,
()
=>
{
state
=
{
state
=
{
...
state
,
...
state
,
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
};
};
mutations
.
MOVE_LIST
(
state
,
{
mutations
.
MOVE_LIST
(
state
,
{
...
@@ -114,7 +131,10 @@ describe('Board Store Mutations', () => {
...
@@ -114,7 +131,10 @@ describe('Board Store Mutations', () => {
listAtNewIndex
:
mockListsWithModel
[
1
],
listAtNewIndex
:
mockListsWithModel
[
1
],
});
});
expect
(
state
.
boardLists
).
toEqual
([
mockListsWithModel
[
1
],
mockListsWithModel
[
0
]]);
expect
(
state
.
boardLists
).
toEqual
({
'
gid://gitlab/List/2
'
:
mockListsWithModel
[
1
],
'
gid://gitlab/List/1
'
:
mockListsWithModel
[
0
],
});
});
});
});
});
...
@@ -122,13 +142,16 @@ describe('Board Store Mutations', () => {
...
@@ -122,13 +142,16 @@ describe('Board Store Mutations', () => {
it
(
'
updates boardLists state with previous order and sets error message
'
,
()
=>
{
it
(
'
updates boardLists state with previous order and sets error message
'
,
()
=>
{
state
=
{
state
=
{
...
state
,
...
state
,
boardLists
:
[
mockListsWithModel
[
1
],
mockListsWithModel
[
0
]],
boardLists
:
{
'
gid://gitlab/List/2
'
:
mockListsWithModel
[
1
],
'
gid://gitlab/List/1
'
:
mockListsWithModel
[
0
],
},
error
:
undefined
,
error
:
undefined
,
};
};
mutations
.
UPDATE_LIST_FAILURE
(
state
,
mockListsWithModel
);
mutations
.
UPDATE_LIST_FAILURE
(
state
,
initialBoardListsState
);
expect
(
state
.
boardLists
).
toEqual
(
mockListsWithModel
);
expect
(
state
.
boardLists
).
toEqual
(
initialBoardListsState
);
expect
(
state
.
error
).
toEqual
(
'
An error occurred while updating the list. Please try again.
'
);
expect
(
state
.
error
).
toEqual
(
'
An error occurred while updating the list. Please try again.
'
);
});
});
});
});
...
@@ -177,7 +200,7 @@ describe('Board Store Mutations', () => {
...
@@ -177,7 +200,7 @@ describe('Board Store Mutations', () => {
'
gid://gitlab/List/1
'
:
[],
'
gid://gitlab/List/1
'
:
[],
},
},
issues
:
{},
issues
:
{},
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
};
};
const
listPageInfo
=
{
const
listPageInfo
=
{
...
@@ -202,7 +225,7 @@ describe('Board Store Mutations', () => {
...
@@ -202,7 +225,7 @@ describe('Board Store Mutations', () => {
it
(
'
sets error message
'
,
()
=>
{
it
(
'
sets error message
'
,
()
=>
{
state
=
{
state
=
{
...
state
,
...
state
,
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
error
:
undefined
,
error
:
undefined
,
};
};
...
@@ -284,7 +307,7 @@ describe('Board Store Mutations', () => {
...
@@ -284,7 +307,7 @@ describe('Board Store Mutations', () => {
state
=
{
state
=
{
...
state
,
...
state
,
issuesByListId
:
listIssues
,
issuesByListId
:
listIssues
,
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
issues
,
issues
,
};
};
...
@@ -332,7 +355,7 @@ describe('Board Store Mutations', () => {
...
@@ -332,7 +355,7 @@ describe('Board Store Mutations', () => {
state
=
{
state
=
{
...
state
,
...
state
,
issuesByListId
:
listIssues
,
issuesByListId
:
listIssues
,
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
};
};
mutations
.
MOVE_ISSUE_FAILURE
(
state
,
{
mutations
.
MOVE_ISSUE_FAILURE
(
state
,
{
...
@@ -400,7 +423,7 @@ describe('Board Store Mutations', () => {
...
@@ -400,7 +423,7 @@ describe('Board Store Mutations', () => {
...
state
,
...
state
,
issuesByListId
:
listIssues
,
issuesByListId
:
listIssues
,
issues
,
issues
,
boardLists
:
mockListsWithModel
,
boardLists
:
initialBoardListsState
,
};
};
mutations
.
ADD_ISSUE_TO_LIST_FAILURE
(
state
,
{
list
:
mockLists
[
0
],
issue
:
mockIssue2
});
mutations
.
ADD_ISSUE_TO_LIST_FAILURE
(
state
,
{
list
:
mockLists
[
0
],
issue
:
mockIssue2
});
...
...
spec/serializers/label_serializer_spec.rb
View file @
02d8146f
...
@@ -37,11 +37,12 @@ RSpec.describe LabelSerializer do
...
@@ -37,11 +37,12 @@ RSpec.describe LabelSerializer do
subject
{
serializer
.
represent_appearance
(
resource
)
}
subject
{
serializer
.
represent_appearance
(
resource
)
}
it
'serializes only attributes used for appearance'
do
it
'serializes only attributes used for appearance'
do
expect
(
subject
.
keys
).
to
eq
([
:id
,
:title
,
:color
,
:text_color
])
expect
(
subject
.
keys
).
to
eq
([
:id
,
:title
,
:color
,
:
project_id
,
:
text_color
])
expect
(
subject
[
:id
]).
to
eq
(
resource
.
id
)
expect
(
subject
[
:id
]).
to
eq
(
resource
.
id
)
expect
(
subject
[
:title
]).
to
eq
(
resource
.
title
)
expect
(
subject
[
:title
]).
to
eq
(
resource
.
title
)
expect
(
subject
[
:color
]).
to
eq
(
resource
.
color
)
expect
(
subject
[
:color
]).
to
eq
(
resource
.
color
)
expect
(
subject
[
:text_color
]).
to
eq
(
resource
.
text_color
)
expect
(
subject
[
:text_color
]).
to
eq
(
resource
.
text_color
)
expect
(
subject
[
:project_id
]).
to
eq
(
resource
.
project_id
)
end
end
end
end
end
end
...
...
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