289 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| import Vue from 'vue';
 | |
| import Visibility from 'visibilityjs';
 | |
| import PipelinesService from './services/pipelines_service';
 | |
| import eventHub from './event_hub';
 | |
| import PipelinesTableComponent from '../vue_shared/components/pipelines_table';
 | |
| import TablePaginationComponent from '../vue_shared/components/table_pagination';
 | |
| import EmptyState from './components/empty_state';
 | |
| import ErrorState from './components/error_state';
 | |
| import NavigationTabs from './components/navigation_tabs';
 | |
| import NavigationControls from './components/nav_controls';
 | |
| import Poll from '../lib/utils/poll';
 | |
| 
 | |
| export default {
 | |
|   props: {
 | |
|     store: {
 | |
|       type: Object,
 | |
|       required: true,
 | |
|     },
 | |
|   },
 | |
| 
 | |
|   components: {
 | |
|     'gl-pagination': TablePaginationComponent,
 | |
|     'pipelines-table-component': PipelinesTableComponent,
 | |
|     'empty-state': EmptyState,
 | |
|     'error-state': ErrorState,
 | |
|     'navigation-tabs': NavigationTabs,
 | |
|     'navigation-controls': NavigationControls,
 | |
|   },
 | |
| 
 | |
|   data() {
 | |
|     const pipelinesData = document.querySelector('#pipelines-list-vue').dataset;
 | |
| 
 | |
|     return {
 | |
|       endpoint: pipelinesData.endpoint,
 | |
|       cssClass: pipelinesData.cssClass,
 | |
|       helpPagePath: pipelinesData.helpPagePath,
 | |
|       newPipelinePath: pipelinesData.newPipelinePath,
 | |
|       canCreatePipeline: pipelinesData.canCreatePipeline,
 | |
|       allPath: pipelinesData.allPath,
 | |
|       pendingPath: pipelinesData.pendingPath,
 | |
|       runningPath: pipelinesData.runningPath,
 | |
|       finishedPath: pipelinesData.finishedPath,
 | |
|       branchesPath: pipelinesData.branchesPath,
 | |
|       tagsPath: pipelinesData.tagsPath,
 | |
|       hasCi: pipelinesData.hasCi,
 | |
|       ciLintPath: pipelinesData.ciLintPath,
 | |
|       state: this.store.state,
 | |
|       apiScope: 'all',
 | |
|       pagenum: 1,
 | |
|       isLoading: false,
 | |
|       hasError: false,
 | |
|       isMakingRequest: false,
 | |
|     };
 | |
|   },
 | |
| 
 | |
|   computed: {
 | |
|     canCreatePipelineParsed() {
 | |
|       return gl.utils.convertPermissionToBoolean(this.canCreatePipeline);
 | |
|     },
 | |
| 
 | |
|     scope() {
 | |
|       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
 | |
|     * and none is returned.
 | |
|     *
 | |
|     * @return {Boolean}
 | |
|     */
 | |
|     shouldRenderEmptyState() {
 | |
|       return !this.isLoading &&
 | |
|         !this.hasError &&
 | |
|         !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;
 | |
|     },
 | |
| 
 | |
|     paths() {
 | |
|       return {
 | |
|         allPath: this.allPath,
 | |
|         pendingPath: this.pendingPath,
 | |
|         finishedPath: this.finishedPath,
 | |
|         runningPath: this.runningPath,
 | |
|         branchesPath: this.branchesPath,
 | |
|         tagsPath: this.tagsPath,
 | |
|       };
 | |
|     },
 | |
| 
 | |
|     pageParameter() {
 | |
|       return gl.utils.getParameterByName('page') || this.pagenum;
 | |
|     },
 | |
| 
 | |
|     scopeParameter() {
 | |
|       return gl.utils.getParameterByName('scope') || this.apiScope;
 | |
|     },
 | |
|   },
 | |
| 
 | |
|   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();
 | |
|     }
 | |
| 
 | |
|     Visibility.change(() => {
 | |
|       if (!Visibility.hidden()) {
 | |
|         poll.restart();
 | |
|       } else {
 | |
|         poll.stop();
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     eventHub.$on('refreshPipelines', this.fetchPipelines);
 | |
|   },
 | |
| 
 | |
|   beforeUpdate() {
 | |
|     if (this.state.pipelines.length &&
 | |
|         this.$children &&
 | |
|         !this.isMakingRequest &&
 | |
|         !this.isLoading) {
 | |
|       this.store.startTimeAgoLoops.call(this, Vue);
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   beforeDestroyed() {
 | |
|     eventHub.$off('refreshPipelines');
 | |
|   },
 | |
| 
 | |
|   methods: {
 | |
|     /**
 | |
|      * Will change the page number and update the URL.
 | |
|      *
 | |
|      * @param  {Number} pageNumber desired page to go to.
 | |
|      */
 | |
|     change(pageNumber) {
 | |
|       const param = gl.utils.setParamInURL('page', pageNumber);
 | |
| 
 | |
|       gl.utils.visitUrl(param);
 | |
|       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,
 | |
|         body: resp.json(),
 | |
|       };
 | |
| 
 | |
|       this.store.storeCount(response.body.count);
 | |
|       this.store.storePipelines(response.body.pipelines);
 | |
|       this.store.storePagination(response.headers);
 | |
| 
 | |
|       this.isLoading = false;
 | |
|     },
 | |
| 
 | |
|     errorCallback() {
 | |
|       this.hasError = true;
 | |
|       this.isLoading = false;
 | |
|     },
 | |
| 
 | |
|     setIsMakingRequest(isMakingRequest) {
 | |
|       this.isMakingRequest = isMakingRequest;
 | |
|     },
 | |
|   },
 | |
| 
 | |
|   template: `
 | |
|     <div :class="cssClass">
 | |
| 
 | |
|       <div
 | |
|         class="top-area scrolling-tabs-container inner-page-scroll-tabs"
 | |
|         v-if="!isLoading && !shouldRenderEmptyState">
 | |
|         <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>
 | |
|         <navigation-tabs
 | |
|           :scope="scope"
 | |
|           :count="state.count"
 | |
|           :paths="paths" />
 | |
| 
 | |
|         <navigation-controls
 | |
|           :new-pipeline-path="newPipelinePath"
 | |
|           :has-ci-enabled="hasCiEnabled"
 | |
|           :help-page-path="helpPagePath"
 | |
|           :ciLintPath="ciLintPath"
 | |
|           :can-create-pipeline="canCreatePipelineParsed " />
 | |
|       </div>
 | |
| 
 | |
|       <div class="content-list pipelines">
 | |
| 
 | |
|         <div
 | |
|           class="realtime-loading"
 | |
|           v-if="isLoading">
 | |
|           <i
 | |
|             class="fa fa-spinner fa-spin"
 | |
|             aria-hidden="true" />
 | |
|         </div>
 | |
| 
 | |
|         <empty-state
 | |
|           v-if="shouldRenderEmptyState"
 | |
|           :help-page-path="helpPagePath" />
 | |
| 
 | |
|         <error-state v-if="shouldRenderErrorState" />
 | |
| 
 | |
|         <div
 | |
|           class="blank-state blank-state-no-icon"
 | |
|           v-if="shouldRenderNoPipelinesMessage">
 | |
|           <h2 class="blank-state-title js-blank-state-title">No pipelines to show.</h2>
 | |
|         </div>
 | |
| 
 | |
|         <div
 | |
|           class="table-holder"
 | |
|           v-if="shouldRenderTable">
 | |
| 
 | |
|           <pipelines-table-component
 | |
|             :pipelines="state.pipelines"
 | |
|             :service="service"/>
 | |
|         </div>
 | |
| 
 | |
|         <gl-pagination
 | |
|           v-if="shouldRenderPagination"
 | |
|           :pagenum="pagenum"
 | |
|           :change="change"
 | |
|           :count="state.count.all"
 | |
|           :pageInfo="state.pageInfo"/>
 | |
|       </div>
 | |
|     </div>
 | |
|   `,
 | |
| };
 |