diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-16 21:09:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-16 21:09:43 +0300 |
commit | 0122d00cac3c058508a2fcb258f12ecfb7bc9055 (patch) | |
tree | b2a0e138ed4113e80588df57b542dc76d5360e2b /app/assets/javascripts/jobs | |
parent | f1357e5566b2c1f4f5e7b933b72a2d24431905e9 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/jobs')
8 files changed, 53 insertions, 394 deletions
diff --git a/app/assets/javascripts/jobs/components/job/empty_state.vue b/app/assets/javascripts/jobs/components/job/empty_state.vue index 053d5a4e740..d0a39025807 100644 --- a/app/assets/javascripts/jobs/components/job/empty_state.vue +++ b/app/assets/javascripts/jobs/components/job/empty_state.vue @@ -1,16 +1,12 @@ <script> import { GlLink } from '@gitlab/ui'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import LegacyManualVariablesForm from '~/jobs/components/job/legacy_manual_variables_form.vue'; import ManualVariablesForm from '~/jobs/components/job/manual_variables_form.vue'; export default { components: { GlLink, - LegacyManualVariablesForm, ManualVariablesForm, }, - mixins: [glFeatureFlagsMixin()], props: { illustrationPath: { type: String, @@ -22,7 +18,7 @@ export default { }, isRetryable: { type: Boolean, - required: false, + required: true, }, jobId: { type: Number, @@ -62,9 +58,6 @@ export default { }, }, computed: { - showGraphQLManualVariablesForm() { - return this.glFeatures?.graphqlJobApp && this.isRetryable; - }, shouldRenderManualVariables() { return this.playable && !this.scheduled; }, @@ -85,16 +78,12 @@ export default { <p v-if="content" data-testid="job-empty-state-content">{{ content }}</p> </div> - <template v-if="showGraphQLManualVariablesForm"> - <manual-variables-form - v-if="shouldRenderManualVariables" - :job-id="jobId" - @hideManualVariablesForm="$emit('hideManualVariablesForm')" - /> - </template> - <template v-else> - <legacy-manual-variables-form v-if="shouldRenderManualVariables" :action="action" /> - </template> + <manual-variables-form + v-if="shouldRenderManualVariables" + :is-retryable="isRetryable" + :job-id="jobId" + @hideManualVariablesForm="$emit('hideManualVariablesForm')" + /> <div v-if="action && !shouldRenderManualVariables" class="text-content"> <div class="text-center"> <gl-link diff --git a/app/assets/javascripts/jobs/components/job/legacy_manual_variables_form.vue b/app/assets/javascripts/jobs/components/job/legacy_manual_variables_form.vue deleted file mode 100644 index 2b6b6f8e59e..00000000000 --- a/app/assets/javascripts/jobs/components/job/legacy_manual_variables_form.vue +++ /dev/null @@ -1,199 +0,0 @@ -<script> -import { - GlFormInputGroup, - GlInputGroupText, - GlFormInput, - GlButton, - GlLink, - GlSprintf, - GlTooltipDirective, -} from '@gitlab/ui'; -import { uniqueId } from 'lodash'; -import { mapActions } from 'vuex'; -import { helpPagePath } from '~/helpers/help_page_helper'; -import { s__ } from '~/locale'; - -export default { - name: 'LegacyManualVariablesForm', - components: { - GlFormInputGroup, - GlInputGroupText, - GlFormInput, - GlButton, - GlLink, - GlSprintf, - }, - directives: { - GlTooltip: GlTooltipDirective, - }, - props: { - action: { - type: Object, - required: false, - default: null, - validator(value) { - return ( - value === null || - (Object.prototype.hasOwnProperty.call(value, 'path') && - Object.prototype.hasOwnProperty.call(value, 'method') && - Object.prototype.hasOwnProperty.call(value, 'button_title')) - ); - }, - }, - }, - inputTypes: { - key: 'key', - value: 'value', - }, - i18n: { - clearInputs: s__('CiVariables|Clear inputs'), - header: s__('CiVariables|Variables'), - keyLabel: s__('CiVariables|Key'), - valueLabel: s__('CiVariables|Value'), - keyPlaceholder: s__('CiVariables|Input variable key'), - valuePlaceholder: s__('CiVariables|Input variable value'), - formHelpText: s__( - 'CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default', - ), - }, - data() { - return { - variables: [ - { - key: '', - secretValue: '', - id: uniqueId(), - }, - ], - triggerBtnDisabled: false, - }; - }, - computed: { - variableSettings() { - return helpPagePath('ci/variables/index', { anchor: 'add-a-cicd-variable-to-a-project' }); - }, - preparedVariables() { - // we need to ensure no empty variables are passed to the API - // and secretValue should be snake_case when passed to the API - return this.variables - .filter((variable) => variable.key !== '') - .map(({ key, secretValue }) => ({ key, secret_value: secretValue })); - }, - }, - methods: { - ...mapActions(['triggerManualJob']), - addEmptyVariable() { - const lastVar = this.variables[this.variables.length - 1]; - - if (lastVar.key === '') { - return; - } - - this.variables.push({ - key: '', - secret_value: '', - id: uniqueId(), - }); - }, - canRemove(index) { - return index < this.variables.length - 1; - }, - deleteVariable(id) { - this.variables.splice( - this.variables.findIndex((el) => el.id === id), - 1, - ); - }, - inputRef(type, id) { - return `${this.$options.inputTypes[type]}-${id}`; - }, - trigger() { - this.triggerBtnDisabled = true; - - this.triggerManualJob(this.preparedVariables); - }, - }, -}; -</script> -<template> - <div class="row gl-justify-content-center"> - <div class="col-10" data-testid="manual-vars-form"> - <label>{{ $options.i18n.header }}</label> - - <div - v-for="(variable, index) in variables" - :key="variable.id" - class="gl-display-flex gl-align-items-center gl-mb-4" - data-testid="ci-variable-row" - > - <gl-form-input-group class="gl-mr-4 gl-flex-grow-1"> - <template #prepend> - <gl-input-group-text> - {{ $options.i18n.keyLabel }} - </gl-input-group-text> - </template> - <gl-form-input - :ref="inputRef('key', variable.id)" - v-model="variable.key" - :placeholder="$options.i18n.keyPlaceholder" - data-testid="ci-variable-key" - @change="addEmptyVariable" - /> - </gl-form-input-group> - - <gl-form-input-group class="gl-flex-grow-2"> - <template #prepend> - <gl-input-group-text> - {{ $options.i18n.valueLabel }} - </gl-input-group-text> - </template> - <gl-form-input - :ref="inputRef('value', variable.id)" - v-model="variable.secretValue" - :placeholder="$options.i18n.valuePlaceholder" - data-testid="ci-variable-value" - /> - </gl-form-input-group> - - <gl-button - v-if="canRemove(index)" - v-gl-tooltip - :aria-label="$options.i18n.clearInputs" - :title="$options.i18n.clearInputs" - class="gl-flex-grow-0 gl-flex-basis-0" - category="tertiary" - variant="danger" - icon="clear" - data-testid="delete-variable-btn" - @click="deleteVariable(variable.id)" - /> - - <!-- delete variable button placeholder to not break flex layout --> - <div v-else class="gl-w-7 gl-mr-3" data-testid="delete-variable-btn-placeholder"></div> - </div> - - <div class="gl-text-center gl-mt-5"> - <gl-sprintf :message="$options.i18n.formHelpText"> - <template #link="{ content }"> - <gl-link :href="variableSettings" target="_blank"> - {{ content }} - </gl-link> - </template> - </gl-sprintf> - </div> - <div class="gl-display-flex gl-justify-content-center gl-mt-5"> - <gl-button - class="gl-mt-5" - variant="confirm" - category="primary" - :aria-label="__('Trigger manual job')" - :disabled="triggerBtnDisabled" - data-testid="trigger-manual-job-btn" - @click="trigger" - > - {{ action.button_title }} - </gl-button> - </div> - </div> - </div> -</template> diff --git a/app/assets/javascripts/jobs/components/job/manual_variables_form.vue b/app/assets/javascripts/jobs/components/job/manual_variables_form.vue index e8edc7fc56f..d7bbd6daed2 100644 --- a/app/assets/javascripts/jobs/components/job/manual_variables_form.vue +++ b/app/assets/javascripts/jobs/components/job/manual_variables_form.vue @@ -10,6 +10,7 @@ import { GlTooltipDirective, } from '@gitlab/ui'; import { cloneDeep, uniqueId } from 'lodash'; +import { mapActions } from 'vuex'; import { fetchPolicies } from '~/lib/graphql'; import { createAlert } from '~/flash'; import { convertToGraphQLId } from '~/graphql_shared/utils'; @@ -58,6 +59,10 @@ export default { }, }, props: { + isRetryable: { + type: Boolean, + required: true, + }, jobId: { type: Number, required: true, @@ -76,9 +81,14 @@ export default { keyLabel: s__('CiVariables|Key'), keyPlaceholder: s__('CiVariables|Input variable key'), runAgainButtonText: s__('CiVariables|Run job again'), + triggerButtonText: s__('CiVariables|Trigger this manual action'), valueLabel: s__('CiVariables|Value'), valuePlaceholder: s__('CiVariables|Input variable value'), }, + variableValueKeys: { + rest: 'secret_value', + gql: 'value', + }, data() { return { job: {}, @@ -90,14 +100,29 @@ export default { }, ], runAgainBtnDisabled: false, + triggerBtnDisabled: false, }; }, computed: { + preparedVariables() { + // filtering out 'id' along with empty variables to send only key, value in the mutation. + // This will be removed in: https://gitlab.com/gitlab-org/gitlab/-/issues/377268 + + return this.variables + .filter((variable) => variable.key !== '') + .map(({ key, value }) => ({ key, [this.valueKey]: value })); + }, + valueKey() { + return this.isRetryable + ? this.$options.variableValueKeys.gql + : this.$options.variableValueKeys.rest; + }, variableSettings() { return helpPagePath('ci/variables/index', { anchor: 'add-a-cicd-variable-to-a-project' }); }, }, methods: { + ...mapActions(['triggerManualJob']), addEmptyVariable() { const lastVar = this.variables[this.variables.length - 1]; @@ -128,18 +153,12 @@ export default { }, async retryJob() { try { - // filtering out 'id' along with empty variables to send only key, value in the mutation. - // This will be removed in: https://gitlab.com/gitlab-org/gitlab/-/issues/377268 - const preparedVariables = this.variables - .filter((variable) => variable.key !== '') - .map(({ key, value }) => ({ key, value })); - const { data } = await this.$apollo.mutate({ mutation: retryJobWithVariablesMutation, variables: { id: convertToGraphQLId(GRAPHQL_ID_TYPES.ciBuild, this.jobId), // we need to ensure no empty variables are passed to the API - variables: preparedVariables, + variables: this.preparedVariables, }, }); if (data.jobRetry?.errors?.length) { @@ -156,6 +175,11 @@ export default { this.retryJob(); }, + triggerJob() { + this.triggerBtnDisabled = true; + + this.triggerManualJob(this.preparedVariables); + }, }, }; </script> @@ -226,7 +250,7 @@ export default { </template> </gl-sprintf> </div> - <div class="gl-display-flex gl-justify-content-center gl-mt-5"> + <div v-if="isRetryable" class="gl-display-flex gl-justify-content-center gl-mt-5"> <gl-button class="gl-mt-5" :aria-label="__('Cancel')" @@ -246,6 +270,19 @@ export default { {{ $options.i18n.runAgainButtonText }} </gl-button> </div> + <div v-else class="gl-display-flex gl-justify-content-center gl-mt-5"> + <gl-button + class="gl-mt-5" + variant="confirm" + category="primary" + :aria-label="__('Trigger manual job')" + :disabled="triggerBtnDisabled" + data-testid="trigger-manual-job-btn" + @click="triggerJob" + > + {{ $options.i18n.triggerButtonText }} + </gl-button> + </div> </div> </div> </template> diff --git a/app/assets/javascripts/jobs/components/job/sidebar/job_sidebar_retry_button.vue b/app/assets/javascripts/jobs/components/job/sidebar/job_sidebar_retry_button.vue index 65175df555a..7183a8b5d03 100644 --- a/app/assets/javascripts/jobs/components/job/sidebar/job_sidebar_retry_button.vue +++ b/app/assets/javascripts/jobs/components/job/sidebar/job_sidebar_retry_button.vue @@ -1,7 +1,6 @@ <script> import { GlButton, GlDropdown, GlDropdownItem, GlModalDirective } from '@gitlab/ui'; import { mapGetters } from 'vuex'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { JOB_SIDEBAR_COPY } from '~/jobs/constants'; export default { @@ -17,7 +16,6 @@ export default { directives: { GlModal: GlModalDirective, }, - mixins: [glFeatureFlagsMixin()], props: { modalId: { type: String, @@ -34,9 +32,6 @@ export default { }, computed: { ...mapGetters(['hasForwardDeploymentFailure']), - showRetryDropdown() { - return this.glFeatures?.graphqlJobApp && this.isManualJob; - }, }, }; </script> @@ -51,7 +46,7 @@ export default { data-testid="retry-job-button" /> <gl-dropdown - v-else-if="showRetryDropdown" + v-else-if="isManualJob" icon="retry" category="primary" :right="true" diff --git a/app/assets/javascripts/jobs/components/job/sidebar/legacy_job_sidebar_retry_button.vue b/app/assets/javascripts/jobs/components/job/sidebar/legacy_job_sidebar_retry_button.vue deleted file mode 100644 index 8a821b69f8c..00000000000 --- a/app/assets/javascripts/jobs/components/job/sidebar/legacy_job_sidebar_retry_button.vue +++ /dev/null @@ -1,53 +0,0 @@ -<script> -import { GlButton, GlModalDirective } from '@gitlab/ui'; -import { mapGetters } from 'vuex'; -import { JOB_SIDEBAR_COPY } from '~/jobs/constants'; - -export default { - name: 'LegacyJobSidebarRetryButton', - i18n: { - retryLabel: JOB_SIDEBAR_COPY.retryJobLabel, - }, - components: { - GlButton, - }, - directives: { - GlModal: GlModalDirective, - }, - props: { - modalId: { - type: String, - required: true, - }, - href: { - type: String, - required: true, - }, - }, - computed: { - ...mapGetters(['hasForwardDeploymentFailure']), - }, -}; -</script> -<template> - <gl-button - v-if="hasForwardDeploymentFailure" - v-gl-modal="modalId" - :aria-label="$options.i18n.retryLabel" - category="primary" - variant="confirm" - icon="retry" - data-testid="retry-job-button" - /> - - <gl-button - v-else - :href="href" - :aria-label="$options.i18n.retryLabel" - category="primary" - variant="confirm" - icon="retry" - data-method="post" - data-testid="retry-job-link" - /> -</template> diff --git a/app/assets/javascripts/jobs/components/job/sidebar/legacy_sidebar_header.vue b/app/assets/javascripts/jobs/components/job/sidebar/legacy_sidebar_header.vue deleted file mode 100644 index 5bbb831a293..00000000000 --- a/app/assets/javascripts/jobs/components/job/sidebar/legacy_sidebar_header.vue +++ /dev/null @@ -1,98 +0,0 @@ -<script> -import { GlButton, GlTooltipDirective } from '@gitlab/ui'; -import { mapActions } from 'vuex'; -import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; -import { JOB_SIDEBAR_COPY, forwardDeploymentFailureModalId, PASSED_STATUS } from '~/jobs/constants'; -import JobSidebarRetryButton from './job_sidebar_retry_button.vue'; - -export default { - name: 'LegacySidebarHeader', - i18n: { - ...JOB_SIDEBAR_COPY, - }, - forwardDeploymentFailureModalId, - directives: { - GlTooltip: GlTooltipDirective, - }, - components: { - GlButton, - JobSidebarRetryButton, - TooltipOnTruncate, - }, - props: { - job: { - type: Object, - required: true, - default: () => ({}), - }, - }, - computed: { - retryButtonCategory() { - return this.job.status && this.job.recoverable ? 'primary' : 'secondary'; - }, - buttonTitle() { - return this.job.status && this.job.status.text === PASSED_STATUS - ? this.$options.i18n.runAgainJobButtonLabel - : this.$options.i18n.retryJobLabel; - }, - }, - methods: { - ...mapActions(['toggleSidebar']), - }, -}; -</script> - -<template> - <div class="gl-py-5 gl-display-flex gl-align-items-center"> - <tooltip-on-truncate :title="job.name" truncate-target="child" - ><h4 class="gl-my-0 gl-mr-3 gl-text-truncate">{{ job.name }}</h4> - </tooltip-on-truncate> - <div class="gl-flex-grow-1 gl-flex-shrink-0 gl-text-right"> - <gl-button - v-if="job.erase_path" - v-gl-tooltip.left - :title="$options.i18n.eraseLogButtonLabel" - :aria-label="$options.i18n.eraseLogButtonLabel" - :href="job.erase_path" - :data-confirm="$options.i18n.eraseLogConfirmText" - class="gl-mr-2" - data-testid="job-log-erase-link" - data-confirm-btn-variant="danger" - data-method="post" - icon="remove" - /> - <job-sidebar-retry-button - v-if="job.retry_path" - v-gl-tooltip.left - :title="buttonTitle" - :aria-label="buttonTitle" - :category="retryButtonCategory" - :href="job.retry_path" - :modal-id="$options.forwardDeploymentFailureModalId" - :is-manual-job="false" - variant="confirm" - data-qa-selector="retry_button" - data-testid="retry-button" - /> - <gl-button - v-if="job.cancel_path" - v-gl-tooltip.left - :title="$options.i18n.cancelJobButtonLabel" - :aria-label="$options.i18n.cancelJobButtonLabel" - :href="job.cancel_path" - variant="danger" - icon="cancel" - data-method="post" - data-testid="cancel-button" - rel="nofollow" - /> - <gl-button - :aria-label="$options.i18n.toggleSidebar" - category="tertiary" - class="gl-md-display-none gl-ml-2" - icon="chevron-double-lg-right" - @click="toggleSidebar" - /> - </div> - </div> -</template> diff --git a/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue b/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue index 02c3d60557b..69271cc9022 100644 --- a/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue +++ b/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue @@ -3,13 +3,11 @@ import { GlButton, GlIcon } from '@gitlab/ui'; import { isEmpty } from 'lodash'; import { mapActions, mapGetters, mapState } from 'vuex'; import { JOB_SIDEBAR_COPY, forwardDeploymentFailureModalId } from '~/jobs/constants'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import ArtifactsBlock from './artifacts_block.vue'; import CommitBlock from './commit_block.vue'; import JobsContainer from './jobs_container.vue'; import JobRetryForwardDeploymentModal from './job_retry_forward_deployment_modal.vue'; import JobSidebarDetailsContainer from './sidebar_job_details_container.vue'; -import LegacySidebarHeader from './legacy_sidebar_header.vue'; import SidebarHeader from './sidebar_header.vue'; import StagesDropdown from './stages_dropdown.vue'; import TriggerBlock from './trigger_block.vue'; @@ -29,12 +27,10 @@ export default { JobsContainer, JobRetryForwardDeploymentModal, JobSidebarDetailsContainer, - LegacySidebarHeader, SidebarHeader, StagesDropdown, TriggerBlock, }, - mixins: [glFeatureFlagsMixin()], props: { artifactHelpUrl: { type: String, @@ -52,9 +48,6 @@ export default { hasTriggers() { return !isEmpty(this.job.trigger); }, - isGraphQL() { - return this.glFeatures?.graphqlJobApp; - }, commit() { return this.job?.pipeline?.commit || {}; }, @@ -85,12 +78,10 @@ export default { <div class="sidebar-container"> <div class="blocks-container"> <sidebar-header - v-if="isGraphQL" :rest-job="job" :job-id="job.id" @updateVariables="$emit('updateVariables')" /> - <legacy-sidebar-header v-else :job="job" /> <div v-if="job.terminal_path || job.new_issue_path" class="gl-py-5" diff --git a/app/assets/javascripts/jobs/components/job/sidebar/sidebar_header.vue b/app/assets/javascripts/jobs/components/job/sidebar/sidebar_header.vue index c124f52ae79..40aec0b0536 100644 --- a/app/assets/javascripts/jobs/components/job/sidebar/sidebar_header.vue +++ b/app/assets/javascripts/jobs/components/job/sidebar/sidebar_header.vue @@ -14,9 +14,6 @@ import { import GetJob from '../graphql/queries/get_job.query.graphql'; import JobSidebarRetryButton from './job_sidebar_retry_button.vue'; -// This component is a port of ~/jobs/components/job/sidebar/legacy_sidebar_header.vue -// It is meant to fetch the job information via GraphQL instead of REST API. - export default { name: 'SidebarHeader', i18n: { |