summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2016-07-25 14:28:19 +0100
committerPhil Hughes <me@iamphill.com>2016-08-17 17:12:47 +0100
commitff7bab37606777d7a0625caa50fb9b0f5690d25e (patch)
tree722c7eca0ff9a50816870a90058001937f3113f0
parentf330585a98b75b75ef2eb9d4897297ada576000d (diff)
downloadgitlab-ce-ff7bab37606777d7a0625caa50fb9b0f5690d25e.tar.gz
When moving to done & the issue belongs to more than 1 board it asks if user wants to remove from all the boards
Can filter issues by author, assignee & milestones
-rw-r--r--app/assets/javascripts/boards/boards_bundle.js.coffee4
-rw-r--r--app/assets/javascripts/boards/components/board.js.coffee2
-rw-r--r--app/assets/javascripts/boards/components/board_delete.js.coffee5
-rw-r--r--app/assets/javascripts/boards/components/board_list.js.coffee35
-rw-r--r--app/assets/javascripts/boards/components/issue_done.js.coffee5
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js.coffee40
-rw-r--r--app/assets/stylesheets/pages/boards.scss51
-rw-r--r--app/views/projects/boards/components/_board.html.haml25
-rw-r--r--app/views/projects/boards/components/_card.html.haml2
9 files changed, 150 insertions, 19 deletions
diff --git a/app/assets/javascripts/boards/boards_bundle.js.coffee b/app/assets/javascripts/boards/boards_bundle.js.coffee
index 8e8a6e2a162..90669d0c0ce 100644
--- a/app/assets/javascripts/boards/boards_bundle.js.coffee
+++ b/app/assets/javascripts/boards/boards_bundle.js.coffee
@@ -11,9 +11,9 @@ $ =>
new Vue
el: '#board-app'
data:
- boards: BoardsStore.state
+ state: BoardsStore.state
ready: ->
service
.all()
.then (resp) ->
- BoardsStore.state.push(board) for board in resp.data
+ BoardsStore.state.boards.push(board) for board in resp.data
diff --git a/app/assets/javascripts/boards/components/board.js.coffee b/app/assets/javascripts/boards/components/board.js.coffee
index 83f06f52c60..fde62ba569b 100644
--- a/app/assets/javascripts/boards/components/board.js.coffee
+++ b/app/assets/javascripts/boards/components/board.js.coffee
@@ -2,7 +2,7 @@ Board = Vue.extend
props:
board: Object
data: ->
- dragging: BoardsStore.dragging
+ filters: BoardsStore.state.filters
methods:
clearSearch: ->
this.query = ''
diff --git a/app/assets/javascripts/boards/components/board_delete.js.coffee b/app/assets/javascripts/boards/components/board_delete.js.coffee
new file mode 100644
index 00000000000..d08831ddafa
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_delete.js.coffee
@@ -0,0 +1,5 @@
+BoardDelete = Vue.extend
+ props:
+ boardId: Number
+
+Vue.component 'board-delete', BoardDelete
diff --git a/app/assets/javascripts/boards/components/board_list.js.coffee b/app/assets/javascripts/boards/components/board_list.js.coffee
index bfd3eadee93..5fe174aa435 100644
--- a/app/assets/javascripts/boards/components/board_list.js.coffee
+++ b/app/assets/javascripts/boards/components/board_list.js.coffee
@@ -2,8 +2,38 @@ BoardList = Vue.extend
props:
disabled: Boolean
boardId: [Number, String]
+ filters: Object
issues: Array
query: String
+ data: ->
+ scrollOffset: 20
+ loadMore: false
+ computed:
+ newDone: -> BoardsStore.state.done
+ methods:
+ listHeight: -> this.$els.list.getBoundingClientRect().height
+ scrollHeight: -> this.$els.list.scrollHeight
+ scrollTop: -> this.$els.list.scrollTop + this.listHeight()
+ loadFromLastId: ->
+ this.loadMore = true
+ setTimeout =>
+ this.loadMore = false
+ , 2000
+ customFilter: (issue) ->
+ returnIssue = issue
+ if this.filters.author?.id
+ if not issue.author? or issue.author?.id != this.filters.author.id
+ returnIssue = null
+
+ if this.filters.assignee?.id
+ if not issue.assignee? or issue.assignee?.id != this.filters.assignee.id
+ returnIssue = null
+
+ if this.filters.milestone?.id
+ if not issue.milestone? or issue.milestone?.id != this.filters.milestone.id
+ returnIssue = null
+
+ return returnIssue
ready: ->
Sortable.create this.$els.list,
group: 'issues'
@@ -26,4 +56,9 @@ BoardList = Vue.extend
onUpdate: (e) ->
console.log e.newIndex, e.oldIndex
+ # Scroll event on list to load more
+ this.$els.list.onscroll = =>
+ if (this.scrollTop() > this.scrollHeight() - this.scrollOffset) and !this.loadMore
+ this.loadFromLastId()
+
Vue.component('board-list', BoardList)
diff --git a/app/assets/javascripts/boards/components/issue_done.js.coffee b/app/assets/javascripts/boards/components/issue_done.js.coffee
new file mode 100644
index 00000000000..f4bf2b86179
--- /dev/null
+++ b/app/assets/javascripts/boards/components/issue_done.js.coffee
@@ -0,0 +1,5 @@
+IssueDone = Vue.extend
+ props:
+ done: Object
+
+Vue.component('issue-done', IssueDone)
diff --git a/app/assets/javascripts/boards/stores/boards_store.js.coffee b/app/assets/javascripts/boards/stores/boards_store.js.coffee
index 5ebf5586a7c..077681b0227 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js.coffee
+++ b/app/assets/javascripts/boards/stores/boards_store.js.coffee
@@ -1,12 +1,18 @@
@BoardsStore =
- state: []
+ state:
+ boards: []
+ done: {}
+ filters:
+ author: {}
+ assignee: {}
+ milestone: {}
moveBoard: (oldIndex, newIndex) ->
- boardFrom = _.find BoardsStore.state, (board) ->
+ boardFrom = _.find BoardsStore.state.boards, (board) ->
board.index is oldIndex
service.updateBoard(boardFrom.id, newIndex)
- boardTo = _.find BoardsStore.state, (board) ->
+ boardTo = _.find BoardsStore.state.boards, (board) ->
board.index is newIndex
boardFrom.index = newIndex
@@ -15,12 +21,13 @@
else
boardTo.index++
moveCardToBoard: (boardFromId, boardToId, issueId, toIndex) ->
- boardFrom = _.find BoardsStore.state, (board) ->
+ boardFrom = _.find BoardsStore.state.boards, (board) ->
board.id is boardFromId
- boardTo = _.find BoardsStore.state, (board) ->
+ boardTo = _.find BoardsStore.state.boards, (board) ->
board.id is boardToId
issue = _.find boardFrom.issues, (issue) ->
issue.id is issueId
+ issueBoards = BoardsStore.getBoardsForIssue(issue)
# Remove the issue from old board
boardFrom.issues = _.reject boardFrom.issues, (issue) ->
@@ -29,13 +36,22 @@
# Add to new boards issues
boardTo.issues.splice(toIndex, 0, issue)
- # If going to done - remove label
- if boardTo.id is 'done' and boardFrom.id != 'backlog'
+ if boardTo.id is 'done'
+ Vue.set(BoardsStore.state.done, 'board', boardFrom)
+ Vue.set(BoardsStore.state.done, 'issue', issue)
+ Vue.set(BoardsStore.state.done, 'boards', issueBoards)
+ else if boardTo.id is 'done' and boardFrom.id != 'backlog'
issue.labels = _.reject issue.labels, (label) ->
label.title is boardFrom.title
- else if boardTo.label?
- foundLabel = _.find issue.labels, (label) ->
- label.title is boardTo.label.title
+ else
+ if boardTo.label?
+ foundLabel = _.find issue.labels, (label) ->
+ label.title is boardTo.label.title
- unless foundLabel?
- issue.labels.push(boardTo.label)
+ unless foundLabel?
+ issue.labels.push(boardTo.label)
+ getBoardsForIssue: (issue) ->
+ _.filter BoardsStore.state.boards, (board) ->
+ foundIssue = _.find board.issues, (boardIssue) ->
+ issue?.id == boardIssue?.id
+ foundIssue?
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 06754e538f4..3bf3fc2fe88 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -33,6 +33,7 @@
.board {
min-width: 400px;
+ max-width: 400px;
height: 100%;
padding-right: ($gl-padding / 2);
padding-left: ($gl-padding / 2);
@@ -103,11 +104,27 @@
}
}
+.board-delete {
+ margin-right: 10px;
+ padding: 0;
+ color: $gray-darkest;
+ background-color: transparent;
+ border: 0;
+
+ &:hover {
+ color: $gl-link-color;
+ }
+}
+
.board-list {
flex: 1;
margin: 0;
padding: 5px;
overflow: scroll;
+
+ &.is-marking-done {
+ flex: 0 0 auto;
+ }
}
.is-ghost {
@@ -154,3 +171,37 @@
margin-right: 8px;
font-weight: 500;
}
+
+.board-done {
+ flex: 1;
+ padding: 10px 18px;
+ color: #8c8c8c;
+ background-color: #fff;
+ border-top: 1px solid $border-color;
+
+ > p {
+ margin: 0;
+ font-size: 1em;
+ }
+}
+
+.board-done-label-list {
+ margin: 10px 0 10px 30px;
+ padding: 0;
+ color: #333;
+ list-style: none;
+
+ > li:not(:last-child) {
+ margin-bottom: 5px;
+ }
+
+ .label {
+ display: inline-block;
+ position: relative;
+ top: 2px;
+ width: 16px;
+ height: 16px;
+ margin-right: 5px;
+ border-radius: $border-radius-default;
+ }
+}
diff --git a/app/views/projects/boards/components/_board.html.haml b/app/views/projects/boards/components/_board.html.haml
index 416ccf8b5fb..d2b27e58ca5 100644
--- a/app/views/projects/boards/components/_board.html.haml
+++ b/app/views/projects/boards/components/_board.html.haml
@@ -1,4 +1,4 @@
-%board{ "inline-template" => true, "v-cloak" => true, "v-for" => "board in boards | orderBy 'index'", ":board" => "board" }
+%board{ "inline-template" => true, "v-cloak" => true, "v-for" => "board in state.boards | orderBy 'index'", ":board" => "board" }
.board{ ":class" => "{ 'is-draggable': !isPreset }" }
.board-inner
%header.board-inner-container.board-header{ ":class" => "{ 'has-border': board.label }", ":style" => "{ borderTopColor: board.label.backgroundColor }" }
@@ -6,6 +6,11 @@
{{ board.title }}
%span.pull-right
{{ board.issues.length }}
+ %board-delete{ "inline-template" => true, "v-if" => "!isPreset" }
+ %button.board-delete.has-tooltip.pull-right{ type: "button", title: "Delete board", data: { placement: "bottom" } }
+ %span.sr-only
+ Delete board
+ = icon("trash")
.board-inner-container.board-search-container{ "v-if" => "board.search" }
%input.form-control{ type: "text", placeholder: "Search issues", "v-model" => "query" }
= icon("search", class: "board-search-icon", "v-show" => "!query")
@@ -13,6 +18,20 @@
%span.sr-only
Clear search
= icon("times", class: "board-search-clear")
- %board-list{ "inline-template" => true, ":board-id" => "board.id", ":issues" => "board.issues", ":disabled" => "#{current_user.nil?}", ":query" => "query" }
- %ul.board-list{ "v-el:list" => true, ":data-board" => "boardId" }
+ %board-list{ "inline-template" => true, ":board-id" => "board.id", ":issues" => "board.issues", ":disabled" => "#{current_user.nil?}", ":query" => "query", ":filters" => "filters" }
+ %ul.board-list{ "v-el:list" => true, ":data-board" => "boardId", ":class" => "{ 'is-marking-done': boardId == 'done' && newDone.board }" }
= render "projects/boards/components/card"
+ %issue-done{ "inline-template" => true, ":done" => "newDone", "v-if" => "boardId == 'done' && newDone.board" }
+ .board-done
+ %p
+ This issue is currently in the following lists:
+ %ul.board-done-label-list
+ %li{ "v-for" => "board in done.boards" }
+ %span.label{ ":style" => "{ 'background-color': board.label.backgroundColor, 'color': board.label.color }" }
+ {{ board.title }}
+ %p
+ Moving it to Done will remove it from all lists and close the issue.
+ %button.btn.btn-gray.btn-block.prepend-top-10{ type: "button" }
+ Remove from all lists and close
+ %button.btn.btn-gray.btn-block{ type: "button" }
+ Remove from {{ done.board.title }} list
diff --git a/app/views/projects/boards/components/_card.html.haml b/app/views/projects/boards/components/_card.html.haml
index 8b373398109..db11654d72f 100644
--- a/app/views/projects/boards/components/_card.html.haml
+++ b/app/views/projects/boards/components/_card.html.haml
@@ -1,4 +1,4 @@
-%li.card{ ":data-issue" => "issue.id", "v-for" => "issue in issues | filterBy query in 'title'" }
+%li.card{ ":data-issue" => "issue.id", "v-for" => "issue in issues | filterBy query in 'title' | filterBy customFilter" }
%h4.card-title
%a{ href: "#", ":title" => "issue.title" }
{{ issue.title }}