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:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
commita7b3560714b4d9cc4ab32dffcd1f74a284b93580 (patch)
tree7452bd5c3545c2fa67a28aa013835fb4fa071baf /app/assets/javascripts/cycle_analytics
parentee9173579ae56a3dbfe5afe9f9410c65bb327ca7 (diff)
Add latest changes from gitlab-org/gitlab@14-8-stable-eev14.8.0-rc42
Diffstat (limited to 'app/assets/javascripts/cycle_analytics')
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue8
-rw-r--r--app/assets/javascripts/cycle_analytics/components/metric_popover.vue61
-rw-r--r--app/assets/javascripts/cycle_analytics/components/metric_tile.vue51
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_table.vue2
-rw-r--r--app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue110
-rw-r--r--app/assets/javascripts/cycle_analytics/constants.js25
-rw-r--r--app/assets/javascripts/cycle_analytics/utils.js30
7 files changed, 57 insertions, 230 deletions
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index bdfabb8e846..3d7a34581b3 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -1,12 +1,12 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import Cookies from 'js-cookie';
import { mapActions, mapState, mapGetters } from 'vuex';
+import { getCookie, setCookie } from '~/lib/utils/common_utils';
+import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
import { toYmd } from '~/analytics/shared/utils';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import StageTable from '~/cycle_analytics/components/stage_table.vue';
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
-import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { __ } from '~/locale';
import { SUMMARY_METRICS_REQUEST, METRICS_REQUESTS } from '../constants';
@@ -35,7 +35,7 @@ export default {
},
data() {
return {
- isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE),
+ isOverviewDialogDismissed: getCookie(OVERVIEW_DIALOG_COOKIE),
};
},
computed: {
@@ -134,7 +134,7 @@ export default {
},
dismissOverviewDialog() {
this.isOverviewDialogDismissed = true;
- Cookies.set(OVERVIEW_DIALOG_COOKIE, '1', { expires: 365 });
+ setCookie(OVERVIEW_DIALOG_COOKIE, '1');
},
isUserAllowed(id) {
const { permissions } = this;
diff --git a/app/assets/javascripts/cycle_analytics/components/metric_popover.vue b/app/assets/javascripts/cycle_analytics/components/metric_popover.vue
deleted file mode 100644
index 8d90e7b2392..00000000000
--- a/app/assets/javascripts/cycle_analytics/components/metric_popover.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<script>
-import { GlPopover, GlLink, GlIcon } from '@gitlab/ui';
-
-export default {
- name: 'MetricPopover',
- components: {
- GlPopover,
- GlLink,
- GlIcon,
- },
- props: {
- metric: {
- type: Object,
- required: true,
- },
- target: {
- type: String,
- required: true,
- },
- },
- computed: {
- metricLinks() {
- return this.metric.links?.filter((link) => !link.docs_link) || [];
- },
- docsLink() {
- return this.metric.links?.find((link) => link.docs_link);
- },
- },
-};
-</script>
-
-<template>
- <gl-popover :target="target" placement="bottom">
- <template #title>
- <span class="gl-display-block gl-text-left" data-testid="metric-label">{{
- metric.label
- }}</span>
- </template>
- <div
- v-for="(link, idx) in metricLinks"
- :key="`link-${idx}`"
- class="gl-display-flex gl-justify-content-space-between gl-text-right gl-py-1"
- data-testid="metric-link"
- >
- <span>{{ link.label }}</span>
- <gl-link :href="link.url" class="gl-font-sm">
- {{ link.name }}
- </gl-link>
- </div>
- <span v-if="metric.description" data-testid="metric-description">{{ metric.description }}</span>
- <gl-link
- v-if="docsLink"
- :href="docsLink.url"
- class="gl-font-sm"
- target="_blank"
- data-testid="metric-docs-link"
- >{{ docsLink.label }}
- <gl-icon name="external-link" class="gl-vertical-align-middle" />
- </gl-link>
- </gl-popover>
-</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/metric_tile.vue b/app/assets/javascripts/cycle_analytics/components/metric_tile.vue
new file mode 100644
index 00000000000..a5c20b237b3
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/components/metric_tile.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { redirectTo } from '~/lib/utils/url_utility';
+import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
+
+export default {
+ name: 'MetricTile',
+ components: {
+ GlSingleStat,
+ MetricPopover,
+ },
+ props: {
+ metric: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ decimalPlaces() {
+ const parsedFloat = parseFloat(this.metric.value);
+ return Number.isNaN(parsedFloat) || Number.isInteger(parsedFloat) ? 0 : 1;
+ },
+ hasLinks() {
+ return this.metric.links?.length && this.metric.links[0].url;
+ },
+ },
+ methods: {
+ clickHandler({ links }) {
+ if (this.hasLinks) {
+ redirectTo(links[0].url);
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div v-bind="$attrs">
+ <gl-single-stat
+ :id="metric.identifier"
+ :value="`${metric.value}`"
+ :title="metric.label"
+ :unit="metric.unit || ''"
+ :should-animate="true"
+ :animation-decimal-places="decimalPlaces"
+ :class="{ 'gl-hover-cursor-pointer': hasLinks }"
+ tabindex="0"
+ @click="clickHandler(metric)"
+ />
+ <metric-popover :metric="metric" :target="metric.identifier" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_table.vue b/app/assets/javascripts/cycle_analytics/components/stage_table.vue
index 8f7a3f99bab..ea5a1291a17 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_table.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_table.vue
@@ -266,7 +266,7 @@ export default {
>
<span class="gl-font-lg">&middot;</span>
<span data-testid="vsa-stage-event-date">
- {{ s__('OpenedNDaysAgo|Opened') }}
+ {{ s__('OpenedNDaysAgo|Created') }}
<gl-link class="gl-text-black-normal" :href="item.url">{{
item.createdAt
}}</gl-link>
diff --git a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue b/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
deleted file mode 100644
index 9671742e564..00000000000
--- a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
+++ /dev/null
@@ -1,110 +0,0 @@
-<script>
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
-import { GlSingleStat } from '@gitlab/ui/dist/charts';
-import { flatten } from 'lodash';
-import createFlash from '~/flash';
-import { sprintf, s__ } from '~/locale';
-import { redirectTo } from '~/lib/utils/url_utility';
-import { METRICS_POPOVER_CONTENT } from '../constants';
-import { removeFlash, prepareTimeMetricsData } from '../utils';
-import MetricPopover from './metric_popover.vue';
-
-const requestData = ({ request, endpoint, path, params, name }) => {
- return request({ endpoint, params, requestPath: path })
- .then(({ data }) => data)
- .catch(() => {
- const message = sprintf(
- s__(
- 'ValueStreamAnalytics|There was an error while fetching value stream analytics %{requestTypeName} data.',
- ),
- { requestTypeName: name },
- );
- createFlash({ message });
- });
-};
-
-const fetchMetricsData = (reqs = [], path, params) => {
- const promises = reqs.map((r) => requestData({ ...r, path, params }));
- return Promise.all(promises).then((responses) =>
- prepareTimeMetricsData(flatten(responses), METRICS_POPOVER_CONTENT),
- );
-};
-
-export default {
- name: 'ValueStreamMetrics',
- components: {
- GlSingleStat,
- GlSkeletonLoading,
- MetricPopover,
- },
- props: {
- requestPath: {
- type: String,
- required: true,
- },
- requestParams: {
- type: Object,
- required: true,
- },
- requests: {
- type: Array,
- required: true,
- },
- },
- data() {
- return {
- metrics: [],
- isLoading: false,
- };
- },
- watch: {
- requestParams() {
- this.fetchData();
- },
- },
- mounted() {
- this.fetchData();
- },
- methods: {
- fetchData() {
- removeFlash();
- this.isLoading = true;
- return fetchMetricsData(this.requests, this.requestPath, this.requestParams)
- .then((data) => {
- this.metrics = data;
- this.isLoading = false;
- })
- .catch(() => {
- this.isLoading = false;
- });
- },
- hasLinks(links) {
- return links?.length && links[0].url;
- },
- clickHandler({ links }) {
- if (this.hasLinks(links)) {
- redirectTo(links[0].url);
- }
- },
- },
-};
-</script>
-<template>
- <div class="gl-display-flex gl-flex-wrap" data-testid="vsa-time-metrics">
- <gl-skeleton-loading v-if="isLoading" class="gl-h-auto gl-py-3 gl-pr-9 gl-my-6" />
- <div v-for="metric in metrics" v-show="!isLoading" :key="metric.key" class="gl-my-6 gl-pr-9">
- <gl-single-stat
- :id="metric.key"
- :value="`${metric.value}`"
- :title="metric.label"
- :unit="metric.unit || ''"
- :should-animate="true"
- :animation-decimal-places="1"
- :class="{ 'gl-hover-cursor-pointer': hasLinks(metric.links) }"
- tabindex="0"
- @click="clickHandler(metric)"
- />
- <metric-popover :metric="metric" :target="metric.key" />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/cycle_analytics/constants.js b/app/assets/javascripts/cycle_analytics/constants.js
index 7d5822b0824..f0b2bd9dc5b 100644
--- a/app/assets/javascripts/cycle_analytics/constants.js
+++ b/app/assets/javascripts/cycle_analytics/constants.js
@@ -36,31 +36,6 @@ export const OVERVIEW_METRICS = {
RECENT_ACTIVITY: 'RECENT_ACTIVITY',
};
-export const METRICS_POPOVER_CONTENT = {
- 'lead-time': {
- description: s__('ValueStreamAnalytics|Median time from issue created to issue closed.'),
- },
- 'cycle-time': {
- description: s__(
- "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.",
- ),
- },
- 'lead-time-for-changes': {
- description: s__(
- 'ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period.',
- ),
- },
- 'new-issue': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
- 'new-issues': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
- deploys: { description: s__('ValueStreamAnalytics|Total number of deploys to production.') },
- 'deployment-frequency': {
- description: s__('ValueStreamAnalytics|Average number of deployments to production per day.'),
- },
- commits: {
- description: s__('ValueStreamAnalytics|Number of commits pushed to the default branch'),
- },
-};
-
export const SUMMARY_METRICS_REQUEST = [
{ endpoint: METRIC_TYPE_SUMMARY, name: __('recent activity'), request: getValueStreamMetrics },
];
diff --git a/app/assets/javascripts/cycle_analytics/utils.js b/app/assets/javascripts/cycle_analytics/utils.js
index 9af63f5f9cc..428bb11b950 100644
--- a/app/assets/javascripts/cycle_analytics/utils.js
+++ b/app/assets/javascripts/cycle_analytics/utils.js
@@ -1,14 +1,5 @@
-import { hideFlash } from '~/flash';
import { parseSeconds } from '~/lib/utils/datetime_utility';
import { formatTimeAsSummary } from '~/lib/utils/datetime/date_format_utility';
-import { slugify } from '~/lib/utils/text_utility';
-
-export const removeFlash = (type = 'alert') => {
- const flashEl = document.querySelector(`.flash-${type}`);
- if (flashEl) {
- hideFlash(flashEl);
- }
-};
/**
* Takes the stages and median data, combined with the selected stage, to build an
@@ -80,30 +71,11 @@ export const filterStagesByHiddenStatus = (stages = [], isHidden = true) =>
* @typedef {Object} TransformedMetricData
* @property {String} label - Title of the metric measured
* @property {String} value - String representing the decimal point value, e.g '1.5'
- * @property {String} key - Slugified string based on the 'title'
+ * @property {String} identifier - Slugified string based on the 'title' or the provided 'identifier' attribute
* @property {String} description - String to display for a description
* @property {String} unit - String representing the decimal point value, e.g '1.5'
*/
-/**
- * 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, ...rest }) => {
- const key = slugify(label);
- return {
- ...rest,
- label,
- key,
- description: popoverContent[key]?.description || '',
- };
- });
-
const extractFeatures = (gon) => ({
cycleAnalyticsForGroups: Boolean(gon?.licensed_features?.cycleAnalyticsForGroups),
});