Commit bcd217dd authored by Martin Wortschack's avatar Martin Wortschack Committed by Phil Hughes

Add identifiers for onboarding popovers

- Add implementation for rendering action popovers
- Don't render component if onboarding is dismissed
- Add goldenTanukiSvgPath prop
- Enable users to dismiss onboarding on every page
- Fix qa selector (due to additional class)
parent 9339c449
......@@ -60,7 +60,7 @@ export default {
</script>
<template>
<div class="table-section section-10 d-none d-sm-none d-md-block pipeline-tags">
<gl-link :href="pipeline.path" class="js-pipeline-url-link">
<gl-link :href="pipeline.path" class="js-pipeline-url-link js-onboarding-pipeline-item">
<span class="pipeline-id">#{{ pipeline.id }}</span>
</gl-link>
<div class="label-container">
......
......@@ -135,11 +135,5 @@
.popover {
min-width: auto;
max-width: 40%;
.popover-body {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
font-size: $gl-font-size-small;
}
}
}
%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown" } }
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
= sprite_icon('plus-square', size: 16)
= sprite_icon('angle-down', css_class: 'caret-down')
.dropdown-menu.dropdown-menu-right
......
......@@ -50,7 +50,7 @@
= link_to project_tree_path(@project), class: 'shortcuts-tree qa-project-menu-repo' do
.nav-icon-container
= sprite_icon('doc-text')
%span.nav-item-name
%span.nav-item-name#js-onboarding-repo-link
= _('Repository')
%ul.sidebar-sub-level-items
......@@ -64,11 +64,11 @@
= _('Files')
= nav_link(controller: [:commit, :commits]) do
= link_to project_commits_path(@project, current_ref) do
= link_to project_commits_path(@project, current_ref), id: 'js-onboarding-commits-link' do
= _('Commits')
= nav_link(html_options: {class: branches_tab_class}) do
= link_to project_branches_path(@project), class: 'qa-branches-link' do
= link_to project_branches_path(@project), class: 'qa-branches-link', id: 'js-onboarding-branches-link' do
= _('Branches')
= nav_link(controller: [:tags]) do
......@@ -98,7 +98,7 @@
= link_to project_issues_path(@project), class: 'shortcuts-issues qa-issues-item' do
.nav-icon-container
= sprite_icon('issues')
%span.nav-item-name
%span.nav-item-name#js-onboarding-issues-link
= _('Issues')
- if @project.issues_enabled?
%span.badge.badge-pill.count.issue_counter
......@@ -153,7 +153,7 @@
= link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests qa-merge-requests-link' do
.nav-icon-container
= sprite_icon('git-merge')
%span.nav-item-name
%span.nav-item-name#js-onboarding-mr-link
= _('Merge Requests')
%span.badge.badge-pill.count.merge_counter.js-merge-counter
= number_with_delimiter(@project.open_merge_requests_count)
......@@ -170,7 +170,7 @@
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines qa-link-pipelines' do
.nav-icon-container
= sprite_icon('rocket')
%span.nav-item-name
%span.nav-item-name#js-onboarding-pipelines-link
= _('CI / CD')
%ul.sidebar-sub-level-items
......@@ -335,7 +335,7 @@
= link_to edit_project_path(@project), class: 'shortcuts-tree' do
.nav-icon-container
= sprite_icon('settings')
%span.nav-item-name.qa-settings-item
%span.nav-item-name.qa-settings-item#js-onboarding-settings-link
= _('Settings')
%ul.sidebar-sub-level-items
......@@ -351,7 +351,7 @@
%span
= _('General')
= nav_link(controller: :project_members) do
= link_to project_project_members_path(@project), title: _('Members'), class: 'qa-link-members-settings' do
= link_to project_project_members_path(@project), title: _('Members'), class: 'qa-link-members-settings', id: 'js-onboarding-settings-members-link' do
%span
= _('Members')
- if can_edit
......
......@@ -56,7 +56,7 @@
- if branch.name != @repository.root_ref
= link_to project_compare_path(@project, @repository.root_ref, branch.name),
class: "btn btn-default #{'prepend-left-10' unless merge_project}",
class: "btn btn-default js-onboarding-compare-branches #{'prepend-left-10' unless merge_project}",
title: s_('Branches|Compare') do
= s_('Branches|Compare')
......
......@@ -20,9 +20,9 @@
.commit-detail.flex-list
.commit-content.qa-commit-content
- if view_details && merge_request
= link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: "commit-row-message item-title"
= link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: "commit-row-message item-title js-onboarding-commit-item"
- else
= link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title")
= link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item")
%span.commit-row-message.d-inline.d-sm-none
&middot;
= commit.short_id
......
......@@ -6,7 +6,7 @@
.issuable-info-container
.issuable-main-info
.issue-title.title
%span.issue-title-text{ dir: "auto" }
%span.issue-title-text.js-onboarding-issue-item{ dir: "auto" }
- if issue.confidential?
%span.has-tooltip{ title: _('Confidential') }
= confidential_icon(issue)
......
......@@ -6,7 +6,7 @@
.issuable-info-container
.issuable-main-info
.merge-request-title.title
%span.merge-request-title-text
%span.merge-request-title-text.js-onboarding-mr-item
= link_to merge_request.title, merge_request_path(merge_request)
- if merge_request.tasks?
%span.task-status.d-none.d-sm-inline-block
......
const renderPopover = () => {
// TODO: implementation will be added in a separate MR
import Vue from 'vue';
import ActionPopover from './components/action_popover.vue';
// retry for 10 times (5 seconds in total)
const maxTries = 10;
const timeout = 500;
const mountComponent = (intervalId, el, { target, content, placement, showPopover }) => {
clearInterval(intervalId);
return new Vue({
el,
render(h) {
return h(ActionPopover, {
props: {
target,
content,
placement,
showDefault: showPopover,
},
});
},
});
};
const renderPopover = (popoverSelector, content, placement, showPopover) => {
const popoverContainer = document.getElementById('js-onboarding-action-popover');
let retry = 0;
if (!popoverContainer) {
return false;
}
// continuously check if target element already exists (might be delayed to to dynamic component creation)
const intervalId = setInterval(() => {
if (retry >= maxTries) {
clearInterval(intervalId);
}
retry += 1;
const target = document.querySelector(popoverSelector);
if (!target) {
return false;
}
return mountComponent(intervalId, popoverContainer, {
target,
content,
placement,
showPopover,
});
}, timeout);
return intervalId;
};
const actionPopoverUtils = {
......
......@@ -121,9 +121,14 @@ export default {
},
handleClickPopoverButton(button) {
const { showExitTourContent, exitTour, redirectPath, nextPart, dismissPopover } = button;
const helpContentItems = this.stepContent.getHelpContent({ projectName: this.projectName });
const helpContentItems = this.stepContent
? this.stepContent.getHelpContent({ projectName: this.projectName })
: null;
const showNextContentItem =
helpContentItems.length > 1 && this.helpContentIndex < helpContentItems.length - 1;
helpContentItems &&
helpContentItems.length > 1 &&
this.helpContentIndex < helpContentItems.length - 1;
// display exit tour content
if (showExitTourContent) {
......@@ -166,6 +171,7 @@ export default {
},
showExitTourContent(showExitTour) {
this.dismissPopover = false;
this.showStepContent = true;
this.setExitTour(showExitTour);
},
handleExitTour() {
......
......@@ -53,16 +53,20 @@ export default {
<div>
<p v-html="helpContent.text"></p>
<template v-if="helpContent.buttons">
<template v-for="(button, index) in helpContent.buttons">
<gl-button
v-for="(button, index) in helpContent.buttons"
v-if="!button.readOnly"
:key="index"
:class="button.btnClass"
class="btn btn-sm mr-2"
:disabled="button.disabled"
@click="callButtonAction(button)"
>
{{ button.text }}
</gl-button>
<span v-else :key="index" :class="button.btnClass" class="btn btn-sm mr-2">
{{ button.text }}
</span>
</template>
</template>
</div>
</gl-popover>
......
......@@ -13,14 +13,14 @@ export default function() {
return false;
}
const { projectFullPath, projectName } = el.dataset;
const tourData = onboardingUtils.getOnboardingLocalStorageState();
const url = window.location.href;
if (!tourData) {
if (!tourData || onboardingUtils.isOnboardingDismissed()) {
return false;
}
const { projectFullPath, projectName, goldenTanukiSvgPath } = el.dataset;
const url = window.location.href;
const { tourKey, lastStepIndex, createdProjectPath } = tourData;
const store = createStore();
......@@ -51,6 +51,7 @@ export default function() {
props: {
tourTitles: TOUR_TITLES,
exitTourContent: EXIT_TOUR_CONTENT,
goldenTanukiSvgPath,
},
});
},
......
......@@ -42,7 +42,7 @@ export default {
target: null,
content: {
text: __('White helpers give contextual information.'),
buttons: [{ text: __('OK'), btnClass: 'btn-primary', disabled: true }],
buttons: [{ text: __('OK'), btnClass: 'btn-primary', readOnly: true }],
},
},
actionPopover: {
......
......@@ -2,5 +2,5 @@
- return unless onboarding_project
#js-onboarding-helper{ data: { project_full_path: onboarding_project[:project_full_path], project_name: onboarding_project[:project_name] } }
#js-onboarding-helper{ data: { project_full_path: onboarding_project[:project_full_path], project_name: onboarding_project[:project_name], golden_tanuki_svg_path: image_path('illustrations/golden_tanuki.svg') } }
#js-onboarding-action-popover
......@@ -4,7 +4,7 @@ module QA::Page
module Project::Pipeline
class Index < QA::Page::Base
view 'app/assets/javascripts/pipelines/components/pipeline_url.vue' do
element :pipeline_link, 'class="js-pipeline-url-link"' # rubocop:disable QA/ElementWithPattern
element :pipeline_link, 'class="js-pipeline-url-link' # rubocop:disable QA/ElementWithPattern
end
def click_on_latest_pipeline
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment