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
This commit is contained in:
parent
4a8e516c1f
commit
3eedb2aede
|
@ -1,57 +1,26 @@
|
||||||
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
|
||||||
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 @@
|
||||||
- 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'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
.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 @@
|
||||||
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
|
||||||
|
|
|
@ -7,15 +7,27 @@ describe 'User Callouts', js: true do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
login_as(user)
|
login_as(user)
|
||||||
project.team << [user, :master]
|
project.team << [user, :master]
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'takes you to the profile preferences when the link is clicked' do
|
it 'takes you to the profile preferences when the link is clicked' do
|
||||||
visit dashboard_projects_path
|
visit dashboard_projects_path
|
||||||
click_link 'Check it out'
|
click_link 'Check it out'
|
||||||
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
|
||||||
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
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
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
|
|
@ -1,2 +0,0 @@
|
||||||
.user-callout{ 'callout-svg' => custom_icon('icon_customization') }
|
|
||||||
|
|
|
@ -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 () {
|
||||||
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();
|
|
||||||
expect(this.userCalloutContainer.is(':visible')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows when cookie is set to false', () => {
|
|
||||||
Cookies.set(USER_CALLOUT_COOKIE, 'false');
|
|
||||||
|
|
||||||
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBeDefined();
|
|
||||||
expect(this.userCalloutContainer.is(':visible')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('hides when user clicks on the dismiss-icon', () => {
|
|
||||||
this.closeButton.click();
|
this.closeButton.click();
|
||||||
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBe('true');
|
expect(Cookies.get(USER_CALLOUT_COOKIE)).toBe('true');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('.user-callout'),
|
||||||
|
).toBeNull();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
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 () {
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in New Issue