diff options
Diffstat (limited to 'app/assets/javascripts/feature_highlight')
6 files changed, 134 insertions, 95 deletions
diff --git a/app/assets/javascripts/feature_highlight/constants.js b/app/assets/javascripts/feature_highlight/constants.js new file mode 100644 index 00000000000..3e4cd11f7d5 --- /dev/null +++ b/app/assets/javascripts/feature_highlight/constants.js @@ -0,0 +1 @@ +export const POPOVER_TARGET_ID = 'feature-highlight-trigger'; diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js deleted file mode 100644 index 2da9aadd2b1..00000000000 --- a/app/assets/javascripts/feature_highlight/feature_highlight.js +++ /dev/null @@ -1,59 +0,0 @@ -import $ from 'jquery'; -import { getSelector, inserted } from './feature_highlight_helper'; -import { togglePopover, mouseenter, debouncedMouseleave } from '../shared/popover'; - -export function setupFeatureHighlightPopover(id, debounceTimeout = 300) { - const $selector = $(getSelector(id)); - const $parent = $selector.parent(); - const $popoverContent = $parent.siblings('.feature-highlight-popover-content'); - const hideOnScroll = togglePopover.bind($selector, false); - - $selector - // Set up popover - .data('content', $popoverContent.prop('outerHTML')) - .popover({ - html: true, - // Override the existing template to add custom CSS classes - template: ` - <div class="popover feature-highlight-popover" role="tooltip"> - <div class="arrow"></div> - <div class="popover-body"></div> - </div> - `, - }) - .on('mouseenter', mouseenter) - .on('mouseleave', debouncedMouseleave(debounceTimeout)) - .on('inserted.bs.popover', inserted) - .on('show.bs.popover', () => { - window.addEventListener('scroll', hideOnScroll, { once: true }); - }) - // Display feature highlight - .removeAttr('disabled'); -} - -const getPriority = (e) => parseInt(e.dataset.highlightPriority, 10) || 0; - -export function findHighestPriorityFeature() { - let priorityFeature; - - const sortedFeatureEls = [].slice - .call(document.querySelectorAll('.js-feature-highlight')) - .sort((a, b) => getPriority(b) - getPriority(a)); - - const [priorityFeatureEl] = sortedFeatureEls; - if (priorityFeatureEl) { - priorityFeature = priorityFeatureEl.dataset.highlight; - } - - return priorityFeature; -} - -export function highlightFeatures() { - const priorityFeature = findHighestPriorityFeature(); - - if (priorityFeature) { - setupFeatureHighlightPopover(priorityFeature); - } - - return priorityFeature; -} diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js index fabc905d756..7b4bed69fb8 100644 --- a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js +++ b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js @@ -1,15 +1,12 @@ -import $ from 'jquery'; +import { deprecatedCreateFlash as Flash } from '~/flash'; import axios from '../lib/utils/axios_utils'; import { __ } from '../locale'; -import { deprecatedCreateFlash as Flash } from '../flash'; -import LazyLoader from '../lazy_loader'; -import { togglePopover } from '../shared/popover'; export const getSelector = (highlightId) => `.js-feature-highlight[data-highlight=${highlightId}]`; -export function dismiss(highlightId) { - axios - .post(this.attr('data-dismiss-endpoint'), { +export function dismiss(endpoint, highlightId) { + return axios + .post(endpoint, { feature_name: highlightId, }) .catch(() => @@ -19,21 +16,4 @@ export function dismiss(highlightId) { ), ), ); - - togglePopover.call(this, false); - this.hide(); -} - -export function inserted() { - const popoverId = this.getAttribute('aria-describedby'); - const highlightId = this.dataset.highlight; - const $popover = $(this); - const dismissWrapper = dismiss.bind($popover, highlightId); - - $(`#${popoverId} .dismiss-feature-highlight`).on('click', dismissWrapper); - - const lazyImg = $(`#${popoverId} .feature-highlight-illustration`)[0]; - if (lazyImg) { - LazyLoader.loadImage(lazyImg); - } } diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_options.js b/app/assets/javascripts/feature_highlight/feature_highlight_options.js deleted file mode 100644 index c5553f0243f..00000000000 --- a/app/assets/javascripts/feature_highlight/feature_highlight_options.js +++ /dev/null @@ -1,12 +0,0 @@ -import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; -import { highlightFeatures } from './feature_highlight'; - -export default function domContentLoaded() { - if (bp.getBreakpointSize() === 'xl') { - highlightFeatures(); - return true; - } - return false; -} - -document.addEventListener('DOMContentLoaded', domContentLoaded); diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue new file mode 100644 index 00000000000..2fd92a1bb11 --- /dev/null +++ b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue @@ -0,0 +1,101 @@ +<script> +import clusterPopover from '@gitlab/svgs/dist/illustrations/cluster_popover.svg'; +import { + GlPopover, + GlSprintf, + GlLink, + GlButton, + GlSafeHtmlDirective as SafeHtml, +} from '@gitlab/ui'; +import { __ } from '~/locale'; +import { POPOVER_TARGET_ID } from './constants'; +import { dismiss } from './feature_highlight_helper'; + +export default { + components: { + GlPopover, + GlSprintf, + GlLink, + GlButton, + }, + directives: { + SafeHtml, + }, + props: { + autoDevopsHelpPath: { + type: String, + required: true, + }, + highlightId: { + type: String, + required: true, + }, + dismissEndpoint: { + type: String, + required: true, + }, + }, + data() { + return { + dismissed: false, + triggerHidden: false, + }; + }, + methods: { + dismiss() { + dismiss(this.dismissEndpoint, this.highlightId); + this.$refs.popover.$emit('close'); + this.dismissed = true; + }, + hideTrigger() { + if (this.dismissed) { + this.triggerHidden = true; + } + }, + }, + clusterPopover, + targetId: POPOVER_TARGET_ID, + i18n: { + highlightMessage: __('Allows you to add and manage Kubernetes clusters.'), + autoDevopsProTipMessage: __( + 'Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!', + ), + dismissButtonLabel: __('Got it!'), + }, +}; +</script> +<template> + <div class="gl-ml-3"> + <span v-if="!triggerHidden" :id="$options.targetId" class="feature-highlight"></span> + <gl-popover + ref="popover" + :target="$options.targetId" + :css-classes="['feature-highlight-popover']" + triggers="hover" + container="body" + placement="right" + boundary="viewport" + @hidden="hideTrigger" + > + <span + v-safe-html="$options.clusterPopover" + class="feature-highlight-illustration gl-display-flex gl-justify-content-center gl-py-4 gl-w-full" + ></span> + <div class="gl-px-4 gl-py-5"> + <p> + {{ $options.i18n.highlightMessage }} + </p> + <p> + <gl-sprintf :message="$options.i18n.autoDevopsProTipMessage"> + <template #link="{ content }"> + <gl-link class="gl-font-sm" :href="autoDevopsHelpPath">{{ content }}</gl-link> + </template> + </gl-sprintf> + </p> + <gl-button size="small" icon="thumb-up" variant="confirm" @click="dismiss"> + {{ $options.i18n.dismissButtonLabel }} + </gl-button> + </div> + </gl-popover> + </div> +</template> diff --git a/app/assets/javascripts/feature_highlight/index.js b/app/assets/javascripts/feature_highlight/index.js new file mode 100644 index 00000000000..3a8b211b3c5 --- /dev/null +++ b/app/assets/javascripts/feature_highlight/index.js @@ -0,0 +1,28 @@ +import Vue from 'vue'; + +const init = async () => { + const el = document.querySelector('.js-feature-highlight'); + + if (!el) { + return null; + } + + const { autoDevopsHelpPath, highlight: highlightId, dismissEndpoint } = el.dataset; + const { default: FeatureHighlight } = await import( + /* webpackChunkName: 'feature_highlight' */ './feature_highlight_popover.vue' + ); + + return new Vue({ + el, + render: (h) => + h(FeatureHighlight, { + props: { + autoDevopsHelpPath, + highlightId, + dismissEndpoint, + }, + }), + }); +}; + +export default init; |