Commit 49bd01cf authored by Filipa Lacerda's avatar Filipa Lacerda

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
parent d5bce06d
import { mapState } from 'vuex';
import Vue from 'vue'; import Vue from 'vue';
import JobMediator from './job_details_mediator'; import Job from '../job';
import jobHeader from './components/header.vue'; import JobHeader from './components/header.vue';
import detailsBlock from './components/sidebar_details_block.vue'; import DetailsBlock from './components/sidebar_details_block.vue';
import createStore from './store';
export default () => { export default () => {
const { dataset } = document.getElementById('js-job-details-vue'); 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 // Header
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
el: '#js-build-header-vue', el: '#js-build-header-vue',
components: { components: {
jobHeader, JobHeader,
},
data() {
return {
mediator,
};
}, },
mounted() { store,
this.mediator.initBuildClass(); computed: {
...mapState(['job', 'isLoading']),
}, },
render(createElement) { render(createElement) {
return createElement('job-header', { return createElement('job-header', {
props: { props: {
isLoading: this.mediator.state.isLoading, isLoading: this.isLoading,
job: this.mediator.store.state.job, job: this.job,
}, },
}); });
}, },
...@@ -41,18 +43,17 @@ export default () => { ...@@ -41,18 +43,17 @@ export default () => {
new Vue({ new Vue({
el: detailsBlockElement, el: detailsBlockElement,
components: { components: {
detailsBlock, DetailsBlock,
}, },
data() { store,
return { computed: {
mediator, ...mapState(['job', 'isLoading']),
};
}, },
render(createElement) { render(createElement) {
return createElement('details-block', { return createElement('details-block', {
props: { props: {
isLoading: this.mediator.state.isLoading, isLoading: this.isLoading,
job: this.mediator.store.state.job, job: this.job,
runnerHelpUrl: dataset.runnerHelpUrl, runnerHelpUrl: dataset.runnerHelpUrl,
terminalPath: detailsBlockDataset.terminalPath, terminalPath: detailsBlockDataset.terminalPath,
}, },
......
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.');
}
}
import axios from '../../lib/utils/axios_utils';
export default class JobService {
constructor(endpoint) {
this.job = endpoint;
}
getJob() {
return axios.get(this.job);
}
}
import * as types from './mutation_types'; import * as types from './mutation_types';
export default { export default {
[types.SET_JOB_ENDPOINT](state, endpoint) {
state.jobEndpoint = endpoint;
},
[types.REQUEST_STATUS_FAVICON](state) { [types.REQUEST_STATUS_FAVICON](state) {
state.fetchingStatusFavicon = true; state.fetchingStatusFavicon = true;
}, },
......
export default class JobStore {
constructor() {
this.state = {
job: {},
};
}
storeJob(job = {}) {
this.state.job = job;
}
}
---
title: Uses Vuex store in job details page and removes old mediator pattern
merge_request:
author:
type: other
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);
});
});
});
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);
});
});
});
...@@ -12,6 +12,13 @@ describe('Jobs Store Mutations', () => { ...@@ -12,6 +12,13 @@ describe('Jobs Store Mutations', () => {
stateCopy = state(); 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', () => { describe('REQUEST_STATUS_FAVICON', () => {
it('should set fetchingStatusFavicon to true', () => { it('should set fetchingStatusFavicon to true', () => {
mutations[types.REQUEST_STATUS_FAVICON](stateCopy); mutations[types.REQUEST_STATUS_FAVICON](stateCopy);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment