Skip to content
Snippets Groups Projects
Commit 7512af29 authored by Phil Hughes's avatar Phil Hughes
Browse files

Issue boards card in JS

Moved the issue boards card template into the JS. This helps to improve
the code coverage & will eventually make it easier to move this to .vue
files
parent 8cc61d0b
No related branches found
No related tags found
No related merge requests found
/* global Vue */
require('./issue_card_inner');
const Store = gl.issueBoards.BoardsStore;
module.exports = {
name: 'BoardsIssueCard',
template: `
<li class="card"
:class="{ 'user-can-drag': !disabled && issue.id, 'is-disabled': disabled || !issue.id, 'is-active': issueDetailVisible }"
:index="index"
:data-issue-id="issue.id"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event)">
<issue-card-inner
:list="list"
:issue="issue"
:issue-link-base="issueLinkBase"
:root-path="rootPath" />
</li>
`,
components: {
'issue-card-inner': gl.issueBoards.IssueCardInner,
},
props: {
list: Object,
issue: Object,
issueLinkBase: String,
disabled: Boolean,
index: Number,
rootPath: String,
},
data () {
return {
showDetail: false,
detailIssue: Store.detail
};
},
computed: {
issueDetailVisible () {
return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
}
},
methods: {
mouseDown () {
this.showDetail = true;
},
mouseMove() {
this.showDetail = false;
},
showIssue (e) {
const targetTagName = e.target.tagName.toLowerCase();
if (targetTagName === 'a' || targetTagName === 'button') return;
if (this.showDetail) {
this.showDetail = false;
if (Store.detail.issue && Store.detail.issue.id === this.issue.id) {
Store.detail.issue = {};
} else {
Store.detail.issue = this.issue;
Store.detail.list = this.list;
}
}
}
}
};
/* eslint-disable comma-dangle, space-before-function-paren, dot-notation */
/* global Vue */
require('./issue_card_inner');
(() => {
const Store = gl.issueBoards.BoardsStore;
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardCard = Vue.extend({
template: '#js-board-list-card',
components: {
'issue-card-inner': gl.issueBoards.IssueCardInner,
},
props: {
list: Object,
issue: Object,
issueLinkBase: String,
disabled: Boolean,
index: Number,
rootPath: String,
},
data () {
return {
showDetail: false,
detailIssue: Store.detail
};
},
computed: {
issueDetailVisible () {
return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
}
},
methods: {
mouseDown () {
this.showDetail = true;
},
mouseMove() {
this.showDetail = false;
},
showIssue (e) {
const targetTagName = e.target.tagName.toLowerCase();
if (targetTagName === 'a' || targetTagName === 'button') return;
if (this.showDetail) {
this.showDetail = false;
if (Store.detail.issue && Store.detail.issue.id === this.issue.id) {
Store.detail.issue = {};
} else {
Store.detail.issue = this.issue;
Store.detail.list = this.list;
}
}
}
}
});
})();
Loading
Loading
@@ -2,7 +2,7 @@
/* global Vue */
/* global Sortable */
 
require('./board_card');
const boardCard = require('./board_card');
require('./board_new_issue');
 
