Commit 606a16ed authored by Martin Wortschack's avatar Martin Wortschack Committed by Fatih Acet

Add onboarding welcome page

- Add "Learn Gitlab" item to help menu
- Add onboarding endpoint
- Add feature flag helper
- Add styles for blue popovers
- Move controller and template to /ee
- Update PO file
- Add changelog entry
parent f42e8221
...@@ -10,6 +10,26 @@ ...@@ -10,6 +10,26 @@
color: $gray-600; color: $gray-600;
} }
} }
&.blue {
background-color: $blue-600;
.popover-body {
color: $white-light;
}
&.bs-popover-bottom {
.arrow::after {
border-bottom-color: $blue-600;
}
}
&.bs-popover-top {
.arrow::after {
border-top-color: $blue-600;
}
}
}
} }
.mr-popover { .mr-popover {
...@@ -18,3 +38,16 @@ ...@@ -18,3 +38,16 @@
line-height: 1.33; line-height: 1.33;
} }
} }
.onboarding-welcome-page {
.popover {
min-width: auto;
max-width: 40%;
.popover-body {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
font-size: $gl-font-size-small;
}
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
- if current_user_menu?(:help) - if current_user_menu?(:help)
%li %li
= link_to _("Help"), help_path = link_to _("Help"), help_path
= render_if_exists "shared/learn_gitlab_menu_item"
%li.divider %li.divider
%li %li
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback" = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
......
const STORAGE_KEY = 'onboarding_state';
export default STORAGE_KEY;
<script>
import { __ } from '~/locale';
import { GlLink, GlPopover } from '@gitlab/ui';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import { redirectTo } from '~/lib/utils/url_utility';
import { resetOnboardingLocalStorage, updateLocalStorage } from './../../utils';
export default {
components: {
GlLink,
GlPopover,
UserAvatarImage,
},
props: {
userAvatarUrl: {
type: String,
required: false,
default: '',
},
projectFullPath: {
type: String,
required: true,
},
skipUrl: {
type: String,
required: true,
},
},
data() {
return {
helpText: __(
"Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>.",
),
};
},
mounted() {
// workaround for appending a custom class to the bs popover which cannot be done via props
// see https://github.com/bootstrap-vue/bootstrap-vue/issues/1983
this.$root.$on('bv::popover::show', bvEventObj => {
const {
target: { dataset },
} = bvEventObj;
if (dataset.class) {
bvEventObj.relatedTarget.classList.add(dataset.class);
}
});
},
methods: {
startTour() {
resetOnboardingLocalStorage();
redirectTo(this.projectFullPath);
},
skipTour() {
updateLocalStorage({ dismissed: true });
redirectTo(this.skipUrl);
},
},
};
</script>
<template>
<div class="onboarding-welcome-page content col-lg-6 ml-auto mr-auto">
<div class="text-center">
<user-avatar-image
:img-src="userAvatarUrl"
:size="64"
css-classes="ml-auto mr-auto"
class="d-inline-block"
/>
<h1>{{ __('Hello there') }}</h1>
<p class="large">{{ __('Welcome to the Guided GitLab Tour') }}</p>
</div>
<p class="mt-4">
{{
__(
'We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color.',
)
}}
</p>
<div class="text-center mt-4 mb-4">
<div
id="popover-container"
class="popover-container d-flex justify-content-around align-items-end mb-8"
>
<button id="help-popover-trigger" type="button" class="btn-link btn-disabled"></button>
<button
id="action-popover-trigger"
type="button"
class="btn-link btn-disabled mb-3"
data-class="blue"
></button>
<gl-popover
target="help-popover-trigger"
placement="top"
container="popover-container"
show
>
<p class="mb-2">
{{ __('White helpers give contextual information.') }}
</p>
<button disabled type="button" :aria-label="__('OK')" class="btn btn-xs popover-btn">
{{ __('OK') }}
</button>
</gl-popover>
<gl-popover
target="action-popover-trigger"
placement="top"
container="popover-container"
show
>
{{ __('Blue helpers indicate an action to be taken.') }}
</gl-popover>
</div>
<gl-link class="btn btn-success" @click="startTour">
{{ __("Ok let's go") }}
</gl-link>
<p class="small mt-8">
<gl-link @click="skipTour">
{{ __('Skip this for now') }}
</gl-link>
</p>
<p class="small ml-4 mr-4" v-html="helpText"></p>
</div>
</div>
</template>
<style scoped>
.popover-container {
height: 140px;
}
.popover-btn[disabled] {
background-color: #1b69b6 !important;
border-color: #1b69b6 !important;
color: white !important;
}
p.large {
font-size: 16px;
}
p.small {
font-size: 12px;
}
.btn-success {
width: 200px;
}
</style>
import Vue from 'vue';
import WelcomePage from './components/welcome_page.vue';
export default function() {
const el = document.getElementById('js-onboarding-welcome');
if (!el) {
return false;
}
const { userAvatarUrl, projectFullPath, skipUrl } = el.dataset;
return new Vue({
el,
render(h) {
return h(WelcomePage, {
props: {
userAvatarUrl,
projectFullPath,
skipUrl,
},
});
},
});
}
import STORAGE_KEY from './constants';
/**
* onboarding_state:
* activeTour: Number
* dismissed: Boolean
*/
const ONBOARDING_PROPS_DEFAULTS = {
activeTourKey: 1,
dismissed: false,
};
export const resetOnboardingLocalStorage = () => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(ONBOARDING_PROPS_DEFAULTS));
};
export const getOnboardingLocalStorageState = () => JSON.parse(localStorage.getItem(STORAGE_KEY));
export const updateLocalStorage = updatedProps => {
let currentState = getOnboardingLocalStorageState();
if (!currentState) {
currentState = resetOnboardingLocalStorage();
}
const onboardingState = {
...currentState,
...updatedProps,
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(onboardingState));
};
import initOnboardingWelcome from 'ee/onboarding/onboarding_welcome';
document.addEventListener('DOMContentLoaded', () => initOnboardingWelcome());
# frozen_string_literal: true
class Explore::OnboardingController < Explore::ApplicationController
before_action :authenticate_user!
before_action :set_project!
layout 'onboarding'
private
def set_project!
@project = get_onboarding_demo_project
render_404 unless @project && can?(current_user, :read_project, @project)
end
def get_onboarding_demo_project
if Gitlab.com? && Feature.enabled?(:user_onboarding)
Project.find_by_full_path("gitlab-org/gitlab-ce")
end
end
end
...@@ -117,6 +117,10 @@ module EE ...@@ -117,6 +117,10 @@ module EE
show show
end end
def user_onboarding_enabled?
::Gitlab.com? && ::Feature.enabled?(:user_onboarding)
end
private private
def appearance def appearance
......
.container.container-limited.limit-container-width.navless-container
#js-onboarding-welcome{ data: { user_avatar_url: avatar_icon_for_user(current_user), project_full_path: @project.web_url, skip_url: root_dashboard_path } }
- page_title _("Onboarding")
- header_title _("Onboarding")
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
%body.navless
= yield
- return unless user_onboarding_enabled?
%li
%a{ href: explore_onboarding_index_path }
= _("Learn GitLab")
%span.badge.badge-success= s_("Badge|New")
# frozen_string_literal: true
namespace :explore do
resources :onboarding, only: [:index]
end
# frozen_string_literal: true
require 'spec_helper'
describe 'User Onboarding' do
let(:user) { create(:user) }
let(:project) { create(:project) }
before do
allow(Gitlab).to receive(:com?) { true }
sign_in(user)
end
context 'when the feature is enabled', :js do
before do
stub_feature_flags(user_onboarding: true)
end
describe 'help menu' do
it 'shows the "Learn GitLab" item in the help menu' do
visit root_dashboard_path
find('.header-help-dropdown-toggle').click
page.within('.header-help') do
expect(page).to have_link('Learn GitLab', href: explore_onboarding_index_path)
end
end
end
context 'welcome page' do
before do
allow(Project).to receive(:find_by_full_path).and_return(project)
project.add_guest(user)
end
it 'shows the "Learn GitLab" welcome page' do
visit explore_onboarding_index_path
expect(page).to have_content('Welcome to the Guided GitLab Tour')
end
end
end
context 'when the feature is disabled' do
before do
stub_feature_flags(user_onboarding: false)
end
describe 'help menu' do
it 'does not show the "Learn GitLab" item in the help menu' do
visit root_dashboard_path
find('.header-help-dropdown-toggle').click
page.within('.header-help') do
expect(page).not_to have_link('Learn GitLab')
end
end
end
end
end
...@@ -1720,6 +1720,9 @@ msgstr "" ...@@ -1720,6 +1720,9 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}" msgid "Badges|e.g. %{exampleUrl}"
msgstr "" msgstr ""
msgid "Badge|New"
msgstr ""
msgid "Balsamiq file could not be loaded." msgid "Balsamiq file could not be loaded."
msgstr "" msgstr ""
...@@ -1846,6 +1849,9 @@ msgstr "" ...@@ -1846,6 +1849,9 @@ msgstr ""
msgid "Blog" msgid "Blog"
msgstr "" msgstr ""
msgid "Blue helpers indicate an action to be taken."
msgstr ""
msgid "Boards" msgid "Boards"
msgstr "" msgstr ""
...@@ -4172,6 +4178,9 @@ msgstr "" ...@@ -4172,6 +4178,9 @@ msgstr ""
msgid "Don't show again" msgid "Don't show again"
msgstr "" msgstr ""
msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
msgstr ""
msgid "Done" msgid "Done"
msgstr "" msgstr ""
...@@ -6301,6 +6310,9 @@ msgstr "" ...@@ -6301,6 +6310,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy" msgid "HealthCheck|Unhealthy"
msgstr "" msgstr ""
msgid "Hello there"
msgstr ""
msgid "Help" msgid "Help"
msgstr "" msgstr ""
...@@ -7135,6 +7147,9 @@ msgstr "" ...@@ -7135,6 +7147,9 @@ msgstr ""
msgid "Lead" msgid "Lead"
msgstr "" msgstr ""
msgid "Learn GitLab"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}" msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "" msgstr ""
...@@ -8423,6 +8438,12 @@ msgstr "" ...@@ -8423,6 +8438,12 @@ msgstr ""
msgid "OfSearchInADropdown|Filter" msgid "OfSearchInADropdown|Filter"
msgstr "" msgstr ""
msgid "Ok let's go"
msgstr ""
msgid "Onboarding"
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}" msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
msgstr "" msgstr ""
...@@ -11195,6 +11216,9 @@ msgstr "" ...@@ -11195,6 +11216,9 @@ msgstr ""
msgid "Size limit per repository (MB)" msgid "Size limit per repository (MB)"
msgstr "" msgstr ""
msgid "Skip this for now"
msgstr ""
msgid "Slack application" msgid "Slack application"
msgstr "" msgstr ""
...@@ -13673,6 +13697,9 @@ msgstr "" ...@@ -13673,6 +13697,9 @@ msgstr ""
msgid "We couldn't find any results matching" msgid "We couldn't find any results matching"
msgstr "" msgstr ""
msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
msgstr ""
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed." msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "" msgstr ""
...@@ -13712,6 +13739,9 @@ msgstr "" ...@@ -13712,6 +13739,9 @@ msgstr ""
msgid "Weight %{weight}" msgid "Weight %{weight}"
msgstr "" msgstr ""
msgid "Welcome to the Guided GitLab Tour"
msgstr ""
msgid "Welcome to your Issue Board!" msgid "Welcome to your Issue Board!"
msgstr "" msgstr ""
...@@ -13732,6 +13762,9 @@ msgstr[1] "" ...@@ -13732,6 +13762,9 @@ msgstr[1] ""
msgid "When:" msgid "When:"
msgstr "" msgstr ""
msgid "White helpers give contextual information."
msgstr ""
msgid "Who can see this group?" msgid "Who can see this group?"
msgstr "" msgstr ""
......
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