debian-mirror-gitlab/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
2023-06-20 00:43:36 +05:30

133 lines
3.7 KiB
Vue

<script>
import { GlIntersectionObserver, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
import produce from 'immer';
import { createAlert } from '~/alert';
import { __ } from '~/locale';
import eventHub from '~/jobs/components/table/event_hub';
import JobsTable from '~/jobs/components/table/jobs_table.vue';
import { JOBS_TAB_FIELDS } from '~/jobs/components/table/constants';
import getPipelineJobs from '../../graphql/queries/get_pipeline_jobs.query.graphql';
export default {
fields: JOBS_TAB_FIELDS,
components: {
GlIntersectionObserver,
GlLoadingIcon,
GlSkeletonLoader,
JobsTable,
},
inject: {
projectPath: {
default: '',
},
pipelineIid: {
default: '',
},
},
apollo: {
jobs: {
query: getPipelineJobs,
variables() {
return {
...this.queryVariables,
};
},
update(data) {
return data.project?.pipeline?.jobs?.nodes || [];
},
result({ data }) {
if (!data) {
return;
}
this.jobsPageInfo = data.project?.pipeline?.jobs?.pageInfo || {};
},
error() {
createAlert({ message: __('An error occurred while fetching the pipelines jobs.') });
},
},
},
data() {
return {
jobs: [],
jobsPageInfo: {},
firstLoad: true,
};
},
computed: {
queryVariables() {
return {
fullPath: this.projectPath,
iid: this.pipelineIid,
};
},
loading() {
return this.$apollo.queries.jobs.loading;
},
showSkeletonLoader() {
return this.firstLoad && this.loading;
},
showLoadingSpinner() {
return !this.firstLoad && this.loading;
},
},
mounted() {
eventHub.$on('jobActionPerformed', this.handleJobAction);
},
beforeDestroy() {
eventHub.$off('jobActionPerformed', this.handleJobAction);
},
methods: {
handleJobAction() {
this.firstLoad = false;
this.$apollo.queries.jobs.refetch();
},
fetchMoreJobs() {
this.firstLoad = false;
this.$apollo.queries.jobs.fetchMore({
variables: {
...this.queryVariables,
after: this.jobsPageInfo.endCursor,
},
updateQuery: (previousResult, { fetchMoreResult }) => {
const results = produce(fetchMoreResult, (draftData) => {
draftData.project.pipeline.jobs.nodes = [
...previousResult.project.pipeline.jobs.nodes,
...draftData.project.pipeline.jobs.nodes,
];
});
return results;
},
});
},
},
};
</script>
<template>
<div>
<div v-if="showSkeletonLoader" class="gl-mt-5">
<gl-skeleton-loader :width="1248" :height="73">
<circle cx="748.031" cy="37.7193" r="15.0307" />
<circle cx="787.241" cy="37.7193" r="15.0307" />
<circle cx="827.759" cy="37.7193" r="15.0307" />
<circle cx="866.969" cy="37.7193" r="15.0307" />
<circle cx="380" cy="37" r="18" />
<rect x="432" y="19" width="126.587" height="15" />
<rect x="432" y="41" width="247" height="15" />
<rect x="158" y="19" width="86.1" height="15" />
<rect x="158" y="41" width="168" height="15" />
<rect x="22" y="19" width="96" height="36" />
<rect x="924" y="30" width="96" height="15" />
<rect x="1057" y="20" width="166" height="35" />
</gl-skeleton-loader>
</div>
<jobs-table v-else :jobs="jobs" :table-fields="$options.fields" data-testid="jobs-tab-table" />
<gl-intersection-observer v-if="jobsPageInfo.hasNextPage" @appear="fetchMoreJobs">
<gl-loading-icon v-if="showLoadingSpinner" size="lg" />
</gl-intersection-observer>
</div>
</template>