From a9496c27c9bb2876b9d94bfbe33f252a931caa8f Mon Sep 17 00:00:00 2001 From: Dennis Tang Date: Mon, 7 May 2018 18:06:02 +0000 Subject: [PATCH] Resolve "Inform users of up to $500 offer for GCP account" --- .../javascripts/clusters/clusters_index.js | 26 +++++----- .../clusters/components/gcp_signup_offer.js | 27 +++++++++++ .../projects/clusters/gcp/login/index.js | 3 ++ .../pages/projects/clusters/new/index.js | 3 ++ .../stylesheets/framework/variables.scss | 16 +++---- app/assets/stylesheets/pages/clusters.scss | 48 +++++++++++++++++++ app/helpers/clusters_helper.rb | 8 ++++ app/helpers/user_callouts_helper.rb | 5 ++ app/models/user_callout.rb | 3 +- .../_gcp_signup_offer_banner.html.haml | 12 +++++ .../projects/clusters/gcp/login.html.haml | 2 + app/views/projects/clusters/index.html.haml | 2 + app/views/projects/clusters/new.html.haml | 2 + .../unreleased/43469-gcp-account-offer.yml | 5 ++ package.json | 2 +- spec/features/projects/clusters/gcp_spec.rb | 40 ++++++++++++++++ yarn.lock | 6 +-- 17 files changed, 185 insertions(+), 25 deletions(-) create mode 100644 app/assets/javascripts/clusters/components/gcp_signup_offer.js create mode 100644 app/assets/javascripts/pages/projects/clusters/gcp/login/index.js create mode 100644 app/assets/javascripts/pages/projects/clusters/new/index.js create mode 100644 app/views/projects/clusters/_gcp_signup_offer_banner.html.haml create mode 100644 changelogs/unreleased/43469-gcp-account-offer.yml diff --git a/app/assets/javascripts/clusters/clusters_index.js b/app/assets/javascripts/clusters/clusters_index.js index 2e3ad244375..1e5c733d151 100644 --- a/app/assets/javascripts/clusters/clusters_index.js +++ b/app/assets/javascripts/clusters/clusters_index.js @@ -1,20 +1,24 @@ -import Flash from '../flash'; -import { s__ } from '../locale'; -import setupToggleButtons from '../toggle_buttons'; +import createFlash from '~/flash'; +import { __ } from '~/locale'; +import setupToggleButtons from '~/toggle_buttons'; +import gcpSignupOffer from '~/clusters/components/gcp_signup_offer'; + import ClustersService from './services/clusters_service'; export default () => { const clusterList = document.querySelector('.js-clusters-list'); + + gcpSignupOffer(); + // The empty state won't have a clusterList if (clusterList) { - setupToggleButtons( - document.querySelector('.js-clusters-list'), - (value, toggle) => - ClustersService.updateCluster(toggle.dataset.endpoint, { cluster: { enabled: value } }) - .catch((err) => { - Flash(s__('ClusterIntegration|Something went wrong on our end.')); - throw err; - }), + setupToggleButtons(document.querySelector('.js-clusters-list'), (value, toggle) => + ClustersService.updateCluster(toggle.dataset.endpoint, { cluster: { enabled: value } }).catch( + err => { + createFlash(__('Something went wrong on our end.')); + throw err; + }, + ), ); } }; diff --git a/app/assets/javascripts/clusters/components/gcp_signup_offer.js b/app/assets/javascripts/clusters/components/gcp_signup_offer.js new file mode 100644 index 00000000000..8bc20a1c09f --- /dev/null +++ b/app/assets/javascripts/clusters/components/gcp_signup_offer.js @@ -0,0 +1,27 @@ +import $ from 'jquery'; +import axios from '~/lib/utils/axios_utils'; +import { __ } from '~/locale'; +import Flash from '~/flash'; + +export default function gcpSignupOffer() { + const alertEl = document.querySelector('.gcp-signup-offer'); + 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/projects/clusters/gcp/login/index.js b/app/assets/javascripts/pages/projects/clusters/gcp/login/index.js new file mode 100644 index 00000000000..0c2d7d7c96a --- /dev/null +++ b/app/assets/javascripts/pages/projects/clusters/gcp/login/index.js @@ -0,0 +1,3 @@ +import gcpSignupOffer from '~/clusters/components/gcp_signup_offer'; + +gcpSignupOffer(); diff --git a/app/assets/javascripts/pages/projects/clusters/new/index.js b/app/assets/javascripts/pages/projects/clusters/new/index.js new file mode 100644 index 00000000000..0c2d7d7c96a --- /dev/null +++ b/app/assets/javascripts/pages/projects/clusters/new/index.js @@ -0,0 +1,3 @@ +import gcpSignupOffer from '~/clusters/components/gcp_signup_offer'; + +gcpSignupOffer(); diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index cbf99e411cd..b5505538541 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -265,6 +265,7 @@ $performance-bar-height: 35px; $flash-height: 52px; $context-header-height: 60px; $breadcrumb-min-height: 48px; +$gcp-signup-offer-icon-max-width: 125px; /* * Common component specific colors @@ -334,11 +335,10 @@ $diff-jagged-border-gradient-color: darken($white-normal, 8%); /* * Fonts */ -$monospace_font: 'Menlo', 'DejaVu Sans Mono', 'Liberation Mono', 'Consolas', - 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace; -$regular_font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif, - 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; +$monospace_font: 'Menlo', 'DejaVu Sans Mono', 'Liberation Mono', 'Consolas', 'Ubuntu Mono', + 'Courier New', 'andale mono', 'lucida console', monospace; +$regular_font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, + 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; /* * Dropdowns @@ -466,11 +466,9 @@ $issue-boards-card-shadow: rgba(186, 186, 186, 0.5); */ $issue-boards-filter-height: 68px; $issue-boards-breadcrumbs-height-xs: 63px; -$issue-board-list-difference-xs: $header-height + - $issue-boards-breadcrumbs-height-xs; +$issue-board-list-difference-xs: $header-height + $issue-boards-breadcrumbs-height-xs; $issue-board-list-difference-sm: $header-height + $breadcrumb-min-height; -$issue-board-list-difference-md: $issue-board-list-difference-sm + - $issue-boards-filter-height; +$issue-board-list-difference-md: $issue-board-list-difference-sm + $issue-boards-filter-height; /* * Avatar diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss index 7b8ee026357..3fd13078131 100644 --- a/app/assets/stylesheets/pages/clusters.scss +++ b/app/assets/stylesheets/pages/clusters.scss @@ -26,3 +26,51 @@ margin-right: 0; } } + +.gcp-signup-offer { + background-color: $blue-50; + border: 1px solid $blue-300; + border-radius: $border-radius-default; + + // TODO: To be superceded by cssLab + &.alert { + padding: 24px 16px; + + &-dismissable { + padding-right: 32px; + + .close { + top: -8px; + right: -16px; + color: $blue-500; + opacity: 1; + } + } + } + + .gcp-logo { + margin-bottom: $gl-padding; + text-align: center; + } + + img { + max-width: $gcp-signup-offer-icon-max-width; + } + + a:not(.btn) { + color: $gl-link-color; + font-weight: normal; + text-decoration: none; + } + + @media (min-width: $screen-sm-min) { + > div { + display: flex; + align-items: center; + } + + .gcp-logo { + margin: 0; + } + } +} diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb index 7e4eb06b99d..c24d340d184 100644 --- a/app/helpers/clusters_helper.rb +++ b/app/helpers/clusters_helper.rb @@ -2,4 +2,12 @@ module ClustersHelper def has_multiple_clusters?(project) false end + + def render_gcp_signup_offer + return unless show_gcp_signup_offer? + + content_tag :section, class: 'no-animate expanded' do + render 'projects/clusters/gcp_signup_offer_banner' + end + end end diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb index 36abfaf19a5..da5fe25c07d 100644 --- a/app/helpers/user_callouts_helper.rb +++ b/app/helpers/user_callouts_helper.rb @@ -1,11 +1,16 @@ module UserCalloutsHelper GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'.freeze + GCP_SIGNUP_OFFER = 'gcp_signup_offer'.freeze def show_gke_cluster_integration_callout?(project) can?(current_user, :create_cluster, project) && !user_dismissed?(GKE_CLUSTER_INTEGRATION) end + def show_gcp_signup_offer? + !user_dismissed?(GCP_SIGNUP_OFFER) + end + private def user_dismissed?(feature_name) diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb index e4b69382626..9d461c6750a 100644 --- a/app/models/user_callout.rb +++ b/app/models/user_callout.rb @@ -2,7 +2,8 @@ class UserCallout < ActiveRecord::Base belongs_to :user enum feature_name: { - gke_cluster_integration: 1 + gke_cluster_integration: 1, + gcp_signup_offer: 2 } validates :user, presence: true diff --git a/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml b/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml new file mode 100644 index 00000000000..d0402197821 --- /dev/null +++ b/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml @@ -0,0 +1,12 @@ +- 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') +.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 } } × + %div + .col-sm-2.gcp-logo + = image_tag 'illustrations/logos/google-cloud-platform_logo.svg' + .col-sm-10 + %h4= s_('ClusterIntegration|Redeem up to $500 in free credit for Google Cloud Platform') + %p= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link } + %a.btn.btn-info{ href: 'https://goo.gl/AaJzRW', target: '_blank', rel: 'noopener noreferrer' } + Apply for credit + diff --git a/app/views/projects/clusters/gcp/login.html.haml b/app/views/projects/clusters/gcp/login.html.haml index dada51f39da..ff046c59a7a 100644 --- a/app/views/projects/clusters/gcp/login.html.haml +++ b/app/views/projects/clusters/gcp/login.html.haml @@ -1,6 +1,8 @@ - breadcrumb_title 'Kubernetes' - page_title _("Login") += render_gcp_signup_offer + .row.prepend-top-default .col-sm-4 = render 'projects/clusters/sidebar' diff --git a/app/views/projects/clusters/index.html.haml b/app/views/projects/clusters/index.html.haml index 17b244f4bf7..a55de84b5cd 100644 --- a/app/views/projects/clusters/index.html.haml +++ b/app/views/projects/clusters/index.html.haml @@ -1,6 +1,8 @@ - breadcrumb_title 'Kubernetes' - page_title "Kubernetes Clusters" += render_gcp_signup_offer + .clusters-container - if @clusters.empty? = render "empty_state" diff --git a/app/views/projects/clusters/new.html.haml b/app/views/projects/clusters/new.html.haml index e004966bdcc..828e2a84753 100644 --- a/app/views/projects/clusters/new.html.haml +++ b/app/views/projects/clusters/new.html.haml @@ -1,6 +1,8 @@ - breadcrumb_title 'Kubernetes' - page_title _("Kubernetes Cluster") += render_gcp_signup_offer + .row.prepend-top-default .col-sm-4 = render 'sidebar' diff --git a/changelogs/unreleased/43469-gcp-account-offer.yml b/changelogs/unreleased/43469-gcp-account-offer.yml new file mode 100644 index 00000000000..323a4b81731 --- /dev/null +++ b/changelogs/unreleased/43469-gcp-account-offer.yml @@ -0,0 +1,5 @@ +--- +title: Add GCP signup offer to cluster index / create pages +merge_request: 18684 +author: +type: added diff --git a/package.json b/package.json index c2137ab8316..094200f5bbe 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "webpack-prod": "NODE_ENV=production webpack --config config/webpack.config.js" }, "dependencies": { - "@gitlab-org/gitlab-svgs": "^1.18.0", + "@gitlab-org/gitlab-svgs": "^1.20.0", "autosize": "^4.0.0", "axios": "^0.17.1", "babel-core": "^6.26.0", diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index dfe8e02dce0..fe334b531f0 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -184,4 +184,44 @@ feature 'Gcp Cluster', :js do expect(page).to have_css('.signin-with-google') end end + + context 'when user has not dismissed GCP signup offer' do + before do + visit project_clusters_path(project) + end + + it 'user sees offer on cluster index page' do + expect(page).to have_css('.gcp-signup-offer') + end + + it 'user sees offer on cluster create page' do + click_link 'Add Kubernetes cluster' + + expect(page).to have_css('.gcp-signup-offer') + end + + it 'user sees offer on cluster GCP login page' do + click_link 'Add Kubernetes cluster' + click_link 'Create on Google Kubernetes Engine' + + expect(page).to have_css('.gcp-signup-offer') + end + end + + context 'when user has dismissed GCP signup offer' do + before do + visit project_clusters_path(project) + end + + it 'user does not see offer after dismissing' do + expect(page).to have_css('.gcp-signup-offer') + + find('.gcp-signup-offer .close').click + wait_for_requests + + click_link 'Add Kubernetes cluster' + + expect(page).not_to have_css('.gcp-signup-offer') + end + end end diff --git a/yarn.lock b/yarn.lock index 33e129a8e51..bf860f032b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,9 +54,9 @@ lodash "^4.2.0" to-fast-properties "^2.0.0" -"@gitlab-org/gitlab-svgs@^1.18.0": - version "1.18.0" - resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.18.0.tgz#7829f0e6de0647dace54c1fcd597ee3424afb233" +"@gitlab-org/gitlab-svgs@^1.20.0": + version "1.20.0" + resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.20.0.tgz#4c3fa3a91e0693114654b0066fb1ef04c0602047" "@sindresorhus/is@^0.7.0": version "0.7.0" -- GitLab