Merge branch '64341-user-callout-deferred-link-support' into 'master'
Add support for deferred links in persistent user callouts. Closes #64341 See merge request gitlab-org/gitlab-ce!30818
This commit is contained in:
commit
31d13a41d3
4 changed files with 123 additions and 2 deletions
|
@ -1,13 +1,17 @@
|
|||
import { parseBoolean } from './lib/utils/common_utils';
|
||||
import axios from './lib/utils/axios_utils';
|
||||
import { __ } from './locale';
|
||||
import Flash from './flash';
|
||||
|
||||
const DEFERRED_LINK_CLASS = 'deferred-link';
|
||||
|
||||
export default class PersistentUserCallout {
|
||||
constructor(container) {
|
||||
const { dismissEndpoint, featureId } = container.dataset;
|
||||
const { dismissEndpoint, featureId, deferLinks } = container.dataset;
|
||||
this.container = container;
|
||||
this.dismissEndpoint = dismissEndpoint;
|
||||
this.featureId = featureId;
|
||||
this.deferLinks = parseBoolean(deferLinks);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
@ -15,9 +19,21 @@ export default class PersistentUserCallout {
|
|||
init() {
|
||||
const closeButton = this.container.querySelector('.js-close');
|
||||
closeButton.addEventListener('click', event => this.dismiss(event));
|
||||
|
||||
if (this.deferLinks) {
|
||||
this.container.addEventListener('click', event => {
|
||||
const isDeferredLink = event.target.classList.contains(DEFERRED_LINK_CLASS);
|
||||
|
||||
if (isDeferredLink) {
|
||||
const { href, target } = event.target;
|
||||
|
||||
this.dismiss(event, { href, target });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dismiss(event) {
|
||||
dismiss(event, deferredLinkOptions = null) {
|
||||
event.preventDefault();
|
||||
|
||||
axios
|
||||
|
@ -26,6 +42,11 @@ export default class PersistentUserCallout {
|
|||
})
|
||||
.then(() => {
|
||||
this.container.remove();
|
||||
|
||||
if (deferredLinkOptions) {
|
||||
const { href, target } = deferredLinkOptions;
|
||||
window.open(href, target);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
|
||||
|
|
8
app/assets/javascripts/privacy_policy_update_callout.js
Normal file
8
app/assets/javascripts/privacy_policy_update_callout.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import PersistentUserCallout from '~/persistent_user_callout';
|
||||
|
||||
function initPrivacyPolicyUpdateCallout() {
|
||||
const callout = document.querySelector('.privacy-policy-update-64341');
|
||||
PersistentUserCallout.factory(callout);
|
||||
}
|
||||
|
||||
export default initPrivacyPolicyUpdateCallout;
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add support for deferred links in persistent user callouts.
|
||||
merge_request: 30818
|
||||
author:
|
||||
type: added
|
|
@ -22,6 +22,24 @@ describe('PersistentUserCallout', () => {
|
|||
return fixture;
|
||||
}
|
||||
|
||||
function createDeferredLinkFixture() {
|
||||
const fixture = document.createElement('div');
|
||||
fixture.innerHTML = `
|
||||
<div
|
||||
class="container"
|
||||
data-dismiss-endpoint="${dismissEndpoint}"
|
||||
data-feature-id="${featureName}"
|
||||
data-defer-links="true"
|
||||
>
|
||||
<button type="button" class="js-close"></button>
|
||||
<a href="/somewhere-pleasant" target="_blank" class="deferred-link">A link</a>
|
||||
<a href="/somewhere-else" target="_blank" class="normal-link">Another link</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return fixture;
|
||||
}
|
||||
|
||||
describe('dismiss', () => {
|
||||
let button;
|
||||
let mockAxios;
|
||||
|
@ -74,6 +92,75 @@ describe('PersistentUserCallout', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('deferred links', () => {
|
||||
let button;
|
||||
let deferredLink;
|
||||
let normalLink;
|
||||
let mockAxios;
|
||||
let persistentUserCallout;
|
||||
let windowSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
const fixture = createDeferredLinkFixture();
|
||||
const container = fixture.querySelector('.container');
|
||||
button = fixture.querySelector('.js-close');
|
||||
deferredLink = fixture.querySelector('.deferred-link');
|
||||
normalLink = fixture.querySelector('.normal-link');
|
||||
mockAxios = new MockAdapter(axios);
|
||||
persistentUserCallout = new PersistentUserCallout(container);
|
||||
spyOn(persistentUserCallout.container, 'remove');
|
||||
windowSpy = spyOn(window, 'open').and.callFake(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockAxios.restore();
|
||||
});
|
||||
|
||||
it('defers loading of a link until callout is dismissed', done => {
|
||||
const { href, target } = deferredLink;
|
||||
mockAxios.onPost(dismissEndpoint).replyOnce(200);
|
||||
|
||||
deferredLink.click();
|
||||
|
||||
setTimeoutPromise()
|
||||
.then(() => {
|
||||
expect(windowSpy).toHaveBeenCalledWith(href, target);
|
||||
expect(persistentUserCallout.container.remove).toHaveBeenCalled();
|
||||
expect(mockAxios.history.post[0].data).toBe(
|
||||
JSON.stringify({ feature_name: featureName }),
|
||||
);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
});
|
||||
|
||||
it('does not dismiss callout on non-deferred links', done => {
|
||||
normalLink.click();
|
||||
|
||||
setTimeoutPromise()
|
||||
.then(() => {
|
||||
expect(windowSpy).not.toHaveBeenCalled();
|
||||
expect(persistentUserCallout.container.remove).not.toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
});
|
||||
|
||||
it('does not follow link when notification is closed', done => {
|
||||
mockAxios.onPost(dismissEndpoint).replyOnce(200);
|
||||
|
||||
button.click();
|
||||
|
||||
setTimeoutPromise()
|
||||
.then(() => {
|
||||
expect(windowSpy).not.toHaveBeenCalled();
|
||||
expect(persistentUserCallout.container.remove).toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
});
|
||||
});
|
||||
|
||||
describe('factory', () => {
|
||||
it('returns an instance of PersistentUserCallout with the provided container property', () => {
|
||||
const fixture = createFixture();
|
||||
|
|
Loading…
Reference in a new issue