From 49c920fbee09ef0af8427d85f8cea313e77c6857 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 15 Mar 2017 09:31:15 +0000 Subject: [PATCH 1/3] Issue boards blank state template in JS file Aim to eventually go to vue files --- .../javascripts/boards/components/board.js | 5 +- .../boards/components/board_blank_state.js | 117 +++++++++++------- .../boards/components/_blank_state.html.haml | 15 --- .../boards/components/_board.html.haml | 2 +- 4 files changed, 74 insertions(+), 65 deletions(-) delete mode 100644 app/views/projects/boards/components/_blank_state.html.haml diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js index 30d3be453be..67c0c419713 100644 --- a/app/assets/javascripts/boards/components/board.js +++ b/app/assets/javascripts/boards/components/board.js @@ -2,7 +2,8 @@ /* global Vue */ /* global Sortable */ -require('./board_blank_state'); +import boardBlankState from './board_blank_state'; + require('./board_delete'); require('./board_list'); @@ -17,7 +18,7 @@ require('./board_list'); components: { 'board-list': gl.issueBoards.BoardList, 'board-delete': gl.issueBoards.BoardDelete, - 'board-blank-state': gl.issueBoards.BoardBlankState + boardBlankState, }, props: { list: Object, diff --git a/app/assets/javascripts/boards/components/board_blank_state.js b/app/assets/javascripts/boards/components/board_blank_state.js index d76314c1892..32c5be0a5fc 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js +++ b/app/assets/javascripts/boards/components/board_blank_state.js @@ -1,53 +1,76 @@ -/* eslint-disable space-before-function-paren, comma-dangle */ -/* global Vue */ /* global ListLabel */ +const Store = gl.issueBoards.BoardsStore; -(() => { - const Store = gl.issueBoards.BoardsStore; +export default { + template: ` +
+

+ Add the following default lists to your Issue Board with one click: +

+ +

+ Starting out with the default set of lists will get you right on the way to making the most of your board. +

+ + +
+ `, + data() { + return { + predefinedLabels: [ + new ListLabel({ title: 'To Do', color: '#F0AD4E' }), + new ListLabel({ title: 'Doing', color: '#5CB85C' }), + ], + }; + }, + methods: { + addDefaultLists() { + this.clearBlankState(); - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.BoardBlankState = Vue.extend({ - data () { - return { - predefinedLabels: [ - new ListLabel({ title: 'To Do', color: '#F0AD4E' }), - new ListLabel({ title: 'Doing', color: '#5CB85C' }) - ] - }; - }, - methods: { - addDefaultLists () { - this.clearBlankState(); - - this.predefinedLabels.forEach((label, i) => { - Store.addList({ + this.predefinedLabels.forEach((label, i) => { + Store.addList({ + title: label.title, + position: i, + list_type: 'label', + label: { title: label.title, - position: i, - list_type: 'label', - label: { - title: label.title, - color: label.color - } + color: label.color, + }, + }); + }); + + Store.state.lists = _.sortBy(Store.state.lists, 'position'); + + // Save the labels + gl.boardService.generateDefaultLists() + .then((resp) => { + resp.json().forEach((listObj) => { + const list = Store.findList('title', listObj.title); + + list.id = listObj.id; + list.label.id = listObj.label.id; + list.getIssues(); }); }); - - Store.state.lists = _.sortBy(Store.state.lists, 'position'); - - // Save the labels - gl.boardService.generateDefaultLists() - .then((resp) => { - resp.json().forEach((listObj) => { - const list = Store.findList('title', listObj.title); - - list.id = listObj.id; - list.label.id = listObj.label.id; - list.getIssues(); - }); - }); - }, - clearBlankState: Store.removeBlankState.bind(Store) - } - }); -})(); + }, + clearBlankState: Store.removeBlankState.bind(Store), + }, +}; diff --git a/app/views/projects/boards/components/_blank_state.html.haml b/app/views/projects/boards/components/_blank_state.html.haml deleted file mode 100644 index 0af40ddf8fe..00000000000 --- a/app/views/projects/boards/components/_blank_state.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -%board-blank-state{ "inline-template" => true, - "v-if" => 'list.id == "blank"' } - .board-blank-state - %p - Add the following default lists to your Issue Board with one click: - %ul.board-blank-state-list - %li{ "v-for" => "label in predefinedLabels" } - %span.label-color{ ":style" => "{ backgroundColor: label.color } " } - {{ label.title }} - %p - Starting out with the default set of lists will get you right on the way to making the most of your board. - %button.btn.btn-create.btn-inverted.btn-block{ type: "button", "@click.stop" => "addDefaultLists" } - Add default lists - %button.btn.btn-default.btn-block{ type: "button", "@click.stop" => "clearBlankState" } - Nevermind, I'll use my own diff --git a/app/views/projects/boards/components/_board.html.haml b/app/views/projects/boards/components/_board.html.haml index 72bce4049de..0bca6a786cb 100644 --- a/app/views/projects/boards/components/_board.html.haml +++ b/app/views/projects/boards/components/_board.html.haml @@ -32,4 +32,4 @@ ":root-path" => "rootPath", "ref" => "board-list" } - if can?(current_user, :admin_list, @project) - = render "projects/boards/components/blank_state" + %board-blank-state{ "v-if" => 'list.id == "blank"' } From 8135ea993ac33a1ef0780e1c93ec063e0487421a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 16 Mar 2017 14:11:02 +0000 Subject: [PATCH 2/3] Catches errors when generating lists --- .../boards/components/board_blank_state.js | 7 ++ .../boards/board_blank_state_spec.js | 92 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 spec/javascripts/boards/board_blank_state_spec.js diff --git a/app/assets/javascripts/boards/components/board_blank_state.js b/app/assets/javascripts/boards/components/board_blank_state.js index 32c5be0a5fc..be9e3d35fa6 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js +++ b/app/assets/javascripts/boards/components/board_blank_state.js @@ -69,6 +69,13 @@ export default { list.label.id = listObj.label.id; list.getIssues(); }); + }) + .catch(() => { + Store.removeList(undefined, 'label'); + Cookies.remove('issue_board_welcome_hidden', { + path: '', + }); + Store.addBlankState(); }); }, clearBlankState: Store.removeBlankState.bind(Store), diff --git a/spec/javascripts/boards/board_blank_state_spec.js b/spec/javascripts/boards/board_blank_state_spec.js new file mode 100644 index 00000000000..0401ad0ab85 --- /dev/null +++ b/spec/javascripts/boards/board_blank_state_spec.js @@ -0,0 +1,92 @@ +import Vue from 'vue'; +import store from '~/boards/stores/boards_store'; +import boardBlankState from '~/boards/components/board_blank_state'; +import mockData from './mock_data'; + +describe('Boards blank state', () => { + let vm; + let fail = false; + + beforeEach((done) => { + const Comp = Vue.extend(boardBlankState); + + gl.issueBoards.BoardsStore.create(); + gl.boardService = new BoardService('/test/issue-boards/board', '', '1'); + + spyOn(gl.boardService, 'generateDefaultLists').and.callFake(() => new Promise((resolve, reject) => { + if (fail) { + reject(); + } else { + resolve({ + json() { + return [{ + id: 1, + title: 'To Do', + label: { id: 1 }, + }, { + id: 2, + title: 'Doing', + label: { id: 2 }, + }] + }, + }); + } + })); + + vm = new Comp(); + + setTimeout(() => { + vm.$mount(); + done(); + }); + }); + + it('renders pre-defined labels', () => { + expect( + vm.$el.querySelectorAll('.board-blank-state-list li').length + ).toBe(2); + + expect( + vm.$el.querySelectorAll('.board-blank-state-list li')[0].textContent.trim() + ).toEqual('To Do'); + + expect( + vm.$el.querySelectorAll('.board-blank-state-list li')[1].textContent.trim() + ).toEqual('Doing'); + }); + + it('clears blank state', (done) => { + vm.$el.querySelector('.btn-default').click(); + + setTimeout(() => { + expect(gl.issueBoards.BoardsStore.welcomeIsHidden()).toBeTruthy(); + + done(); + }); + }); + + it('creates pre-defined labels', (done) => { + vm.$el.querySelector('.btn-create').click(); + + setTimeout(() => { + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); + expect(gl.issueBoards.BoardsStore.state.lists[0].title).toEqual('To Do'); + expect(gl.issueBoards.BoardsStore.state.lists[1].title).toEqual('Doing'); + + done(); + }); + }); + + it('resets the store if request fails', (done) => { + fail = true; + + vm.$el.querySelector('.btn-create').click(); + + setTimeout(() => { + expect(gl.issueBoards.BoardsStore.welcomeIsHidden()).toBeFalsy(); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + + done(); + }); + }); +}); From de93054e784918fd824575e3bffbea18297c5701 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 16 Mar 2017 15:15:51 +0000 Subject: [PATCH 3/3] Fixed eslint --- .../boards/components/board_blank_state.js | 1 + spec/javascripts/boards/board_blank_state_spec.js | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/boards/components/board_blank_state.js b/app/assets/javascripts/boards/components/board_blank_state.js index be9e3d35fa6..52893d4642b 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js +++ b/app/assets/javascripts/boards/components/board_blank_state.js @@ -1,4 +1,5 @@ /* global ListLabel */ +/* global Cookies */ const Store = gl.issueBoards.BoardsStore; export default { diff --git a/spec/javascripts/boards/board_blank_state_spec.js b/spec/javascripts/boards/board_blank_state_spec.js index 0401ad0ab85..47baf83512f 100644 --- a/spec/javascripts/boards/board_blank_state_spec.js +++ b/spec/javascripts/boards/board_blank_state_spec.js @@ -1,7 +1,8 @@ +/* global BoardService */ import Vue from 'vue'; -import store from '~/boards/stores/boards_store'; +import '~/boards/stores/boards_store'; import boardBlankState from '~/boards/components/board_blank_state'; -import mockData from './mock_data'; +import './mock_data'; describe('Boards blank state', () => { let vm; @@ -27,7 +28,7 @@ describe('Boards blank state', () => { id: 2, title: 'Doing', label: { id: 2 }, - }] + }]; }, }); } @@ -43,15 +44,15 @@ describe('Boards blank state', () => { it('renders pre-defined labels', () => { expect( - vm.$el.querySelectorAll('.board-blank-state-list li').length + vm.$el.querySelectorAll('.board-blank-state-list li').length, ).toBe(2); expect( - vm.$el.querySelectorAll('.board-blank-state-list li')[0].textContent.trim() + vm.$el.querySelectorAll('.board-blank-state-list li')[0].textContent.trim(), ).toEqual('To Do'); expect( - vm.$el.querySelectorAll('.board-blank-state-list li')[1].textContent.trim() + vm.$el.querySelectorAll('.board-blank-state-list li')[1].textContent.trim(), ).toEqual('Doing'); });