summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/analytics/shared/utils.js
blob: 701cdcf0a2dd8eea9bb981c7a0c09a3bee87b94a (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
import { flatten } from 'lodash';
import dateFormat from '~/lib/dateformat';
import { slugify } from '~/lib/utils/text_utility';
import { joinPaths } from '~/lib/utils/url_utility';
import { urlQueryToFilter } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import { dateFormats, METRICS_POPOVER_CONTENT } from './constants';

export const filterBySearchTerm = (data = [], searchTerm = '', filterByKey = 'name') => {
  if (!searchTerm?.length) return data;
  return data.filter((item) => item[filterByKey].toLowerCase().includes(searchTerm.toLowerCase()));
};

export const toYmd = (date) => dateFormat(date, dateFormats.isoDate);

/**
 * Takes a url and extracts query parameters used for the shared
 * filter bar
 *
 * @param {string} url The URL to extract query parameters from
 * @returns {Object}
 */
export const extractFilterQueryParameters = (url = '') => {
  const {
    source_branch_name: selectedSourceBranch = null,
    target_branch_name: selectedTargetBranch = null,
    author_username: selectedAuthor = null,
    milestone_title: selectedMilestone = null,
    assignee_username: selectedAssigneeList = [],
    label_name: selectedLabelList = [],
  } = urlQueryToFilter(url);

  return {
    selectedSourceBranch,
    selectedTargetBranch,
    selectedAuthor,
    selectedMilestone,
    selectedAssigneeList,
    selectedLabelList,
  };
};

/**
 * Takes a url and extracts sorting and pagination query parameters into an object
 *
 * @param {string} url The URL to extract query parameters from
 * @returns {Object}
 */
export const extractPaginationQueryParameters = (url = '') => {
  const { sort, direction, page } = urlQueryToFilter(url);
  return {
    sort: sort?.value || null,
    direction: direction?.value || null,
    page: page?.value || null,
  };
};

export const getDataZoomOption = ({
  totalItems = 0,
  maxItemsPerPage = 40,
  dataZoom = [{ type: 'slider', bottom: 10, start: 0 }],
}) => {
  if (totalItems <= maxItemsPerPage) {
    return {};
  }

  const intervalEnd = Math.ceil((maxItemsPerPage / totalItems) * 100);

  return dataZoom.map((item) => {
    return {
      ...item,
      end: intervalEnd,
    };
  });
};

export const removeFlash = (type = 'alert') => {
  // flash-warning don't have dismiss button.
  document.querySelector(`.flash-${type} .js-close`)?.click();
};

/**
 * Prepares metric data to be rendered in the metric_card component
 *
 * @param {MetricData[]} data - The metric data to be rendered
 * @param {Object} popoverContent - Key value pair of data to display in the popover
 * @returns {TransformedMetricData[]} An array of metrics ready to render in the metric_card
 */
export const prepareTimeMetricsData = (data = [], popoverContent = {}) =>
  data.map(({ title: label, identifier, ...rest }) => {
    const metricIdentifier = identifier || slugify(label);
    return {
      ...rest,
      label,
      identifier: metricIdentifier,
      description: popoverContent[metricIdentifier]?.description || '',
    };
  });

const requestData = ({ request, endpoint, requestPath, params, name }) => {
  return request({ endpoint, params, requestPath })
    .then(({ data }) => data)
    .catch(() => {
      throw new Error(name);
    });
};

/**
 * Takes a configuration array of metrics requests (key metrics and DORA) and returns
 * a flat array of all the responses. Different metrics are retrieved from different endpoints
 * additionally we only support certain metrics for FOSS users.
 *
 * @param {Array} requests - array of metric api requests to be made
 * @param {String} requestPath - path for the group / project we are requesting
 * @param {Object} params - optional parameters to filter, including `created_after` and `created_before` dates
 * @returns a flat array of metrics
 */
export const fetchMetricsData = (requests = [], requestPath, params) => {
  const promises = requests.map((r) => requestData({ ...r, requestPath, params }));
  return Promise.all(promises).then((responses) =>
    prepareTimeMetricsData(flatten(responses), METRICS_POPOVER_CONTENT),
  );
};

/**
 * Generates a URL link to the VSD dashboard based on the group
 * and project paths passed into the method.
 *
 * @param {String} groupPath - Path of the specified group
 * @param {Array} projectPaths - Array of project paths to include in the `query` parameter
 * @returns a URL or blank string if there is no groupPath set
 */
export const generateValueStreamsDashboardLink = (groupPath, projectPaths = []) => {
  if (groupPath.length) {
    const query = projectPaths.length ? `?query=${projectPaths.join(',')}` : '';
    const dashboardsSlug = '/-/analytics/dashboards';
    const segments = [gon.relative_url_root || '', '/groups', groupPath, dashboardsSlug];
    return joinPaths(...segments).concat(query);
  }
  return '';
};