diff --git a/app/assets/javascripts/user_callout.js b/app/assets/javascripts/user_callout.js index b91fc698629..5d10bfc8290 100644 --- a/app/assets/javascripts/user_callout.js +++ b/app/assets/javascripts/user_callout.js @@ -3,20 +3,35 @@ ((global) => { const userCalloutElementName = '#user-callout'; + const dismissIcon = '.dismiss-icon'; + const userCalloutBtn = '.user-callout-btn'; + + const USER_CALLOUT_COOKIE = 'user_callout_dismissed'; class UserCallout { constructor() { + this.isCalloutDismissed = Cookies.get(USER_CALLOUT_COOKIE); this.init(); } init() { $(document) - .on('DOMContentLoaded', () => { - const element = $(userCalloutElementName); - console.log('element:', element); - }); + .on('click', dismissIcon, () => this.closeAndDismissCallout()) + .on('click', userCalloutBtn, () => this.closeAndDismissCallout()) + .on('DOMContentLoaded', () => this.isUserCalloutDismissed()); + } + + closeAndDismissCallout() { + $(userCalloutElementName).hide(); + Cookies.set(USER_CALLOUT_COOKIE, '1'); + } + + isUserCalloutDismissed() { + if (!this.isCalloutDismissed) { + $(userCalloutElementName).show(); + } } } global.UserCallout = UserCallout; -})(window.gl || (window.gl = {})); \ No newline at end of file +})(window.gl || (window.gl = {})); diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 9add1bafdb3..c9dab696092 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -279,6 +279,7 @@ table.u2f-registrations { } #user-callout { + display: none; margin: 24px auto 0; .bordered-box { @@ -291,8 +292,8 @@ table.u2f-registrations { overflow: hidden; .dismiss-icon { - position: absolute; - right: $user-callout-right; + float: right; + margin-right: 20px; cursor: pointer; color: $cycle-analytics-dismiss-icon-color; } @@ -306,4 +307,10 @@ table.u2f-registrations { } } } + + @media(max-width: $screen-xs-max) { + .inner-content { + padding-left: 30px; + } + } } diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 0aec51cf7c9..48b0fd504f4 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -1,18 +1,5 @@ = content_for :flash_message do = render 'shared/project_limit' -#user-callout - .bordered-box.landing.content-block - = icon("times", class: "dismiss-icon") - .row - .col-sm-3.col-xs-12.svg-container - = custom_icon('icon_cycle_analytics_splash') - .col-sm-8.col-xs-12.inner-content - %h4 - Customize your experience - %p - Change syntax themes, default project pages, and more in preferences. - - = link_to "Check it out", profile_preferences_path, class: 'btn' .top-area %ul.nav-links = nav_link(page: [dashboard_projects_path, root_path]) do diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index 4f36a4a1c73..c7a8beab0d5 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -5,6 +5,8 @@ - page_title "Projects" - header_title "Projects", dashboard_projects_path += render partial: 'shared/user_callout' + - if @projects.any? || params[:filter_projects] = render 'dashboard/projects_head' @@ -15,3 +17,6 @@ = render 'projects' - else = render "zero_authorized_projects" + +:javascript + var userCallout = new gl.UserCallout(); \ No newline at end of file diff --git a/app/views/shared/_user_callout.html.haml b/app/views/shared/_user_callout.html.haml new file mode 100644 index 00000000000..079957a9867 --- /dev/null +++ b/app/views/shared/_user_callout.html.haml @@ -0,0 +1,13 @@ +#user-callout + .bordered-box.landing.content-block + = icon("times", class: "dismiss-icon") + .row + .col-sm-3.col-xs-12.svg-container + = custom_icon('icon_customization') + .col-sm-8.col-xs-12.inner-content + %h4 + Customize your experience + %p + Change syntax themes, default project pages, and more in preferences. + + = link_to "Check it out", profile_preferences_path, class: 'btn user-callout-btn' \ No newline at end of file diff --git a/app/views/shared/icons/_icon_customization.svg b/app/views/shared/icons/_icon_customization.svg new file mode 100644 index 00000000000..b2579208039 --- /dev/null +++ b/app/views/shared/icons/_icon_customization.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index a3e35961261..bee65875a99 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -98,19 +98,9 @@ Snippets %div{ class: container_class } - #user-callout - .bordered-box.landing.content-block - = icon("times", class: "dismiss-icon") - .row - .col-sm-3.col-xs-12.svg-container - = custom_icon('icon_cycle_analytics_splash') - .col-sm-8.col-xs-12.inner-content - %h4 - Customize your experience - %p - Change syntax themes, default project pages, and more in preferences. - - = link_to "Check it out", profile_preferences_path, class: 'btn' + = render partial: 'shared/user_callout' + %div{ class: container_class } + .tab-content #activity.tab-pane .row-content-block.calender-block.white.second-block.hidden-xs .user-calendar{ data: { href: user_calendar_path } } diff --git a/spec/features/user_callout_spec.rb b/spec/features/user_callout_spec.rb new file mode 100644 index 00000000000..9ab22475b5e --- /dev/null +++ b/spec/features/user_callout_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe 'User Callouts', js: true do + let(:user) { create(:user) } + let(:project) { create(:empty_project, path: 'gitlab', name: 'sample') } + + before do + login_as(user) + project.team << [user, :master] + end + + it 'takes you to the profile preferences when the link is clicked' do + visit dashboard_projects_path + click_link 'Check it out' + expect(current_path).to eq profile_preferences_path + end + + describe 'user callout should appear in two routes' do + it 'shows up on the user profile' do + visit user_path(user) + expect(find('#user-callout')).to have_content 'Customize your experience' + end + + it 'shows up on the dashboard projects' do + visit dashboard_projects_path + expect(find('#user-callout')).to have_content 'Customize your experience' + end + end + + it 'hides the user callout when click on the dismiss icon' do + visit user_path(user) + within('#user-callout') do + find('.dismiss-icon').click + end + expect(page).not_to have_selector('#user-callout') + end +end \ No newline at end of file diff --git a/spec/javascripts/fixtures/user_callout.html.haml b/spec/javascripts/fixtures/user_callout.html.haml new file mode 100644 index 00000000000..2aa6bf4b604 --- /dev/null +++ b/spec/javascripts/fixtures/user_callout.html.haml @@ -0,0 +1,12 @@ +#user-callout + .bordered-box.landing.content-block + %i.fa.fa-times.dismiss-icon + .row + .col-sm-3.col-xs-12.svg-container + .col-sm-8.col-xs-12.inner-content + %h4 + Customize your experience + %p + Change syntax themes, default project pages, and more in preferences. + %a{ href: 'foo', class:'user-callout-btn' } + Check it out \ No newline at end of file diff --git a/spec/javascripts/user_callout_spec.js b/spec/javascripts/user_callout_spec.js new file mode 100644 index 00000000000..26a12bed067 --- /dev/null +++ b/spec/javascripts/user_callout_spec.js @@ -0,0 +1,42 @@ +/* esint-disable space-before-function-paren, arrow-body-style */ +require('~/user_callout'); + +((global) => { + const USER_CALLOUT_COOKIE = 'user_callout_dismissed'; + const Cookie = window.Cookies; + + describe('UserCallout', function () { + const fixtureName = 'static/user_callout.html.raw'; + preloadFixtures(fixtureName); + + it('should be defined in the global scope', () => { + expect(global.UserCallout).toBeDefined(); + }); + + beforeEach(() => { + loadFixtures(fixtureName); + this.userCallout = new global.UserCallout(); + this.dismissIcon = $('.dismiss-icon'); + this.userCalloutContainer = $('#user-callout'); + this.userCalloutBtn = $('.user-callout-btn'); + Cookie.set(USER_CALLOUT_COOKIE, 0); + }); + + it('shows when cookie is set to false', () => { + expect(Cookie.get(USER_CALLOUT_COOKIE)).toBeDefined(); + expect(this.userCalloutContainer.is(':visible')).toBe(true); + }); + + it('hides when user clicks on the dismiss-icon', () => { + this.dismissIcon.click(); + expect(this.userCalloutContainer.is(':visible')).toBe(false); + expect(Cookie.get(USER_CALLOUT_COOKIE)).toBe('1'); + }); + + it('hides when user clicks on the "check it out" button', () => { + this.userCalloutBtn.click(); + expect(this.userCalloutContainer.is(':visible')).toBe(false); + expect(Cookie.get(USER_CALLOUT_COOKIE)).toBe('1'); + }); + }); +})(window.gl || (window.gl = {}));