debian-mirror-gitlab/app/assets/javascripts/pipelines/components/pipelines.vue

281 lines
7.8 KiB
Vue
Raw Normal View History

2017-09-10 17:25:29 +05:30
<script>
2018-03-17 18:26:18 +05:30
import _ from 'underscore';
2017-09-10 17:25:29 +05:30
import PipelinesService from '../services/pipelines_service';
import pipelinesMixin from '../mixins/pipelines';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
2018-03-17 18:26:18 +05:30
import navigationTabs from '../../vue_shared/components/navigation_tabs.vue';
2017-09-10 17:25:29 +05:30
import navigationControls from './nav_controls.vue';
2018-03-17 18:26:18 +05:30
import {
convertPermissionToBoolean,
getParameterByName,
parseQueryStringIntoObject,
} from '../../lib/utils/common_utils';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
2017-09-10 17:25:29 +05:30
export default {
components: {
tablePagination,
navigationTabs,
navigationControls,
},
mixins: [
pipelinesMixin,
2018-03-17 18:26:18 +05:30
CIPaginationMixin,
2017-09-10 17:25:29 +05:30
],
2018-03-17 18:26:18 +05:30
props: {
store: {
type: Object,
required: true,
},
// Can be rendered in 3 different places, with some visual differences
// Accepts root | child
// `root` -> main view
// `child` -> rendered inside MR or Commit View
viewType: {
type: String,
required: false,
default: 'root',
},
},
2017-09-10 17:25:29 +05:30
data() {
const pipelinesData = document.querySelector('#pipelines-list-vue').dataset;
return {
endpoint: pipelinesData.endpoint,
helpPagePath: pipelinesData.helpPagePath,
2018-03-17 18:26:18 +05:30
emptyStateSvgPath: pipelinesData.emptyStateSvgPath,
errorStateSvgPath: pipelinesData.errorStateSvgPath,
autoDevopsPath: pipelinesData.helpAutoDevopsPath,
2017-09-10 17:25:29 +05:30
newPipelinePath: pipelinesData.newPipelinePath,
canCreatePipeline: pipelinesData.canCreatePipeline,
hasCi: pipelinesData.hasCi,
ciLintPath: pipelinesData.ciLintPath,
2018-03-17 18:26:18 +05:30
resetCachePath: pipelinesData.resetCachePath,
2017-09-10 17:25:29 +05:30
state: this.store.state,
2018-03-17 18:26:18 +05:30
scope: getParameterByName('scope') || 'all',
page: getParameterByName('page') || '1',
requestData: {},
2017-09-10 17:25:29 +05:30
};
},
computed: {
canCreatePipelineParsed() {
2018-03-17 18:26:18 +05:30
return convertPermissionToBoolean(this.canCreatePipeline);
2017-09-10 17:25:29 +05:30
},
/**
* The empty state should only be rendered when the request is made to fetch all pipelines
* and none is returned.
*
* @return {Boolean}
*/
shouldRenderEmptyState() {
return !this.isLoading &&
!this.hasError &&
this.hasMadeRequest &&
!this.state.pipelines.length &&
(this.scope === 'all' || this.scope === null);
},
/**
* When a specific scope does not have pipelines we render a message.
*
* @return {Boolean}
*/
shouldRenderNoPipelinesMessage() {
return !this.isLoading &&
!this.hasError &&
!this.state.pipelines.length &&
this.scope !== 'all' &&
this.scope !== null;
},
shouldRenderTable() {
return !this.hasError &&
!this.isLoading && this.state.pipelines.length;
},
/**
* Pagination should only be rendered when there is more than one page.
*
* @return {Boolean}
*/
shouldRenderPagination() {
return !this.isLoading &&
this.state.pipelines.length &&
this.state.pageInfo.total > this.state.pageInfo.perPage;
},
hasCiEnabled() {
return this.hasCi !== undefined;
},
2018-03-17 18:26:18 +05:30
tabs() {
const { count } = this.state;
return [
{
name: 'All',
scope: 'all',
count: count.all,
isActive: this.scope === 'all',
},
{
name: 'Pending',
scope: 'pending',
count: count.pending,
isActive: this.scope === 'pending',
},
{
name: 'Running',
scope: 'running',
count: count.running,
isActive: this.scope === 'running',
},
{
name: 'Finished',
scope: 'finished',
count: count.finished,
isActive: this.scope === 'finished',
},
{
name: 'Branches',
scope: 'branches',
isActive: this.scope === 'branches',
},
{
name: 'Tags',
scope: 'tags',
isActive: this.scope === 'tags',
},
];
2017-09-10 17:25:29 +05:30
},
},
created() {
this.service = new PipelinesService(this.endpoint);
2018-03-17 18:26:18 +05:30
this.requestData = { page: this.page, scope: this.scope };
2017-09-10 17:25:29 +05:30
},
methods: {
2018-03-17 18:26:18 +05:30
successCallback(resp) {
return resp.json().then((response) => {
// Because we are polling & the user is interacting verify if the response received
// matches the last request made
if (_.isEqual(parseQueryStringIntoObject(resp.url.split('?')[1]), this.requestData)) {
this.store.storeCount(response.count);
this.store.storePagination(resp.headers);
this.setCommonData(response.pipelines);
}
});
},
2017-09-10 17:25:29 +05:30
/**
2018-03-17 18:26:18 +05:30
* Handles URL and query parameter changes.
* When the user uses the pagination or the tabs,
* - update URL
* - Make API request to the server with new parameters
* - Update the polling function
* - Update the internal state
2017-09-10 17:25:29 +05:30
*/
2018-03-17 18:26:18 +05:30
updateContent(parameters) {
this.updateInternalState(parameters);
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
// fetch new data
return this.service.getPipelines(this.requestData)
.then((response) => {
this.isLoading = false;
this.successCallback(response);
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
// restart polling
this.poll.restart({ data: this.requestData });
})
.catch(() => {
this.isLoading = false;
this.errorCallback();
// restart polling
this.poll.restart();
});
2017-09-10 17:25:29 +05:30
},
},
};
</script>
<template>
2018-03-17 18:26:18 +05:30
<div class="pipelines-container">
2017-09-10 17:25:29 +05:30
<div
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
2018-03-17 18:26:18 +05:30
v-if="!shouldRenderEmptyState"
>
2017-09-10 17:25:29 +05:30
<div class="fade-left">
<i
class="fa fa-angle-left"
aria-hidden="true">
</i>
</div>
<div class="fade-right">
<i
class="fa fa-angle-right"
aria-hidden="true">
</i>
</div>
2018-03-17 18:26:18 +05:30
2017-09-10 17:25:29 +05:30
<navigation-tabs
2018-03-17 18:26:18 +05:30
:tabs="tabs"
@onChangeTab="onChangeTab"
scope="pipelines"
/>
2017-09-10 17:25:29 +05:30
<navigation-controls
:new-pipeline-path="newPipelinePath"
:has-ci-enabled="hasCiEnabled"
:help-page-path="helpPagePath"
2018-03-17 18:26:18 +05:30
:reset-cache-path="resetCachePath"
:ci-lint-path="ciLintPath"
2017-09-10 17:25:29 +05:30
:can-create-pipeline="canCreatePipelineParsed "
2018-03-17 18:26:18 +05:30
/>
2017-09-10 17:25:29 +05:30
</div>
<div class="content-list pipelines">
<loading-icon
label="Loading Pipelines"
size="3"
v-if="isLoading"
2018-03-17 18:26:18 +05:30
class="prepend-top-20"
/>
2017-09-10 17:25:29 +05:30
<empty-state
v-if="shouldRenderEmptyState"
:help-page-path="helpPagePath"
2018-03-17 18:26:18 +05:30
:empty-state-svg-path="emptyStateSvgPath"
/>
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
<error-state
v-if="shouldRenderErrorState"
:error-state-svg-path="errorStateSvgPath"
/>
2017-09-10 17:25:29 +05:30
<div
2018-03-17 18:26:18 +05:30
class="blank-state-row"
v-if="shouldRenderNoPipelinesMessage"
>
<div class="blank-state-center">
<h2 class="blank-state-title js-blank-state-title">No pipelines to show.</h2>
</div>
2017-09-10 17:25:29 +05:30
</div>
<div
class="table-holder"
2018-03-17 18:26:18 +05:30
v-if="shouldRenderTable"
>
2017-09-10 17:25:29 +05:30
<pipelines-table-component
:pipelines="state.pipelines"
:update-graph-dropdown="updateGraphDropdown"
2018-03-17 18:26:18 +05:30
:auto-devops-help-path="autoDevopsPath"
:view-type="viewType"
/>
2017-09-10 17:25:29 +05:30
</div>
<table-pagination
v-if="shouldRenderPagination"
2018-03-17 18:26:18 +05:30
:change="onChangePage"
:page-info="state.pageInfo"
/>
2017-09-10 17:25:29 +05:30
</div>
</div>
</template>