Uniformize code between both pipelines tables
This commit is contained in:
parent
1d15ad02cb
commit
05cfba6f6d
|
@ -1,29 +1,25 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import Vue from 'vue';
|
||||
import VueResource from 'vue-resource';
|
||||
import CommitPipelinesTable from './pipelines_table';
|
||||
|
||||
Vue.use(VueResource);
|
||||
import commitPipelinesTable from './pipelines_table.vue';
|
||||
|
||||
/**
|
||||
* Commits View > Pipelines Tab > Pipelines Table.
|
||||
*
|
||||
* Renders Pipelines table in pipelines tab in the commits show view.
|
||||
* Used in:
|
||||
* - Commit details View > Pipelines Tab > Pipelines Table.
|
||||
* - Merge Request details View > Pipelines Tab > Pipelines Table.
|
||||
* - New Merge Request View > Pipelines Tab > Pipelines Table.
|
||||
*/
|
||||
|
||||
// export for use in merge_request_tabs.js (TODO: remove this hack)
|
||||
window.gl = window.gl || {};
|
||||
window.gl.CommitPipelinesTable = CommitPipelinesTable;
|
||||
|
||||
$(() => {
|
||||
gl.commits = gl.commits || {};
|
||||
gl.commits.pipelines = gl.commits.pipelines || {};
|
||||
const CommitPipelinesTable = Vue.extend(commitPipelinesTable);
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
|
||||
|
||||
if (pipelineTableViewEl && pipelineTableViewEl.dataset.disableInitialization === undefined) {
|
||||
gl.commits.pipelines.PipelinesTableBundle = new CommitPipelinesTable().$mount();
|
||||
pipelineTableViewEl.appendChild(gl.commits.pipelines.PipelinesTableBundle.$el);
|
||||
const table = new CommitPipelinesTable({
|
||||
propsData: {
|
||||
endpoint: pipelineTableViewEl.dataset.endpoint,
|
||||
helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
|
||||
},
|
||||
}).$mount();
|
||||
pipelineTableViewEl.appendChild(table.$el);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,191 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import Visibility from 'visibilityjs';
|
||||
import pipelinesTableComponent from '../../vue_shared/components/pipelines_table.vue';
|
||||
import PipelinesService from '../../pipelines/services/pipelines_service';
|
||||
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
||||
import eventHub from '../../pipelines/event_hub';
|
||||
import emptyState from '../../pipelines/components/empty_state.vue';
|
||||
import errorState from '../../pipelines/components/error_state.vue';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
import '../../lib/utils/common_utils';
|
||||
import '../../vue_shared/vue_resource_interceptor';
|
||||
import Poll from '../../lib/utils/poll';
|
||||
|
||||
/**
|
||||
*
|
||||
* Uses `pipelines-table-component` to render Pipelines table with an API call.
|
||||
* Endpoint is provided in HTML and passed as `endpoint`.
|
||||
* We need a store to store the received environemnts.
|
||||
* We need a service to communicate with the server.
|
||||
*
|
||||
*/
|
||||
|
||||
export default Vue.component('pipelines-table', {
|
||||
|
||||
components: {
|
||||
pipelinesTableComponent,
|
||||
errorState,
|
||||
emptyState,
|
||||
loadingIcon,
|
||||
},
|
||||
|
||||
/**
|
||||
* Accesses the DOM to provide the needed data.
|
||||
* Returns the necessary props to render `pipelines-table-component` component.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
data() {
|
||||
const store = new PipelineStore();
|
||||
|
||||
return {
|
||||
endpoint: null,
|
||||
helpPagePath: null,
|
||||
store,
|
||||
state: store.state,
|
||||
isLoading: false,
|
||||
hasError: false,
|
||||
isMakingRequest: false,
|
||||
updateGraphDropdown: false,
|
||||
hasMadeRequest: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
shouldRenderErrorState() {
|
||||
return this.hasError && !this.isLoading;
|
||||
},
|
||||
|
||||
/**
|
||||
* Empty state is only rendered if after the first request we receive no pipelines.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
shouldRenderEmptyState() {
|
||||
return !this.state.pipelines.length &&
|
||||
!this.isLoading &&
|
||||
this.hasMadeRequest &&
|
||||
!this.hasError;
|
||||
},
|
||||
|
||||
shouldRenderTable() {
|
||||
return !this.isLoading &&
|
||||
this.state.pipelines.length > 0 &&
|
||||
!this.hasError;
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* When the component is about to be mounted, tell the service to fetch the data
|
||||
*
|
||||
* A request to fetch the pipelines will be made.
|
||||
* In case of a successfull response we will store the data in the provided
|
||||
* store, in case of a failed response we need to warn the user.
|
||||
*
|
||||
*/
|
||||
beforeMount() {
|
||||
const element = document.querySelector('#commit-pipeline-table-view');
|
||||
|
||||
this.endpoint = element.dataset.endpoint;
|
||||
this.helpPagePath = element.dataset.helpPagePath;
|
||||
this.service = new PipelinesService(this.endpoint);
|
||||
|
||||
this.poll = new Poll({
|
||||
resource: this.service,
|
||||
method: 'getPipelines',
|
||||
successCallback: this.successCallback,
|
||||
errorCallback: this.errorCallback,
|
||||
notificationCallback: this.setIsMakingRequest,
|
||||
});
|
||||
|
||||
if (!Visibility.hidden()) {
|
||||
this.isLoading = true;
|
||||
this.poll.makeRequest();
|
||||
} else {
|
||||
// If tab is not visible we need to make the first request so we don't show the empty
|
||||
// state without knowing if there are any pipelines
|
||||
this.fetchPipelines();
|
||||
}
|
||||
|
||||
Visibility.change(() => {
|
||||
if (!Visibility.hidden()) {
|
||||
this.poll.restart();
|
||||
} else {
|
||||
this.poll.stop();
|
||||
}
|
||||
});
|
||||
|
||||
eventHub.$on('refreshPipelines', this.fetchPipelines);
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
eventHub.$off('refreshPipelines');
|
||||
},
|
||||
|
||||
destroyed() {
|
||||
this.poll.stop();
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchPipelines() {
|
||||
this.isLoading = true;
|
||||
|
||||
return this.service.getPipelines()
|
||||
.then(response => this.successCallback(response))
|
||||
.catch(() => this.errorCallback());
|
||||
},
|
||||
|
||||
successCallback(resp) {
|
||||
const response = resp.json();
|
||||
|
||||
this.hasMadeRequest = true;
|
||||
|
||||
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
||||
const pipelines = response.pipelines || response;
|
||||
this.store.storePipelines(pipelines);
|
||||
this.isLoading = false;
|
||||
this.updateGraphDropdown = true;
|
||||
},
|
||||
|
||||
errorCallback() {
|
||||
this.hasError = true;
|
||||
this.isLoading = false;
|
||||
this.updateGraphDropdown = false;
|
||||
},
|
||||
|
||||
setIsMakingRequest(isMakingRequest) {
|
||||
this.isMakingRequest = isMakingRequest;
|
||||
|
||||
if (isMakingRequest) {
|
||||
this.updateGraphDropdown = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
template: `
|
||||
<div class="content-list pipelines">
|
||||
|
||||
<loading-icon
|
||||
label="Loading pipelines"
|
||||
size="3"
|
||||
v-if="isLoading"
|
||||
/>
|
||||
|
||||
<empty-state
|
||||
v-if="shouldRenderEmptyState"
|
||||
:help-page-path="helpPagePath" />
|
||||
|
||||
<error-state v-if="shouldRenderErrorState" />
|
||||
|
||||
<div
|
||||
class="table-holder"
|
||||
v-if="shouldRenderTable">
|
||||
<pipelines-table-component
|
||||
:pipelines="state.pipelines"
|
||||
:service="service"
|
||||
:update-graph-dropdown="updateGraphDropdown"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,90 @@
|
|||
<script>
|
||||
import PipelinesService from '../../pipelines/services/pipelines_service';
|
||||
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
||||
import pipelinesMixin from '../../pipelines/mixins/pipelines';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
endpoint: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
helpPagePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
mixins: [
|
||||
pipelinesMixin,
|
||||
],
|
||||
|
||||
data() {
|
||||
const store = new PipelineStore();
|
||||
|
||||
return {
|
||||
store,
|
||||
state: store.state,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Empty state is only rendered if after the first request we receive no pipelines.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
shouldRenderEmptyState() {
|
||||
return !this.state.pipelines.length &&
|
||||
!this.isLoading &&
|
||||
this.hasMadeRequest &&
|
||||
!this.hasError;
|
||||
},
|
||||
|
||||
shouldRenderTable() {
|
||||
return !this.isLoading &&
|
||||
this.state.pipelines.length > 0 &&
|
||||
!this.hasError;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.service = new PipelinesService(this.endpoint);
|
||||
},
|
||||
methods: {
|
||||
successCallback(resp) {
|
||||
const response = resp.json();
|
||||
|
||||
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
||||
const pipelines = response.pipelines || response;
|
||||
this.setCommonData(pipelines);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="content-list pipelines">
|
||||
|
||||
<loading-icon
|
||||
label="Loading pipelines"
|
||||
size="3"
|
||||
v-if="isLoading"
|
||||
/>
|
||||
|
||||
<empty-state
|
||||
v-if="shouldRenderEmptyState"
|
||||
:help-page-path="helpPagePath"
|
||||
/>
|
||||
|
||||
<error-state
|
||||
v-if="shouldRenderErrorState"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="table-holder"
|
||||
v-if="shouldRenderTable">
|
||||
<pipelines-table-component
|
||||
:pipelines="state.pipelines"
|
||||
:update-graph-dropdown="updateGraphDropdown"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -3,10 +3,12 @@
|
|||
/* global Flash */
|
||||
/* global notes */
|
||||
|
||||
import Vue from 'vue';
|
||||
import Cookies from 'js-cookie';
|
||||
import './breakpoints';
|
||||
import './flash';
|
||||
import BlobForkSuggestion from './blob/blob_fork_suggestion';
|
||||
import commitPipelinesTable from './commit/pipelines/pipelines_table.vue';
|
||||
|
||||
/* eslint-disable max-len */
|
||||
// MergeRequestTabs
|
||||
|
@ -233,11 +235,18 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion';
|
|||
}
|
||||
|
||||
mountPipelinesView() {
|
||||
this.commitPipelinesTable = new gl.CommitPipelinesTable().$mount();
|
||||
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
|
||||
const CommitPipelinesTable = Vue.extend(commitPipelinesTable);
|
||||
this.commitPipelinesTable = new CommitPipelinesTable({
|
||||
propsData: {
|
||||
endpoint: pipelineTableViewEl.dataset.endpoint,
|
||||
helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
// $mount(el) replaces the el with the new rendered component. We need it in order to mount
|
||||
// it everytime this tab is clicked - https://vuejs.org/v2/api/#vm-mount
|
||||
document.querySelector('#commit-pipeline-table-view')
|
||||
.appendChild(this.commitPipelinesTable.$el);
|
||||
pipelineTableViewEl.appendChild(this.commitPipelinesTable.$el);
|
||||
}
|
||||
|
||||
loadDiff(source) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script>
|
||||
/* eslint-disable no-new, no-alert */
|
||||
/* global Flash */
|
||||
import '~/flash';
|
||||
|
||||
import eventHub from '../event_hub';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
import tooltipMixin from '../../vue_shared/mixins/tooltip';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -11,53 +11,42 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
service: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
cssClass: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
confirmActionMessage: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
loadingIcon,
|
||||
},
|
||||
|
||||
mixins: [
|
||||
tooltipMixin,
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
iconClass() {
|
||||
return `fa fa-${this.icon}`;
|
||||
},
|
||||
|
||||
buttonClass() {
|
||||
return `btn has-tooltip ${this.cssClass}`;
|
||||
return `btn ${this.cssClass}`;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClick() {
|
||||
if (this.confirmActionMessage && confirm(this.confirmActionMessage)) {
|
||||
|
@ -66,21 +55,11 @@ export default {
|
|||
this.makeRequest();
|
||||
}
|
||||
},
|
||||
|
||||
makeRequest() {
|
||||
this.isLoading = true;
|
||||
|
||||
$(this.$el).tooltip('destroy');
|
||||
|
||||
this.service.postAction(this.endpoint)
|
||||
.then(() => {
|
||||
this.isLoading = false;
|
||||
eventHub.$emit('refreshPipelines');
|
||||
})
|
||||
.catch(() => {
|
||||
this.isLoading = false;
|
||||
new Flash('An error occured while making the request.');
|
||||
});
|
||||
$(this.$refs.tooltip).tooltip('destroy');
|
||||
eventHub.$emit('postAction', this.endpoint);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -95,10 +74,12 @@ export default {
|
|||
:aria-label="title"
|
||||
data-container="body"
|
||||
data-placement="top"
|
||||
ref="tooltip"
|
||||
:disabled="isLoading">
|
||||
<i
|
||||
:class="iconClass"
|
||||
aria-hidden="true" />
|
||||
aria-hidden="true">
|
||||
</i>
|
||||
<loading-icon v-if="isLoading" />
|
||||
</button>
|
||||
</template>
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
<script>
|
||||
import Visibility from 'visibilityjs';
|
||||
import PipelinesService from '../services/pipelines_service';
|
||||
import eventHub from '../event_hub';
|
||||
import pipelinesTableComponent from '../../vue_shared/components/pipelines_table.vue';
|
||||
import pipelinesMixin from '../mixins/pipelines';
|
||||
import tablePagination from '../../vue_shared/components/table_pagination.vue';
|
||||
import emptyState from './empty_state.vue';
|
||||
import errorState from './error_state.vue';
|
||||
import navigationTabs from './navigation_tabs.vue';
|
||||
import navigationControls from './nav_controls.vue';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
import Poll from '../../lib/utils/poll';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -20,13 +14,12 @@
|
|||
},
|
||||
components: {
|
||||
tablePagination,
|
||||
pipelinesTableComponent,
|
||||
emptyState,
|
||||
errorState,
|
||||
navigationTabs,
|
||||
navigationControls,
|
||||
loadingIcon,
|
||||
},
|
||||
mixins: [
|
||||
pipelinesMixin,
|
||||
],
|
||||
data() {
|
||||
const pipelinesData = document.querySelector('#pipelines-list-vue').dataset;
|
||||
|
||||
|
@ -47,11 +40,6 @@
|
|||
state: this.store.state,
|
||||
apiScope: 'all',
|
||||
pagenum: 1,
|
||||
isLoading: false,
|
||||
hasError: false,
|
||||
isMakingRequest: false,
|
||||
updateGraphDropdown: false,
|
||||
hasMadeRequest: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -62,9 +50,6 @@
|
|||
const scope = gl.utils.getParameterByName('scope');
|
||||
return scope === null ? 'all' : scope;
|
||||
},
|
||||
shouldRenderErrorState() {
|
||||
return this.hasError && !this.isLoading;
|
||||
},
|
||||
|
||||
/**
|
||||
* The empty state should only be rendered when the request is made to fetch all pipelines
|
||||
|
@ -106,7 +91,6 @@
|
|||
this.state.pipelines.length &&
|
||||
this.state.pageInfo.total > this.state.pageInfo.perPage;
|
||||
},
|
||||
|
||||
hasCiEnabled() {
|
||||
return this.hasCi !== undefined;
|
||||
},
|
||||
|
@ -129,37 +113,7 @@
|
|||
},
|
||||
created() {
|
||||
this.service = new PipelinesService(this.endpoint);
|
||||
|
||||
const poll = new Poll({
|
||||
resource: this.service,
|
||||
method: 'getPipelines',
|
||||
data: { page: this.pageParameter, scope: this.scopeParameter },
|
||||
successCallback: this.successCallback,
|
||||
errorCallback: this.errorCallback,
|
||||
notificationCallback: this.setIsMakingRequest,
|
||||
});
|
||||
|
||||
if (!Visibility.hidden()) {
|
||||
this.isLoading = true;
|
||||
poll.makeRequest();
|
||||
} else {
|
||||
// If tab is not visible we need to make the first request so we don't show the empty
|
||||
// state without knowing if there are any pipelines
|
||||
this.fetchPipelines();
|
||||
}
|
||||
|
||||
Visibility.change(() => {
|
||||
if (!Visibility.hidden()) {
|
||||
poll.restart();
|
||||
} else {
|
||||
poll.stop();
|
||||
}
|
||||
});
|
||||
|
||||
eventHub.$on('refreshPipelines', this.fetchPipelines);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('refreshPipelines');
|
||||
this.requestData = { page: this.pageParameter, scope: this.scopeParameter };
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
|
@ -174,15 +128,6 @@
|
|||
return param;
|
||||
},
|
||||
|
||||
fetchPipelines() {
|
||||
if (!this.isMakingRequest) {
|
||||
this.isLoading = true;
|
||||
|
||||
this.service.getPipelines({ scope: this.scopeParameter, page: this.pageParameter })
|
||||
.then(response => this.successCallback(response))
|
||||
.catch(() => this.errorCallback());
|
||||
}
|
||||
},
|
||||
successCallback(resp) {
|
||||
const response = {
|
||||
headers: resp.headers,
|
||||
|
@ -190,33 +135,14 @@
|
|||
};
|
||||
|
||||
this.store.storeCount(response.body.count);
|
||||
this.store.storePipelines(response.body.pipelines);
|
||||
this.store.storePagination(response.headers);
|
||||
|
||||
this.isLoading = false;
|
||||
this.updateGraphDropdown = true;
|
||||
this.hasMadeRequest = true;
|
||||
},
|
||||
|
||||
errorCallback() {
|
||||
this.hasError = true;
|
||||
this.isLoading = false;
|
||||
this.updateGraphDropdown = false;
|
||||
},
|
||||
|
||||
setIsMakingRequest(isMakingRequest) {
|
||||
this.isMakingRequest = isMakingRequest;
|
||||
|
||||
if (isMakingRequest) {
|
||||
this.updateGraphDropdown = false;
|
||||
}
|
||||
this.setCommonData(response.body.pipelines);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div :class="cssClass">
|
||||
|
||||
<div
|
||||
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
|
||||
v-if="!isLoading && !shouldRenderEmptyState">
|
||||
|
@ -274,7 +200,6 @@
|
|||
|
||||
<pipelines-table-component
|
||||
:pipelines="state.pipelines"
|
||||
:service="service"
|
||||
:update-graph-dropdown="updateGraphDropdown"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -11,10 +11,6 @@
|
|||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
service: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
loadingIcon,
|
||||
|
@ -31,17 +27,9 @@
|
|||
|
||||
$(this.$refs.tooltip).tooltip('destroy');
|
||||
|
||||
this.service.postAction(endpoint)
|
||||
.then(() => {
|
||||
this.isLoading = false;
|
||||
eventHub.$emit('refreshPipelines');
|
||||
})
|
||||
.catch(() => {
|
||||
this.isLoading = false;
|
||||
// eslint-disable-next-line no-new
|
||||
new Flash('An error occured while making the request.');
|
||||
});
|
||||
eventHub.$emit('postAction', endpoint);
|
||||
},
|
||||
|
||||
isActionDisabled(action) {
|
||||
if (action.playable === undefined) {
|
||||
return false;
|
||||
|
|
|
@ -12,10 +12,6 @@
|
|||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
service: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
updateGraphDropdown: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
@ -57,7 +53,6 @@
|
|||
v-for="model in pipelines"
|
||||
:key="model.id"
|
||||
:pipeline="model"
|
||||
:service="service"
|
||||
:update-graph-dropdown="updateGraphDropdown"
|
||||
/>
|
||||
</div>
|
|
@ -1,13 +1,13 @@
|
|||
<script>
|
||||
/* eslint-disable no-param-reassign */
|
||||
import asyncButtonComponent from '../../pipelines/components/async_button.vue';
|
||||
import pipelinesActionsComponent from '../../pipelines/components/pipelines_actions.vue';
|
||||
import pipelinesArtifactsComponent from '../../pipelines/components/pipelines_artifacts.vue';
|
||||
import ciBadge from './ci_badge_link.vue';
|
||||
import pipelineStage from '../../pipelines/components/stage.vue';
|
||||
import pipelineUrl from '../../pipelines/components/pipeline_url.vue';
|
||||
import pipelinesTimeago from '../../pipelines/components/time_ago.vue';
|
||||
import commitComponent from './commit.vue';
|
||||
import asyncButtonComponent from './async_button.vue';
|
||||
import pipelinesActionsComponent from './pipelines_actions.vue';
|
||||
import pipelinesArtifactsComponent from './pipelines_artifacts.vue';
|
||||
import ciBadge from '../../vue_shared/components/ci_badge_link.vue';
|
||||
import pipelineStage from './stage.vue';
|
||||
import pipelineUrl from './pipeline_url.vue';
|
||||
import pipelinesTimeago from './time_ago.vue';
|
||||
import commitComponent from '../../vue_shared/components/commit.vue';
|
||||
|
||||
/**
|
||||
* Pipeline table row.
|
||||
|
@ -20,10 +20,6 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
service: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
updateGraphDropdown: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
@ -271,7 +267,6 @@ export default {
|
|||
<pipelines-actions-component
|
||||
v-if="pipeline.details.manual_actions.length"
|
||||
:actions="pipeline.details.manual_actions"
|
||||
:service="service"
|
||||
/>
|
||||
|
||||
<pipelines-artifacts-component
|
||||
|
@ -282,7 +277,6 @@ export default {
|
|||
|
||||
<async-button-component
|
||||
v-if="pipeline.flags.retryable"
|
||||
:service="service"
|
||||
:endpoint="pipeline.retry_path"
|
||||
css-class="js-pipelines-retry-button btn-default btn-retry"
|
||||
title="Retry"
|
||||
|
@ -291,7 +285,6 @@ export default {
|
|||
|
||||
<async-button-component
|
||||
v-if="pipeline.flags.cancelable"
|
||||
:service="service"
|
||||
:endpoint="pipeline.cancel_path"
|
||||
css-class="js-pipelines-cancel-button btn-remove"
|
||||
title="Cancel"
|
|
@ -0,0 +1,103 @@
|
|||
/* global Flash */
|
||||
import '~/flash';
|
||||
import Visibility from 'visibilityjs';
|
||||
import Poll from '../../lib/utils/poll';
|
||||
import emptyState from '../components/empty_state.vue';
|
||||
import errorState from '../components/error_state.vue';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
import pipelinesTableComponent from '../components/pipelines_table.vue';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
pipelinesTableComponent,
|
||||
errorState,
|
||||
emptyState,
|
||||
loadingIcon,
|
||||
},
|
||||
computed: {
|
||||
shouldRenderErrorState() {
|
||||
return this.hasError && !this.isLoading;
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
hasError: false,
|
||||
isMakingRequest: false,
|
||||
updateGraphDropdown: false,
|
||||
hasMadeRequest: false,
|
||||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.poll = new Poll({
|
||||
resource: this.service,
|
||||
method: 'getPipelines',
|
||||
data: this.requestData ? this.requestData : undefined,
|
||||
successCallback: this.successCallback,
|
||||
errorCallback: this.errorCallback,
|
||||
notificationCallback: this.setIsMakingRequest,
|
||||
});
|
||||
|
||||
if (!Visibility.hidden()) {
|
||||
this.isLoading = true;
|
||||
this.poll.makeRequest();
|
||||
} else {
|
||||
// If tab is not visible we need to make the first request so we don't show the empty
|
||||
// state without knowing if there are any pipelines
|
||||
this.fetchPipelines();
|
||||
}
|
||||
|
||||
Visibility.change(() => {
|
||||
if (!Visibility.hidden()) {
|
||||
this.poll.restart();
|
||||
} else {
|
||||
this.poll.stop();
|
||||
}
|
||||
});
|
||||
|
||||
eventHub.$on('refreshPipelines', this.fetchPipelines);
|
||||
eventHub.$on('postAction', this.postAction);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('refreshPipelines');
|
||||
eventHub.$on('postAction', this.postAction);
|
||||
},
|
||||
destroyed() {
|
||||
this.poll.stop();
|
||||
},
|
||||
methods: {
|
||||
fetchPipelines() {
|
||||
if (!this.isMakingRequest) {
|
||||
this.isLoading = true;
|
||||
|
||||
this.service.getPipelines(this.requestData)
|
||||
.then(response => this.successCallback(response))
|
||||
.catch(() => this.errorCallback());
|
||||
}
|
||||
},
|
||||
setCommonData(pipelines) {
|
||||
this.store.storePipelines(pipelines);
|
||||
this.isLoading = false;
|
||||
this.updateGraphDropdown = true;
|
||||
this.hasMadeRequest = true;
|
||||
},
|
||||
errorCallback() {
|
||||
this.hasError = true;
|
||||
this.isLoading = false;
|
||||
this.updateGraphDropdown = false;
|
||||
},
|
||||
setIsMakingRequest(isMakingRequest) {
|
||||
this.isMakingRequest = isMakingRequest;
|
||||
|
||||
if (isMakingRequest) {
|
||||
this.updateGraphDropdown = false;
|
||||
}
|
||||
},
|
||||
postAction(endpoint) {
|
||||
this.service.postAction(endpoint)
|
||||
.then(() => eventHub.$emit('refreshPipelines'))
|
||||
.catch(() => new Flash('An error occured while making the request.'));
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,15 +1,15 @@
|
|||
import Vue from 'vue';
|
||||
import PipelinesTable from '~/commit/pipelines/pipelines_table';
|
||||
import pipelinesTable from '~/commit/pipelines/pipelines_table.vue';
|
||||
|
||||
describe('Pipelines table in Commits and Merge requests', () => {
|
||||
const jsonFixtureName = 'pipelines/pipelines.json';
|
||||
let pipeline;
|
||||
let PipelinesTable;
|
||||
|
||||
preloadFixtures('static/pipelines_table.html.raw');
|
||||
preloadFixtures(jsonFixtureName);
|
||||
|
||||
beforeEach(() => {
|
||||
loadFixtures('static/pipelines_table.html.raw');
|
||||
PipelinesTable = Vue.extend(pipelinesTable);
|
||||
const pipelines = getJSONFixture(jsonFixtureName).pipelines;
|
||||
pipeline = pipelines.find(p => p.id === 1);
|
||||
});
|
||||
|
@ -26,8 +26,11 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
Vue.http.interceptors.push(pipelinesEmptyResponse);
|
||||
|
||||
this.component = new PipelinesTable({
|
||||
el: document.querySelector('#commit-pipeline-table-view'),
|
||||
});
|
||||
propsData: {
|
||||
endpoint: 'endpoint',
|
||||
helpPagePath: 'foo',
|
||||
},
|
||||
}).$mount();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
@ -58,8 +61,11 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
Vue.http.interceptors.push(pipelinesResponse);
|
||||
|
||||
this.component = new PipelinesTable({
|
||||
el: document.querySelector('#commit-pipeline-table-view'),
|
||||
});
|
||||
propsData: {
|
||||
endpoint: 'endpoint',
|
||||
helpPagePath: 'foo',
|
||||
},
|
||||
}).$mount();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -92,8 +98,11 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
|||
Vue.http.interceptors.push(pipelinesErrorResponse);
|
||||
|
||||
this.component = new PipelinesTable({
|
||||
el: document.querySelector('#commit-pipeline-table-view'),
|
||||
});
|
||||
propsData: {
|
||||
endpoint: 'endpoint',
|
||||
helpPagePath: 'foo',
|
||||
},
|
||||
}).$mount();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#commit-pipeline-table-view{ data: { endpoint: "endpoint", "help-page-path": "foo" } }
|
|
@ -1,25 +1,20 @@
|
|||
import Vue from 'vue';
|
||||
import asyncButtonComp from '~/pipelines/components/async_button.vue';
|
||||
import eventHub from '~/pipelines/event_hub';
|
||||
|
||||
describe('Pipelines Async Button', () => {
|
||||
let component;
|
||||
let spy;
|
||||
let AsyncButtonComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
AsyncButtonComponent = Vue.extend(asyncButtonComp);
|
||||
|
||||
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
|
||||
|
||||
component = new AsyncButtonComponent({
|
||||
propsData: {
|
||||
endpoint: '/foo',
|
||||
title: 'Foo',
|
||||
icon: 'fa fa-foo',
|
||||
cssClass: 'bar',
|
||||
service: {
|
||||
postAction: spy,
|
||||
},
|
||||
},
|
||||
}).$mount();
|
||||
});
|
||||
|
@ -33,7 +28,7 @@ describe('Pipelines Async Button', () => {
|
|||
});
|
||||
|
||||
it('should render the provided title', () => {
|
||||
expect(component.$el.getAttribute('title')).toContain('Foo');
|
||||
expect(component.$el.getAttribute('data-original-title')).toContain('Foo');
|
||||
expect(component.$el.getAttribute('aria-label')).toContain('Foo');
|
||||
});
|
||||
|
||||
|
@ -41,37 +36,12 @@ describe('Pipelines Async Button', () => {
|
|||
expect(component.$el.getAttribute('class')).toContain('bar');
|
||||
});
|
||||
|
||||
it('should call the service when it is clicked with the provided endpoint', () => {
|
||||
component.$el.click();
|
||||
expect(spy).toHaveBeenCalledWith('/foo');
|
||||
});
|
||||
|
||||
it('should hide loading if request fails', () => {
|
||||
spy = jasmine.createSpy('spy').and.returnValue(Promise.reject());
|
||||
|
||||
component = new AsyncButtonComponent({
|
||||
propsData: {
|
||||
endpoint: '/foo',
|
||||
title: 'Foo',
|
||||
icon: 'fa fa-foo',
|
||||
cssClass: 'bar',
|
||||
dataAttributes: {
|
||||
'data-foo': 'foo',
|
||||
},
|
||||
service: {
|
||||
postAction: spy,
|
||||
},
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
component.$el.click();
|
||||
expect(component.$el.querySelector('.fa-spinner')).toBe(null);
|
||||
});
|
||||
|
||||
describe('With confirm dialog', () => {
|
||||
it('should call the service when confimation is positive', () => {
|
||||
spyOn(window, 'confirm').and.returnValue(true);
|
||||
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
|
||||
eventHub.$on('postAction', (endpoint) => {
|
||||
expect(endpoint).toEqual('/foo');
|
||||
});
|
||||
|
||||
component = new AsyncButtonComponent({
|
||||
propsData: {
|
||||
|
@ -79,15 +49,11 @@ describe('Pipelines Async Button', () => {
|
|||
title: 'Foo',
|
||||
icon: 'fa fa-foo',
|
||||
cssClass: 'bar',
|
||||
service: {
|
||||
postAction: spy,
|
||||
},
|
||||
confirmActionMessage: 'bar',
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
component.$el.click();
|
||||
expect(spy).toHaveBeenCalledWith('/foo');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,6 @@ import pipelinesActionsComp from '~/pipelines/components/pipelines_actions.vue';
|
|||
|
||||
describe('Pipelines Actions dropdown', () => {
|
||||
let component;
|
||||
let spy;
|
||||
let actions;
|
||||
let ActionsComponent;
|
||||
|
||||
|
@ -22,14 +21,9 @@ describe('Pipelines Actions dropdown', () => {
|
|||
},
|
||||
];
|
||||
|
||||
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
|
||||
|
||||
component = new ActionsComponent({
|
||||
propsData: {
|
||||
actions,
|
||||
service: {
|
||||
postAction: spy,
|
||||
},
|
||||
},
|
||||
}).$mount();
|
||||
});
|
||||
|
@ -40,31 +34,6 @@ describe('Pipelines Actions dropdown', () => {
|
|||
).toEqual(actions.length);
|
||||
});
|
||||
|
||||
it('should call the service when an action is clicked', () => {
|
||||
component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click();
|
||||
component.$el.querySelector('.js-pipeline-action-link').click();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(actions[0].path);
|
||||
});
|
||||
|
||||
it('should hide loading if request fails', () => {
|
||||
spy = jasmine.createSpy('spy').and.returnValue(Promise.reject());
|
||||
|
||||
component = new ActionsComponent({
|
||||
propsData: {
|
||||
actions,
|
||||
service: {
|
||||
postAction: spy,
|
||||
},
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click();
|
||||
component.$el.querySelector('.js-pipeline-action-link').click();
|
||||
|
||||
expect(component.$el.querySelector('.fa-spinner')).toEqual(null);
|
||||
});
|
||||
|
||||
it('should render a disabled action when it\'s not playable', () => {
|
||||
expect(
|
||||
component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
import tableRowComp from '~/vue_shared/components/pipelines_table_row.vue';
|
||||
import tableRowComp from '~/pipelines/components/pipelines_table_row.vue';
|
||||
|
||||
describe('Pipelines Table Row', () => {
|
||||
const jsonFixtureName = 'pipelines/pipelines.json';
|
|
@ -1,5 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
import pipelinesTableComp from '~/vue_shared/components/pipelines_table.vue';
|
||||
import pipelinesTableComp from '~/pipelines/components/pipelines_table.vue';
|
||||
import '~/lib/utils/datetime_utility';
|
||||
|
||||
describe('Pipelines Table', () => {
|
||||
|
@ -22,7 +22,6 @@ describe('Pipelines Table', () => {
|
|||
component = new PipelinesTableComponent({
|
||||
propsData: {
|
||||
pipelines: [],
|
||||
service: {},
|
||||
},
|
||||
}).$mount();
|
||||
});
|
||||
|
@ -48,7 +47,6 @@ describe('Pipelines Table', () => {
|
|||
const component = new PipelinesTableComponent({
|
||||
propsData: {
|
||||
pipelines: [],
|
||||
service: {},
|
||||
},
|
||||
}).$mount();
|
||||
expect(component.$el.querySelectorAll('.commit.gl-responsive-table-row').length).toEqual(0);
|
||||
|
@ -58,10 +56,8 @@ describe('Pipelines Table', () => {
|
|||
describe('with data', () => {
|
||||
it('should render rows', () => {
|
||||
const component = new PipelinesTableComponent({
|
||||
el: document.querySelector('.test-dom-element'),
|
||||
propsData: {
|
||||
pipelines: [pipeline],
|
||||
service: {},
|
||||
},
|
||||
}).$mount();
|
||||
|
Loading…
Reference in New Issue