Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/pipelines/components/pipelines_list')
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue53
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue106
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue220
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue79
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue165
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_jobs_list.vue179
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue121
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/utils.js19
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue69
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_labels.vue170
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue172
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue113
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue104
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue37
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue239
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue449
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue72
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue130
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue159
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue50
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue240
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue61
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js52
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue82
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue47
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue104
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue66
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue113
28 files changed, 0 insertions, 3471 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
deleted file mode 100644
index 3bbdfc73e1b..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-<script>
-import { GlEmptyState } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue';
-import PipelinesCiTemplates from './empty_state/pipelines_ci_templates.vue';
-import IosTemplates from './empty_state/ios_templates.vue';
-
-export default {
- i18n: {
- noCiDescription: s__('Pipelines|This project is not currently set up to run pipelines.'),
- },
- name: 'PipelinesEmptyState',
- components: {
- GlEmptyState,
- GitlabExperiment,
- PipelinesCiTemplates,
- IosTemplates,
- },
- props: {
- emptyStateSvgPath: {
- type: String,
- required: true,
- },
- canSetCi: {
- type: Boolean,
- required: true,
- },
- registrationToken: {
- type: String,
- required: false,
- default: null,
- },
- },
-};
-</script>
-<template>
- <div>
- <gitlab-experiment v-if="canSetCi" name="ios_specific_templates">
- <template #control>
- <pipelines-ci-templates />
- </template>
- <template #candidate>
- <ios-templates :registration-token="registrationToken" />
- </template>
- </gitlab-experiment>
- <gl-empty-state
- v-else
- title=""
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.noCiDescription"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
deleted file mode 100644
index 439dc0eb253..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
+++ /dev/null
@@ -1,106 +0,0 @@
-<script>
-import { GlAvatar, GlButton } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
-import Tracking from '~/tracking';
-
-export default {
- components: {
- GlAvatar,
- GlButton,
- },
- mixins: [Tracking.mixin()],
- inject: ['pipelineEditorPath', 'suggestedCiTemplates'],
- props: {
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- filterTemplates: {
- type: Array,
- required: false,
- default: () => [],
- },
- },
- data() {
- const templates = this.suggestedCiTemplates
- .filter(
- (template) => !this.filterTemplates.length || this.filterTemplates.includes(template.name),
- )
- .map(({ name, logo, title }) => {
- return {
- name: title || name,
- description: sprintf(this.$options.i18n.description, { name: title || name }),
- isPng: logo.endsWith('png'),
- logo,
- link: mergeUrlParams({ template: name }, this.pipelineEditorPath),
- };
- });
-
- return {
- templates,
- };
- },
- methods: {
- trackEvent(template) {
- this.track('template_clicked', {
- label: template,
- });
- },
- logoStyle(template) {
- return template.isPng ? { objectFit: 'contain' } : '';
- },
- },
- i18n: {
- description: s__(
- 'Pipelines|Continuous integration and deployment template to test and deploy your %{name} project.',
- ),
- cta: s__('Pipelines|Use template'),
- },
- AVATAR_SHAPE_OPTION_RECT,
-};
-</script>
-<template>
- <ul class="gl-list-style-none gl-pl-0">
- <li v-for="template in templates" :key="template.name">
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-pt-3"
- >
- <div class="gl-display-flex gl-flex-direction-row gl-align-items-center">
- <gl-avatar
- :alt="template.name"
- class="gl-mr-5 gl-bg-white dark-mode-override"
- :class="{ 'gl-p-2': template.isPng }"
- :style="logoStyle(template)"
- :shape="$options.AVATAR_SHAPE_OPTION_RECT"
- :size="48"
- :src="template.logo"
- data-testid="template-logo"
- />
- <div class="gl-flex-direction-row">
- <div class="gl-mb-3">
- <strong class="gl-text-gray-800" data-testid="template-name">
- {{ template.name }}
- </strong>
- </div>
- <p class="gl-mb-0 gl-font-sm" data-testid="template-description">
- {{ template.description }}
- </p>
- </div>
- </div>
- <gl-button
- :disabled="disabled"
- category="primary"
- variant="confirm"
- :href="template.link"
- data-testid="template-link"
- @click="trackEvent(template.name)"
- >
- {{ $options.i18n.cta }}
- </gl-button>
- </div>
- </li>
- </ul>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue
deleted file mode 100644
index 5208f9a3ce7..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue
+++ /dev/null
@@ -1,220 +0,0 @@
-<script>
-import { GlButton, GlCard, GlSprintf, GlLink, GlPopover, GlModalDirective } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import { mergeUrlParams, DOCS_URL } from '~/lib/utils/url_utility';
-import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
-import apolloProvider from '~/pipelines/graphql/provider';
-import CiTemplates from './ci_templates.vue';
-
-export default {
- components: {
- GlButton,
- GlCard,
- GlSprintf,
- GlLink,
- GlPopover,
- RunnerInstructionsModal,
- CiTemplates,
- },
- directives: {
- GlModalDirective,
- },
- inject: ['pipelineEditorPath', 'iosRunnersAvailable'],
- props: {
- registrationToken: {
- type: String,
- required: false,
- default: null,
- },
- },
- apolloProvider,
- iOSTemplateName: 'iOS-Fastlane',
- modalId: 'runner-instructions-modal',
- runnerDocsLink: `${DOCS_URL}/runner/install/osx`,
- whatElseLink: helpPagePath('ci/index.md'),
- i18n: {
- title: s__('Pipelines|Get started with GitLab CI/CD'),
- subtitle: s__('Pipelines|Building for iOS?'),
- explanation: s__("Pipelines|We'll walk you through how to deploy to iOS in two easy steps."),
- runnerSetupTitle: s__('Pipelines|1. Set up a runner'),
- runnerSetupButton: s__('Pipelines|Set up a runner'),
- runnerSetupBodyUnfinished: s__(
- 'Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline.',
- ),
- runnerSetupBodyFinished: s__(
- 'Pipelines|You have runners available to run your job now. No need to do anything else.',
- ),
- runnerSetupPopoverTitle: s__(
- "Pipelines|Let's get that runner set up! %{emojiStart}tada%{emojiEnd}",
- ),
- runnerSetupPopoverBodyLine1: s__(
- 'Pipelines|Follow these instructions to install GitLab Runner on macOS.',
- ),
- runnerSetupPopoverBodyLine2: s__(
- 'Pipelines|Need more information to set up your runner? %{linkStart}Check out our documentation%{linkEnd}.',
- ),
- configurePipelineTitle: s__('Pipelines|2. Configure deployment pipeline'),
- configurePipelineBody: s__("Pipelines|We'll guide you through a simple pipeline set-up."),
- configurePipelineButton: s__('Pipelines|Configure pipeline'),
- noWalkthroughTitle: s__("Pipelines|Don't need a guide? Jump in right away with a template."),
- noWalkthroughExplanation: s__('Pipelines|Based on your project, we recommend this template:'),
- notBuildingForIos: s__(
- "Pipelines|Not building for iOS or not what you're looking for? %{linkStart}See what else%{linkEnd} GitLab CI/CD has to offer.",
- ),
- },
- data() {
- return {
- isModalShown: false,
- isPopoverShown: false,
- isRunnerSetupFinished: this.iosRunnersAvailable,
- popoverTarget: `${this.$options.modalId}___BV_modal_content_`,
- configurePipelineLink: mergeUrlParams(
- { template: this.$options.iOSTemplateName },
- this.pipelineEditorPath,
- ),
- };
- },
- computed: {
- runnerSetupBodyText() {
- return this.iosRunnersAvailable
- ? this.$options.i18n.runnerSetupBodyFinished
- : this.$options.i18n.runnerSetupBodyUnfinished;
- },
- },
- methods: {
- showModal() {
- this.isModalShown = true;
- },
- hideModal() {
- this.togglePopover();
- this.isRunnerSetupFinished = true;
- },
- togglePopover() {
- this.isPopoverShown = !this.isPopoverShown;
- },
- },
-};
-</script>
-
-<template>
- <div>
- <h2 class="gl-font-size-h2 gl-text-gray-900">{{ $options.i18n.title }}</h2>
- <h3 class="gl-font-lg gl-text-gray-900 gl-mt-1">{{ $options.i18n.subtitle }}</h3>
- <p>{{ $options.i18n.explanation }}</p>
-
- <div class="gl-lg-display-flex">
- <div class="gl-lg-display-flex gl-lg-w-25p gl-lg-pr-4 gl-mb-4">
- <gl-card body-class="gl-display-flex gl-flex-grow-1">
- <div
- class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-justify-content-space-between gl-align-items-flex-start"
- >
- <div>
- <div class="gl-py-5">
- <gl-emoji
- v-show="isRunnerSetupFinished"
- class="gl-font-size-h2-xl"
- data-name="white_check_mark"
- data-testid="runner-setup-marked-completed"
- />
- <gl-emoji
- v-show="!isRunnerSetupFinished"
- class="gl-font-size-h2-xl"
- data-name="tools"
- data-testid="runner-setup-marked-todo"
- />
- </div>
- <span class="gl-text-gray-800 gl-font-weight-bold">
- {{ $options.i18n.runnerSetupTitle }}
- </span>
- <p class="gl-font-sm gl-mt-3">{{ runnerSetupBodyText }}</p>
- </div>
-
- <gl-button
- v-if="!iosRunnersAvailable"
- v-gl-modal-directive="$options.modalId"
- category="primary"
- variant="confirm"
- @click="showModal"
- >
- {{ $options.i18n.runnerSetupButton }}
- </gl-button>
- <runner-instructions-modal
- v-if="isModalShown"
- :modal-id="$options.modalId"
- :registration-token="registrationToken"
- default-platform-name="osx"
- @shown="togglePopover"
- @hide="hideModal"
- />
- <gl-popover
- v-if="isPopoverShown"
- :show="true"
- :show-close-button="true"
- :target="popoverTarget"
- triggers="manual"
- placement="left"
- fallback-placement="clockwise"
- >
- <template #title>
- <gl-sprintf :message="$options.i18n.runnerSetupPopoverTitle">
- <template #emoji="{ content }">
- <gl-emoji class="gl-ml-2" :data-name="content" />
- </template>
- </gl-sprintf>
- </template>
- <div class="gl-mb-5">
- {{ $options.i18n.runnerSetupPopoverBodyLine1 }}
- </div>
- <gl-sprintf :message="$options.i18n.runnerSetupPopoverBodyLine2">
- <template #link="{ content }">
- <gl-link :href="$options.runnerDocsLink" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </gl-popover>
- </div>
- </gl-card>
- </div>
- <div class="gl-lg-display-flex gl-lg-w-25p gl-lg-pr-4 gl-mb-4">
- <gl-card body-class="gl-display-flex gl-flex-grow-1">
- <div
- class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-justify-content-space-between gl-align-items-flex-start"
- >
- <div>
- <div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="tools" /></div>
- <span class="gl-text-gray-800 gl-font-weight-bold">
- {{ $options.i18n.configurePipelineTitle }}
- </span>
- <p class="gl-font-sm gl-mt-3">{{ $options.i18n.configurePipelineBody }}</p>
- </div>
-
- <gl-button
- :disabled="!isRunnerSetupFinished"
- category="primary"
- variant="confirm"
- data-testid="configure-pipeline-link"
- :href="configurePipelineLink"
- >
- {{ $options.i18n.configurePipelineButton }}
- </gl-button>
- </div>
- </gl-card>
- </div>
- </div>
- <h3 class="gl-font-lg gl-text-gray-900 gl-mt-5">{{ $options.i18n.noWalkthroughTitle }}</h3>
- <p>{{ $options.i18n.noWalkthroughExplanation }}</p>
- <ci-templates
- :filter-templates="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
- $options.iOSTemplateName,
- ] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
- :disabled="!isRunnerSetupFinished"
- />
- <p>
- <gl-sprintf :message="$options.i18n.notBuildingForIos">
- <template #link="{ content }">
- <gl-link :href="$options.whatElseLink">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue
deleted file mode 100644
index a6297213402..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue
+++ /dev/null
@@ -1,79 +0,0 @@
-<script>
-import { GlButton, GlCard, GlSprintf } from '@gitlab/ui';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { STARTER_TEMPLATE_NAME, I18N } from '~/ci/pipeline_editor/constants';
-import Tracking from '~/tracking';
-import CiTemplates from './ci_templates.vue';
-
-export default {
- components: {
- GlButton,
- GlCard,
- GlSprintf,
- CiTemplates,
- },
- mixins: [Tracking.mixin()],
- STARTER_TEMPLATE_NAME,
- I18N,
- inject: ['pipelineEditorPath'],
- data() {
- return {
- gettingStartedTemplateUrl: mergeUrlParams(
- { template: STARTER_TEMPLATE_NAME },
- this.pipelineEditorPath,
- ),
- tracker: null,
- };
- },
- methods: {
- trackEvent(template) {
- this.track('template_clicked', {
- label: template,
- });
- },
- },
-};
-</script>
-<template>
- <div>
- <h2 class="gl-font-size-h2 gl-text-gray-900">{{ $options.I18N.title }}</h2>
-
- <h2 class="gl-font-lg gl-text-gray-900">{{ $options.I18N.learnBasics.title }}</h2>
- <p class="gl-text-gray-800 gl-mb-6">
- <gl-sprintf :message="$options.I18N.learnBasics.subtitle">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
-
- <div class="gl-lg-w-25p gl-lg-pr-5 gl-mb-8">
- <gl-card>
- <div class="gl-flex-direction-row">
- <div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="wave" /></div>
- <div class="gl-mb-3">
- <strong class="gl-text-gray-800 gl-mb-2">
- {{ $options.I18N.learnBasics.gettingStarted.title }}
- </strong>
- </div>
- <p class="gl-font-sm">{{ $options.I18N.learnBasics.gettingStarted.description }}</p>
- </div>
-
- <gl-button
- category="primary"
- variant="confirm"
- :href="gettingStartedTemplateUrl"
- data-testid="test-template-link"
- @click="trackEvent($options.STARTER_TEMPLATE_NAME)"
- >
- {{ $options.I18N.learnBasics.gettingStarted.cta }}
- </gl-button>
- </gl-card>
- </div>
-
- <h2 class="gl-font-lg gl-text-gray-900">{{ $options.I18N.templates.title }}</h2>
- <p class="gl-text-gray-800 gl-mb-6">{{ $options.I18N.templates.subtitle }}</p>
-
- <ci-templates />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue
deleted file mode 100644
index edf4cc87a87..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue
+++ /dev/null
@@ -1,165 +0,0 @@
-<script>
-import { GlButton, GlIcon, GlLink, GlTooltip } from '@gitlab/ui';
-import { createAlert } from '~/alert';
-import { __, s__, sprintf } from '~/locale';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import SafeHtml from '~/vue_shared/directives/safe_html';
-import { BRIDGE_KIND } from '~/pipelines/components/graph/constants';
-import RetryMrFailedJobMutation from '../../../graphql/mutations/retry_mr_failed_job.mutation.graphql';
-
-export default {
- components: {
- CiIcon,
- GlButton,
- GlIcon,
- GlLink,
- GlTooltip,
- },
- directives: {
- SafeHtml,
- },
- props: {
- job: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- isHovered: false,
- isJobLogVisible: false,
- isLoadingAction: false,
- };
- },
- computed: {
- canReadBuild() {
- return this.job.userPermissions.readBuild;
- },
- canRetryJob() {
- return this.job.retryable && this.job.userPermissions.updateBuild && !this.isBridgeJob;
- },
- isBridgeJob() {
- return this.job.kind === BRIDGE_KIND;
- },
- jobChevronName() {
- return this.isJobLogVisible ? 'chevron-down' : 'chevron-right';
- },
- jobTrace() {
- if (this.canReadBuild) {
- return this.job?.trace?.htmlSummary || this.$options.i18n.noTraceText;
- }
-
- return this.$options.i18n.cannotReadBuild;
- },
- parsedJobId() {
- return getIdFromGraphQLId(this.job.id);
- },
- tooltipErrorText() {
- return this.isBridgeJob
- ? this.$options.i18n.cannotRetryTrigger
- : this.$options.i18n.cannotRetry;
- },
- tooltipText() {
- return sprintf(this.$options.i18n.jobActionTooltipText, { jobName: this.job.name });
- },
- },
- methods: {
- setActiveRow() {
- this.isHovered = true;
- },
- resetActiveRow() {
- this.isHovered = false;
- },
- async retryJob() {
- try {
- this.isLoadingAction = true;
-
- const {
- data: {
- jobRetry: { errors },
- },
- } = await this.$apollo.mutate({
- mutation: RetryMrFailedJobMutation,
- variables: { id: this.job.id },
- });
-
- if (errors.length > 0) {
- throw new Error(errors[0]);
- }
-
- this.$emit('job-retried', this.job.name);
- } catch (error) {
- createAlert({ message: error?.message || this.$options.i18n.retryError });
- } finally {
- this.isLoadingAction = false;
- }
- },
- toggleJobLog(event) {
- // Do not toggle the log visibility when clicking on a link
- if (event.target.tagName === 'A') {
- return;
- }
- this.isJobLogVisible = !this.isJobLogVisible;
- },
- },
- i18n: {
- cannotReadBuild: s__("Job|You do not have permission to read this job's log."),
- cannotRetry: s__('Job|You do not have permission to run this job again.'),
- cannotRetryTrigger: s__('Job|You cannot rerun trigger jobs from this list.'),
- jobActionTooltipText: s__('Pipelines|Retry %{jobName} Job'),
- noTraceText: s__('Job|No job log'),
- retry: __('Retry'),
- retryError: __('There was an error while retrying this job'),
- },
-};
-</script>
-<template>
- <div class="container-fluid gl-grid-tpl-rows-auto">
- <div
- class="row gl-my-3 gl-cursor-pointer gl-display-flex gl-align-items-center"
- :aria-pressed="isJobLogVisible"
- role="button"
- tabindex="0"
- data-testid="widget-row"
- @click="toggleJobLog"
- @keyup.enter="toggleJobLog"
- @keyup.space="toggleJobLog"
- @mouseover="setActiveRow"
- @mouseout="resetActiveRow"
- >
- <div class="col-6 gl-text-gray-900 gl-font-weight-bold gl-text-left">
- <gl-icon :name="jobChevronName" />
- <ci-icon :status="job.detailedStatus" />
- {{ job.name }}
- </div>
- <div class="col-2 gl-text-left">{{ job.stage.name }}</div>
- <div class="col-2 gl-text-left">
- <gl-link :href="job.detailedStatus.detailsPath">#{{ parsedJobId }}</gl-link>
- </div>
- <gl-tooltip v-if="!canRetryJob" :target="() => $refs.retryBtn" placement="top">
- {{ tooltipErrorText }}
- </gl-tooltip>
- <div class="col-2 gl-text-right">
- <span ref="retryBtn">
- <gl-button
- :disabled="!canRetryJob"
- icon="retry"
- category="tertiary"
- :loading="isLoadingAction"
- :title="$options.i18n.retry"
- :aria-label="$options.i18n.retry"
- @click.stop="retryJob"
- />
- </span>
- </div>
- </div>
- <div v-if="isJobLogVisible" class="row">
- <pre
- v-safe-html="jobTrace"
- class="gl-bg-gray-900 gl-text-white gl-w-full"
- data-testid="job-log"
- ></pre>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_jobs_list.vue b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_jobs_list.vue
deleted file mode 100644
index 2c5aa84bc4f..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_jobs_list.vue
+++ /dev/null
@@ -1,179 +0,0 @@
-<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import { createAlert } from '~/alert';
-import { __, s__, sprintf } from '~/locale';
-import { getQueryHeaders } from '~/pipelines/components/graph/utils';
-import getPipelineFailedJobs from '../../../graphql/queries/get_pipeline_failed_jobs.query.graphql';
-import { graphqlEtagPipelinePath, sortJobsByStatus } from './utils';
-import FailedJobDetails from './failed_job_details.vue';
-
-const POLL_INTERVAL = 10000;
-
-const JOB_ID_HEADER = __('ID');
-const JOB_NAME_HEADER = __('Name');
-const STAGE_HEADER = __('Stage');
-
-export default {
- components: {
- GlLoadingIcon,
- FailedJobDetails,
- },
- inject: ['graphqlPath'],
- props: {
- failedJobsCount: {
- required: true,
- type: Number,
- },
- isPipelineActive: {
- required: true,
- type: Boolean,
- },
- pipelineIid: {
- type: Number,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- failedJobs: [],
- isActive: false,
- isLoadingMore: false,
- };
- },
- apollo: {
- failedJobs: {
- context() {
- return getQueryHeaders(this.graphqlResourceEtag);
- },
- query: getPipelineFailedJobs,
- pollInterval: POLL_INTERVAL,
- variables() {
- return {
- fullPath: this.projectPath,
- pipelineIid: this.pipelineIid,
- };
- },
- update(data) {
- const jobs = data?.project?.pipeline?.jobs?.nodes || [];
- return sortJobsByStatus(jobs);
- },
- result({ data }) {
- const pipeline = data?.project?.pipeline;
-
- if (pipeline?.jobs?.count) {
- this.$emit('failed-jobs-count', pipeline.jobs.count);
- this.isActive = pipeline.active;
- }
- },
- error(e) {
- createAlert({ message: e?.message || this.$options.i18n.fetchError, variant: 'danger' });
- },
- },
- },
- computed: {
- graphqlResourceEtag() {
- return graphqlEtagPipelinePath(this.graphqlPath, this.pipelineIid);
- },
- hasFailedJobs() {
- return this.failedJobs.length > 0;
- },
- isInitialLoading() {
- return this.isLoading && !this.isLoadingMore;
- },
- isLoading() {
- return this.$apollo.queries.failedJobs.loading;
- },
- },
- watch: {
- isPipelineActive(flag) {
- // Turn polling on and off based on REST actions
- // By refetching jobs, we will get the graphql `active`
- // field to update properly and cascade the polling changes
- this.refetchJobs();
- this.handlePolling(flag);
- },
- isActive(flag) {
- this.handlePolling(flag);
- },
- failedJobsCount(count) {
- // If the REST data is updated first, we force a refetch
- // to keep them in sync
- if (this.failedJobs.length !== count) {
- this.$apollo.queries.failedJobs.refetch();
- }
- },
- },
- mounted() {
- if (!this.isActive && !this.isPipelineActive) {
- this.handlePolling(false);
- }
- },
- methods: {
- handlePolling(isActive) {
- // If the pipeline status has changed and the widget is not expanded,
- // We start polling.
- if (isActive) {
- this.$apollo.queries.failedJobs.startPolling(POLL_INTERVAL);
- } else {
- this.$apollo.queries.failedJobs.stopPolling();
- }
- },
- async retryJob(jobName) {
- await this.refetchJobs();
-
- this.$toast.show(sprintf(this.$options.i18n.retriedJobsSuccess, { jobName }));
- },
- async refetchJobs() {
- this.isLoadingMore = true;
-
- try {
- await this.$apollo.queries.failedJobs.refetch();
- } catch {
- createAlert(this.$options.i18n.fetchError);
- } finally {
- this.isLoadingMore = false;
- }
- },
- },
- columns: [
- { text: JOB_NAME_HEADER, class: 'col-6' },
- { text: STAGE_HEADER, class: 'col-2' },
- { text: JOB_ID_HEADER, class: 'col-2' },
- ],
- i18n: {
- fetchError: __('There was a problem fetching failed jobs'),
- noFailedJobs: s__('Pipeline|No failed jobs in this pipeline 🎉'),
- retriedJobsSuccess: __('%{jobName} job is being retried'),
- },
-};
-</script>
-
-<template>
- <div>
- <gl-loading-icon v-if="isInitialLoading" class="gl-p-4" />
- <div v-else-if="!hasFailedJobs" class="gl-p-4">{{ $options.i18n.noFailedJobs }}</div>
- <div v-else class="container-fluid gl-grid-tpl-rows-auto">
- <div class="row gl-my-4 gl-text-gray-900">
- <div
- v-for="col in $options.columns"
- :key="col.text"
- class="gl-font-weight-bold gl-text-left"
- :class="col.class"
- data-testid="header"
- >
- {{ col.text }}
- </div>
- </div>
- </div>
- <failed-job-details
- v-for="job in failedJobs"
- :key="job.id"
- :job="job"
- @job-retried="retryJob"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue
deleted file mode 100644
index 60c429459bf..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue
+++ /dev/null
@@ -1,121 +0,0 @@
-<script>
-import { GlButton, GlCard, GlIcon, GlLink, GlPopover, GlSprintf } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-import FailedJobsList from './failed_jobs_list.vue';
-
-export default {
- components: {
- GlButton,
- GlCard,
- GlIcon,
- GlLink,
- GlPopover,
- GlSprintf,
- FailedJobsList,
- },
- inject: ['fullPath'],
- props: {
- failedJobsCount: {
- required: true,
- type: Number,
- },
- isPipelineActive: {
- required: true,
- type: Boolean,
- },
- pipelineIid: {
- required: true,
- type: Number,
- },
- pipelinePath: {
- required: true,
- type: String,
- },
- projectPath: {
- required: true,
- type: String,
- },
- },
- data() {
- return {
- currentFailedJobsCount: this.failedJobsCount,
- isActive: false,
- isExpanded: false,
- };
- },
- computed: {
- bodyClasses() {
- return this.isExpanded ? '' : 'gl-display-none';
- },
- failedJobsCountText() {
- return sprintf(this.$options.i18n.failedJobsLabel, { count: this.currentFailedJobsCount });
- },
- iconName() {
- return this.isExpanded ? 'chevron-down' : 'chevron-right';
- },
- popoverId() {
- return `popover-${this.pipelineIid}`;
- },
- },
- watch: {
- failedJobsCount(val) {
- this.currentFailedJobsCount = val;
- },
- },
- methods: {
- setFailedJobsCount(count) {
- this.currentFailedJobsCount = count;
- },
- toggleWidget() {
- this.isExpanded = !this.isExpanded;
- },
- },
- i18n: {
- additionalInfoPopover: s__(
- 'Pipelines|You will see a maximum of 100 jobs in this list. To view all failed jobs, %{linkStart}go to the details page%{linkEnd} of this pipeline.',
- ),
- additionalInfoTitle: __('Limitation on this view'),
- failedJobsLabel: __('Failed jobs (%{count})'),
- },
-};
-</script>
-<template>
- <gl-card
- class="gl-new-card"
- :class="{ 'gl-border-white gl-hover-border-gray-100': !isExpanded }"
- header-class="gl-new-card-header gl-px-3 gl-py-3"
- body-class="gl-new-card-body"
- data-testid="failed-jobs-card"
- :aria-expanded="isExpanded.toString()"
- >
- <template #header>
- <gl-button
- variant="link"
- class="gl-text-gray-700! gl-font-weight-semibold"
- @click="toggleWidget"
- >
- <gl-icon :name="iconName" />
- {{ failedJobsCountText }}
- <gl-icon :id="popoverId" name="information-o" class="gl-ml-2" />
- <gl-popover :target="popoverId" placement="top">
- <template #title> {{ $options.i18n.additionalInfoTitle }} </template>
- <slot>
- <gl-sprintf :message="$options.i18n.additionalInfoPopover">
- <template #link="{ content }">
- <gl-link class="gl-font-sm" :href="pipelinePath">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </slot>
- </gl-popover>
- </gl-button>
- </template>
- <failed-jobs-list
- v-if="isExpanded"
- :failed-jobs-count="failedJobsCount"
- :is-pipeline-active="isPipelineActive"
- :pipeline-iid="pipelineIid"
- :project-path="projectPath"
- @failed-jobs-count="setFailedJobsCount"
- />
- </gl-card>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/utils.js b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/utils.js
deleted file mode 100644
index 2d0c467c54f..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/utils.js
+++ /dev/null
@@ -1,19 +0,0 @@
-export const isFailedJob = (job = {}) => {
- return job?.detailedStatus?.group === 'failed' || false;
-};
-
-export const sortJobsByStatus = (jobs = []) => {
- const newJobs = [...jobs];
-
- return newJobs.sort((a) => {
- if (isFailedJob(a)) {
- return -1;
- }
-
- return 1;
- });
-};
-
-export const graphqlEtagPipelinePath = (graphqlPath, pipelineId) => {
- return `${graphqlPath}pipelines/id/${pipelineId}`;
-};
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue b/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
deleted file mode 100644
index 235126fea0c..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-
-export default {
- name: 'PipelineNavControls',
- components: {
- GlButton,
- },
- props: {
- newPipelinePath: {
- type: String,
- required: false,
- default: null,
- },
-
- resetCachePath: {
- type: String,
- required: false,
- default: null,
- },
-
- ciLintPath: {
- type: String,
- required: false,
- default: null,
- },
-
- isResetCacheButtonLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- methods: {
- onClickResetCache() {
- this.$emit('resetRunnersCache', this.resetCachePath);
- },
- },
-};
-</script>
-<template>
- <div class="nav-controls">
- <gl-button
- v-if="resetCachePath"
- :loading="isResetCacheButtonLoading"
- class="js-clear-cache"
- data-testid="clear-cache-button"
- @click="onClickResetCache"
- >
- {{ s__('Pipelines|Clear runner caches') }}
- </gl-button>
-
- <gl-button v-if="ciLintPath" :href="ciLintPath" class="js-ci-lint" data-testid="ci-lint-button">
- {{ s__('Pipelines|CI lint') }}
- </gl-button>
-
- <gl-button
- v-if="newPipelinePath"
- :href="newPipelinePath"
- variant="confirm"
- category="primary"
- class="js-run-pipeline"
- data-testid="run-pipeline-button"
- data-qa-selector="run_pipeline_button"
- >
- {{ s__('Pipeline|Run pipeline') }}
- </gl-button>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_labels.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_labels.vue
deleted file mode 100644
index 40b2454b8c1..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_labels.vue
+++ /dev/null
@@ -1,170 +0,0 @@
-<script>
-import { GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import { SCHEDULE_ORIGIN } from '../../constants';
-
-export default {
- components: {
- GlBadge,
- GlLink,
- GlPopover,
- GlSprintf,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- inject: {
- targetProjectFullPath: {
- default: '',
- },
- },
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- pipelineScheduleUrl: {
- type: String,
- required: true,
- },
- },
- computed: {
- isScheduled() {
- return this.pipeline.source === SCHEDULE_ORIGIN;
- },
- isInFork() {
- return Boolean(
- this.targetProjectFullPath &&
- this.pipeline?.project?.full_path !== `/${this.targetProjectFullPath}`,
- );
- },
- autoDevopsTagId() {
- return `pipeline-url-autodevops-${this.pipeline.id}`;
- },
- autoDevopsHelpPath() {
- return helpPagePath('topics/autodevops/index.md');
- },
- },
-};
-</script>
-<template>
- <div class="label-container gl-mt-1">
- <gl-badge
- v-if="isScheduled"
- v-gl-tooltip
- :href="pipelineScheduleUrl"
- target="__blank"
- :title="__('This pipeline was triggered by a schedule.')"
- variant="info"
- size="sm"
- data-testid="pipeline-url-scheduled"
- >{{ __('Scheduled') }}</gl-badge
- >
- <gl-badge
- v-if="pipeline.flags.latest"
- v-gl-tooltip
- :title="__('Latest pipeline for the most recent commit on this branch')"
- variant="success"
- size="sm"
- data-testid="pipeline-url-latest"
- >{{ __('latest') }}</gl-badge
- >
- <gl-badge
- v-if="pipeline.flags.merge_train_pipeline"
- v-gl-tooltip
- :title="
- s__(
- 'Pipeline|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch.',
- )
- "
- variant="info"
- size="sm"
- data-testid="pipeline-url-train"
- >{{ s__('Pipeline|merge train') }}</gl-badge
- >
- <gl-badge
- v-if="pipeline.flags.yaml_errors"
- v-gl-tooltip
- :title="pipeline.yaml_errors"
- variant="danger"
- size="sm"
- data-testid="pipeline-url-yaml"
- >{{ __('yaml invalid') }}</gl-badge
- >
- <gl-badge
- v-if="pipeline.flags.failure_reason"
- v-gl-tooltip
- :title="pipeline.failure_reason"
- variant="danger"
- size="sm"
- data-testid="pipeline-url-failure"
- >{{ __('error') }}</gl-badge
- >
- <template v-if="pipeline.flags.auto_devops">
- <gl-link
- :id="autoDevopsTagId"
- tabindex="0"
- data-testid="pipeline-url-autodevops"
- role="button"
- >
- <gl-badge variant="info" size="sm">
- {{ __('Auto DevOps') }}
- </gl-badge>
- </gl-link>
- <gl-popover :target="autoDevopsTagId" triggers="focus" placement="top">
- <template #title>
- <div class="gl-font-weight-normal gl-line-height-normal">
- <gl-sprintf
- :message="
- __(
- 'This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}',
- )
- "
- >
- <template #strong="{ content }">
- <b>{{ content }}</b>
- </template>
- </gl-sprintf>
- </div>
- </template>
- <gl-link
- :href="autoDevopsHelpPath"
- data-testid="pipeline-url-autodevops-link"
- target="_blank"
- >
- {{ __('Learn more about Auto DevOps') }}
- </gl-link>
- </gl-popover>
- </template>
-
- <gl-badge
- v-if="pipeline.flags.stuck"
- variant="warning"
- size="sm"
- data-testid="pipeline-url-stuck"
- >{{ __('stuck') }}</gl-badge
- >
- <gl-badge
- v-if="pipeline.flags.detached_merge_request_pipeline"
- v-gl-tooltip
- :title="
- s__(
- `Pipeline|This pipeline ran on the contents of this merge request's source branch, not the target branch.`,
- )
- "
- variant="info"
- size="sm"
- data-testid="pipeline-url-detached"
- >{{ s__('Pipeline|merge request') }}</gl-badge
- >
- <gl-badge
- v-if="isInFork"
- v-gl-tooltip
- :title="__('Pipeline ran in fork of project')"
- variant="info"
- size="sm"
- data-testid="pipeline-url-fork"
- >{{ __('fork') }}</gl-badge
- >
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
deleted file mode 100644
index 747d94d92f2..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
+++ /dev/null
@@ -1,172 +0,0 @@
-<script>
-import {
- GlAlert,
- GlDropdown,
- GlDropdownItem,
- GlSearchBoxByType,
- GlLoadingIcon,
- GlTooltipDirective,
-} from '@gitlab/ui';
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import axios from '~/lib/utils/axios_utils';
-import { __, s__ } from '~/locale';
-import Tracking from '~/tracking';
-import { TRACKING_CATEGORIES } from '../../constants';
-
-export const i18n = {
- downloadArtifacts: __('Download artifacts'),
- artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
- artifactsFetchWarningMessage: s__(
- 'Pipelines|Failed to update. Please reload page to update the list of artifacts.',
- ),
- emptyArtifactsMessage: __('No artifacts found'),
-};
-
-export default {
- i18n,
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: {
- GlAlert,
- GlDropdown,
- GlDropdownItem,
- GlSearchBoxByType,
- GlLoadingIcon,
- },
- mixins: [Tracking.mixin()],
- inject: {
- artifactsEndpoint: {
- default: '',
- },
- artifactsEndpointPlaceholder: {
- default: '',
- },
- },
- props: {
- pipelineId: {
- type: Number,
- required: true,
- },
- },
- data() {
- return {
- artifacts: [],
- hasError: false,
- isLoading: false,
- searchQuery: '',
- isNewPipeline: false,
- };
- },
- computed: {
- hasArtifacts() {
- return this.artifacts.length > 0;
- },
- filteredArtifacts() {
- return this.searchQuery.length > 0
- ? fuzzaldrinPlus.filter(this.artifacts, this.searchQuery, { key: 'name' })
- : this.artifacts;
- },
- },
- watch: {
- pipelineId() {
- this.isNewPipeline = true;
- },
- },
- methods: {
- fetchArtifacts() {
- // refactor tracking based on action once this dropdown supports
- // actions other than artifacts
- this.track('click_artifacts_dropdown', { label: TRACKING_CATEGORIES.table });
-
- // Preserve the last good list and present it if a request fails
- const oldArtifacts = [...this.artifacts];
- this.artifacts = [];
-
- this.hasError = false;
- this.isLoading = true;
-
- // Replace the placeholder with the ID of the pipeline we are viewing
- const endpoint = this.artifactsEndpoint.replace(
- this.artifactsEndpointPlaceholder,
- this.pipelineId,
- );
- return axios
- .get(endpoint)
- .then(({ data }) => {
- this.artifacts = data.artifacts;
- this.isNewPipeline = false;
- })
- .catch(() => {
- this.hasError = true;
- if (!this.isNewPipeline) {
- this.artifacts = oldArtifacts;
- }
- })
- .finally(() => {
- this.isLoading = false;
- });
- },
- handleDropdownShown() {
- if (this.hasArtifacts) {
- this.$refs.searchInput.focusInput();
- }
- },
- },
-};
-</script>
-<template>
- <gl-dropdown
- v-gl-tooltip
- :title="$options.i18n.downloadArtifacts"
- :text="$options.i18n.downloadArtifacts"
- :aria-label="$options.i18n.downloadArtifacts"
- :header-text="$options.i18n.downloadArtifacts"
- icon="download"
- data-testid="pipeline-multi-actions-dropdown"
- right
- lazy
- text-sr-only
- @show="fetchArtifacts"
- @shown="handleDropdownShown"
- >
- <gl-alert v-if="hasError && !hasArtifacts" variant="danger" :dismissible="false">
- {{ $options.i18n.artifactsFetchErrorMessage }}
- </gl-alert>
-
- <gl-loading-icon v-else-if="isLoading" size="sm" />
-
- <gl-dropdown-item v-else-if="!hasArtifacts" data-testid="artifacts-empty-message">
- {{ $options.i18n.emptyArtifactsMessage }}
- </gl-dropdown-item>
-
- <template #header>
- <gl-search-box-by-type v-if="hasArtifacts" ref="searchInput" v-model.trim="searchQuery" />
- </template>
-
- <gl-dropdown-item
- v-for="(artifact, i) in filteredArtifacts"
- :key="i"
- :href="artifact.path"
- rel="nofollow"
- download
- class="gl-word-break-word"
- data-testid="artifact-item"
- >
- {{ artifact.name }}
- </gl-dropdown-item>
-
- <template #footer>
- <gl-dropdown-item
- v-if="hasError && hasArtifacts"
- class="gl-list-style-none"
- disabled
- data-testid="artifacts-fetch-warning"
- >
- <span class="gl-font-sm">
- {{ $options.i18n.artifactsFetchWarningMessage }}
- </span>
- </gl-dropdown-item>
- </template>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
deleted file mode 100644
index caeee7edefe..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-<script>
-import { GlButton, GlTooltipDirective, GlModalDirective } from '@gitlab/ui';
-import Tracking from '~/tracking';
-import eventHub from '../../event_hub';
-import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL, TRACKING_CATEGORIES } from '../../constants';
-import PipelineMultiActions from './pipeline_multi_actions.vue';
-import PipelinesManualActions from './pipelines_manual_actions.vue';
-
-export default {
- BUTTON_TOOLTIP_RETRY,
- BUTTON_TOOLTIP_CANCEL,
- directives: {
- GlTooltip: GlTooltipDirective,
- GlModalDirective,
- },
- components: {
- GlButton,
- PipelineMultiActions,
- PipelinesManualActions,
- },
- mixins: [Tracking.mixin()],
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- cancelingPipeline: {
- type: Number,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- isRetrying: false,
- };
- },
- computed: {
- hasActions() {
- return (
- this.pipeline?.details?.has_manual_actions || this.pipeline?.details?.has_scheduled_actions
- );
- },
- isCancelling() {
- return this.cancelingPipeline === this.pipeline.id;
- },
- },
- watch: {
- pipeline() {
- this.isRetrying = false;
- },
- },
- methods: {
- handleCancelClick() {
- this.trackClick('click_cancel_button');
- eventHub.$emit('openConfirmationModal', {
- pipeline: this.pipeline,
- endpoint: this.pipeline.cancel_path,
- });
- },
- handleRetryClick() {
- this.isRetrying = true;
- this.trackClick('click_retry_button');
- eventHub.$emit('retryPipeline', this.pipeline.retry_path);
- },
- trackClick(action) {
- this.track(action, { label: TRACKING_CATEGORIES.table });
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-text-right">
- <div class="btn-group">
- <pipelines-manual-actions v-if="hasActions" :iid="pipeline.iid" />
-
- <gl-button
- v-if="pipeline.flags.retryable"
- v-gl-tooltip.hover
- :aria-label="$options.BUTTON_TOOLTIP_RETRY"
- :title="$options.BUTTON_TOOLTIP_RETRY"
- :disabled="isRetrying"
- :loading="isRetrying"
- class="js-pipelines-retry-button"
- data-qa-selector="pipeline_retry_button"
- data-testid="pipelines-retry-button"
- icon="retry"
- variant="default"
- category="secondary"
- @click="handleRetryClick"
- />
-
- <gl-button
- v-if="pipeline.flags.cancelable"
- v-gl-tooltip.hover
- v-gl-modal-directive="'confirmation-modal'"
- :aria-label="$options.BUTTON_TOOLTIP_CANCEL"
- :title="$options.BUTTON_TOOLTIP_CANCEL"
- :loading="isCancelling"
- :disabled="isCancelling"
- icon="cancel"
- variant="danger"
- category="primary"
- class="js-pipelines-cancel-button gl-ml-1"
- data-testid="pipelines-cancel-button"
- @click="handleCancelClick"
- />
-
- <pipeline-multi-actions :pipeline-id="pipeline.id" />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
deleted file mode 100644
index 9f38be668f2..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-<script>
-import { GlLink, GlModal, GlSprintf } from '@gitlab/ui';
-import { isEmpty } from 'lodash';
-import { __, s__, sprintf } from '~/locale';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
-
-/**
- * Pipeline Stop Modal.
- *
- * Renders the modal used to confirm stopping a pipeline.
- */
-export default {
- components: {
- GlModal,
- GlLink,
- GlSprintf,
- CiIcon,
- },
- props: {
- pipeline: {
- type: Object,
- required: true,
- deep: true,
- },
- },
- computed: {
- modalTitle() {
- return sprintf(
- s__('Pipeline|Stop pipeline #%{pipelineId}?'),
- {
- pipelineId: `${this.pipeline.id}`,
- },
- false,
- );
- },
- modalText() {
- return s__(`Pipeline|You’re about to stop pipeline #%{pipelineId}.`);
- },
- hasRef() {
- return !isEmpty(this.pipeline.ref);
- },
- primaryProps() {
- return {
- text: s__('Pipeline|Stop pipeline'),
- attributes: { variant: 'danger' },
- };
- },
- cancelProps() {
- return {
- text: __('Cancel'),
- };
- },
- },
- methods: {
- emitSubmit(event) {
- this.$emit('submit', event);
- },
- },
-};
-</script>
-<template>
- <gl-modal
- modal-id="confirmation-modal"
- :title="modalTitle"
- :action-primary="primaryProps"
- :action-cancel="cancelProps"
- @primary="emitSubmit($event)"
- >
- <p>
- <gl-sprintf :message="modalText">
- <template #pipelineId>
- <strong>{{ pipeline.id }}</strong>
- </template>
- </gl-sprintf>
- </p>
-
- <p v-if="pipeline">
- <ci-icon
- v-if="pipeline.details"
- :status="pipeline.details.status"
- class="vertical-align-middle"
- />
-
- <span class="font-weight-bold">{{ __('Pipeline') }}</span>
-
- <a :href="pipeline.path" class="js-pipeline-path link-commit">#{{ pipeline.id }}</a>
- <template v-if="hasRef">
- {{ __('from') }}
- <a :href="pipeline.ref.path" class="link-commit ref-name">{{ pipeline.ref.name }}</a>
- </template>
- </p>
-
- <template v-if="pipeline.commit">
- <p>
- <span class="font-weight-bold">{{ __('Commit') }}</span>
-
- <gl-link :href="pipeline.commit.commit_path" class="js-commit-sha commit-sha link-commit">
- {{ pipeline.commit.short_id }}
- </gl-link>
- </p>
- <p>{{ pipeline.commit.title }}</p>
- </template>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
deleted file mode 100644
index 2a73795db0a..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-<script>
-import { GlAvatarLink, GlAvatar, GlTooltipDirective } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-export default {
- components: {
- GlAvatarLink,
- GlAvatar,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [glFeatureFlagMixin()],
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- },
- computed: {
- user() {
- return this.pipeline.user;
- },
- },
-};
-</script>
-<template>
- <div class="pipeline-triggerer" data-testid="pipeline-triggerer">
- <gl-avatar-link v-if="user" v-gl-tooltip :href="user.path" :title="user.name" class="gl-ml-3">
- <gl-avatar :size="32" :src="user.avatar_url" />
- </gl-avatar-link>
-
- <span v-else class="gl-ml-3">
- {{ s__('Pipelines|API') }}
- </span>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
deleted file mode 100644
index ff1a01d5037..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ /dev/null
@@ -1,239 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlTooltipDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
-import Tracking from '~/tracking';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import { ICONS, TRACKING_CATEGORIES } from '../../constants';
-import PipelineLabels from './pipeline_labels.vue';
-
-export default {
- components: {
- GlIcon,
- GlLink,
- PipelineLabels,
- TooltipOnTruncate,
- UserAvatarLink,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [Tracking.mixin()],
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- pipelineScheduleUrl: {
- type: String,
- required: true,
- },
- pipelineKey: {
- type: String,
- required: true,
- },
- refClass: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- mergeRequestRef() {
- return this.pipeline?.merge_request;
- },
- commitRef() {
- return this.pipeline?.ref;
- },
- commitTag() {
- return this.commitRef?.tag;
- },
- commitUrl() {
- return this.pipeline?.commit?.commit_path;
- },
- commitShortSha() {
- return this.pipeline?.commit?.short_id;
- },
- refUrl() {
- return this.commitRef?.ref_url || this.commitRef?.path;
- },
- tooltipTitle() {
- return this.mergeRequestRef?.title || this.commitRef?.name;
- },
- commitAuthor() {
- let commitAuthorInformation;
- const pipelineCommit = this.pipeline?.commit;
- const pipelineCommitAuthor = pipelineCommit?.author;
-
- if (!pipelineCommit) {
- return null;
- }
-
- // 1. person who is an author of a commit might be a GitLab user
- if (pipelineCommitAuthor) {
- // 2. if person who is an author of a commit is a GitLab user
- // they can have a GitLab avatar
- if (pipelineCommitAuthor?.avatar_url) {
- commitAuthorInformation = pipelineCommitAuthor;
-
- // 3. If GitLab user does not have avatar, they might have a Gravatar
- } else if (pipelineCommit.author_gravatar_url) {
- commitAuthorInformation = {
- ...pipelineCommitAuthor,
- avatar_url: pipelineCommit.author_gravatar_url,
- };
- }
- // 4. If committer is not a GitLab User, they can have a Gravatar
- } else {
- commitAuthorInformation = {
- avatar_url: pipelineCommit.author_gravatar_url,
- path: `mailto:${pipelineCommit.author_email}`,
- username: pipelineCommit.author_name,
- };
- }
-
- return commitAuthorInformation;
- },
- commitIcon() {
- let name = '';
-
- if (this.commitTag) {
- name = ICONS.TAG;
- } else if (this.mergeRequestRef) {
- name = ICONS.MR;
- } else {
- name = ICONS.BRANCH;
- }
-
- return name;
- },
- commitIconTooltipTitle() {
- switch (this.commitIcon) {
- case ICONS.TAG:
- return __('Tag');
- case ICONS.MR:
- return __('Merge Request');
- default:
- return __('Branch');
- }
- },
- commitTitle() {
- return this.pipeline?.commit?.title;
- },
- pipelineName() {
- return this.pipeline?.name;
- },
- },
- methods: {
- trackClick(action) {
- this.track(action, { label: TRACKING_CATEGORIES.table });
- },
- },
-};
-</script>
-<template>
- <div class="pipeline-tags" data-testid="pipeline-url-table-cell">
- <div v-if="pipelineName" class="gl-mb-2" data-testid="pipeline-name-container">
- <span class="gl-display-flex">
- <tooltip-on-truncate
- :title="pipelineName"
- class="gl-flex-grow-1 gl-text-truncate gl-text-gray-900"
- >
- <gl-link
- :href="pipeline.path"
- class="gl-text-blue-600!"
- data-testid="pipeline-url-link"
- >{{ pipelineName }}</gl-link
- >
- </tooltip-on-truncate>
- </span>
- </div>
-
- <div v-if="!pipelineName" class="commit-title gl-mb-2" data-testid="commit-title-container">
- <span v-if="commitTitle" class="gl-display-flex">
- <tooltip-on-truncate :title="commitTitle" class="gl-flex-grow-1 gl-text-truncate">
- <gl-link
- :href="commitUrl"
- class="commit-row-message gl-text-blue-600!"
- data-testid="commit-title"
- @click="trackClick('click_commit_title')"
- >{{ commitTitle }}</gl-link
- >
- </tooltip-on-truncate>
- </span>
- <span v-else class="gl-text-gray-500">{{
- __("Can't find HEAD commit for this branch")
- }}</span>
- </div>
- <div class="gl-mb-2">
- <gl-link
- :href="pipeline.path"
- class="gl-mr-1 gl-text-blue-500!"
- data-testid="pipeline-url-link"
- data-qa-selector="pipeline_url_link"
- @click="trackClick('click_pipeline_id')"
- >#{{ pipeline[pipelineKey] }}</gl-link
- >
- <!--Commit row-->
- <div class="gl-display-inline-flex gl-rounded-base gl-px-2 gl-bg-gray-50 gl-text-gray-700">
- <tooltip-on-truncate :title="tooltipTitle" truncate-target="child" placement="top">
- <gl-icon
- v-gl-tooltip
- :name="commitIcon"
- :title="commitIconTooltipTitle"
- :size="12"
- data-testid="commit-icon-type"
- />
- <gl-link
- v-if="mergeRequestRef"
- :href="mergeRequestRef.path"
- class="gl-font-sm gl-font-monospace gl-text-gray-700! gl-hover-text-gray-900!"
- :class="refClass"
- data-testid="merge-request-ref"
- @click="trackClick('click_mr_ref')"
- >{{ mergeRequestRef.iid }}</gl-link
- >
- <gl-link
- v-else
- :href="refUrl"
- class="gl-font-sm gl-font-monospace gl-text-gray-700! gl-hover-text-gray-900!"
- :class="refClass"
- data-testid="commit-ref-name"
- @click="trackClick('click_commit_name')"
- >{{ commitRef.name }}</gl-link
- >
- </tooltip-on-truncate>
- </div>
- <div
- class="gl-display-inline-block gl-rounded-base gl-font-sm gl-px-2 gl-bg-gray-50 gl-text-black-normal"
- >
- <gl-icon
- v-gl-tooltip
- name="commit"
- class="commit-icon gl-mr-1"
- :title="__('Commit')"
- :size="12"
- data-testid="commit-icon"
- />
- <gl-link
- :href="commitUrl"
- class="gl-font-sm gl-font-monospace gl-mr-0 gl-text-gray-700!"
- data-testid="commit-short-sha"
- @click="trackClick('click_commit_sha')"
- >{{ commitShortSha }}</gl-link
- >
- </div>
- <user-avatar-link
- v-if="commitAuthor"
- :link-href="commitAuthor.path"
- :img-src="commitAuthor.avatar_url"
- :img-size="16"
- :img-alt="commitAuthor.name"
- :tooltip-text="commitAuthor.name"
- class="gl-ml-1"
- />
- <!--End of commit row-->
- </div>
- <pipeline-labels :pipeline-schedule-url="pipelineScheduleUrl" :pipeline="pipeline" />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
deleted file mode 100644
index 574d291a767..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ /dev/null
@@ -1,449 +0,0 @@
-<!-- eslint-disable vue/multi-word-component-names -->
-<script>
-import { GlEmptyState, GlIcon, GlLoadingIcon, GlCollapsibleListbox } from '@gitlab/ui';
-import { isEqual } from 'lodash';
-import * as Sentry from '@sentry/browser';
-import { createAlert, VARIANT_INFO, VARIANT_WARNING } from '~/alert';
-import { getParameterByName } from '~/lib/utils/url_utility';
-import { __, s__ } from '~/locale';
-import Tracking from '~/tracking';
-import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
-import { isLoggedIn } from '~/lib/utils/common_utils';
-import setSortPreferenceMutation from '~/issues/list/queries/set_sort_preference.mutation.graphql';
-import {
- ANY_TRIGGER_AUTHOR,
- RAW_TEXT_WARNING,
- FILTER_TAG_IDENTIFIER,
- PipelineKeyOptions,
- TRACKING_CATEGORIES,
-} from '../../constants';
-import PipelinesMixin from '../../mixins/pipelines_mixin';
-import PipelinesService from '../../services/pipelines_service';
-import { validateParams } from '../../utils';
-import EmptyState from './empty_state.vue';
-import NavigationControls from './nav_controls.vue';
-import PipelinesFilteredSearch from './pipelines_filtered_search.vue';
-import PipelinesTableComponent from './pipelines_table.vue';
-
-export default {
- PipelineKeyOptions,
- components: {
- EmptyState,
- GlCollapsibleListbox,
- GlEmptyState,
- GlIcon,
- GlLoadingIcon,
- NavigationTabs,
- NavigationControls,
- PipelinesFilteredSearch,
- PipelinesTableComponent,
- TablePagination,
- },
- mixins: [PipelinesMixin, Tracking.mixin()],
- 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',
- },
- endpoint: {
- type: String,
- required: true,
- },
- pipelineScheduleUrl: {
- type: String,
- required: false,
- default: '',
- },
- emptyStateSvgPath: {
- type: String,
- required: true,
- },
- errorStateSvgPath: {
- type: String,
- required: true,
- },
- noPipelinesSvgPath: {
- type: String,
- required: true,
- },
- hasGitlabCi: {
- type: Boolean,
- required: true,
- },
- canCreatePipeline: {
- type: Boolean,
- required: true,
- },
- ciLintPath: {
- type: String,
- required: false,
- default: null,
- },
- resetCachePath: {
- type: String,
- required: false,
- default: null,
- },
- newPipelinePath: {
- type: String,
- required: false,
- default: null,
- },
- projectId: {
- type: String,
- required: true,
- },
- defaultBranchName: {
- type: String,
- required: false,
- default: null,
- },
- params: {
- type: Object,
- required: true,
- },
- registrationToken: {
- type: String,
- required: false,
- default: null,
- },
- defaultVisibilityPipelineIdType: {
- type: String,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- // Start with loading state to avoid a glitch when the empty state will be rendered
- isLoading: true,
- state: this.store.state,
- scope: getParameterByName('scope') || 'all',
- page: getParameterByName('page') || '1',
- requestData: {},
- isResetCacheButtonLoading: false,
- visibilityPipelineIdType: this.defaultVisibilityPipelineIdType,
- };
- },
- stateMap: {
- // with tabs
- loading: 'loading',
- tableList: 'tableList',
- error: 'error',
- emptyTab: 'emptyTab',
-
- // without tabs
- emptyState: 'emptyState',
- },
- scopes: {
- all: 'all',
- finished: 'finished',
- branches: 'branches',
- tags: 'tags',
- },
- computed: {
- /**
- * `hasGitlabCi` handles both internal and external CI.
- * The order on which the checks are made in this method is
- * important to guarantee we handle all the corner cases.
- */
- stateToRender() {
- const { stateMap } = this.$options;
-
- if (this.isLoading) {
- return stateMap.loading;
- }
-
- if (this.hasError) {
- return stateMap.error;
- }
-
- if (this.state.pipelines.length) {
- return stateMap.tableList;
- }
-
- if ((this.scope !== 'all' && this.scope !== null) || this.hasGitlabCi) {
- return stateMap.emptyTab;
- }
-
- return stateMap.emptyState;
- },
- /**
- * Tabs are rendered in all states except empty state.
- * They are not rendered before the first request to avoid a flicker on first load.
- */
- shouldRenderTabs() {
- const { stateMap } = this.$options;
- return (
- this.hasMadeRequest &&
- [stateMap.loading, stateMap.tableList, stateMap.error, stateMap.emptyTab].includes(
- this.stateToRender,
- )
- );
- },
-
- shouldRenderButtons() {
- return (
- (this.newPipelinePath || this.resetCachePath || this.ciLintPath) && this.shouldRenderTabs
- );
- },
-
- shouldRenderPagination() {
- return !this.isLoading && !this.hasError;
- },
-
- emptyTabMessage() {
- if (this.scope === this.$options.scopes.finished) {
- return s__('Pipelines|There are currently no finished pipelines.');
- }
-
- return s__('Pipelines|There are currently no pipelines.');
- },
-
- tabs() {
- const { count } = this.state;
- const { scopes } = this.$options;
-
- return [
- {
- name: __('All'),
- scope: scopes.all,
- count: count.all,
- isActive: this.scope === 'all',
- },
- {
- name: __('Finished'),
- scope: scopes.finished,
- isActive: this.scope === 'finished',
- },
- {
- name: __('Branches'),
- scope: scopes.branches,
- isActive: this.scope === 'branches',
- },
- {
- name: __('Tags'),
- scope: scopes.tags,
- isActive: this.scope === 'tags',
- },
- ];
- },
- validatedParams() {
- return validateParams(this.params);
- },
- selectedPipelineKeyOption() {
- return (
- this.$options.PipelineKeyOptions.find((e) => this.visibilityPipelineIdType === e.value) ||
- this.$options.PipelineKeyOptions[0]
- );
- },
- },
- created() {
- this.service = new PipelinesService(this.endpoint);
- this.requestData = { page: this.page, scope: this.scope, ...this.validatedParams };
- },
- methods: {
- onChangeTab(scope) {
- if (this.scope === scope) {
- return;
- }
-
- let params = {
- scope,
- page: '1',
- };
-
- params = this.onChangeWithFilter(params);
-
- this.updateContent(params);
-
- this.track('click_filter_tabs', { label: TRACKING_CATEGORIES.tabs, property: scope });
- },
- successCallback(resp) {
- // Because we are polling & the user is interacting verify if the response received
- // matches the last request made
- if (isEqual(resp.config.params, this.requestData)) {
- this.store.storeCount(resp.data.count);
- this.store.storePagination(resp.headers);
- this.setCommonData(resp.data.pipelines);
- }
- },
- handleResetRunnersCache(endpoint) {
- this.isResetCacheButtonLoading = true;
-
- this.service
- .postAction(endpoint)
- .then(() => {
- this.isResetCacheButtonLoading = false;
- createAlert({
- message: s__('Pipelines|Project cache successfully reset.'),
- variant: VARIANT_INFO,
- });
- })
- .catch(() => {
- this.isResetCacheButtonLoading = false;
- createAlert({
- message: s__('Pipelines|Something went wrong while cleaning runners cache.'),
- });
- });
- },
- resetRequestData() {
- this.requestData = { page: this.page, scope: this.scope };
- },
- filterPipelines(filters) {
- this.resetRequestData();
-
- filters.forEach((filter) => {
- // do not add Any for username query param, so we
- // can fetch all trigger authors
- if (
- filter.type &&
- filter.value.data !== ANY_TRIGGER_AUTHOR &&
- filter.type !== FILTER_TAG_IDENTIFIER
- ) {
- this.requestData[filter.type] = filter.value.data;
- }
-
- if (filter.type === FILTER_TAG_IDENTIFIER) {
- this.requestData.ref = filter.value.data;
- }
-
- if (!filter.type) {
- createAlert({
- message: RAW_TEXT_WARNING,
- variant: VARIANT_WARNING,
- });
- }
- });
-
- if (filters.length === 0) {
- this.resetRequestData();
- }
-
- this.updateContent({ ...this.requestData, page: '1' });
- },
- changeVisibilityPipelineIDType(idType) {
- this.visibilityPipelineIdType = idType;
- this.saveVisibilityPipelineIDType(idType);
- },
- saveVisibilityPipelineIDType(idType) {
- if (!isLoggedIn()) return;
-
- this.$apollo
- .mutate({
- mutation: setSortPreferenceMutation,
- variables: { input: { visibilityPipelineIdType: idType.toUpperCase() } },
- })
- .then(({ data }) => {
- if (data.userPreferencesUpdate.errors.length) {
- throw new Error(data.userPreferencesUpdate.errors);
- }
- })
- .catch((error) => {
- Sentry.captureException(error);
- });
- },
- },
-};
-</script>
-<template>
- <div class="pipelines-container">
- <div
- v-if="shouldRenderTabs || shouldRenderButtons"
- class="top-area scrolling-tabs-container inner-page-scroll-tabs gl-border-none"
- >
- <div class="fade-left"><gl-icon name="chevron-lg-left" :size="12" /></div>
- <div class="fade-right"><gl-icon name="chevron-lg-right" :size="12" /></div>
-
- <navigation-tabs
- v-if="shouldRenderTabs"
- :tabs="tabs"
- scope="pipelines"
- @onChangeTab="onChangeTab"
- />
-
- <navigation-controls
- v-if="shouldRenderButtons"
- :new-pipeline-path="newPipelinePath"
- :reset-cache-path="resetCachePath"
- :ci-lint-path="ciLintPath"
- :is-reset-cache-button-loading="isResetCacheButtonLoading"
- @resetRunnersCache="handleResetRunnersCache"
- />
- </div>
-
- <div v-if="stateToRender !== $options.stateMap.emptyState" class="gl-display-flex">
- <div class="row-content-block gl-display-flex gl-flex-grow-1 gl-border-b-0">
- <pipelines-filtered-search
- class="gl-display-flex gl-flex-grow-1 gl-mr-4"
- :project-id="projectId"
- :default-branch-name="defaultBranchName"
- :params="validatedParams"
- @filterPipelines="filterPipelines"
- />
- <gl-collapsible-listbox
- v-model="visibilityPipelineIdType"
- data-testid="pipeline-key-collapsible-box"
- :toggle-text="selectedPipelineKeyOption.text"
- :items="$options.PipelineKeyOptions"
- @select="changeVisibilityPipelineIDType"
- />
- </div>
- </div>
-
- <div class="content-list pipelines">
- <gl-loading-icon
- v-if="stateToRender === $options.stateMap.loading"
- :label="s__('Pipelines|Loading Pipelines')"
- size="lg"
- class="prepend-top-20"
- />
-
- <empty-state
- v-else-if="stateToRender === $options.stateMap.emptyState"
- :empty-state-svg-path="emptyStateSvgPath"
- :can-set-ci="canCreatePipeline"
- :registration-token="registrationToken"
- />
-
- <gl-empty-state
- v-else-if="stateToRender === $options.stateMap.error"
- :svg-path="errorStateSvgPath"
- :title="s__('Pipelines|There was an error fetching the pipelines.')"
- :description="s__('Pipelines|Try again in a few moments or contact your support team.')"
- />
-
- <gl-empty-state
- v-else-if="stateToRender === $options.stateMap.emptyTab"
- :svg-path="noPipelinesSvgPath"
- :title="emptyTabMessage"
- />
-
- <div v-else-if="stateToRender === $options.stateMap.tableList">
- <pipelines-table-component
- :pipelines="state.pipelines"
- :pipeline-schedule-url="pipelineScheduleUrl"
- :update-graph-dropdown="updateGraphDropdown"
- :view-type="viewType"
- :pipeline-key-option="selectedPipelineKeyOption"
- />
- </div>
-
- <table-pagination
- v-if="shouldRenderPagination"
- :change="onChangePage"
- :page-info="state.pageInfo"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
deleted file mode 100644
index 4452db64b0a..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
+++ /dev/null
@@ -1,72 +0,0 @@
-<script>
-import { GlDisclosureDropdown, GlTooltipDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export const i18n = {
- artifacts: __('Artifacts'),
- artifactSectionHeader: __('Download artifacts'),
-};
-
-export default {
- i18n,
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: {
- GlDisclosureDropdown,
- },
- inject: {
- artifactsEndpoint: {
- default: '',
- },
- artifactsEndpointPlaceholder: {
- default: '',
- },
- },
- props: {
- pipelineId: {
- type: Number,
- required: true,
- },
- artifacts: {
- type: Array,
- required: false,
- default: () => [],
- },
- },
- computed: {
- items() {
- return [
- {
- name: this.$options.i18n.artifactSectionHeader,
- items: this.artifacts.map(({ name, path }) => ({
- text: name,
- href: path,
- extraAttrs: {
- download: '',
- rel: 'nofollow',
- },
- })),
- },
- ];
- },
- shouldShowDropdown() {
- return this.artifacts?.length;
- },
- },
-};
-</script>
-<template>
- <gl-disclosure-dropdown
- v-if="shouldShowDropdown"
- v-gl-tooltip
- class="build-artifacts js-pipeline-dropdown-download"
- :title="$options.i18n.artifacts"
- :toggle-text="$options.i18n.artifacts"
- :aria-label="$options.i18n.artifacts"
- icon="download"
- placement="right"
- text-sr-only
- :items="items"
- />
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
deleted file mode 100644
index 7dc1e60610e..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
+++ /dev/null
@@ -1,130 +0,0 @@
-<script>
-import { GlFilteredSearch } from '@gitlab/ui';
-import { map } from 'lodash';
-import { s__ } from '~/locale';
-import Tracking from '~/tracking';
-import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
-import { TRACKING_CATEGORIES } from '../../constants';
-import PipelineBranchNameToken from './tokens/pipeline_branch_name_token.vue';
-import PipelineSourceToken from './tokens/pipeline_source_token.vue';
-import PipelineStatusToken from './tokens/pipeline_status_token.vue';
-import PipelineTagNameToken from './tokens/pipeline_tag_name_token.vue';
-import PipelineTriggerAuthorToken from './tokens/pipeline_trigger_author_token.vue';
-
-export default {
- userType: 'username',
- branchType: 'ref',
- tagType: 'tag',
- statusType: 'status',
- sourceType: 'source',
- defaultTokensLength: 1,
- components: {
- GlFilteredSearch,
- },
- mixins: [Tracking.mixin()],
- props: {
- projectId: {
- type: String,
- required: true,
- },
- defaultBranchName: {
- type: String,
- required: false,
- default: null,
- },
- params: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- internalValue: [],
- };
- },
- computed: {
- selectedTypes() {
- return this.value.map((i) => i.type);
- },
- tokens() {
- return [
- {
- type: this.$options.userType,
- icon: 'user',
- title: s__('Pipeline|Trigger author'),
- unique: true,
- token: PipelineTriggerAuthorToken,
- operators: OPERATORS_IS,
- projectId: this.projectId,
- },
- {
- type: this.$options.branchType,
- icon: 'branch',
- title: s__('Pipeline|Branch name'),
- unique: true,
- token: PipelineBranchNameToken,
- operators: OPERATORS_IS,
- projectId: this.projectId,
- defaultBranchName: this.defaultBranchName,
- disabled: this.selectedTypes.includes(this.$options.tagType),
- },
- {
- type: this.$options.tagType,
- icon: 'tag',
- title: s__('Pipeline|Tag name'),
- unique: true,
- token: PipelineTagNameToken,
- operators: OPERATORS_IS,
- projectId: this.projectId,
- disabled: this.selectedTypes.includes(this.$options.branchType),
- },
- {
- type: this.$options.statusType,
- icon: 'status',
- title: s__('Pipeline|Status'),
- unique: true,
- token: PipelineStatusToken,
- operators: OPERATORS_IS,
- },
- {
- type: this.$options.sourceType,
- icon: 'trigger-source',
- title: s__('Pipeline|Source'),
- unique: true,
- token: PipelineSourceToken,
- operators: OPERATORS_IS,
- },
- ];
- },
- parsedParams() {
- return map(this.params, (val, key) => ({
- type: key,
- value: { data: val, operator: '=' },
- }));
- },
- value: {
- get() {
- return this.internalValue.length > 0 ? this.internalValue : this.parsedParams;
- },
- set(value) {
- this.internalValue = value;
- },
- },
- },
- methods: {
- onSubmit(filters) {
- this.track('click_filtered_search', { label: TRACKING_CATEGORIES.search });
- this.$emit('filterPipelines', filters);
- },
- },
-};
-</script>
-
-<template>
- <gl-filtered-search
- v-model="value"
- :placeholder="__('Filter pipelines')"
- :available-tokens="tokens"
- @submit="onSubmit"
- />
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
deleted file mode 100644
index 262e82677a7..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
+++ /dev/null
@@ -1,159 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import { createAlert } from '~/alert';
-import axios from '~/lib/utils/axios_utils';
-import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
-import { s__, __, sprintf } from '~/locale';
-import Tracking from '~/tracking';
-import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
-import eventHub from '../../event_hub';
-import { TRACKING_CATEGORIES } from '../../constants';
-import getPipelineActionsQuery from '../../graphql/queries/get_pipeline_actions.query.graphql';
-
-export default {
- name: 'PipelinesManualActions',
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: {
- GlCountdown,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
- GlLoadingIcon,
- },
- mixins: [Tracking.mixin()],
- inject: ['fullPath', 'manualActionsLimit'],
- props: {
- iid: {
- type: Number,
- required: true,
- },
- },
- apollo: {
- actions: {
- query: getPipelineActionsQuery,
- variables() {
- return {
- fullPath: this.fullPath,
- iid: this.iid,
- limit: this.manualActionsLimit,
- };
- },
- skip() {
- return !this.hasDropdownBeenShown;
- },
- update({ project }) {
- return project?.pipeline?.jobs?.nodes || [];
- },
- },
- },
- data() {
- return {
- isLoading: false,
- actions: [],
- hasDropdownBeenShown: false,
- };
- },
- computed: {
- isActionsLoading() {
- return this.$apollo.queries.actions.loading;
- },
- isDropdownLimitReached() {
- return this.actions.length === this.manualActionsLimit;
- },
- },
- methods: {
- async onClickAction(action) {
- if (action.scheduledAt) {
- const confirmationMessage = sprintf(
- s__(
- 'DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes.',
- ),
- { jobName: action.name },
- );
-
- const confirmed = await confirmAction(confirmationMessage);
-
- if (!confirmed) {
- return;
- }
- }
-
- this.isLoading = true;
-
- /**
- * Ideally, the component would not make an api call directly.
- * However, in order to use the eventhub and know when to
- * toggle back the `isLoading` property we'd need an ID
- * to track the request with a watcher - since this component
- * is rendered at least 20 times in the same page, moving the
- * api call directly here is the most performant solution
- */
- axios
- .post(`${action.playPath}.json`)
- .then(() => {
- this.isLoading = false;
- eventHub.$emit('updateTable');
- })
- .catch(() => {
- this.isLoading = false;
- createAlert({ message: __('An error occurred while making the request.') });
- });
- },
- fetchActions() {
- this.hasDropdownBeenShown = true;
-
- this.$apollo.queries.actions.refetch();
-
- this.trackClick();
- },
- trackClick() {
- this.track('click_manual_actions', { label: TRACKING_CATEGORIES.table });
- },
- },
-};
-</script>
-<template>
- <gl-dropdown
- v-gl-tooltip
- :title="__('Run manual or delayed jobs')"
- :loading="isLoading"
- data-testid="pipelines-manual-actions-dropdown"
- right
- lazy
- icon="play"
- @shown="fetchActions"
- >
- <gl-dropdown-item v-if="isActionsLoading">
- <div class="gl-display-flex">
- <gl-loading-icon class="mr-2" />
- <span>{{ __('Loading...') }}</span>
- </div>
- </gl-dropdown-item>
-
- <gl-dropdown-item
- v-for="action in actions"
- v-else
- :key="action.id"
- :disabled="!action.canPlayJob"
- @click="onClickAction(action)"
- >
- <div class="gl-display-flex gl-justify-content-space-between gl-flex-wrap">
- {{ action.name }}
- <span v-if="action.scheduledAt">
- <gl-icon name="clock" />
- <gl-countdown :end-date-string="action.scheduledAt" />
- </span>
- </div>
- </gl-dropdown-item>
-
- <template #footer>
- <gl-dropdown-item v-if="isDropdownLimitReached">
- <span class="gl-font-sm gl-text-gray-300!" data-testid="limit-reached-msg">
- {{ __('Showing first 50 actions.') }}
- </span>
- </gl-dropdown-item>
- </template>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
deleted file mode 100644
index 00ab8a25ca1..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
+++ /dev/null
@@ -1,50 +0,0 @@
-<script>
-import { CHILD_VIEW, TRACKING_CATEGORIES } from '~/pipelines/constants';
-import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue';
-import Tracking from '~/tracking';
-import PipelinesTimeago from './time_ago.vue';
-
-export default {
- components: {
- CiBadgeLink,
- PipelinesTimeago,
- },
- mixins: [Tracking.mixin()],
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- viewType: {
- type: String,
- required: true,
- },
- },
- computed: {
- pipelineStatus() {
- return this.pipeline?.details?.status ?? {};
- },
- isChildView() {
- return this.viewType === CHILD_VIEW;
- },
- },
- methods: {
- trackClick() {
- this.track('click_ci_status_badge', { label: TRACKING_CATEGORIES.table });
- },
- },
-};
-</script>
-
-<template>
- <div>
- <ci-badge-link
- class="gl-mb-3"
- :status="pipelineStatus"
- :show-text="!isChildView"
- data-qa-selector="pipeline_commit_status"
- @ciStatusBadgeClick="trackClick"
- />
- <pipelines-timeago :pipeline="pipeline" />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
deleted file mode 100644
index c03085e6419..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ /dev/null
@@ -1,240 +0,0 @@
-<script>
-import { GlTableLite, GlTooltipDirective } from '@gitlab/ui';
-import { cleanLeadingSeparator } from '~/lib/utils/url_utility';
-import { s__, __ } from '~/locale';
-import Tracking from '~/tracking';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
-import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
-import PipelineFailedJobsWidget from '~/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue';
-import eventHub from '../../event_hub';
-import { TRACKING_CATEGORIES } from '../../constants';
-import PipelineOperations from './pipeline_operations.vue';
-import PipelineStopModal from './pipeline_stop_modal.vue';
-import PipelineTriggerer from './pipeline_triggerer.vue';
-import PipelineUrl from './pipeline_url.vue';
-import PipelinesStatusBadge from './pipelines_status_badge.vue';
-
-const HIDE_TD_ON_MOBILE = 'gl-display-none! gl-lg-display-table-cell!';
-const DEFAULT_TH_CLASSES =
- 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!';
-
-export default {
- components: {
- GlTableLite,
- LegacyPipelineMiniGraph,
- PipelineFailedJobsWidget,
- PipelineOperations,
- PipelinesStatusBadge,
- PipelineStopModal,
- PipelineTriggerer,
- PipelineUrl,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [Tracking.mixin(), glFeatureFlagMixin()],
- inject: {
- withFailedJobsDetails: {
- default: false,
- },
- },
- props: {
- pipelines: {
- type: Array,
- required: true,
- },
- pipelineScheduleUrl: {
- type: String,
- required: false,
- default: '',
- },
- updateGraphDropdown: {
- type: Boolean,
- required: false,
- default: false,
- },
- viewType: {
- type: String,
- required: true,
- },
- pipelineKeyOption: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- pipelineId: 0,
- pipeline: {},
- endpoint: '',
- cancelingPipeline: null,
- };
- },
- computed: {
- showFailedJobsWidget() {
- return this.glFeatures.ciJobFailuresInMr;
- },
- tableFields() {
- return [
- {
- key: 'status',
- label: s__('Pipeline|Status'),
- thClass: DEFAULT_TH_CLASSES,
- columnClass: 'gl-w-15p',
- tdClass: this.tdClasses,
- thAttr: { 'data-testid': 'status-th' },
- },
- {
- key: 'pipeline',
- label: __('Pipeline'),
- thClass: DEFAULT_TH_CLASSES,
- tdClass: `${this.tdClasses}`,
- columnClass: 'gl-w-30p',
- thAttr: { 'data-testid': 'pipeline-th' },
- },
- {
- key: 'triggerer',
- label: s__('Pipeline|Triggerer'),
- thClass: DEFAULT_TH_CLASSES,
- tdClass: `${this.tdClasses} ${HIDE_TD_ON_MOBILE}`,
- columnClass: 'gl-w-10p',
- thAttr: { 'data-testid': 'triggerer-th' },
- },
- {
- key: 'stages',
- label: s__('Pipeline|Stages'),
- thClass: DEFAULT_TH_CLASSES,
- tdClass: this.tdClasses,
- columnClass: 'gl-w-quarter',
- thAttr: { 'data-testid': 'stages-th' },
- },
- {
- key: 'actions',
- thClass: DEFAULT_TH_CLASSES,
- tdClass: this.tdClasses,
- columnClass: 'gl-w-15p',
- thAttr: { 'data-testid': 'actions-th' },
- },
- ];
- },
- tdClasses() {
- return this.withFailedJobsDetails ? 'gl-pb-0! gl-border-none!' : 'pl-p-5!';
- },
- pipelinesWithDetails() {
- if (this.withFailedJobsDetails) {
- return this.pipelines.map((p) => {
- return { ...p, _showDetails: true };
- });
- }
-
- return this.pipelines;
- },
- },
- watch: {
- pipelines() {
- this.cancelingPipeline = null;
- },
- },
- created() {
- eventHub.$on('openConfirmationModal', this.setModalData);
- },
- beforeDestroy() {
- eventHub.$off('openConfirmationModal', this.setModalData);
- },
- methods: {
- getDownstreamPipelines(pipeline) {
- const downstream = pipeline.triggered;
- return keepLatestDownstreamPipelines(downstream);
- },
- getProjectPath(item) {
- return cleanLeadingSeparator(item.project.full_path);
- },
- failedJobsCount(pipeline) {
- return pipeline?.failed_builds?.length || 0;
- },
- setModalData(data) {
- this.pipelineId = data.pipeline.id;
- this.pipeline = data.pipeline;
- this.endpoint = data.endpoint;
- },
- onSubmit() {
- eventHub.$emit('postAction', this.endpoint);
- this.cancelingPipeline = this.pipelineId;
- },
- trackPipelineMiniGraph() {
- this.track('click_minigraph', { label: TRACKING_CATEGORIES.table });
- },
- },
- TBODY_TR_ATTR: {
- 'data-testid': 'pipeline-table-row',
- 'data-qa-selector': 'pipeline_row_container',
- },
-};
-</script>
-<template>
- <div class="ci-table">
- <gl-table-lite
- :fields="tableFields"
- :items="pipelinesWithDetails"
- :tbody-tr-attr="$options.TBODY_TR_ATTR"
- stacked="lg"
- fixed
- >
- <template #head(actions)>
- <span class="gl-display-block gl-lg-display-none!">{{ s__('Pipeline|Actions') }}</span>
- <slot name="table-header-actions"></slot>
- </template>
-
- <template #table-colgroup="{ fields }">
- <col v-for="field in fields" :key="field.key" :class="field.columnClass" />
- </template>
-
- <template #cell(status)="{ item }">
- <pipelines-status-badge :pipeline="item" :view-type="viewType" />
- </template>
-
- <template #cell(pipeline)="{ item }">
- <pipeline-url
- :pipeline="item"
- :pipeline-schedule-url="pipelineScheduleUrl"
- :pipeline-key="pipelineKeyOption.value"
- ref-color="gl-text-black-normal"
- />
- </template>
-
- <template #cell(triggerer)="{ item }">
- <pipeline-triggerer :pipeline="item" />
- </template>
-
- <template #cell(stages)="{ item }">
- <legacy-pipeline-mini-graph
- :downstream-pipelines="getDownstreamPipelines(item)"
- :pipeline-path="item.path"
- :stages="item.details.stages"
- :update-dropdown="updateGraphDropdown"
- :upstream-pipeline="item.triggered_by"
- @miniGraphStageClick="trackPipelineMiniGraph"
- />
- </template>
-
- <template #cell(actions)="{ item }">
- <pipeline-operations :pipeline="item" :canceling-pipeline="cancelingPipeline" />
- </template>
-
- <template #row-details="{ item }">
- <pipeline-failed-jobs-widget
- v-if="showFailedJobsWidget"
- :failed-jobs-count="failedJobsCount(item)"
- :is-pipeline-active="item.active"
- :pipeline-iid="item.iid"
- :pipeline-path="item.path"
- :project-path="getProjectPath(item)"
- class="gl-ml-n4 gl-mt-n3 gl-mb-n1"
- />
- </template>
- </gl-table-lite>
-
- <pipeline-stop-modal :pipeline="pipeline" @submit="onSubmit" />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
deleted file mode 100644
index 70343544638..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import { formatTime } from '~/lib/utils/datetime_utility';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-
-export default {
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: { GlIcon },
- mixins: [timeagoMixin],
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- fontSize: {
- type: String,
- required: false,
- default: 'gl-font-sm',
- validator: (fontSize) => ['gl-font-sm', 'gl-font-md'].includes(fontSize),
- },
- },
- computed: {
- duration() {
- return this.pipeline?.details?.duration;
- },
- durationFormatted() {
- return formatTime(this.duration * 1000);
- },
- finishedTime() {
- return this.pipeline?.details?.finished_at || this.pipeline?.finishedAt;
- },
- },
-};
-</script>
-<template>
- <div
- class="gl-display-flex gl-flex-direction-column gl-align-items-flex-end gl-lg-align-items-flex-start"
- :class="fontSize"
- >
- <p v-if="duration" class="duration gl-display-inline-flex gl-align-items-center">
- <gl-icon name="timer" class="gl-mr-2" :size="12" />
- {{ durationFormatted }}
- </p>
-
- <p v-if="finishedTime" class="finished-at gl-display-inline-flex gl-align-items-center">
- <gl-icon name="calendar" class="gl-mr-2" :size="12" data-testid="calendar-icon" />
-
- <time
- v-gl-tooltip
- :title="tooltipTitle(finishedTime)"
- :datetime="finishedTime"
- data-placement="top"
- data-container="body"
- >
- {{ timeFormatted(finishedTime) }}
- </time>
- </p>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js
deleted file mode 100644
index d8f15cfde91..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import { s__ } from '~/locale';
-
-export const PIPELINE_SOURCES = [
- {
- text: s__('PipelineSource|Push'),
- value: 'push',
- },
- {
- text: s__('PipelineSource|Web'),
- value: 'web',
- },
- {
- text: s__('PipelineSource|Trigger'),
- value: 'trigger',
- },
- {
- text: s__('PipelineSource|Schedule'),
- value: 'schedule',
- },
- {
- text: s__('PipelineSource|API'),
- value: 'api',
- },
- {
- text: s__('PipelineSource|External'),
- value: 'external',
- },
- {
- text: s__('PipelineSource|Pipeline'),
- value: 'pipeline',
- },
- {
- text: s__('PipelineSource|Chat'),
- value: 'chat',
- },
- {
- text: s__('PipelineSource|Web IDE'),
- value: 'webide',
- },
- {
- text: s__('PipelineSource|Merge Request'),
- value: 'merge_request_event',
- },
- {
- text: s__('PipelineSource|External Pull Request'),
- value: 'external_pull_request_event',
- },
- {
- text: s__('PipelineSource|Parent Pipeline'),
- value: 'parent_pipeline',
- },
-];
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
deleted file mode 100644
index 81f46d5f2f9..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<script>
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
-import { debounce } from 'lodash';
-import Api from '~/api';
-import { createAlert } from '~/alert';
-import { FETCH_BRANCH_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
-
-export default {
- components: {
- GlFilteredSearchToken,
- GlFilteredSearchSuggestion,
- GlLoadingIcon,
- },
- props: {
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- branches: null,
- loading: true,
- };
- },
- created() {
- this.fetchBranches();
- },
- methods: {
- fetchBranches(searchterm) {
- Api.branches(this.config.projectId, searchterm)
- .then(({ data }) => {
- this.branches = data.map((branch) => branch.name);
- if (!searchterm && this.config.defaultBranchName) {
- // Shift the default branch to the top of the list
- this.branches = this.branches.filter(
- (branch) => branch !== this.config.defaultBranchName,
- );
- this.branches.unshift(this.config.defaultBranchName);
- }
- this.loading = false;
- })
- .catch((err) => {
- createAlert({
- message: FETCH_BRANCH_ERROR_MESSAGE,
- });
- this.loading = false;
- throw err;
- });
- },
- searchBranches: debounce(function debounceSearch({ data }) {
- this.fetchBranches(data);
- }, FILTER_PIPELINES_SEARCH_DELAY),
- },
-};
-</script>
-
-<template>
- <gl-filtered-search-token
- :config="config"
- v-bind="{ ...$props, ...$attrs }"
- v-on="$listeners"
- @input="searchBranches"
- >
- <template #suggestions>
- <gl-loading-icon v-if="loading" size="sm" />
- <template v-else>
- <gl-filtered-search-suggestion
- v-for="(branch, index) in branches"
- :key="index"
- :value="branch"
- >
- {{ branch }}
- </gl-filtered-search-suggestion>
- </template>
- </template>
- </gl-filtered-search-token>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue
deleted file mode 100644
index 9643ddfbd21..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-<script>
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import { PIPELINE_SOURCES } from 'ee_else_ce/pipelines/components/pipelines_list/tokens/constants';
-
-export default {
- PIPELINE_SOURCES,
- components: {
- GlFilteredSearchToken,
- GlFilteredSearchSuggestion,
- },
- props: {
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- computed: {
- activeSource() {
- return PIPELINE_SOURCES.find((source) => source.value === this.value.data);
- },
- },
-};
-</script>
-
-<template>
- <gl-filtered-search-token v-bind="{ ...$props, ...$attrs }" v-on="$listeners">
- <template #view>
- <div class="gl-display-flex gl-align-items-center">
- <span>{{ activeSource.text }}</span>
- </div>
- </template>
-
- <template #suggestions>
- <gl-filtered-search-suggestion
- v-for="source in $options.PIPELINE_SOURCES"
- :key="source.value"
- :value="source.value"
- >
- {{ source.text }}
- </gl-filtered-search-suggestion>
- </template>
- </gl-filtered-search-token>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue
deleted file mode 100644
index 020a08b8cee..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-<script>
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlIcon } from '@gitlab/ui';
-import { s__ } from '~/locale';
-
-export default {
- components: {
- GlFilteredSearchToken,
- GlFilteredSearchSuggestion,
- GlIcon,
- },
- props: {
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- computed: {
- statuses() {
- return [
- {
- class: 'ci-status-icon-canceled',
- icon: 'status_canceled',
- text: s__('Pipeline|Canceled'),
- value: 'canceled',
- },
- {
- class: 'ci-status-icon-created',
- icon: 'status_created',
- text: s__('Pipeline|Created'),
- value: 'created',
- },
- {
- class: 'ci-status-icon-failed',
- icon: 'status_failed',
- text: s__('Pipeline|Failed'),
- value: 'failed',
- },
- {
- class: 'ci-status-icon-manual',
- icon: 'status_manual',
- text: s__('Pipeline|Manual'),
- value: 'manual',
- },
- {
- class: 'ci-status-icon-success',
- icon: 'status_success',
- text: s__('Pipeline|Passed'),
- value: 'success',
- },
- {
- class: 'ci-status-icon-pending',
- icon: 'status_pending',
- text: s__('Pipeline|Pending'),
- value: 'pending',
- },
- {
- class: 'ci-status-icon-running',
- icon: 'status_running',
- text: s__('Pipeline|Running'),
- value: 'running',
- },
- {
- class: 'ci-status-icon-skipped',
- icon: 'status_skipped',
- text: s__('Pipeline|Skipped'),
- value: 'skipped',
- },
- ];
- },
- findActiveStatus() {
- return this.statuses.find((status) => status.value === this.value.data);
- },
- },
-};
-</script>
-
-<template>
- <gl-filtered-search-token v-bind="{ ...$props, ...$attrs }" v-on="$listeners">
- <template #view>
- <div class="gl-display-flex gl-align-items-center">
- <div :class="findActiveStatus.class">
- <gl-icon :name="findActiveStatus.icon" class="gl-mr-2 gl-display-block" />
- </div>
- <span>{{ findActiveStatus.text }}</span>
- </div>
- </template>
- <template #suggestions>
- <gl-filtered-search-suggestion
- v-for="(status, index) in statuses"
- :key="index"
- :value="status.value"
- >
- <div class="gl-display-flex" :class="status.class">
- <gl-icon :name="status.icon" class="gl-mr-3" />
- <span>{{ status.text }}</span>
- </div>
- </gl-filtered-search-suggestion>
- </template>
- </gl-filtered-search-token>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
deleted file mode 100644
index b32f5de2d7e..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-<script>
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
-import { debounce } from 'lodash';
-import Api from '~/api';
-import { createAlert } from '~/alert';
-import { FETCH_TAG_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
-
-export default {
- components: {
- GlFilteredSearchToken,
- GlFilteredSearchSuggestion,
- GlLoadingIcon,
- },
- props: {
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- tags: null,
- loading: true,
- };
- },
- created() {
- this.fetchTags();
- },
- methods: {
- fetchTags(searchTerm) {
- Api.tags(this.config.projectId, searchTerm)
- .then(({ data }) => {
- this.tags = data.map((tag) => tag.name);
- this.loading = false;
- })
- .catch((err) => {
- createAlert({
- message: FETCH_TAG_ERROR_MESSAGE,
- });
- this.loading = false;
- throw err;
- });
- },
- searchTags: debounce(function debounceSearch({ data }) {
- this.fetchTags(data);
- }, FILTER_PIPELINES_SEARCH_DELAY),
- },
-};
-</script>
-
-<template>
- <gl-filtered-search-token v-bind="{ ...$props, ...$attrs }" v-on="$listeners" @input="searchTags">
- <template #suggestions>
- <gl-loading-icon v-if="loading" size="sm" />
- <template v-else>
- <gl-filtered-search-suggestion v-for="(tag, index) in tags" :key="index" :value="tag">
- {{ tag }}
- </gl-filtered-search-suggestion>
- </template>
- </template>
- </gl-filtered-search-token>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
deleted file mode 100644
index a89354c671a..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-<script>
-import {
- GlFilteredSearchToken,
- GlAvatar,
- GlFilteredSearchSuggestion,
- GlDropdownDivider,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { debounce } from 'lodash';
-import Api from '~/api';
-import { createAlert } from '~/alert';
-import {
- ANY_TRIGGER_AUTHOR,
- FETCH_AUTHOR_ERROR_MESSAGE,
- FILTER_PIPELINES_SEARCH_DELAY,
-} from '../../../constants';
-
-export default {
- anyTriggerAuthor: ANY_TRIGGER_AUTHOR,
- components: {
- GlFilteredSearchToken,
- GlAvatar,
- GlFilteredSearchSuggestion,
- GlDropdownDivider,
- GlLoadingIcon,
- },
- props: {
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- users: [],
- loading: true,
- };
- },
- computed: {
- currentValue() {
- return this.value.data.toLowerCase();
- },
- activeUser() {
- return this.users.find((user) => {
- return user.username.toLowerCase() === this.currentValue;
- });
- },
- },
- created() {
- this.fetchProjectUsers();
- },
- methods: {
- fetchProjectUsers(searchTerm) {
- Api.projectUsers(this.config.projectId, searchTerm)
- .then((users) => {
- this.users = users;
- this.loading = false;
- })
- .catch((err) => {
- createAlert({
- message: FETCH_AUTHOR_ERROR_MESSAGE,
- });
- this.loading = false;
- throw err;
- });
- },
- searchAuthors: debounce(function debounceSearch({ data }) {
- this.fetchProjectUsers(data);
- }, FILTER_PIPELINES_SEARCH_DELAY),
- },
-};
-</script>
-
-<template>
- <gl-filtered-search-token
- :config="config"
- v-bind="{ ...$props, ...$attrs }"
- v-on="$listeners"
- @input="searchAuthors"
- >
- <template #view="{ inputValue }">
- <gl-avatar v-if="activeUser" :size="16" :src="activeUser.avatar_url" class="gl-mr-2" />
- <span>{{ activeUser ? activeUser.name : inputValue }}</span>
- </template>
- <template #suggestions>
- <gl-filtered-search-suggestion :value="$options.anyTriggerAuthor">{{
- $options.anyTriggerAuthor
- }}</gl-filtered-search-suggestion>
- <gl-dropdown-divider />
-
- <gl-loading-icon v-if="loading" size="sm" />
- <template v-else>
- <gl-filtered-search-suggestion
- v-for="user in users"
- :key="user.username"
- :value="user.username"
- >
- <div class="d-flex">
- <gl-avatar :size="32" :src="user.avatar_url" />
- <div>
- <div>{{ user.name }}</div>
- <div>@{{ user.username }}</div>
- </div>
- </div>
- </gl-filtered-search-suggestion>
- </template>
- </template>
- </gl-filtered-search-token>
-</template>