diff options
Diffstat (limited to 'app/assets')
10 files changed, 186 insertions, 21 deletions
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue index b865c9deb72..22ee368b8e0 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue +++ b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue @@ -12,11 +12,18 @@ export default { type: String, required: true, }, + kubernetesIntegrationHelpPath: { + type: String, + required: true, + }, }, }; </script> <template> - <eks-cluster-configuration-form - :gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath" - /> + <div class="js-create-eks-cluster"> + <eks-cluster-configuration-form + :gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath" + :kubernetes-integration-help-path="kubernetesIntegrationHelpPath" + /> + </div> </template> diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue index d451516dd35..1188cf08850 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue +++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue @@ -35,6 +35,10 @@ export default { type: String, required: true, }, + kubernetesIntegrationHelpPath: { + type: String, + required: true, + }, }, computed: { ...mapState([ @@ -94,6 +98,20 @@ export default { securityGroupDropdownDisabled() { return !this.selectedVpc; }, + kubernetesIntegrationHelpText() { + const escapedUrl = _.escape(this.kubernetesIntegrationHelpPath); + + return sprintf( + s__( + 'ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration.', + ), + { + link_start: `<a href="${escapedUrl}" target="_blank" rel="noopener noreferrer">`, + link_end: '</a>', + }, + false, + ); + }, roleDropdownHelpText() { return sprintf( s__( @@ -212,6 +230,10 @@ export default { </script> <template> <form name="eks-cluster-configuration-form"> + <h2> + {{ s__('ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster') }} + </h2> + <p v-html="kubernetesIntegrationHelpText"></p> <div class="form-group"> <label class="label-bold" for="eks-cluster-name">{{ s__('ClusterIntegration|Kubernetes cluster name') diff --git a/app/assets/javascripts/create_cluster/eks_cluster/index.js b/app/assets/javascripts/create_cluster/eks_cluster/index.js index 77454a2bc00..1f595e9b2df 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/index.js +++ b/app/assets/javascripts/create_cluster/eks_cluster/index.js @@ -5,25 +5,22 @@ import createStore from './store'; Vue.use(Vuex); -export default () => - new Vue({ - el: '.js-create-eks-cluster-form-container', +export default el => { + const { gitlabManagedClusterHelpPath, kubernetesIntegrationHelpPath } = el.dataset; + + return new Vue({ + el, store: createStore(), components: { CreateEksCluster, }, - data() { - const { gitlabManagedClusterHelpPath } = document.querySelector(this.$options.el).dataset; - - return { - gitlabManagedClusterHelpPath, - }; - }, render(createElement) { return createElement('create-eks-cluster', { props: { - gitlabManagedClusterHelpPath: this.gitlabManagedClusterHelpPath, + gitlabManagedClusterHelpPath, + kubernetesIntegrationHelpPath, }, }); }, }); +}; diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue index 3528f0a9335..cd298e2c692 100644 --- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue +++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue @@ -4,6 +4,8 @@ import { GlEmptyState, GlButton, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ import Icon from '~/vue_shared/components/icon.vue'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import { __ } from '~/locale'; +import TrackEventDirective from '~/vue_shared/directives/track_event'; +import { trackViewInSentryOptions, trackClickErrorLinkToSentryOptions } from '../utils'; export default { fields: [ @@ -21,6 +23,9 @@ export default { Icon, TimeAgo, }, + directives: { + TrackEvent: TrackEventDirective, + }, props: { indexPath: { type: String, @@ -53,6 +58,8 @@ export default { }, methods: { ...mapActions(['startPolling', 'restartPolling']), + trackViewInSentryOptions, + trackClickErrorLinkToSentryOptions, }, }; </script> @@ -65,7 +72,13 @@ export default { </div> <div v-else> <div class="d-flex justify-content-end"> - <gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank"> + <gl-button + v-track-event="trackViewInSentryOptions(externalUrl)" + class="my-3 ml-auto" + variant="primary" + :href="externalUrl" + target="_blank" + > {{ __('View in Sentry') }} <icon name="external-link" class="flex-shrink-0" /> </gl-button> @@ -80,7 +93,12 @@ export default { </template> <template slot="error" slot-scope="errors"> <div class="d-flex flex-column"> - <gl-link :href="errors.item.externalUrl" class="d-flex text-dark" target="_blank"> + <gl-link + v-track-event="trackClickErrorLinkToSentryOptions(errors.item.externalUrl)" + :href="errors.item.externalUrl" + class="d-flex text-dark" + target="_blank" + > <strong class="text-truncate">{{ errors.item.title.trim() }}</strong> <icon name="external-link" class="ml-1 flex-shrink-0" /> </gl-link> diff --git a/app/assets/javascripts/error_tracking/utils.js b/app/assets/javascripts/error_tracking/utils.js new file mode 100644 index 00000000000..b832b1371b1 --- /dev/null +++ b/app/assets/javascripts/error_tracking/utils.js @@ -0,0 +1,23 @@ +/* eslint-disable @gitlab/i18n/no-non-i18n-strings */ + +/** + * Tracks snowplow event when user clicks View in Sentry btn + * @param {String} externalUrl that will be send as a property for the event + */ +export const trackViewInSentryOptions = url => ({ + category: 'Error Tracking', + action: 'click_view_in_sentry', + label: 'External Url', + property: url, +}); + +/** + * Tracks snowplow event when User clicks on error link to Sentry + * @param {String} externalUrl that will be send as a property for the event + */ +export const trackClickErrorLinkToSentryOptions = url => ({ + category: 'Error Tracking', + action: 'click_error_link_to_sentry', + label: 'Error Link', + property: url, +}); diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 09afa16e283..2e35ef8d4b0 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -21,7 +21,14 @@ import MonitorSingleStatChart from './charts/single_stat.vue'; import GraphGroup from './graph_group.vue'; import EmptyState from './empty_state.vue'; import { sidebarAnimationDuration, timeWindows } from '../constants'; -import { getTimeDiff, getTimeWindow } from '../utils'; +import TrackEventDirective from '~/vue_shared/directives/track_event'; + +import { + getTimeDiff, + getTimeWindow, + downloadCSVOptions, + generateLinkToChartOptions, +} from '../utils'; let sidebarMutationObserver; @@ -43,6 +50,7 @@ export default { directives: { GlModal: GlModalDirective, GlTooltip: GlTooltipDirective, + TrackEvent: TrackEventDirective, }, props: { externalDashboardUrl: { @@ -322,6 +330,8 @@ export default { groupHasData(group) { return this.chartsWithData(group.metrics).length > 0; }, + downloadCSVOptions, + generateLinkToChartOptions, }, addMetric: { title: s__('Metrics|Add metric'), @@ -552,10 +562,19 @@ export default { <template slot="button-content"> <icon name="ellipsis_v" class="text-secondary" /> </template> - <gl-dropdown-item :href="downloadCsv(graphData)" download="chart_metrics.csv"> + <gl-dropdown-item + v-track-event="downloadCSVOptions(graphData.title)" + :href="downloadCsv(graphData)" + download="chart_metrics.csv" + > {{ __('Download CSV') }} </gl-dropdown-item> <gl-dropdown-item + v-track-event=" + generateLinkToChartOptions( + generateLink(groupData.group, graphData.title, graphData.y_label), + ) + " class="js-chart-link" :data-clipboard-text=" generateLink(groupData.group, graphData.title, graphData.y_label) diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue index af0d8335c43..1a14d06f4c8 100644 --- a/app/assets/javascripts/monitoring/components/panel_type.vue +++ b/app/assets/javascripts/monitoring/components/panel_type.vue @@ -13,6 +13,8 @@ import Icon from '~/vue_shared/components/icon.vue'; import MonitorTimeSeriesChart from './charts/time_series.vue'; import MonitorSingleStatChart from './charts/single_stat.vue'; import MonitorEmptyChart from './charts/empty_chart.vue'; +import TrackEventDirective from '~/vue_shared/directives/track_event'; +import { downloadCSVOptions, generateLinkToChartOptions } from '../utils'; export default { components: { @@ -27,6 +29,7 @@ export default { directives: { GlModal: GlModalDirective, GlTooltip: GlTooltipDirective, + TrackEvent: TrackEventDirective, }, props: { clipboardText: { @@ -84,6 +87,8 @@ export default { showToast() { this.$toast.show(__('Link copied')); }, + downloadCSVOptions, + generateLinkToChartOptions, }, }; </script> @@ -121,13 +126,18 @@ export default { <template slot="button-content"> <icon name="ellipsis_v" class="text-secondary" /> </template> - <gl-dropdown-item :href="downloadCsv" download="chart_metrics.csv"> + <gl-dropdown-item + v-track-event="downloadCSVOptions(graphData.title)" + :href="downloadCsv" + download="chart_metrics.csv" + > {{ __('Download CSV') }} </gl-dropdown-item> <gl-dropdown-item + v-track-event="generateLinkToChartOptions(clipboardText)" class="js-chart-link" :data-clipboard-text="clipboardText" - @click="showToast" + @click="showToast(clipboardText)" > {{ __('Generate link to chart') }} </gl-dropdown-item> diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js index a134b4e3c33..9049695b992 100644 --- a/app/assets/javascripts/monitoring/utils.js +++ b/app/assets/javascripts/monitoring/utils.js @@ -45,4 +45,47 @@ export const graphDataValidatorForValues = (isValues, graphData) => { ); }; +/* eslint-disable @gitlab/i18n/no-non-i18n-strings */ +/** + * Checks that element that triggered event is located on cluster health check dashboard + * @param {HTMLElement} element to check against + * @returns {boolean} + */ +const isClusterHealthBoard = () => (document.body.dataset.page || '').includes(':clusters:show'); + +/** + * Tracks snowplow event when user generates link to metric chart + * @param {String} chart link that will be sent as a property for the event + * @return {Object} config object for event tracking + */ +export const generateLinkToChartOptions = chartLink => { + const isCLusterHealthBoard = isClusterHealthBoard(); + + const category = isCLusterHealthBoard + ? 'Cluster Monitoring' + : 'Incident Management::Embedded metrics'; + const action = isCLusterHealthBoard + ? 'generate_link_to_cluster_metric_chart' + : 'generate_link_to_metrics_chart'; + + return { category, action, label: 'Chart link', property: chartLink }; +}; + +/** + * Tracks snowplow event when user downloads CSV of cluster metric + * @param {String} chart title that will be sent as a property for the event + */ +export const downloadCSVOptions = title => { + const isCLusterHealthBoard = isClusterHealthBoard(); + + const category = isCLusterHealthBoard + ? 'Cluster Monitoring' + : 'Incident Management::Embedded metrics'; + const action = isCLusterHealthBoard + ? 'download_csv_of_cluster_metric_chart' + : 'download_csv_of_metrics_dashboard_chart'; + + return { category, action, label: 'Chart title', property: title }; +}; + export default {}; diff --git a/app/assets/javascripts/pages/projects/clusters/new/index.js b/app/assets/javascripts/pages/projects/clusters/new/index.js index 55aa29c9797..14d5ab21555 100644 --- a/app/assets/javascripts/pages/projects/clusters/new/index.js +++ b/app/assets/javascripts/pages/projects/clusters/new/index.js @@ -1,7 +1,13 @@ document.addEventListener('DOMContentLoaded', () => { if (gon.features.createEksClusters) { import(/* webpackChunkName: 'eks_cluster' */ '~/create_cluster/eks_cluster') - .then(({ default: initCreateEKSCluster }) => initCreateEKSCluster()) + .then(({ default: initCreateEKSCluster }) => { + const el = document.querySelector('.js-create-eks-cluster-form-container'); + + if (el) { + initCreateEKSCluster(el); + } + }) .catch(() => {}); } }); diff --git a/app/assets/javascripts/vue_shared/directives/track_event.js b/app/assets/javascripts/vue_shared/directives/track_event.js new file mode 100644 index 00000000000..d1c05c5c267 --- /dev/null +++ b/app/assets/javascripts/vue_shared/directives/track_event.js @@ -0,0 +1,20 @@ +import Tracking from '~/tracking'; + +export default { + bind(el, binding) { + el.dataset.trackingOptions = JSON.stringify(binding.value || {}); + + el.addEventListener('click', () => { + const { category, action, label, property, value } = JSON.parse(el.dataset.trackingOptions); + if (!category || !action) { + return; + } + Tracking.event(category, action, { label, property, value }); + }); + }, + update(el, binding) { + if (binding.value !== binding.oldValue) { + el.dataset.trackingOptions = JSON.stringify(binding.value || {}); + } + }, +}; |