Merge branch '50904-use-vuex-store-job' into 'master'
Uses new Vuex store in job log page See merge request gitlab-org/gitlab-ce!21961
This commit is contained in:
commit
1eefdf5da5
9 changed files with 38 additions and 174 deletions
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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.');
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
export default class JobStore {
|
||||
constructor() {
|
||||
this.state = {
|
||||
job: {},
|
||||
};
|
||||
}
|
||||
|
||||
storeJob(job = {}) {
|
||||
this.state.job = job;
|
||||
}
|
||||
}
|
5
changelogs/unreleased/50904-use-vuex-store-job.yml
Normal file
5
changelogs/unreleased/50904-use-vuex-store-job.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Uses Vuex store in job details page and removes old mediator pattern
|
||||
merge_request:
|
||||
author:
|
||||
type: other
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue