From 874544507cde6c079fdbc29132c1b2e01a633d73 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 7 Nov 2018 05:06:40 +0000 Subject: [PATCH] Promote the GitLab.com Gold trial on a users default dashboard Show a dismissable callout on a users dashboard for a free trial of the GitLab.com Gold plan. Hide the callout from users who have dismissed the callout, are already on a trial or are already on the gold plan --- .../javascripts/clusters/clusters_bundle.js | 10 ++++-- app/assets/javascripts/dismissable_callout.js | 27 --------------- .../pages/groups/clusters/index/index.js | 6 ++-- app/assets/javascripts/pages/groups/index.js | 10 ++++-- .../pages/projects/clusters/index/index.js | 6 ++-- .../javascripts/pages/projects/index.js | 6 ++-- app/assets/javascripts/pages/root/index.js | 5 +++ .../javascripts/persistent_user_callout.js | 34 +++++++++++++++++++ .../_gcp_signup_offer_banner.html.haml | 4 +-- app/views/dashboard/activity.html.haml | 3 ++ app/views/dashboard/groups/index.html.haml | 2 ++ app/views/dashboard/issues.html.haml | 2 ++ app/views/dashboard/merge_requests.html.haml | 2 ++ app/views/dashboard/projects/index.html.haml | 2 ++ .../dashboard/projects/starred.html.haml | 2 ++ app/views/dashboard/todos/index.html.haml | 2 ++ app/views/explore/groups/index.html.haml | 2 ++ app/views/explore/projects/index.html.haml | 2 ++ app/views/explore/projects/starred.html.haml | 2 ++ app/views/explore/projects/trending.html.haml | 2 ++ .../features/dashboard/merge_requests_spec.rb | 1 + 21 files changed, 93 insertions(+), 39 deletions(-) delete mode 100644 app/assets/javascripts/dismissable_callout.js create mode 100644 app/assets/javascripts/pages/root/index.js create mode 100644 app/assets/javascripts/persistent_user_callout.js diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index 71fc2ac7d80..f1c34b2d947 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -1,6 +1,6 @@ import Visibility from 'visibilityjs'; import Vue from 'vue'; -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '../persistent_user_callout'; import { s__, sprintf } from '../locale'; import Flash from '../flash'; import Poll from '../lib/utils/poll'; @@ -65,7 +65,7 @@ export default class Clusters { this.showTokenButton = document.querySelector('.js-show-cluster-token'); this.tokenField = document.querySelector('.js-cluster-token'); - initDismissableCallout('.js-cluster-security-warning'); + Clusters.initDismissableCallout(); initSettingsPanels(); setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area')); this.initApplications(clusterType); @@ -106,6 +106,12 @@ export default class Clusters { }); } + static initDismissableCallout() { + const callout = document.querySelector('.js-cluster-security-warning'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new + } + addListeners() { if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken); eventHub.$on('installApplication', this.installApplication); diff --git a/app/assets/javascripts/dismissable_callout.js b/app/assets/javascripts/dismissable_callout.js deleted file mode 100644 index 5185b019376..00000000000 --- a/app/assets/javascripts/dismissable_callout.js +++ /dev/null @@ -1,27 +0,0 @@ -import $ from 'jquery'; -import axios from '~/lib/utils/axios_utils'; -import { __ } from '~/locale'; -import Flash from '~/flash'; - -export default function initDismissableCallout(alertSelector) { - const alertEl = document.querySelector(alertSelector); - if (!alertEl) { - return; - } - - const closeButtonEl = alertEl.getElementsByClassName('close')[0]; - const { dismissEndpoint, featureId } = closeButtonEl.dataset; - - closeButtonEl.addEventListener('click', () => { - axios - .post(dismissEndpoint, { - feature_name: featureId, - }) - .then(() => { - $(alertEl).alert('close'); - }) - .catch(() => { - Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.')); - }); - }); -} diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js index 845a5f7042c..21efc4f6d00 100644 --- a/app/assets/javascripts/pages/groups/clusters/index/index.js +++ b/app/assets/javascripts/pages/groups/clusters/index/index.js @@ -1,5 +1,7 @@ -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '~/persistent_user_callout'; document.addEventListener('DOMContentLoaded', () => { - initDismissableCallout('.gcp-signup-offer'); + const callout = document.querySelector('.gcp-signup-offer'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new }); diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/index.js index bf80d8b8193..00e2d7fc998 100644 --- a/app/assets/javascripts/pages/groups/index.js +++ b/app/assets/javascripts/pages/groups/index.js @@ -1,6 +1,12 @@ -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '~/persistent_user_callout'; import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +function initCallout() { + const callout = document.querySelector('.gcp-signup-offer'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new +} + document.addEventListener('DOMContentLoaded', () => { const { page } = document.body.dataset; const newClusterViews = [ @@ -10,7 +16,7 @@ document.addEventListener('DOMContentLoaded', () => { ]; if (newClusterViews.indexOf(page) > -1) { - initDismissableCallout('.gcp-signup-offer'); + initCallout(); initGkeDropdowns(); } }); diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js index 845a5f7042c..21efc4f6d00 100644 --- a/app/assets/javascripts/pages/projects/clusters/index/index.js +++ b/app/assets/javascripts/pages/projects/clusters/index/index.js @@ -1,5 +1,7 @@ -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '~/persistent_user_callout'; document.addEventListener('DOMContentLoaded', () => { - initDismissableCallout('.gcp-signup-offer'); + const callout = document.querySelector('.gcp-signup-offer'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new }); diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js index 5659e13981a..b0345b4e50d 100644 --- a/app/assets/javascripts/pages/projects/index.js +++ b/app/assets/javascripts/pages/projects/index.js @@ -1,5 +1,5 @@ -import initDismissableCallout from '~/dismissable_callout'; import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import PersistentUserCallout from '../../persistent_user_callout'; import Project from './project'; import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation'; @@ -12,7 +12,9 @@ document.addEventListener('DOMContentLoaded', () => { ]; if (newClusterViews.indexOf(page) > -1) { - initDismissableCallout('.gcp-signup-offer'); + const callout = document.querySelector('.gcp-signup-offer'); + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new + initGkeDropdowns(); } diff --git a/app/assets/javascripts/pages/root/index.js b/app/assets/javascripts/pages/root/index.js new file mode 100644 index 00000000000..09f8185d3b5 --- /dev/null +++ b/app/assets/javascripts/pages/root/index.js @@ -0,0 +1,5 @@ +// if the "projects dashboard" is a user's default dashboard, when they visit the +// instance root index, the dashboard will be served by the root controller instead +// of a dashboard controller. The root index redirects for all other default dashboards. + +import '../dashboard/projects/index'; diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js new file mode 100644 index 00000000000..1e34e74a152 --- /dev/null +++ b/app/assets/javascripts/persistent_user_callout.js @@ -0,0 +1,34 @@ +import axios from './lib/utils/axios_utils'; +import { __ } from './locale'; +import Flash from './flash'; + +export default class PersistentUserCallout { + constructor(container) { + const { dismissEndpoint, featureId } = container.dataset; + this.container = container; + this.dismissEndpoint = dismissEndpoint; + this.featureId = featureId; + + this.init(); + } + + init() { + const closeButton = this.container.querySelector('.js-close'); + closeButton.addEventListener('click', event => this.dismiss(event)); + } + + dismiss(event) { + event.preventDefault(); + + axios + .post(this.dismissEndpoint, { + feature_name: this.featureId, + }) + .then(() => { + this.container.remove(); + }) + .catch(() => { + Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.')); + }); + } +} diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml index 73b11d509d3..85d1002243b 100644 --- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml +++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml @@ -1,6 +1,6 @@ - link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer') -.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert' } - %button.close{ type: "button", data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } × +.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } + %button.close.js-close{ type: "button" } × .gcp-signup-offer--content .gcp-signup-offer--icon.append-right-8 = sprite_icon("information", size: 16) diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml index 31d4b3da4f1..4dbda5c754b 100644 --- a/app/views/dashboard/activity.html.haml +++ b/app/views/dashboard/activity.html.haml @@ -4,6 +4,9 @@ = content_for :meta_tags do = auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity") + += render_if_exists "shared/gold_trial_callout" + - page_title "Activity" - header_title "Activity", activity_dashboard_path diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 50f39f93283..2f7add600e4 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -1,6 +1,8 @@ - @hide_top_links = true - page_title "Groups" - header_title "Groups", dashboard_groups_path + += render_if_exists "shared/gold_trial_callout" = render 'dashboard/groups_head' - if params[:filter].blank? && @groups.empty? diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index fdd5c19d562..afd46412fab 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -4,6 +4,8 @@ = content_for :meta_tags do = auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues") += render_if_exists "shared/gold_trial_callout" + .page-title-holder %h1.page-title= _('Issues') diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 77cfa1271df..3e5f13b92e3 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -2,6 +2,8 @@ - page_title _("Merge Requests") - @breadcrumb_link = merge_requests_dashboard_path(assignee_username: current_user.username) += render_if_exists "shared/gold_trial_callout" + .page-title-holder %h1.page-title= _('Merge Requests') diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index deed774a4a5..446b4715b2d 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -4,6 +4,8 @@ = content_for :meta_tags do = auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity") += render_if_exists "shared/gold_trial_callout" + - page_title "Projects" - header_title "Projects", dashboard_projects_path diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index 8933d9e31ff..ad08409c8fe 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -4,6 +4,8 @@ - page_title "Starred Projects" - header_title "Projects", dashboard_projects_path += render_if_exists "shared/gold_trial_callout" + %div{ class: container_class } = render "projects/last_push" = render 'dashboard/projects_head' diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index d2593179f17..47729321961 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -2,6 +2,8 @@ - page_title "Todos" - header_title "Todos", dashboard_todos_path += render_if_exists "shared/gold_trial_callout" + .page-title-holder %h1.page-title= _('Todos') diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index a3eafc61d0a..869be4e8581 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -2,6 +2,8 @@ - page_title _("Groups") - header_title _("Groups"), dashboard_groups_path += render_if_exists "shared/gold_trial_callout" + - if current_user = render 'dashboard/groups_head' - else diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 452f390695c..d18dec7bd8e 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -2,6 +2,8 @@ - page_title _("Projects") - header_title _("Projects"), dashboard_projects_path += render_if_exists "shared/gold_trial_callout" + - if current_user = render 'dashboard/projects_head' - else diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 452f390695c..d18dec7bd8e 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -2,6 +2,8 @@ - page_title _("Projects") - header_title _("Projects"), dashboard_projects_path += render_if_exists "shared/gold_trial_callout" + - if current_user = render 'dashboard/projects_head' - else diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index 452f390695c..d18dec7bd8e 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -2,6 +2,8 @@ - page_title _("Projects") - header_title _("Projects"), dashboard_projects_path += render_if_exists "shared/gold_trial_callout" + - if current_user = render 'dashboard/projects_head' - else diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb index 282bf542e77..9ffa75aee47 100644 --- a/spec/features/dashboard/merge_requests_spec.rb +++ b/spec/features/dashboard/merge_requests_spec.rb @@ -6,6 +6,7 @@ describe 'Dashboard Merge Requests' do include ProjectForksHelper let(:current_user) { create :user } + let(:user) { current_user } let(:project) { create(:project) } let(:public_project) { create(:project, :public, :repository) }