Commit ed1da57a authored by Phil Hughes's avatar Phil Hughes Committed by Douglas Barbosa Alexandre

Multiple issue boards frontend

parent 93d6ff27
......@@ -6,6 +6,7 @@
//= require_tree ./services
//= require_tree ./mixins
//= require ./components/board
//= require ./components/boards_selector
//= require ./components/new_list_dropdown
//= require ./vue_resource_interceptor
......@@ -22,7 +23,8 @@ $(() => {
gl.IssueBoardsApp = new Vue({
el: $boardApp,
components: {
'board': gl.issueBoards.Board
'board': gl.issueBoards.Board,
'boards-selector': gl.issueBoards.BoardsSelector
},
data: {
state: Store.state,
......
(() => {
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardSelectorForm = Vue.extend({
props: {
type: String,
currentBoard: Object,
currentPage: String,
reload: Boolean
},
data () {
return {
board: {
id: false,
name: ''
}
};
},
ready () {
if (this.currentBoard && Object.keys(this.currentBoard).length) {
this.board = Vue.util.extend({}, this.currentBoard);
}
},
computed: {
buttonText () {
if (this.type === 'new') {
return 'Create';
} else {
return 'Save';
}
}
},
methods: {
submit () {
gl.boardService.createBoard(this.board)
.then(() => {
if (this.currentBoard) {
this.currentBoard.name = this.board.name;
}
// Enable the button thanks to our jQuery disabling it
$(this.$els.submitBtn).enable();
// Reset the selectors current page
this.currentPage = '';
this.reload = true;
});
}
}
});
})();
//= require ./board_new_form
(() => {
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardsSelector = Vue.extend({
components: {
'board-selector-form': gl.issueBoards.BoardSelectorForm
},
props: {
currentBoard: Object,
endpoint: String
},
data () {
return {
open: false,
loading: true,
boards: [],
currentPage: '',
reload: false
};
},
watch: {
reload () {
if (this.reload) {
this.boards = [];
this.loading = true;
this.reload = false;
this.loadBoards(false);
}
}
},
computed: {
showDelete () {
return this.boards.length > 1;
},
title () {
if (this.currentPage === 'edit') {
return 'Edit board';
} else if (this.currentPage === 'new') {
return 'Create new board';
} else {
return 'Go to a board';
}
}
},
methods: {
showPage (page) {
this.currentPage = page;
},
toggleDropdown () {
this.open = !this.open;
},
loadBoards (toggleDropdown = true) {
if (toggleDropdown) {
this.toggleDropdown();
}
if (this.open && !this.boards.length) {
this.$http.get(this.endpoint).then((resp) => {
this.loading = false;
this.boards = resp.json();
});
}
}
}
});
})();
......@@ -2,6 +2,8 @@ class BoardService {
constructor (root, boardId) {
Vue.http.options.root = root;
this.boards = Vue.resource(`${root}{/id}`);
this.lists = Vue.resource(`${root}/${boardId}/lists{/id}`, {}, {
generate: {
method: 'POST',
......@@ -17,6 +19,14 @@ class BoardService {
});
}
createBoard (board) {
if (board.id) {
return this.boards.update({ id: board.id }, board);
} else {
return this.boards.save({}, board);
}
}
all () {
return this.lists.get();
}
......
......@@ -151,6 +151,10 @@
white-space: nowrap;
overflow: hidden;
&.text-danger {
color: $gl-danger;
}
&:hover,
&:focus,
&.is-focused {
......
lex
[v-cloak] {
display: none;
}
......@@ -56,7 +55,6 @@ lex
.boards-list {
height: calc(100vh - 152px);
width: 100%;
padding-top: 25px;
padding-bottom: 25px;
padding-right: ($gl-padding / 2);
padding-left: ($gl-padding / 2);
......@@ -64,9 +62,9 @@ lex
white-space: nowrap;
@media (min-width: $screen-sm-min) {
height: 475px; // Needed for PhantomJS
height: calc(100vh - 220px);
min-height: 475px;
height: 409px; // Needed for PhantomJS
height: calc(100vh - 290px);
min-height: 409px;
}
}
......@@ -265,3 +263,38 @@ lex
border-width: 1px 0 1px 1px;
}
}
.boards-title-holder {
padding: 25px 13px $gl-padding;
.dropdown-menu {
margin-top: -15px;
margin-left: 8px;
}
}
.boards-switcher {
padding: 0;
border: 0;
outline: 0;
background: none;
font-size: 19px;
font-weight: 600;
> .fa {
position: relative;
top: 2px;
margin-left: 5px;
}
}
.board-selector-page-two {
padding-left: 10px;
padding-right: 10px;
white-space: normal;
}
.board-delete-btns {
padding-top: 12px;
border-top: 1px solid $border-color;
}
%boards-selector{ "inline-template" => true,
endpoint: namespace_project_boards_path(@project.namespace, @project, :json),
":current-board" => "#{board.to_json}" }
.boards-title-holder.dropdown
%button.boards-switcher{ "@click" => "loadBoards",
data: { toggle: "dropdown" } }
{{ currentBoard.name }}
= icon("caret-down")
.dropdown-menu
.dropdown-title
%button.dropdown-title-button.dropdown-menu-back{ type: "button",
aria: { label: "Go back" },
"@click.stop.prevent" => "showPage('')",
"v-if" => "currentPage !== ''" }
= icon("arrow-left")
{{ title }}
%button.dropdown-title-button.dropdown-menu-close{ type: "button",
aria: { label: "Close" } }
= icon("times", class: "dropdown-menu-close-icon")
.dropdown-content{ "v-if" => "currentPage === ''" }
%ul{ "v-if" => "!loading" }
%li{ "v-for" => "board in boards" }
%a{ ":href" => "'#{namespace_project_boards_path(@project.namespace, @project)}/' + board.id" }
{{ board.name }}
.text-center{ "v-if" => "loading" }
= icon("spin spinner")
%board-selector-form{ "inline-template" => true,
"v-if" => "currentPage === 'edit'",
"type" => "edit",
":current-board.sync" => "currentBoard",
":current-page.sync" => "currentPage",
":reload.sync" => "reload" }
= render "projects/boards/components/form"
%board-selector-form{ "inline-template" => true,
"v-if" => "currentPage === 'new'",
"type" => "new",
":current-page.sync" => "currentPage",
":reload.sync" => "reload" }
= render "projects/boards/components/form"
.dropdown-footer{ "v-if" => "currentPage === ''" }
%ul.dropdown-footer-list
%li
%a{ "@click.stop.prevent" => "showPage('new')" }
Create new board
%li
%a{ "@click.stop.prevent" => "showPage('edit')" }
Edit board name
%li{ "v-if" => "showDelete" }
= link_to "",
class: "text-danger",
method: :delete,
":href" => "'#{namespace_project_boards_path(@project.namespace, @project)}/' + currentBoard.id" do
Delete board
.dropdown-content.board-selector-page-two
%form{ "@submit.prevent" => "submit" }
%label.label-light{ for: "board-new-name" }
Board name
%input.form-control{ type: "text",
id: "board-new-name",
"v-model" => "board.name" }
.clearfix.prepend-top-10
%button.btn.btn-primary.pull-left{ type: "submit",
":disabled" => "board.name === ''",
"v-el:submit-btn" => true }
{{ buttonText }}
%button.btn.btn-default.pull-right{ type: "button",
"@click.stop.prevent" => "currentPage = ''" }
Cancel
......@@ -11,6 +11,7 @@
= render 'shared/issuable/filter', type: :boards
.boards-list#board-app{ "v-cloak" => true, data: board_data }
= render "title", board: @boards.first
.boards-app-loading.text-center{ "v-if" => "loading" }
= icon("spinner spin")
= render "projects/boards/components/board"
......@@ -11,6 +11,7 @@
= render 'shared/issuable/filter', type: :boards
.boards-list#board-app{ "v-cloak" => true, data: board_data }
= render "title", board: @board
.boards-app-loading.text-center{ "v-if" => "loading" }
= icon("spinner spin")
= render "projects/boards/components/board"
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