Commit 6478adf1 authored by Phil Hughes's avatar Phil Hughes

Hooked up JS to allow issues to be moved between columns

parent 5dc41ecd
#= require vue
#= require Sortable
#= require_tree ./stores
#= require_tree ./components
$ ->
new Vue
el: '#board-app'
data:
boards: BoardsStore.state
interaction: BoardsStore.dragging
Board = Vue.extend
props:
disabled: Boolean
board: Object
data: ->
dragging: BoardsStore.dragging
methods:
clearSearch: ->
this.query = ''
ready: ->
Sortable.create this.$els.list,
group: 'boards'
disabled: this.disabled
animation: 150
scroll: document.getElementById('board-app')
scrollSensitivity: 150
scrollSpeed: 50
forceFallback: true
fallbackClass: 'is-dragging'
ghostClass: 'is-ghost'
onAdd: (e) ->
fromBoardId = e.from.getAttribute('data-board')
fromBoardId = parseInt(fromBoardId) || fromBoardId
toBoardId = e.to.getAttribute('data-board')
toBoardId = parseInt(toBoardId) || toBoardId
issueId = parseInt(e.item.getAttribute('data-issue'))
BoardsStore.moveCardToBoard(fromBoardId, toBoardId, issueId, e.newIndex)
onUpdate: (e) ->
console.log e.newIndex, e.oldIndex
onStart: ->
BoardsStore.dragging = true
Vue.component('board', Board)
Card = Vue.extend
data: ->
Vue.component('card', Card)
@BoardsStore =
state: [
{id: 'backlog', title: 'Backlog', index: 0, search: true, issues: [{ id: 1, title: 'Test', labels: []}]},
{id: 1, title: 'Frontend', index: 1, label: { title: 'Frontend', backgroundColor: '#44ad8e', textColor: '#ffffff' }, issues: [{ id: 3, title: 'Frontend bug', labels: [{ title: 'Frontend', backgroundColor: '#44ad8e', textColor: '#ffffff' }, { title: 'UX', backgroundColor: '#44ad8e', textColor: '#ffffff' }]}]},
{id: 'done', title: 'Done', index: 99999999, issues: [{ id: 2, title: 'Testing done', labels: []}]}
]
interaction: {
dragging: false
}
moveCardToBoard: (boardFromId, boardToId, issueId, toIndex) ->
boardFrom = _.find BoardsStore.state, (board) ->
board.id is boardFromId
boardTo = _.find BoardsStore.state, (board) ->
board.id is boardToId
issue = _.find boardFrom.issues, (issue) ->
issue.id is issueId
# Remove the issue from old board
boardFrom.issues = _.reject boardFrom.issues, (issue) ->
issue.id is issueId
# Add to new boards issues and increase count
boardTo.issues.splice(toIndex, 0, issue)
# If going to done - remove label
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
unless foundLabel?
issue.labels.push(boardTo.label)
[v-cloak] {
display: none;
}
.issue-boards-page {
.page-with-sidebar {
display: flex;
......@@ -20,6 +24,7 @@
.boards-list {
display: flex;
height: 100%;
min-height: 455px;
padding-top: 25px;
padding-right: ($gl-padding / 2);
padding-left: ($gl-padding / 2);
......@@ -29,7 +34,6 @@
.board {
min-width: 400px;
height: 100%;
min-height: 500px;
padding-right: ($gl-padding / 2);
padding-left: ($gl-padding / 2);
}
......@@ -45,6 +49,16 @@
border-radius: $border-radius-default;
}
.board-header {
border-top-left-radius: $border-radius-default;
border-top-right-radius: $border-radius-default;
&.has-border {
padding-top: ($gl-padding - 3px);
border-top: 3px solid;
}
}
.board-inner-container {
border-bottom: 1px solid $border-color;
padding: $gl-padding;
......@@ -56,7 +70,37 @@
}
.board-search-container {
position: relative;
background-color: #fff;
.form-control {
padding-right: 30px;
}
}
.board-search-icon,
.board-search-clear-btn {
position: absolute;
right: $gl-padding + 10px;
top: 50%;
margin-top: -7px;
font-size: 14px;
}
.board-search-icon {
color: $gl-placeholder-color;
}
.board-search-clear-btn {
padding: 0;
line-height: 1;
background: transparent;
border: 0;
outline: 0;
&:hover {
color: $gl-link-color;
}
}
.board-list {
......@@ -77,11 +121,26 @@
&:not(:last-child) {
margin-bottom: 5px;
}
&.is-dragging {
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
// Important because plugin sets inline CSS
opacity: 1!important;
}
&.is-ghost {
opacity: 0;
}
}
.card-title {
margin: 0;
font-size: 1em;
a {
color: inherit;
}
}
.card-footer {
......@@ -89,7 +148,7 @@
.label {
margin-right: 4px;
font-size: (14px / $issue-boards-font-size);
font-size: (14px / $issue-boards-font-size) * 1em;
}
}
......
%board{ "inline-template" => true, "v-cloak" => true, "v-for" => "board in boards | orderBy 'index'", ":board" => "board", ":disabled" => "#{current_user.nil?}" }
.board
.board-inner
%header.board-inner-container.board-header{ ":class" => "{ 'has-border': board.label }", ":style" => "{ borderTopColor: board.label.backgroundColor }" }
%h3.board-title
{{ board.title }}
%span.pull-right
{{ board.issues.length }}
.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")
%button.board-search-clear-btn{ type: "button", role: "button", "@click" => "clearSearch", "v-show" => "query" }
%span.sr-only
Clear search
= icon("times", class: "board-search-clear")
%ul.board-list{ "v-el:list" => true, ":data-board" => "board.id" }
= render "projects/boards/components/card"
%li.card{ "v-for" => "issue in board.issues", ":data-issue" => "issue.id" }
%h4.card-title
%a{ href: "#" }
{{ issue.title }}
.card-footer
%span.card-number
\#288
%span.label.color-label{ "v-for" => "label in issue.labels", ":style" => "{ backgroundColor: label.backgroundColor, color: label.textColor }" }
{{ label.title }}
- @no_container = true
- @content_class = "issue-boards-content"
- page_title "Boards"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('boards/boards_bundle.js')
= render "projects/issues/head"
.boards-list
.board
.board-inner
%header.board-inner-container
%h3.board-title
Backlog
%span.pull-right
5
.board-inner-container.board-search-container
%input.form-control{ type: "text", placeholder: "Search issues" }
%ul.board-list
%li.card
%h4.card-title
Issue title
.card-footer
%span.card-number
\#288
%span.label.color-label{ style: "background-color: #428bca; color: #FFFFFF" }
label
= render 'shared/issuable/filter', type: :boards
.boards-list#board-app{ ":class" => "{ 'is-dragging': interaction.dragging }"}
{{ interaction.dragging }}
= render "projects/boards/components/board"
......@@ -27,7 +27,11 @@
= render "shared/issuable/label_dropdown"
.pull-right
- if controller.controller_name != 'boards'
= render 'shared/sort_dropdown'
- else
%button.btn.btn-create{ type: "button" }
Create new list
- if controller.controller_name == 'issues'
.issues_bulk_update.hide
......
......@@ -85,6 +85,7 @@ module Gitlab
config.assets.precompile << "users/users_bundle.js"
config.assets.precompile << "network/network_bundle.js"
config.assets.precompile << "profile/profile_bundle.js"
config.assets.precompile << "boards/boards_bundle.js"
config.assets.precompile << "lib/utils/*.js"
config.assets.precompile << "lib/*.js"
config.assets.precompile << "u2f.js"
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment