cycle_analytics_bundle.js 5.18 KB
Newer Older
1
import $ from 'jquery';
2
import Vue from 'vue';
3
import Cookies from 'js-cookie';
4
import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
5
import { deprecatedCreateFlash as Flash } from '../flash';
6
import { __ } from '~/locale';
7
import Translate from '../vue_shared/translate';
8
import banner from './components/banner.vue';
9 10 11 12 13
import stageCodeComponent from './components/stage_code_component.vue';
import stageComponent from './components/stage_component.vue';
import stageReviewComponent from './components/stage_review_component.vue';
import stageStagingComponent from './components/stage_staging_component.vue';
import stageTestComponent from './components/stage_test_component.vue';
14
import stageNavItem from './components/stage_nav_item.vue';
15 16
import CycleAnalyticsService from './cycle_analytics_service';
import CycleAnalyticsStore from './cycle_analytics_store';
17

18 19
Vue.use(Translate);

20
export default () => {
21
  const OVERVIEW_DIALOG_COOKIE = 'cycle_analytics_help_dismissed';
22
  const cycleAnalyticsEl = document.querySelector('#cycle-analytics');
23

24 25
  // eslint-disable-next-line no-new
  new Vue({
26 27
    el: '#cycle-analytics',
    name: 'CycleAnalytics',
28
    components: {
29
      GlEmptyState,
30
      GlLoadingIcon,
31 32
      banner,
      'stage-issue-component': stageComponent,
Gosia Ksionek's avatar
Gosia Ksionek committed
33
      'stage-plan-component': stageComponent,
34 35 36 37 38
      'stage-code-component': stageCodeComponent,
      'stage-test-component': stageTestComponent,
      'stage-review-component': stageReviewComponent,
      'stage-staging-component': stageStagingComponent,
      'stage-production-component': stageComponent,
39
      'stage-nav-item': stageNavItem,
40
    },
41 42 43 44 45 46 47 48 49 50
    data() {
      return {
        store: CycleAnalyticsStore,
        state: CycleAnalyticsStore.state,
        isLoading: false,
        isLoadingStage: false,
        isEmptyStage: false,
        hasError: false,
        startDate: 30,
        isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE),
51
        service: this.createCycleAnalyticsService(cycleAnalyticsEl.dataset.requestPath),
52
      };
53 54 55
    },
    computed: {
      currentStage() {
56
        return this.store.currentActiveStage();
57 58
      },
    },
59
    created() {
60
      // Conditional check placed here to prevent this method from being called on the
61
      // new Value Stream Analytics page (i.e. the new page will be initialized blank and only
62 63 64
      // after a group is selected the cycle analyitcs data will be fetched). Once the
      // old (current) page has been removed this entire created method as well as the
      // variable itself can be completely removed.
65
      // Follow up issue: https://gitlab.com/gitlab-org/gitlab-foss/issues/64490
66
      if (cycleAnalyticsEl.dataset.requestPath) this.fetchCycleAnalyticsData();
67 68
    },
    methods: {
69
      handleError() {
70
        this.store.setErrorState(true);
71
        return new Flash(__('There was an error while fetching value stream analytics data.'));
72 73 74 75 76
      },
      initDropdown() {
        const $dropdown = $('.js-ca-dropdown');
        const $label = $dropdown.find('.dropdown-label');

77
        // eslint-disable-next-line @gitlab/no-global-event-off
78 79 80 81 82 83 84
        $dropdown
          .find('li a')
          .off('click')
          .on('click', e => {
            e.preventDefault();
            const $target = $(e.currentTarget);
            this.startDate = $target.data('value');
85

86 87 88
            $label.text($target.text().trim());
            this.fetchCycleAnalyticsData({ startDate: this.startDate });
          });
89 90
      },
      fetchCycleAnalyticsData(options) {
91
        const fetchOptions = options || { startDate: this.startDate };
92

93
        this.isLoading = true;
94

95
        this.service
96
          .fetchCycleAnalyticsData(fetchOptions)
97
          .then(response => {
98
            this.store.setCycleAnalyticsData(response);
99
            this.selectDefaultStage();
100
            this.initDropdown();
101
            this.isLoading = false;
102
          })
103
          .catch(() => {
104 105 106 107 108
            this.handleError();
            this.isLoading = false;
          });
      },
      selectDefaultStage() {
109
        const stage = this.state.stages[0];
110
        this.selectStage(stage);
111 112 113 114 115
      },
      selectStage(stage) {
        if (this.isLoadingStage) return;
        if (this.currentStage === stage) return;

116
        if (!stage.isUserAllowed) {
117
          this.store.setActiveStage(stage);
118 119 120
          return;
        }

121
        this.isLoadingStage = true;
122 123
        this.store.setStageEvents([], stage);
        this.store.setActiveStage(stage);
124

125
        this.service
126 127 128
          .fetchStageData({
            stage,
            startDate: this.startDate,
129
            projectIds: this.selectedProjectIds,
130
          })
131
          .then(response => {
132
            this.isEmptyStage = !response.events.length;
133 134
            this.store.setStageEvents(response.events, stage);
            this.isLoadingStage = false;
135
          })
136
          .catch(() => {
137 138
            this.isEmptyStage = true;
            this.isLoadingStage = false;
139
          });
140 141 142
      },
      dismissOverviewDialog() {
        this.isOverviewDialogDismissed = true;
143
        Cookies.set(OVERVIEW_DIALOG_COOKIE, '1', { expires: 365 });
144
      },
145 146 147 148 149
      createCycleAnalyticsService(requestPath) {
        return new CycleAnalyticsService({
          requestPath,
        });
      },
150
    },
151
  });
152
};