Uses new Vuex store in job log page

Removes old mediator and service pattern and uses the new store.
Middle step before moving everything into one single vue app
This commit is contained in:
Filipa Lacerda 2018-09-27 14:13:17 +01:00
parent d5bce06df1
commit 49bd01cf24
9 changed files with 38 additions and 174 deletions

View File

@ -1,34 +1,36 @@
import { mapState } from 'vuex';
import Vue from 'vue';
import JobMediator from './job_details_mediator';
import jobHeader from './components/header.vue';
import detailsBlock from './components/sidebar_details_block.vue';
import Job from '../job';
import JobHeader from './components/header.vue';
import DetailsBlock from './components/sidebar_details_block.vue';
import createStore from './store';
export default () => {
const { dataset } = document.getElementById('js-job-details-vue');
const mediator = new JobMediator({ endpoint: dataset.endpoint });
mediator.fetchJob();
// eslint-disable-next-line no-new
new Job();
const store = createStore();
store.dispatch('setJobEndpoint', dataset.endpoint);
store.dispatch('fetchJob');
// Header
// eslint-disable-next-line no-new
new Vue({
el: '#js-build-header-vue',
components: {
jobHeader,
JobHeader,
},
data() {
return {
mediator,
};
},
mounted() {
this.mediator.initBuildClass();
store,
computed: {
...mapState(['job', 'isLoading']),
},
render(createElement) {
return createElement('job-header', {
props: {
isLoading: this.mediator.state.isLoading,
job: this.mediator.store.state.job,
isLoading: this.isLoading,
job: this.job,
},
});
},
@ -41,18 +43,17 @@ export default () => {
new Vue({
el: detailsBlockElement,
components: {
detailsBlock,
DetailsBlock,
},
data() {
return {
mediator,
};
store,
computed: {
...mapState(['job', 'isLoading']),
},
render(createElement) {
return createElement('details-block', {
props: {
isLoading: this.mediator.state.isLoading,
job: this.mediator.store.state.job,
isLoading: this.isLoading,
job: this.job,
runnerHelpUrl: dataset.runnerHelpUrl,
terminalPath: detailsBlockDataset.terminalPath,
},

View File

@ -1,65 +0,0 @@
import Visibility from 'visibilityjs';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import JobStore from './stores/job_store';
import JobService from './services/job_service';
import Job from '../job';
export default class JobMediator {
constructor(options = {}) {
this.options = options;
this.store = new JobStore();
this.service = new JobService(options.endpoint);
this.state = {
isLoading: false,
};
}
initBuildClass() {
this.build = new Job();
}
fetchJob() {
this.poll = new Poll({
resource: this.service,
method: 'getJob',
successCallback: response => this.successCallback(response),
errorCallback: () => this.errorCallback(),
});
if (!Visibility.hidden()) {
this.state.isLoading = true;
this.poll.makeRequest();
} else {
this.getJob();
}
Visibility.change(() => {
if (!Visibility.hidden()) {
this.poll.restart();
} else {
this.poll.stop();
}
});
}
getJob() {
return this.service
.getJob()
.then(response => this.successCallback(response))
.catch(() => this.errorCallback());
}
successCallback(response) {
this.state.isLoading = false;
return this.store.storeJob(response.data);
}
errorCallback() {
this.state.isLoading = false;
return new Flash('An error occurred while fetching the job.');
}
}

View File

@ -1,11 +0,0 @@
import axios from '../../lib/utils/axios_utils';
export default class JobService {
constructor(endpoint) {
this.job = endpoint;
}
getJob() {
return axios.get(this.job);
}
}

View File

@ -1,6 +1,9 @@
import * as types from './mutation_types';
export default {
[types.SET_JOB_ENDPOINT](state, endpoint) {
state.jobEndpoint = endpoint;
},
[types.REQUEST_STATUS_FAVICON](state) {
state.fetchingStatusFavicon = true;
},

View File

@ -1,11 +0,0 @@
export default class JobStore {
constructor() {
this.state = {
job: {},
};
}
storeJob(job = {}) {
this.state.job = job;
}
}

View File

@ -0,0 +1,5 @@
---
title: Uses Vuex store in job details page and removes old mediator pattern
merge_request:
author:
type: other

View File

@ -1,39 +0,0 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import JobMediator from '~/jobs/job_details_mediator';
import job from '../mock_data';
describe('JobMediator', () => {
let mediator;
let mock;
beforeEach(() => {
mediator = new JobMediator({ endpoint: 'jobs/40291672.json' });
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
it('should set defaults', () => {
expect(mediator.store).toBeDefined();
expect(mediator.service).toBeDefined();
expect(mediator.options).toEqual({ endpoint: 'jobs/40291672.json' });
expect(mediator.state.isLoading).toEqual(false);
});
describe('request and store data', () => {
beforeEach(() => {
mock.onGet().reply(200, job, {});
});
it('should store received data', (done) => {
mediator.fetchJob();
setTimeout(() => {
expect(mediator.store.state.job).toEqual(job);
done();
}, 0);
});
});
});

View File

@ -1,26 +0,0 @@
import JobStore from '~/jobs/stores/job_store';
import job from '../mock_data';
describe('Job Store', () => {
let store;
beforeEach(() => {
store = new JobStore();
});
it('should set defaults', () => {
expect(store.state.job).toEqual({});
});
describe('storeJob', () => {
it('should store empty object if none is provided', () => {
store.storeJob();
expect(store.state.job).toEqual({});
});
it('should store provided argument', () => {
store.storeJob(job);
expect(store.state.job).toEqual(job);
});
});
});

View File

@ -12,6 +12,13 @@ describe('Jobs Store Mutations', () => {
stateCopy = state();
});
describe('SET_JOB_ENDPOINT', () => {
it('should set jobEndpoint', () => {
mutations[types.SET_JOB_ENDPOINT](stateCopy, 'job/21312321.json');
expect(stateCopy.jobEndpoint).toEqual('job/21312321.json');
});
});
describe('REQUEST_STATUS_FAVICON', () => {
it('should set fetchingStatusFavicon to true', () => {
mutations[types.REQUEST_STATUS_FAVICON](stateCopy);