Moved issue boards new issue form template
This commit is contained in:
parent
11dd2348c4
commit
9cd53cd8e7
7 changed files with 297 additions and 91 deletions
|
@ -3,7 +3,7 @@ require('./issue_card_inner');
|
|||
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
name: 'BoardsIssueCard',
|
||||
template: `
|
||||
<li class="card"
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
|
92
app/assets/javascripts/boards/components/board_new_issue.js
Normal file
92
app/assets/javascripts/boards/components/board_new_issue.js
Normal 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>
|
||||
`,
|
||||
};
|
|
@ -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();
|
||||
},
|
||||
});
|
||||
})();
|
|
@ -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",
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
189
spec/javascripts/boards/board_new_issue_spec.js
Normal file
189
spec/javascripts/boards/board_new_issue_spec.js
Normal 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);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue