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

pipelines_manual_actions.vue « components « pipelines_page « ci « javascripts « assets « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4dacd474bdec607e240c445a7d5ef10d0b62432d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<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>