Moved issue boards new issue form template

This commit is contained in:
Phil Hughes 2017-02-28 10:23:19 +00:00
parent 11dd2348c4
commit 9cd53cd8e7
7 changed files with 297 additions and 91 deletions

View file

@ -3,7 +3,7 @@ require('./issue_card_inner');
const Store = gl.issueBoards.BoardsStore;
module.exports = {
export default {
name: 'BoardsIssueCard',
template: `
<li class="card"

View file

@ -2,8 +2,8 @@
/* global Vue */
/* global Sortable */
const boardCard = require('./board_card');
require('./board_new_issue');
import boardNewIssue from './board_new_issue';
import boardCard from './board_card';
(() => {
const Store = gl.issueBoards.BoardsStore;
@ -15,7 +15,7 @@ require('./board_new_issue');
template: '#js-board-list-template',
components: {
boardCard,
'board-new-issue': gl.issueBoards.BoardNewIssue
boardNewIssue,
},
props: {
disabled: Boolean,
@ -81,6 +81,12 @@ require('./board_new_issue');
});
}
},
toggleForm() {
this.showIssueForm = !this.showIssueForm;
},
},
created() {
gl.IssueBoardsApp.$on(`hide-issue-form-${this.list.id}`, this.toggleForm);
},
mounted () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({
@ -115,6 +121,9 @@ require('./board_new_issue');
this.loadNextPage();
}
};
}
},
beforeDestroy() {
gl.IssueBoardsApp.$off(`hide-issue-form-${this.list.id}`, this.toggleForm);
},
});
})();

View file

@ -0,0 +1,92 @@
/* global ListIssue */
const Store = gl.issueBoards.BoardsStore;
export default {
name: 'BoardNewIssue',
props: {
list: Object,
},
data() {
return {
title: '',
error: false,
};
},
methods: {
submit(e) {
e.preventDefault();
if (this.title.trim() === '') return;
this.error = false;
const labels = this.list.label ? [this.list.label] : [];
const issue = new ListIssue({
title: this.title,
labels,
subscribed: true,
});
this.list.newIssue(issue)
.then(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
Store.detail.issue = issue;
Store.detail.list = this.list;
})
.catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
// Remove the issue
this.list.removeIssue(issue);
// Show error message
this.error = true;
});
this.cancel();
},
cancel() {
this.title = '';
gl.IssueBoardsApp.$emit(`hide-issue-form-${this.list.id}`);
},
},
mounted() {
this.$refs.input.focus();
},
template: `
<div class="card board-new-issue-form">
<form @submit="submit($event)">
<div class="flash-container"
v-if="error">
<div class="flash-alert">
An error occured. Please try again.
</div>
</div>
<label class="label-light"
:for="list.id + '-title'">
Title
</label>
<input class="form-control"
type="text"
v-model="title"
ref="input"
:id="list.id + '-title'" />
<div class="clearfix prepend-top-10">
<button class="btn btn-success pull-left"
type="submit"
:disabled="title === ''"
ref="submit-button">
Submit issue
</button>
<button class="btn btn-default pull-right"
type="button"
@click="cancel">
Cancel
</button>
</div>
</form>
</div>
`,
};

View file

@ -1,64 +0,0 @@
/* eslint-disable comma-dangle, no-unused-vars */
/* global Vue */
/* global ListIssue */
(() => {
const Store = gl.issueBoards.BoardsStore;
window.gl = window.gl || {};
gl.issueBoards.BoardNewIssue = Vue.extend({
props: {
list: Object,
},
data() {
return {
title: '',
error: false
};
},
methods: {
submit(e) {
e.preventDefault();
if (this.title.trim() === '') return;
this.error = false;
const labels = this.list.label ? [this.list.label] : [];
const issue = new ListIssue({
title: this.title,
labels,
subscribed: true
});
this.list.newIssue(issue)
.then((data) => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
Store.detail.issue = issue;
Store.detail.list = this.list;
})
.catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
// Remove the issue
this.list.removeIssue(issue);
// Show error message
this.error = true;
});
this.cancel();
},
cancel() {
this.title = '';
this.$parent.showIssueForm = false;
}
},
mounted() {
this.$refs.input.focus();
},
});
})();

View file

@ -2,28 +2,8 @@
.board-list-loading.text-center{ "v-if" => "loading" }
= icon("spinner spin")
- if can? current_user, :create_issue, @project
%board-new-issue{ "inline-template" => true,
":list" => "list",
%board-new-issue{ ":list" => "list",
"v-if" => 'list.type !== "done" && showIssueForm' }
.card.board-new-issue-form
%form{ "@submit" => "submit($event)" }
.flash-container{ "v-if" => "error" }
.flash-alert
An error occured. Please try again.
%label.label-light{ ":for" => 'list.id + "-title"' }
Title
%input.form-control{ type: "text",
"v-model" => "title",
"ref" => "input",
":id" => 'list.id + "-title"' }
.clearfix.prepend-top-10
%button.btn.btn-success.pull-left{ type: "submit",
":disabled" => 'title === ""',
"ref" => "submit-button" }
Submit issue
%button.btn.btn-default.pull-right{ type: "button",
"@click" => "cancel" }
Cancel
%ul.board-list{ "ref" => "list",
"v-show" => "!loading",
":data-board" => "list.id",

View file

@ -8,7 +8,7 @@
require('~/boards/models/list');
require('~/boards/models/label');
require('~/boards/stores/boards_store');
const boardCard = require('~/boards/components/board_card');
const boardCard = require('~/boards/components/board_card').default;
require('./mock_data');
describe('Issue card', () => {

View file

@ -0,0 +1,189 @@
/* global Vue */
import boardNewIssue from '~/boards/components/board_new_issue';
require('~/boards/models/list');
require('./mock_data');
require('es6-promise').polyfill();
fdescribe('Issue boards new issue form', () => {
let vm;
let list;
const promiseReturn = {
json() {
return {
iid: 100,
};
},
};
const submitIssue = () => {
vm.$el.querySelector('.btn-success').click();
};
beforeEach((done) => {
const BoardNewIssueComp = Vue.extend(boardNewIssue);
Vue.http.interceptors.push(boardsMockInterceptor);
gl.boardService = new BoardService('/test/issue-boards/board', '', '1');
gl.issueBoards.BoardsStore.create();
gl.IssueBoardsApp = new Vue();
setTimeout(() => {
list = new List(listObj);
spyOn(gl.boardService, 'newIssue').and.callFake(() => {
return new Promise((resolve, reject) => {
if (vm.title === 'error') {
reject();
} else {
resolve(promiseReturn);
}
});
});
vm = new BoardNewIssueComp({
propsData: {
list,
},
}).$mount();
done();
}, 0);
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
});
it('disables submit button if title is empty', () => {
expect(vm.$el.querySelector('.btn-success').disabled).toBe(true);
});
it('enables submit button if title is not empty', (done) => {
vm.title = 'Testing Title';
setTimeout(() => {
expect(vm.$el.querySelector('.form-control').value).toBe('Testing Title');
expect(vm.$el.querySelector('.btn-success').disabled).not.toBe(true);
done();
}, 0);
});
it('clears title after clicking cancel', (done) => {
vm.$el.querySelector('.btn-default').click();
setTimeout(() => {
expect(vm.title).toBe('');
done();
}, 0);
});
it('does not create new issue if title is empty', (done) => {
submitIssue();
setTimeout(() => {
expect(gl.boardService.newIssue).not.toHaveBeenCalled();
done();
}, 0);
});
describe('submit success', () => {
it('creates new issue', (done) => {
vm.title = 'submit title';
setTimeout(() => {
submitIssue();
expect(gl.boardService.newIssue).toHaveBeenCalled();
done();
}, 0);
});
it('enables button after submit', (done) => {
vm.title= 'submit issue';
setTimeout(() => {
submitIssue();
expect(vm.$el.querySelector('.btn-success').disbled).not.toBe(true);
done();
}, 0);
});
it('clears title after submit', (done) => {
vm.title = 'submit issue';
setTimeout(() => {
submitIssue();
expect(vm.title).toBe('');
done();
}, 0);
});
it('adds new issue to list after submit', (done) => {
vm.title = 'submit issue';
setTimeout(() => {
submitIssue();
expect(list.issues.length).toBe(2);
expect(list.issues[1].title).toBe('submit issue');
expect(list.issues[1].subscribed).toBe(true);
done();
}, 0);
});
it('sets detail issue after submit', (done) => {
vm.title = 'submit issue';
setTimeout(() => {
submitIssue();
expect(gl.issueBoards.BoardsStore.detail.issue.title).toBe('submit issue');
done();
});
});
it('sets detail list after submit', (done) => {
vm.title = 'submit issue';
setTimeout(() => {
submitIssue();
expect(gl.issueBoards.BoardsStore.detail.list.id).toBe(list.id);
done();
}, 0);
});
});
describe('submit error', () => {
it('removes issue', (done) => {
vm.title = 'error';
setTimeout(() => {
submitIssue();
setTimeout(() => {
expect(list.issues.length).toBe(1);
done();
}, 500);
}, 0);
});
it('shows error', (done) => {
vm.title = 'error';
submitIssue();
setTimeout(() => {
submitIssue();
setTimeout(() => {
expect(vm.error).toBe(true);
done();
}, 500);
}, 0);
});
});
});