Switch boards to Axios

This commit is contained in:
Eric Eastwood 2017-12-15 02:31:14 -06:00
parent ac9e65a9b9
commit 4ffc863afd
15 changed files with 137 additions and 154 deletions

View file

@ -2,7 +2,6 @@
import _ from 'underscore';
import Vue from 'vue';
import VueResource from 'vue-resource';
import Flash from '../flash';
import { __ } from '../locale';
import FilteredSearchBoards from './filtered_search_boards';
@ -25,8 +24,6 @@ import './components/new_list_dropdown';
import './components/modal/index';
import '../vue_shared/vue_resource_interceptor';
Vue.use(VueResource);
$(() => {
const $boardApp = document.getElementById('board-app');
const Store = gl.issueBoards.BoardsStore;
@ -95,9 +92,9 @@ $(() => {
Store.disabled = this.disabled;
gl.boardService.all()
.then(response => response.json())
.then((resp) => {
resp.forEach((board) => {
.then(res => res.data)
.then((data) => {
data.forEach((board) => {
const list = Store.addList(board, this.defaultAvatar);
if (list.type === 'closed') {
@ -112,7 +109,9 @@ $(() => {
Store.addBlankState();
this.loading = false;
})
.catch(() => new Flash('An error occurred. Please try again.'));
.catch(() => {
Flash('An error occurred while fetching the board lists. Please try again.');
});
},
methods: {
updateTokens() {
@ -123,7 +122,7 @@ $(() => {
if (sidebarInfoEndpoint && newIssue.subscribed === undefined) {
newIssue.setFetchingState('subscriptions', true);
BoardService.getIssueInfo(sidebarInfoEndpoint)
.then(res => res.json())
.then(res => res.data)
.then((data) => {
newIssue.setFetchingState('subscriptions', false);
newIssue.updateData({

View file

@ -65,7 +65,7 @@ export default {
// Save the labels
gl.boardService.generateDefaultLists()
.then(resp => resp.json())
.then(res => res.data)
.then((data) => {
data.forEach((listObj) => {
const list = Store.findList('title', listObj.title);

View file

@ -89,7 +89,7 @@ gl.issueBoards.IssuesModal = Vue.extend({
page: this.page,
per: this.perPage,
}))
.then(resp => resp.json())
.then(res => res.data)
.then((data) => {
if (clearIssues) {
this.issues = [];

View file

@ -40,7 +40,7 @@ class List {
save () {
return gl.boardService.createList(this.label.id)
.then(resp => resp.json())
.then(res => res.data)
.then((data) => {
this.id = data.id;
this.type = data.list_type;
@ -90,7 +90,7 @@ class List {
}
return gl.boardService.getIssuesForList(this.id, data)
.then(resp => resp.json())
.then(res => res.data)
.then((data) => {
this.loading = false;
this.issuesSize = data.size;
@ -108,7 +108,7 @@ class List {
this.issuesSize += 1;
return gl.boardService.newIssue(this.id, issue)
.then(resp => resp.json())
.then(res => res.data)
.then((data) => {
issue.id = data.id;
issue.iid = data.iid;

View file

@ -1,82 +1,79 @@
/* eslint-disable space-before-function-paren, comma-dangle, no-param-reassign, camelcase, max-len, no-unused-vars */
import Vue from 'vue';
import axios from '../../lib/utils/axios_utils';
import { mergeUrlParams } from '../../lib/utils/url_utility';
export default class BoardService {
constructor ({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId }) {
this.boards = Vue.resource(`${boardsEndpoint}{/id}.json`, {}, {
issues: {
method: 'GET',
url: `${gon.relative_url_root}/-/boards/${boardId}/issues.json`,
}
});
this.lists = Vue.resource(`${listsEndpoint}{/id}`, {}, {
generate: {
method: 'POST',
url: `${listsEndpoint}/generate.json`
}
});
this.issue = Vue.resource(`${gon.relative_url_root}/-/boards/${boardId}/issues{/id}`, {});
this.issues = Vue.resource(`${listsEndpoint}{/id}/issues`, {}, {
bulkUpdate: {
method: 'POST',
url: bulkUpdatePath,
constructor({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId }) {
this.boardsEndpoint = boardsEndpoint;
this.boardId = boardId;
this.listsEndpoint = listsEndpoint;
this.listsEndpointGenerate = `${listsEndpoint}/generate.json`;
this.bulkUpdatePath = bulkUpdatePath;
}
generateBoardsPath(id) {
return `${this.boardsEndpoint}${id ? `/${id}` : ''}.json`;
}
generateIssuesPath(id) {
return `${this.listsEndpoint}${id ? `/${id}` : ''}/issues`;
}
static generateIssuePath(boardId, id) {
return `${gon.relative_url_root}/-/boards/${boardId ? `/${boardId}` : ''}/issues${id ? `/${id}` : ''}`;
}
all() {
return axios.get(this.listsEndpoint);
}
generateDefaultLists() {
return axios.post(this.listsEndpointGenerate, {});
}
createList(labelId) {
return axios.post(this.listsEndpoint, {
list: {
label_id: labelId,
},
});
}
all () {
return this.lists.get();
}
generateDefaultLists () {
return this.lists.generate({});
}
createList (label_id) {
return this.lists.save({}, {
updateList(id, position) {
return axios.put(`${this.listsEndpoint}/${id}`, {
list: {
label_id
}
position,
},
});
}
updateList (id, position) {
return this.lists.update({ id }, {
list: {
position
}
});
destroyList(id) {
return axios.delete(`${this.listsEndpoint}/${id}`);
}
destroyList (id) {
return this.lists.delete({ id });
}
getIssuesForList (id, filter = {}) {
getIssuesForList(id, filter = {}) {
const data = { id };
Object.keys(filter).forEach((key) => { data[key] = filter[key]; });
return this.issues.get(data);
return axios.get(mergeUrlParams(data, this.generateIssuesPath(id)));
}
moveIssue (id, from_list_id = null, to_list_id = null, move_before_id = null, move_after_id = null) {
return this.issue.update({ id }, {
from_list_id,
to_list_id,
move_before_id,
move_after_id,
moveIssue(id, fromListId = null, toListId = null, moveBeforeId = null, moveAfterId = null) {
return axios.put(BoardService.generateIssuePath(this.boardId, id), {
from_list_id: fromListId,
to_list_id: toListId,
move_before_id: moveBeforeId,
move_after_id: moveAfterId,
});
}
newIssue (id, issue) {
return this.issues.save({ id }, {
issue
newIssue(id, issue) {
return axios.post(this.generateIssuesPath(id), {
issue,
});
}
getBacklog(data) {
return this.boards.issues(data);
return axios.get(mergeUrlParams(data, `${gon.relative_url_root}/-/boards/${this.boardId}/issues.json`));
}
bulkUpdate(issueIds, extraData = {}) {
@ -86,15 +83,15 @@ export default class BoardService {
}),
};
return this.issues.bulkUpdate(data);
return axios.post(this.bulkUpdatePath, data);
}
static getIssueInfo(endpoint) {
return Vue.http.get(endpoint);
return axios.get(endpoint);
}
static toggleIssueSubscription(endpoint) {
return Vue.http.post(endpoint);
return axios.post(endpoint);
}
}

View file

@ -1,9 +1,8 @@
/* global BoardService */
/* global mockBoardService */
import Vue from 'vue';
import '~/boards/stores/boards_store';
import boardBlankState from '~/boards/components/board_blank_state';
import './mock_data';
import { mockBoardService } from './mock_data';
describe('Boards blank state', () => {
let vm;
@ -20,17 +19,15 @@ describe('Boards blank state', () => {
reject();
} else {
resolve({
json() {
return [{
id: 1,
title: 'To Do',
label: { id: 1 },
}, {
id: 2,
title: 'Doing',
label: { id: 2 },
}];
},
data: [{
id: 1,
title: 'To Do',
label: { id: 1 },
}, {
id: 2,
title: 'Doing',
label: { id: 2 },
}],
});
}
}));

View file

@ -1,12 +1,11 @@
/* global List */
/* global ListAssignee */
/* global ListLabel */
/* global listObj */
/* global boardsMockInterceptor */
/* global BoardService */
/* global mockBoardService */
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import '~/boards/models/assignee';
import eventHub from '~/boards/eventhub';
@ -14,13 +13,15 @@ import '~/boards/models/list';
import '~/boards/models/label';
import '~/boards/stores/boards_store';
import boardCard from '~/boards/components/board_card.vue';
import './mock_data';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('Board card', () => {
let vm;
let mock;
beforeEach((done) => {
Vue.http.interceptors.push(boardsMockInterceptor);
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
gl.issueBoards.BoardsStore.create();
@ -54,7 +55,7 @@ describe('Board card', () => {
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
mock.reset();
});
it('returns false when detailIssue is empty', () => {

View file

@ -1,11 +1,9 @@
/* global BoardService */
/* global boardsMockInterceptor */
/* global List */
/* global listObj */
/* global ListIssue */
/* global mockBoardService */
import Vue from 'vue';
import _ from 'underscore';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Sortable from 'vendor/Sortable';
import BoardList from '~/boards/components/board_list';
import eventHub from '~/boards/eventhub';
@ -13,18 +11,20 @@ import '~/boards/mixins/sortable_default_options';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/stores/boards_store';
import './mock_data';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
window.Sortable = Sortable;
describe('Board list component', () => {
let mock;
let component;
beforeEach((done) => {
const el = document.createElement('div');
document.body.appendChild(el);
Vue.http.interceptors.push(boardsMockInterceptor);
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
gl.issueBoards.BoardsStore.create();
gl.IssueBoardsApp = new Vue();
@ -60,7 +60,7 @@ describe('Board list component', () => {
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
mock.reset();
});
it('renders component', () => {

View file

@ -1,24 +1,22 @@
/* global boardsMockInterceptor */
/* global BoardService */
/* global List */
/* global listObj */
/* global mockBoardService */
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import boardNewIssue from '~/boards/components/board_new_issue';
import '~/boards/models/list';
import './mock_data';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('Issue boards new issue form', () => {
let vm;
let list;
let mock;
let newIssueMock;
const promiseReturn = {
json() {
return {
iid: 100,
};
data: {
iid: 100,
},
};
@ -35,7 +33,9 @@ describe('Issue boards new issue form', () => {
const BoardNewIssueComp = Vue.extend(boardNewIssue);
Vue.http.interceptors.push(boardsMockInterceptor);
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
gl.issueBoards.BoardsStore.create();
gl.IssueBoardsApp = new Vue();
@ -56,7 +56,10 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
afterEach(() => vm.$destroy());
afterEach(() => {
vm.$destroy();
mock.reset();
});
it('calls submit if submit button is clicked', (done) => {
spyOn(vm, 'submit').and.callFake(e => e.preventDefault());

View file

@ -1,12 +1,10 @@
/* eslint-disable comma-dangle, one-var, no-unused-vars */
/* global BoardService */
/* global boardsMockInterceptor */
/* global listObj */
/* global listObjDuplicate */
/* global ListIssue */
/* global mockBoardService */
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Cookies from 'js-cookie';
import '~/boards/models/issue';
@ -15,11 +13,14 @@ import '~/boards/models/list';
import '~/boards/models/assignee';
import '~/boards/services/board_service';
import '~/boards/stores/boards_store';
import './mock_data';
import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('Store', () => {
let mock;
beforeEach(() => {
Vue.http.interceptors.push(boardsMockInterceptor);
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
gl.issueBoards.BoardsStore.create();
@ -34,7 +35,7 @@ describe('Store', () => {
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
mock.reset();
});
it('starts with a blank state', () => {

View file

@ -1,9 +1,8 @@
/* global mockBoardService */
import Vue from 'vue';
import '~/boards/services/board_service';
import '~/boards/components/board';
import '~/boards/models/list';
import '../mock_data';
import { mockBoardService } from '../mock_data';
describe('Board component', () => {
let vm;

View file

@ -1,6 +1,5 @@
/* global ListAssignee */
/* global ListLabel */
/* global listObj */
/* global ListIssue */
import Vue from 'vue';
@ -11,7 +10,7 @@ import '~/boards/models/list';
import '~/boards/models/assignee';
import '~/boards/stores/boards_store';
import '~/boards/components/issue_card_inner';
import './mock_data';
import { listObj } from './mock_data';
describe('Issue card component', () => {
const user = new ListAssignee({

View file

@ -1,7 +1,6 @@
/* eslint-disable comma-dangle */
/* global BoardService */
/* global ListIssue */
/* global mockBoardService */
import Vue from 'vue';
import '~/boards/models/issue';
@ -10,7 +9,7 @@ import '~/boards/models/list';
import '~/boards/models/assignee';
import '~/boards/services/board_service';
import '~/boards/stores/boards_store';
import './mock_data';
import { mockBoardService } from './mock_data';
describe('Issue model', () => {
let issue;

View file

@ -1,13 +1,10 @@
/* eslint-disable comma-dangle */
/* global boardsMockInterceptor */
/* global BoardService */
/* global mockBoardService */
/* global List */
/* global ListIssue */
/* global listObj */
/* global listObjDuplicate */
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import '~/boards/models/issue';
import '~/boards/models/label';
@ -15,13 +12,15 @@ import '~/boards/models/list';
import '~/boards/models/assignee';
import '~/boards/services/board_service';
import '~/boards/stores/boards_store';
import './mock_data';
import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('List model', () => {
let list;
let mock;
beforeEach(() => {
Vue.http.interceptors.push(boardsMockInterceptor);
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService({
bulkUpdatePath: '/test/issue-boards/board/1/lists',
});
@ -31,7 +30,7 @@ describe('List model', () => {
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
mock.reset();
});
it('gets issues when created', (done) => {
@ -158,10 +157,8 @@ describe('List model', () => {
describe('newIssue', () => {
beforeEach(() => {
spyOn(gl.boardService, 'newIssue').and.returnValue(Promise.resolve({
json() {
return {
id: 42,
};
data: {
id: 42,
},
}));
});

View file

@ -1,20 +1,20 @@
/* global BoardService */
/* eslint-disable comma-dangle, no-unused-vars, quote-props */
const listObj = {
id: _.random(10000),
export const listObj = {
id: 300,
position: 0,
title: 'Test',
list_type: 'label',
label: {
id: _.random(10000),
id: 5000,
title: 'Testing',
color: 'red',
description: 'testing;'
}
};
const listObjDuplicate = {
export const listObjDuplicate = {
id: listObj.id,
position: 1,
title: 'Test',
@ -27,9 +27,9 @@ const listObjDuplicate = {
}
};
const BoardsMockData = {
export const BoardsMockData = {
'GET': {
'/test/boards/1{/id}/issues': {
'/test/-/boards/1/lists/300/issues?id=300&page=1&=': {
issues: [{
title: 'Testing',
id: 1,
@ -41,7 +41,7 @@ const BoardsMockData = {
}
},
'POST': {
'/test/boards/1{/id}': listObj
'/test/-/boards/1/lists': listObj
},
'PUT': {
'/test/issue-boards/board/1/lists{/id}': {}
@ -51,17 +51,14 @@ const BoardsMockData = {
}
};
const boardsMockInterceptor = (request, next) => {
const body = BoardsMockData[request.method][request.url];
next(request.respondWith(JSON.stringify(body), {
status: 200
}));
export const boardsMockInterceptor = (config) => {
const body = BoardsMockData[config.method.toUpperCase()][config.url];
return [200, body];
};
const mockBoardService = (opts = {}) => {
const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/board';
const listsEndpoint = opts.listsEndpoint || '/test/boards/1';
export const mockBoardService = (opts = {}) => {
const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/boards.json';
const listsEndpoint = opts.listsEndpoint || '/test/-/boards/1/lists';
const bulkUpdatePath = opts.bulkUpdatePath || '';
const boardId = opts.boardId || '1';
@ -72,9 +69,3 @@ const mockBoardService = (opts = {}) => {
boardId,
});
};
window.listObj = listObj;
window.listObjDuplicate = listObjDuplicate;
window.BoardsMockData = BoardsMockData;
window.boardsMockInterceptor = boardsMockInterceptor;
window.mockBoardService = mockBoardService;