diff options
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue')
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue index 94359d7d6ac..cea7fb8260a 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue @@ -1,29 +1,41 @@ <script> -import { GlButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui'; +import { + GlButton, + GlLink, + GlTooltipDirective, + GlLoadingIcon, + GlSafeHtmlDirective, +} from '@gitlab/ui'; import * as Sentry from '@sentry/browser'; import { normalizeHeaders } from '~/lib/utils/common_utils'; import { sprintf, __ } from '~/locale'; import Poll from '~/lib/utils/poll'; +import HelpPopover from '~/vue_shared/components/help_popover.vue'; import ActionButtons from '../action_buttons.vue'; import { EXTENSION_ICONS } from '../../constants'; +import { createTelemetryHub } from '../extensions/telemetry'; import ContentRow from './widget_content_row.vue'; import DynamicContent from './dynamic_content.vue'; import StatusIcon from './status_icon.vue'; const FETCH_TYPE_COLLAPSED = 'collapsed'; const FETCH_TYPE_EXPANDED = 'expanded'; +const WIDGET_PREFIX = 'Widget'; export default { components: { ActionButtons, StatusIcon, + GlLink, GlButton, GlLoadingIcon, ContentRow, DynamicContent, + HelpPopover, }, directives: { GlTooltip: GlTooltipDirective, + SafeHtml: GlSafeHtmlDirective, }, props: { /** @@ -72,8 +84,8 @@ export default { }, statusIconName: { type: String, - default: 'neutral', required: false, + default: 'neutral', validator: (value) => Object.keys(EXTENSION_ICONS).indexOf(value) > -1, }, isCollapsible: { @@ -88,6 +100,26 @@ export default { widgetName: { type: String, required: true, + // see https://docs.gitlab.com/ee/development/fe_guide/merge_request_widget_extensions.html#add-new-widgets + validator: (val) => val.startsWith(WIDGET_PREFIX), + }, + telemetry: { + type: Boolean, + required: false, + default: true, + }, + /** + * @typedef {Object} helpPopover + * @property {Object} options + * @property {String} options.title + * @property {Object} content + * @property {String} content.text + * @property {String} content.learnMorePath + */ + helpPopover: { + type: Object, + required: false, + default: null, }, }, data() { @@ -98,6 +130,7 @@ export default { isLoadingExpandedContent: false, summaryError: null, contentError: null, + telemetryHub: null, }; }, computed: { @@ -113,8 +146,14 @@ export default { this.$emit('is-loading', newValue); }, }, + created() { + if (this.telemetry) { + this.telemetryHub = createTelemetryHub(this.widgetName); + } + }, async mounted() { this.isLoading = true; + this.telemetryHub?.viewed(); try { await this.fetch(this.fetchCollapsedData, FETCH_TYPE_COLLAPSED); @@ -125,12 +164,21 @@ export default { this.isLoading = false; }, methods: { + onActionClick(action) { + if (action.fullReport) { + this.telemetryHub?.fullReportClicked(); + } + }, toggleCollapsed() { this.isCollapsed = !this.isCollapsed; - if (this.isExpandedForTheFirstTime && typeof this.fetchExpandedData === 'function') { - this.isExpandedForTheFirstTime = false; - this.fetchExpandedContent(); + if (this.isExpandedForTheFirstTime) { + this.telemetryHub?.expanded({ type: this.summaryStatusIcon }); + + if (typeof this.fetchExpandedData === 'function') { + this.isExpandedForTheFirstTime = false; + this.fetchExpandedContent(); + } } }, async fetchExpandedContent() { @@ -184,6 +232,9 @@ export default { }, }, failedStatusIcon: EXTENSION_ICONS.failed, + i18n: { + learnMore: __('Learn more'), + }, }; </script> @@ -204,11 +255,34 @@ export default { <span v-if="summaryError">{{ summaryError }}</span> <slot v-else name="summary">{{ isLoading ? loadingText : summary }}</slot> </div> - <action-buttons - v-if="actionButtons.length > 0" - :widget="widgetName" - :tertiary-buttons="actionButtons" - /> + <div class="gl-display-flex"> + <help-popover + v-if="helpPopover" + :options="helpPopover.options" + :class="{ 'gl-mr-3': actionButtons.length > 0 }" + > + <template v-if="helpPopover.content"> + <p + v-if="helpPopover.content.text" + v-safe-html="helpPopover.content.text" + class="gl-mb-0" + ></p> + <gl-link + v-if="helpPopover.content.learnMorePath" + :href="helpPopover.content.learnMorePath" + target="_blank" + class="gl-font-sm" + >{{ $options.i18n.learnMore }}</gl-link + > + </template> + </help-popover> + <action-buttons + v-if="actionButtons.length > 0" + :widget="widgetName" + :tertiary-buttons="actionButtons" + @clickedAction="onActionClick" + /> + </div> <div v-if="isCollapsible" class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6" |