summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFatih Acet <acetfatih@gmail.com>2017-05-30 11:40:21 +0000
committerFatih Acet <acetfatih@gmail.com>2017-05-30 11:40:21 +0000
commitebd6e5f351a53b55e15631f01d1bc96ff04e4065 (patch)
treefd51a190cb3e1d3605dc4bb4865754c29b062c70
parentffe52f0143a222350c8356084215ff5e502ead20 (diff)
parent13dd82b5de6a2076f33defc9f12bc05f98891423 (diff)
downloadgitlab-ce-ebd6e5f351a53b55e15631f01d1bc96ff04e4065.tar.gz
Merge branch '32916-browser-notifications-for-pipeline-running-in-a-mr-is-gone' into 'master'
Resolve "Browser notifications for pipeline running in a MR is gone" Closes #32916 See merge request !11734
-rw-r--r--app/assets/javascripts/lib/utils/notify.js85
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/dependencies.js1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js12
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js2
-rw-r--r--lib/gitlab/gon_helper.rb3
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js37
8 files changed, 100 insertions, 43 deletions
diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js
index 66f39122a66..973d6119158 100644
--- a/app/assets/javascripts/lib/utils/notify.js
+++ b/app/assets/javascripts/lib/utils/notify.js
@@ -1,47 +1,48 @@
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, consistent-return, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, no-param-reassign, max-len */
-(function() {
- (function(w) {
- var notificationGranted, notifyMe, notifyPermissions;
- notificationGranted = function(message, opts, onclick) {
- var notification;
- notification = new Notification(message, opts);
- setTimeout(function() {
- return notification.close();
- // Hide the notification after X amount of seconds
- }, 8000);
- if (onclick) {
- return notification.onclick = onclick;
- }
- };
- notifyPermissions = function() {
- if ('Notification' in window) {
- return Notification.requestPermission();
- }
- };
- notifyMe = function(message, body, icon, onclick) {
- var opts;
- opts = {
- body: body,
- icon: icon
- };
- // Let's check if the browser supports notifications
- if (!('Notification' in window)) {
+function notificationGranted(message, opts, onclick) {
+ var notification;
+ notification = new Notification(message, opts);
+ setTimeout(function() {
+ // Hide the notification after X amount of seconds
+ return notification.close();
+ }, 8000);
+
+ return notification.onclick = onclick || notification.close;
+}
- // do nothing
- } else if (Notification.permission === 'granted') {
- // If it's okay let's create a notification
+function notifyPermissions() {
+ if ('Notification' in window) {
+ return Notification.requestPermission();
+ }
+}
+
+function notifyMe(message, body, icon, onclick) {
+ var opts;
+ opts = {
+ body: body,
+ icon: icon
+ };
+ // Let's check if the browser supports notifications
+ if (!('Notification' in window)) {
+ // do nothing
+ } else if (Notification.permission === 'granted') {
+ // If it's okay let's create a notification
+ return notificationGranted(message, opts, onclick);
+ } else if (Notification.permission !== 'denied') {
+ return Notification.requestPermission(function(permission) {
+ // If the user accepts, let's create a notification
+ if (permission === 'granted') {
return notificationGranted(message, opts, onclick);
- } else if (Notification.permission !== 'denied') {
- return Notification.requestPermission(function(permission) {
- // If the user accepts, let's create a notification
- if (permission === 'granted') {
- return notificationGranted(message, opts, onclick);
- }
- });
}
- };
- w.notify = notifyMe;
- return w.notifyPermissions = notifyPermissions;
- })(window);
-}).call(window);
+ });
+ }
+}
+
+const notify = {
+ notificationGranted,
+ notifyPermissions,
+ notifyMe,
+};
+
+export default notify;
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index f0958972130..1ac82b7e291 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -56,7 +56,6 @@ import './lib/utils/animate';
import './lib/utils/bootstrap_linked_tabs';
import './lib/utils/common_utils';
import './lib/utils/datetime_utility';
-import './lib/utils/notify';
import './lib/utils/pretty_time';
import './lib/utils/text_utility';
import './lib/utils/url_utility';
diff --git a/app/assets/javascripts/vue_merge_request_widget/dependencies.js b/app/assets/javascripts/vue_merge_request_widget/dependencies.js
index bfe30ee4c08..fe5e1bbb55c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/dependencies.js
+++ b/app/assets/javascripts/vue_merge_request_widget/dependencies.js
@@ -41,3 +41,4 @@ export { default as getStateKey } from './stores/get_state_key';
export { default as mrWidgetOptions } from './mr_widget_options';
export { default as stateMaps } from './stores/state_maps';
export { default as SquashBeforeMerge } from './components/states/mr_widget_squash_before_merge';
+export { default as notify } from '../lib/utils/notify';
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index cd65ac069c5..43ef468c303 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -4,6 +4,8 @@ import {
} from './dependencies';
document.addEventListener('DOMContentLoaded', () => {
+ gl.mrWidgetData.gitlabLogo = gon.gitlab_logo;
+
const vm = new Vue(mrWidgetOptions);
window.gl.mrWidget = {
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
index 99600b6664e..2339a00ddd0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
@@ -29,6 +29,7 @@ import {
eventHub,
stateMaps,
SquashBeforeMerge,
+ notify,
} from './dependencies';
export default {
@@ -77,8 +78,10 @@ export default {
this.service.checkStatus()
.then(res => res.json())
.then((res) => {
+ this.handleNotification(res);
this.mr.setData(res);
this.setFavicon();
+
if (cb) {
cb.call(null, res);
}
@@ -136,6 +139,15 @@ export default {
new Flash('Something went wrong. Please try again.'); // eslint-disable-line
});
},
+ handleNotification(data) {
+ if (data.ci_status === this.mr.ciStatus) return;
+
+ const label = data.pipeline.details.status.label;
+ const title = `Pipeline ${label}`;
+ const message = `Pipeline ${label} for "${data.title}"`;
+
+ notify.notifyMe(title, message, this.mr.gitlabLogo);
+ },
resumePolling() {
this.pollingInterval.resume();
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index dc4b2195050..69bc1436284 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -5,6 +5,8 @@ export default class MergeRequestStore {
constructor(data) {
this.sha = data.diff_head_sha;
+ this.gitlabLogo = data.gitlabLogo;
+
this.setData(data);
}
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 21f2e6b6970..319633656ff 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -1,3 +1,5 @@
+# rubocop:disable Metrics/AbcSize
+
module Gitlab
module GonHelper
def add_gon_variables
@@ -13,6 +15,7 @@ module Gitlab
gon.sentry_dsn = current_application_settings.clientside_sentry_dsn if current_application_settings.clientside_sentry_enabled
gon.gitlab_url = Gitlab.config.gitlab.url
gon.revision = Gitlab::REVISION
+ gon.gitlab_logo = ActionController::Base.helpers.asset_path('gitlab_logo.png')
if current_user
gon.current_user_id = current_user.id
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index bdc18243a15..3a0c50b750f 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options';
import eventHub from '~/vue_merge_request_widget/event_hub';
+import notify from '~/lib/utils/notify';
import mockData from './mock_data';
const createComponent = () => {
@@ -107,6 +108,8 @@ describe('mrWidgetOptions', () => {
it('should tell service to check status', (done) => {
spyOn(vm.service, 'checkStatus').and.returnValue(returnPromise(mockData));
spyOn(vm.mr, 'setData');
+ spyOn(vm, 'handleNotification');
+
let isCbExecuted = false;
const cb = () => {
isCbExecuted = true;
@@ -117,6 +120,7 @@ describe('mrWidgetOptions', () => {
setTimeout(() => {
expect(vm.service.checkStatus).toHaveBeenCalled();
expect(vm.mr.setData).toHaveBeenCalled();
+ expect(vm.handleNotification).toHaveBeenCalledWith(mockData);
expect(isCbExecuted).toBeTruthy();
done();
}, 333);
@@ -254,6 +258,39 @@ describe('mrWidgetOptions', () => {
});
});
+ describe('handleNotification', () => {
+ const data = {
+ ci_status: 'running',
+ title: 'title',
+ pipeline: { details: { status: { label: 'running-label' } } },
+ };
+
+ beforeEach(() => {
+ spyOn(notify, 'notifyMe');
+
+ vm.mr.ciStatus = 'failed';
+ vm.mr.gitlabLogo = 'logo.png';
+ });
+
+ it('should call notifyMe', () => {
+ vm.handleNotification(data);
+
+ expect(notify.notifyMe).toHaveBeenCalledWith(
+ 'Pipeline running-label',
+ 'Pipeline running-label for "title"',
+ 'logo.png',
+ );
+ });
+
+ it('should not call notifyMe if the status has not changed', () => {
+ vm.mr.ciStatus = data.ci_status;
+
+ vm.handleNotification(data);
+
+ expect(notify.notifyMe).not.toHaveBeenCalled();
+ });
+ });
+
describe('resumePolling', () => {
it('should call stopTimer on pollingInterval', () => {
spyOn(vm.pollingInterval, 'resume');