Commit 013a90e5 authored by PaytonBurdette's avatar PaytonBurdette Committed by Payton Burdette

Disable action buttons on click

After first click disable action buttons
for jobs table. On next fetch they are
enabled again. This will prevent extra
api requests.
parent 9f4a28ae
......@@ -58,6 +58,14 @@ export default {
required: true,
},
},
data() {
return {
retryBtnDisabled: false,
cancelBtnDisabled: false,
playManualBtnDisabled: false,
unscheduleBtnDisabled: false,
};
},
computed: {
hasArtifacts() {
return this.job.artifacts.nodes.find((artifact) => artifact.fileType === FILE_TYPE_ARCHIVE);
......@@ -132,15 +140,23 @@ export default {
});
},
cancelJob() {
this.cancelBtnDisabled = true;
this.postJobAction(this.$options.jobCancel, cancelJobMutation);
},
retryJob() {
this.retryBtnDisabled = true;
this.postJobAction(this.$options.jobRetry, retryJobMutation);
},
playJob() {
this.playManualBtnDisabled = true;
this.postJobAction(this.$options.jobPlay, playJobMutation);
},
unscheduleJob() {
this.unscheduleBtnDisabled = true;
this.postJobAction(this.$options.jobUnschedule, unscheduleJobMutation);
},
},
......@@ -155,6 +171,7 @@ export default {
data-testid="cancel-button"
icon="cancel"
:title="$options.CANCEL"
:disabled="cancelBtnDisabled"
@click="cancelJob()"
/>
<template v-else-if="isScheduled">
......@@ -179,6 +196,7 @@ export default {
<gl-button
icon="time-out"
:title="$options.ACTIONS_UNSCHEDULE"
:disabled="unscheduleBtnDisabled"
data-testid="unschedule"
@click="unscheduleJob()"
/>
......@@ -189,6 +207,7 @@ export default {
v-if="manualJobPlayable"
icon="play"
:title="$options.ACTIONS_PLAY"
:disabled="playManualBtnDisabled"
data-testid="play"
@click="playJob()"
/>
......@@ -197,6 +216,7 @@ export default {
icon="repeat"
:title="$options.ACTIONS_RETRY"
:method="currentJobMethod"
:disabled="retryBtnDisabled"
data-testid="retry"
@click="retryJob()"
/>
......
import { GlModal } from '@gitlab/ui';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ActionsCell from '~/jobs/components/table/cells/actions_cell.vue';
import JobPlayMutation from '~/jobs/components/table/graphql/mutations/job_play.mutation.graphql';
import JobRetryMutation from '~/jobs/components/table/graphql/mutations/job_retry.mutation.graphql';
import JobUnscheduleMutation from '~/jobs/components/table/graphql/mutations/job_unschedule.mutation.graphql';
import JobCancelMutation from '~/jobs/components/table/graphql/mutations/job_cancel.mutation.graphql';
import {
playableJob,
retryableJob,
cancelableJob,
scheduledJob,
cannotRetryJob,
cannotPlayJob,
......@@ -20,6 +23,7 @@ describe('Job actions cell', () => {
const findRetryButton = () => wrapper.findByTestId('retry');
const findPlayButton = () => wrapper.findByTestId('play');
const findCancelButton = () => wrapper.findByTestId('cancel-button');
const findDownloadArtifactsButton = () => wrapper.findByTestId('download-artifacts');
const findCountdownButton = () => wrapper.findByTestId('countdown');
const findPlayScheduledJobButton = () => wrapper.findByTestId('play-scheduled');
......@@ -32,6 +36,7 @@ describe('Job actions cell', () => {
data: { JobUnscheduleMutation: { jobId: scheduledJob.id } },
};
const MUTATION_SUCCESS_PLAY = { data: { JobPlayMutation: { jobId: playableJob.id } } };
const MUTATION_SUCCESS_CANCEL = { data: { JobCancelMutation: { jobId: cancelableJob.id } } };
const $toast = {
show: jest.fn(),
......@@ -88,6 +93,7 @@ describe('Job actions cell', () => {
${findPlayButton} | ${'play'} | ${playableJob}
${findRetryButton} | ${'retry'} | ${retryableJob}
${findDownloadArtifactsButton} | ${'download artifacts'} | ${playableJob}
${findCancelButton} | ${'cancel'} | ${cancelableJob}
`('displays the $action button', ({ button, jobType }) => {
createComponent(jobType);
......@@ -98,6 +104,7 @@ describe('Job actions cell', () => {
button | mutationResult | action | jobType | mutationFile
${findPlayButton} | ${MUTATION_SUCCESS_PLAY} | ${'play'} | ${playableJob} | ${JobPlayMutation}
${findRetryButton} | ${MUTATION_SUCCESS} | ${'retry'} | ${retryableJob} | ${JobRetryMutation}
${findCancelButton} | ${MUTATION_SUCCESS_CANCEL} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation}
`('performs the $action mutation', ({ button, mutationResult, jobType, mutationFile }) => {
createComponent(jobType, mutationResult);
......@@ -111,6 +118,24 @@ describe('Job actions cell', () => {
});
});
it.each`
button | action | jobType
${findPlayButton} | ${'play'} | ${playableJob}
${findRetryButton} | ${'retry'} | ${retryableJob}
${findCancelButton} | ${'cancel'} | ${cancelableJob}
${findUnscheduleButton} | ${'unschedule'} | ${scheduledJob}
`('disables the $action button after first request', async ({ button, jobType }) => {
createComponent(jobType);
expect(button().props('disabled')).toBe(false);
button().vm.$emit('click');
await waitForPromises();
expect(button().props('disabled')).toBe(true);
});
describe('Scheduled Jobs', () => {
const today = () => new Date('2021-08-31');
......
......@@ -1653,6 +1653,65 @@ export const retryableJob = {
__typename: 'CiJob',
};
export const cancelableJob = {
artifacts: {
nodes: [],
__typename: 'CiJobArtifactConnection',
},
allowFailure: false,
status: 'PENDING',
scheduledAt: null,
manualJob: false,
triggered: null,
createdByTag: false,
detailedStatus: {
id: 'pending-1305-1305',
detailsPath: '/root/lots-of-jobs-project/-/jobs/1305',
group: 'pending',
icon: 'status_pending',
label: 'pending',
text: 'pending',
tooltip: 'pending',
action: {
id: 'Ci::Build-pending-1305',
buttonTitle: 'Cancel this job',
icon: 'cancel',
method: 'post',
path: '/root/lots-of-jobs-project/-/jobs/1305/cancel',
title: 'Cancel',
__typename: 'StatusAction',
},
__typename: 'DetailedStatus',
},
id: 'gid://gitlab/Ci::Build/1305',
refName: 'main',
refPath: '/root/lots-of-jobs-project/-/commits/main',
tags: [],
shortSha: '750605f2',
commitPath: '/root/lots-of-jobs-project/-/commit/750605f29530778cf0912779eba6d073128962a5',
stage: {
id: 'gid://gitlab/Ci::Stage/181',
name: 'deploy',
__typename: 'CiStage',
},
name: 'job_212',
duration: null,
finishedAt: null,
coverage: null,
retryable: false,
playable: false,
cancelable: true,
active: true,
stuck: false,
userPermissions: {
readBuild: true,
readJobArtifacts: true,
updateBuild: true,
__typename: 'JobPermissions',
},
__typename: 'CiJob',
};
export const cannotRetryJob = {
...retryableJob,
userPermissions: { readBuild: true, updateBuild: false, __typename: 'JobPermissions' },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment