Commit 3eedb2ae authored by Phil Hughes's avatar Phil Hughes

Refactored the user callout class

Instead of the JS being in charge of the HTML, the HAML now handles it.
The HAML can then check the cookie & show it needed. It also allows the
HAML access to the paths so we don't have to pass that through.

Closes #29955
parent 4a8e516c
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
const userCalloutElementName = '.user-callout';
const closeButton = '.close-user-callout';
const userCalloutBtn = '.user-callout-btn';
const userCalloutSvgAttrName = 'callout-svg';
const USER_CALLOUT_COOKIE = 'user_callout_dismissed'; const USER_CALLOUT_COOKIE = 'user_callout_dismissed';
const USER_CALLOUT_TEMPLATE = `
<div class="bordered-box landing content-block">
<button class="btn btn-default close close-user-callout" type="button">
<i class="fa fa-times dismiss-icon"></i>
</button>
<div class="row">
<div class="col-sm-3 col-xs-12 svg-container">
</div>
<div class="col-sm-8 col-xs-12 inner-content">
<h4>
Customize your experience
</h4>
<p>
Change syntax themes, default project pages, and more in preferences.
</p>
<a class="btn user-callout-btn" href="/profile/preferences">Check it out</a>
</div>
</div>
</div>`;
export default class UserCallout { export default class UserCallout {
constructor() { constructor() {
this.isCalloutDismissed = Cookies.get(USER_CALLOUT_COOKIE); this.isCalloutDismissed = Cookies.get(USER_CALLOUT_COOKIE);
this.userCalloutBody = $(userCalloutElementName); this.userCalloutBody = $('.user-callout');
this.userCalloutSvg = $(userCalloutElementName).attr(userCalloutSvgAttrName);
$(userCalloutElementName).removeAttr(userCalloutSvgAttrName);
this.init(); this.init();
} }
init() { init() {
const $template = $(USER_CALLOUT_TEMPLATE);
if (!this.isCalloutDismissed || this.isCalloutDismissed === 'false') { if (!this.isCalloutDismissed || this.isCalloutDismissed === 'false') {
$template.find('.svg-container').append(this.userCalloutSvg); $('.js-close-callout').on('click', e => this.dismissCallout(e));
this.userCalloutBody.append($template);
$template.find(closeButton).on('click', e => this.dismissCallout(e));
$template.find(userCalloutBtn).on('click', e => this.dismissCallout(e));
} else {
this.userCalloutBody.remove();
} }
} }
dismissCallout(e) { dismissCallout(e) {
Cookies.set(USER_CALLOUT_COOKIE, 'true');
const $currentTarget = $(e.currentTarget); const $currentTarget = $(e.currentTarget);
if ($currentTarget.hasClass('close-user-callout')) {
Cookies.set(USER_CALLOUT_COOKIE, 'true');
if ($currentTarget.hasClass('close')) {
this.userCalloutBody.remove(); this.userCalloutBody.remove();
} }
} }
......
...@@ -306,4 +306,8 @@ module ApplicationHelper ...@@ -306,4 +306,8 @@ module ApplicationHelper
def active_when(condition) def active_when(condition)
'active' if condition 'active' if condition
end end
def show_user_callout?
cookies[:user_callout_dismissed] == 'true'
end
end end
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
- page_title "Projects" - page_title "Projects"
- header_title "Projects", dashboard_projects_path - header_title "Projects", dashboard_projects_path
.user-callout{ 'callout-svg' => custom_icon('icon_customization') } - unless show_user_callout?
= render 'shared/user_callout'
- if @projects.any? || params[:name] - if @projects.any? || params[:name]
= render 'dashboard/projects_head' = render 'dashboard/projects_head'
......
.user-callout
.bordered-box.landing.content-block
%button.btn.btn-default.close.js-close-callout{ type: 'button',
'aria-label' => 'Dismiss customize experience box' }
= icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
.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 btn-default js-close-callout'
...@@ -97,8 +97,8 @@ ...@@ -97,8 +97,8 @@
Snippets Snippets
%div{ class: container_class } %div{ class: container_class }
- if @user == current_user - if @user == current_user && !show_user_callout?
.user-callout{ 'callout-svg' => custom_icon('icon_customization') } = render 'shared/user_callout'
.tab-content .tab-content
#activity.tab-pane #activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs .row-content-block.calender-block.white.second-block.hidden-xs
......
...@@ -16,6 +16,18 @@ describe 'User Callouts', js: true do ...@@ -16,6 +16,18 @@ describe 'User Callouts', js: true do
expect(current_path).to eq profile_preferences_path expect(current_path).to eq profile_preferences_path
end end
it 'does not show when cookie is set' do
visit dashboard_projects_path
within('.user-callout') do
find('.close').click
end
visit dashboard_projects_path
expect(page).not_to have_selector('.user-callout')
end
describe 'user callout should appear in two routes' do describe 'user callout should appear in two routes' do
it 'shows up on the user profile' do it 'shows up on the user profile' do
visit user_path(user) visit user_path(user)
...@@ -31,7 +43,7 @@ describe 'User Callouts', js: true do ...@@ -31,7 +43,7 @@ describe 'User Callouts', js: true do
it 'hides the user callout when click on the dismiss icon' do it 'hides the user callout when click on the dismiss icon' do
visit user_path(user) visit user_path(user)
within('.user-callout') do within('.user-callout') do
find('.close-user-callout').click find('.close').click
end end
expect(page).not_to have_selector('.user-callout') expect(page).not_to have_selector('.user-callout')
end end
......
require 'spec_helper'
describe Dashboard::ProjectsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, namespace: namespace, path: 'builds-project') }
render_views
before(:all) do
clean_frontend_fixtures('dashboard/')
end
before(:each) do
sign_in(admin)
end
it 'dashboard/user-callout.html.raw' do |example|
rendered = render_template('shared/_user_callout')
store_frontend_fixture(rendered, example.description)
end
private
def render_template(template_file_name)
controller.prepend_view_path(JavaScriptFixturesHelpers::FIXTURE_PATH)
controller.render_to_string(template_file_name, layout: false)
end
end
.user-callout{ 'callout-svg' => custom_icon('icon_customization') }
...@@ -4,7 +4,7 @@ import UserCallout from '~/user_callout'; ...@@ -4,7 +4,7 @@ import UserCallout from '~/user_callout';
const USER_CALLOUT_COOKIE = 'user_callout_dismissed'; const USER_CALLOUT_COOKIE = 'user_callout_dismissed';
describe('UserCallout', function () { describe('UserCallout', function () {
const fixtureName = 'static/user_callout.html.raw'; const fixtureName = 'dashboard/user-callout.html.raw';
preloadFixtures(fixtureName); preloadFixtures(fixtureName);
beforeEach(() => { beforeEach(() => {
...@@ -12,26 +12,22 @@ describe('UserCallout', function () { ...@@ -12,26 +12,22 @@ describe('UserCallout', function () {
Cookies.remove(USER_CALLOUT_COOKIE); Cookies.remove(USER_CALLOUT_COOKIE);
this.userCallout = new UserCallout(); this.userCallout = new UserCallout();
this.closeButton = $('.close-user-callout'); this.closeButton = $('.js-close-callout.close');
this.userCalloutBtn = $('.user-callout-btn'); this.userCalloutBtn = $('.js-close-callout:not(.close)');
this.userCalloutContainer = $('.user-callout'); this.userCalloutContainer = $('.user-callout');
}); });
it('does not show when cookie is set not defined', () => { it('hides when user clicks on the dismiss-icon', (done) => {
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBeUndefined(); this.closeButton.click();
expect(this.userCalloutContainer.is(':visible')).toBe(true); expect(Cookies.get(USER_CALLOUT_COOKIE)).toBe('true');
});
it('shows when cookie is set to false', () => { setTimeout(() => {
Cookies.set(USER_CALLOUT_COOKIE, 'false'); expect(
document.querySelector('.user-callout'),
).toBeNull();
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBeDefined(); done();
expect(this.userCalloutContainer.is(':visible')).toBe(true);
}); });
it('hides when user clicks on the dismiss-icon', () => {
this.closeButton.click();
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBe('true');
}); });
it('hides when user clicks on the "check it out" button', () => { it('hides when user clicks on the "check it out" button', () => {
...@@ -39,19 +35,3 @@ describe('UserCallout', function () { ...@@ -39,19 +35,3 @@ describe('UserCallout', function () {
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBe('true'); expect(Cookies.get(USER_CALLOUT_COOKIE)).toBe('true');
}); });
}); });
describe('UserCallout when cookie is present', function () {
const fixtureName = 'static/user_callout.html.raw';
preloadFixtures(fixtureName);
beforeEach(() => {
loadFixtures(fixtureName);
Cookies.set(USER_CALLOUT_COOKIE, 'true');
this.userCallout = new UserCallout();
this.userCalloutContainer = $('.user-callout');
});
it('removes the DOM element', () => {
expect(this.userCalloutContainer.length).toBe(0);
});
});
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