(() => {
Loading
Loading
@@ -14,7 +14,7 @@ require('./board_new_issue');
gl.issueBoards.BoardList = Vue.extend({
template: '#js-board-list-template',
components: {
'board-card': gl.issueBoards.BoardCard,
boardCard,
'board-new-issue': gl.issueBoards.BoardNewIssue
},
props: {
Loading
Loading
Loading
Loading
@@ -8,7 +8,6 @@
 
%script#js-board-template{ type: "text/x-template" }= render "projects/boards/components/board"
%script#js-board-list-template{ type: "text/x-template" }= render "projects/boards/components/board_list"
%script#js-board-list-card{ type: "text/x-template" }= render "projects/boards/components/card"
 
= render "projects/issues/head"
 
Loading
Loading
%li.card{ ":class" => '{ "user-can-drag": !disabled && issue.id, "is-disabled": disabled || !issue.id, "is-active": issueDetailVisible }',
":index" => "index",
":data-issue-id" => "issue.id",
"@mousedown" => "mouseDown",
"@mousemove" => "mouseMove",
"@mouseup" => "showIssue($event)" }
%issue-card-inner{ ":list" => "list",
":issue" => "issue",
":issue-link-base" => "issueLinkBase",
":root-path" => "rootPath" }
/* global Vue */
/* global List */
/* global listObj */
require('~/boards/models/list');
require('~/boards/models/label');
require('~/boards/stores/boards_store');
const boardCard = require('~/boards/components/board_card');
require('./mock_data');
describe('Issue card', () => {
let vm;
beforeEach((done) => {
Vue.http.interceptors.push(boardsMockInterceptor);
gl.boardService = new BoardService('/test/issue-boards/board', '', '1');
gl.issueBoards.BoardsStore.create();
gl.issueBoards.BoardsStore.detail.issue = {};
const BoardCardComp = Vue.extend(boardCard);
const list = new List(listObj);
const label1 = new ListLabel({
id: 3,
title: 'testing 123',
color: 'blue',
text_color: 'white',
description: 'test',
});
setTimeout(() => {
list.issues[0].labels.push(label1);
vm = new BoardCardComp({
propsData: {
list,
issue: list.issues[0],
issueLinkBase: '/',
disabled: false,
index: 0,
rootPath: '/',
},
}).$mount();;
done();
}, 0);
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
});
it('returns false when detailIssue is empty', () => {
expect(vm.issueDetailVisible).toBe(false);
});
it('returns true when detailIssue is equal to card issue', () => {
gl.issueBoards.BoardsStore.detail.issue = vm.issue;
expect(vm.issueDetailVisible).toBe(true);
});
it('adds user-can-drag class if not disabled', () => {
expect(vm.$el.classList.contains('user-can-drag')).toBe(true);
});
it('does not add user-can-drag class disabled', (done) => {
vm.disabled = true;
setTimeout(() => {
expect(vm.$el.classList.contains('user-can-drag')).toBe(false);
done();
}, 0);
});
it('does not add disabled class', () => {
expect(vm.$el.classList.contains('is-disabled')).toBe(false);
});
it('adds disabled class is disabled is true', (done) => {
vm.disabled = true;
setTimeout(() => {
expect(vm.$el.classList.contains('is-disabled')).toBe(true);
done();
}, 0);
});
describe('mouse events', () => {
const triggerEvent = (eventName, el = vm.$el) => {
const event = document.createEvent('MouseEvents');
event.initMouseEvent(eventName, true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
el.dispatchEvent(event);
};
it('sets showDetail to true on mousedown', () => {
triggerEvent('mousedown');
expect(vm.showDetail).toBe(true);
});
it('sets showDetail to false on mousemove', () => {
triggerEvent('mousedown');
expect(vm.showDetail).toBe(true);
triggerEvent('mousemove');
expect(vm.showDetail).toBe(false);
});
it('does not set detail issue if showDetail is false', () => {
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
});
it('does not set detail issue if link is clicked', () => {
triggerEvent('mouseup', vm.$el.querySelector('a'));
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
});
it('does not set detail issue if button is clicked', () => {
triggerEvent('mouseup', vm.$el.querySelector('button'));
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
});
it('does not set detail issue if showDetail is false', () => {
triggerEvent('mouseup');
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
});
it('sets detail issue to card issue on mouse up', () => {
triggerEvent('mousedown');
triggerEvent('mouseup');
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual(vm.issue);
expect(gl.issueBoards.BoardsStore.detail.list).toEqual(vm.list);
});
it('adds active class if detail issue is set', (done) => {
triggerEvent('mousedown');
triggerEvent('mouseup');
setTimeout(() => {
expect(vm.$el.classList.contains('is-active')).toBe(true);
done();
}, 0);
});
it('resets detail issue to empty if already set', () => {
triggerEvent('mousedown');
triggerEvent('mouseup');
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual(vm.issue);
triggerEvent('mousedown');
triggerEvent('mouseup');
expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment