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
93095b50
Commit
93095b50
authored
Nov 17, 2020
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Boards - Move issue using VueX action
Refactor drag & drop issue for graphQL boards
parent
736b3160
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
139 additions
and
18 deletions
+139
-18
app/assets/javascripts/boards/components/board_column_new.vue
...assets/javascripts/boards/components/board_column_new.vue
+1
-0
app/assets/javascripts/boards/components/board_list.vue
app/assets/javascripts/boards/components/board_list.vue
+0
-2
app/assets/javascripts/boards/components/board_list_new.vue
app/assets/javascripts/boards/components/board_list_new.vue
+86
-12
spec/frontend/boards/board_list_new_spec.js
spec/frontend/boards/board_list_new_spec.js
+52
-4
No files found.
app/assets/javascripts/boards/components/board_column_new.vue
View file @
93095b50
...
...
@@ -85,6 +85,7 @@ export default {
:disabled=
"disabled"
:issues=
"listIssues"
:list=
"list"
:can-admin-list=
"canAdminList"
/>
<!-- Will be only available in EE -->
...
...
app/assets/javascripts/boards/components/board_list.vue
View file @
93095b50
...
...
@@ -6,7 +6,6 @@ import boardCard from './board_card.vue';
import
eventHub
from
'
../eventhub
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
{
sprintf
,
__
}
from
'
~/locale
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
{
deprecatedCreateFlash
as
createFlash
}
from
'
~/flash
'
;
import
{
getBoardSortableDefaultOptions
,
...
...
@@ -25,7 +24,6 @@ export default {
boardNewIssue
,
GlLoadingIcon
,
},
mixins
:
[
glFeatureFlagMixin
()],
props
:
{
disabled
:
{
type
:
Boolean
,
...
...
app/assets/javascripts/boards/components/board_list_new.vue
View file @
93095b50
<
script
>
import
Draggable
from
'
vuedraggable
'
;
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
defaultSortableConfig
from
'
~/sortable/sortable_config
'
;
import
BoardNewIssue
from
'
./board_new_issue_new.vue
'
;
import
BoardCard
from
'
./board_card.vue
'
;
import
eventHub
from
'
../eventhub
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
{
sprintf
,
__
}
from
'
~/locale
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
export
default
{
name
:
'
BoardList
'
,
...
...
@@ -15,7 +16,6 @@ export default {
BoardNewIssue
,
GlLoadingIcon
,
},
mixins
:
[
glFeatureFlagMixin
()],
props
:
{
disabled
:
{
type
:
Boolean
,
...
...
@@ -29,6 +29,11 @@ export default {
type
:
Array
,
required
:
true
,
},
canAdminList
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
data
()
{
return
{
...
...
@@ -55,12 +60,32 @@ export default {
loading
()
{
return
this
.
listsFlags
[
this
.
list
.
id
]?.
isLoading
;
},
listRef
()
{
// When list is draggable, the reference to the list needs to be accessed differently
return
this
.
canAdminList
?
this
.
$refs
.
list
.
$el
:
this
.
$refs
.
list
;
},
treeRootWrapper
()
{
return
this
.
canAdminList
?
Draggable
:
'
ul
'
;
},
treeRootOptions
()
{
const
options
=
{
...
defaultSortableConfig
,
fallbackOnBody
:
false
,
group
:
'
boards-list
'
,
tag
:
'
ul
'
,
'
ghost-class
'
:
'
board-card-drag-active
'
,
'
data-list-id
'
:
this
.
list
.
id
,
value
:
this
.
issues
,
};
return
this
.
canAdminList
?
options
:
{};
},
},
watch
:
{
filters
:
{
handler
()
{
this
.
list
.
loadingMore
=
false
;
this
.
$refs
.
list
.
scrollTop
=
0
;
this
.
listRef
.
scrollTop
=
0
;
},
deep
:
true
,
},
...
...
@@ -76,26 +101,26 @@ export default {
},
mounted
()
{
// Scroll event on list to load more
this
.
$refs
.
list
.
addEventListener
(
'
scroll
'
,
this
.
onScroll
);
this
.
listRef
.
addEventListener
(
'
scroll
'
,
this
.
onScroll
);
},
beforeDestroy
()
{
eventHub
.
$off
(
`toggle-issue-form-
${
this
.
list
.
id
}
`
,
this
.
toggleForm
);
eventHub
.
$off
(
`scroll-board-list-
${
this
.
list
.
id
}
`
,
this
.
scrollToTop
);
this
.
$refs
.
list
.
removeEventListener
(
'
scroll
'
,
this
.
onScroll
);
this
.
listRef
.
removeEventListener
(
'
scroll
'
,
this
.
onScroll
);
},
methods
:
{
...
mapActions
([
'
fetchIssuesForList
'
]),
...
mapActions
([
'
fetchIssuesForList
'
,
'
moveIssue
'
]),
listHeight
()
{
return
this
.
$refs
.
list
.
getBoundingClientRect
().
height
;
return
this
.
listRef
.
getBoundingClientRect
().
height
;
},
scrollHeight
()
{
return
this
.
$refs
.
list
.
scrollHeight
;
return
this
.
listRef
.
scrollHeight
;
},
scrollTop
()
{
return
this
.
$refs
.
list
.
scrollTop
+
this
.
listHeight
();
return
this
.
listRef
.
scrollTop
+
this
.
listHeight
();
},
scrollToTop
()
{
this
.
$refs
.
list
.
scrollTop
=
0
;
this
.
listRef
.
scrollTop
=
0
;
},
loadNextPage
()
{
const
loadingDone
=
()
=>
{
...
...
@@ -120,6 +145,50 @@ export default {
}
});
},
handleDragOnStart
()
{
document
.
body
.
classList
.
add
(
'
is-dragging
'
);
},
handleDragOnEnd
(
params
)
{
document
.
body
.
classList
.
remove
(
'
is-dragging
'
);
const
{
newIndex
,
oldIndex
,
from
,
to
,
item
}
=
params
;
const
{
issueId
,
issueIid
,
issuePath
}
=
item
.
dataset
;
const
{
children
}
=
to
;
let
moveBeforeId
;
let
moveAfterId
;
// If issue is being moved within the same list
if
(
from
===
to
)
{
if
(
newIndex
>
oldIndex
&&
children
.
length
>
1
)
{
// If issue is being moved down we look for the issue that ends up before
moveBeforeId
=
Number
(
children
[
newIndex
].
dataset
.
issueId
);
}
else
if
(
newIndex
<
oldIndex
&&
children
.
length
>
1
)
{
// If issue is being moved up we look for the issue that ends up after
moveAfterId
=
Number
(
children
[
newIndex
].
dataset
.
issueId
);
}
else
{
// If issue remains in the same list at the same position we do nothing
return
;
}
}
else
{
// We look for the issue that ends up before the moved issue if it exists
if
(
children
[
newIndex
-
1
])
{
moveBeforeId
=
Number
(
children
[
newIndex
-
1
].
dataset
.
issueId
);
}
// We look for the issue that ends up after the moved issue if it exists
if
(
children
[
newIndex
])
{
moveAfterId
=
Number
(
children
[
newIndex
].
dataset
.
issueId
);
}
}
this
.
moveIssue
({
issueId
,
issueIid
,
issuePath
,
fromListId
:
from
.
dataset
.
listId
,
toListId
:
to
.
dataset
.
listId
,
moveBeforeId
,
moveAfterId
,
});
},
},
};
</
script
>
...
...
@@ -139,13 +208,18 @@ export default {
<gl-loading-icon
/>
</div>
<board-new-issue
v-if=
"list.type !== 'closed' && showIssueForm"
:list=
"list"
/>
<ul
<component
:is=
"treeRootWrapper"
v-show=
"!loading"
ref=
"list"
v-bind=
"treeRootOptions"
:data-board=
"list.id"
:data-board-type=
"list.type"
:class=
"
{ 'bg-danger-100': issuesSizeExceedsMax }"
class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2 js-board-list"
data-testid="tree-root-wrapper"
@start="handleDragOnStart"
@end="handleDragOnEnd"
>
<board-card
v-for=
"(issue, index) in issues"
...
...
@@ -161,6 +235,6 @@ export default {
<span
v-if=
"issues.length === list.issuesSize"
>
{{
__
(
'
Showing all issues
'
)
}}
</span>
<span
v-else
>
{{
paginatedIssueText
}}
</span>
</li>
</
ul
>
</
component
>
</div>
</
template
>
spec/frontend/boards/board_list_new_spec.js
View file @
93095b50
...
...
@@ -9,7 +9,7 @@ import BoardList from '~/boards/components/board_list_new.vue';
import
BoardCard
from
'
~/boards/components/board_card.vue
'
;
import
'
~/boards/models/issue
'
;
import
'
~/boards/models/list
'
;
import
{
listObj
,
mockIssuesByListId
,
issues
}
from
'
./mock_data
'
;
import
{
listObj
,
mockIssuesByListId
,
issues
,
mockIssues
}
from
'
./mock_data
'
;
import
defaultState
from
'
~/boards/stores/state
'
;
const
localVue
=
createLocalVue
();
...
...
@@ -71,6 +71,7 @@ const createComponent = ({
disabled
:
false
,
list
,
issues
:
[
issue
],
canAdminList
:
true
,
...
componentProps
,
},
store
,
...
...
@@ -96,6 +97,7 @@ describe('Board list component', () => {
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
renders component
'
,
()
=>
{
...
...
@@ -173,17 +175,18 @@ describe('Board list component', () => {
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
loads more issues after scrolling
'
,
()
=>
{
wrapper
.
vm
.
$refs
.
list
.
dispatchEvent
(
new
Event
(
'
scroll
'
));
wrapper
.
vm
.
listRef
.
dispatchEvent
(
new
Event
(
'
scroll
'
));
expect
(
actions
.
fetchIssuesForList
).
toHaveBeenCalled
();
});
it
(
'
does not load issues if already loading
'
,
()
=>
{
wrapper
.
vm
.
$refs
.
list
.
dispatchEvent
(
new
Event
(
'
scroll
'
));
wrapper
.
vm
.
$refs
.
list
.
dispatchEvent
(
new
Event
(
'
scroll
'
));
wrapper
.
vm
.
listRef
.
dispatchEvent
(
new
Event
(
'
scroll
'
));
wrapper
.
vm
.
listRef
.
dispatchEvent
(
new
Event
(
'
scroll
'
));
expect
(
actions
.
fetchIssuesForList
).
toHaveBeenCalledTimes
(
1
);
});
...
...
@@ -206,6 +209,7 @@ describe('Board list component', () => {
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
when issue count exceeds max issue count
'
,
()
=>
{
...
...
@@ -233,4 +237,48 @@ describe('Board list component', () => {
});
});
});
describe
(
'
drag & drop issue
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
handleDragOnStart
'
,
()
=>
{
it
(
'
adds a class `is-dragging` to document body
'
,
()
=>
{
expect
(
document
.
body
.
classList
.
contains
(
'
is-dragging
'
)).
toBe
(
false
);
wrapper
.
find
(
`[data-testid="tree-root-wrapper"]`
).
vm
.
$emit
(
'
start
'
);
expect
(
document
.
body
.
classList
.
contains
(
'
is-dragging
'
)).
toBe
(
true
);
});
});
describe
(
'
handleDragOnEnd
'
,
()
=>
{
it
(
'
removes class `is-dragging` from document body
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
moveIssue
'
).
mockImplementation
(()
=>
{});
document
.
body
.
classList
.
add
(
'
is-dragging
'
);
wrapper
.
find
(
`[data-testid="tree-root-wrapper"]`
).
vm
.
$emit
(
'
end
'
,
{
oldIndex
:
1
,
newIndex
:
0
,
item
:
{
dataset
:
{
issueId
:
mockIssues
[
0
].
id
,
issueIid
:
mockIssues
[
0
].
iid
,
issuePath
:
mockIssues
[
0
].
referencePath
,
},
},
to
:
{
children
:
[],
dataset
:
{
listId
:
'
gid://gitlab/List/1
'
}
},
from
:
{
dataset
:
{
listId
:
'
gid://gitlab/List/2
'
}
},
});
expect
(
document
.
body
.
classList
.
contains
(
'
is-dragging
'
)).
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