-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from spenceralger/notification_service
Initial phase of notification service
- Loading branch information
Showing
17 changed files
with
820 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
define(function (require) { | ||
var notify = require('modules').get('notify'); | ||
var _ = require('lodash'); | ||
var $ = require('jquery'); | ||
var MutableWatcher = require('utils/mutable_watcher'); | ||
var nextTick = require('utils/next_tick'); | ||
|
||
var defaultToastOpts = { | ||
title: 'Notice', | ||
lifetime: 7000 | ||
}; | ||
|
||
var transformKey = (function () { | ||
var el = document.createElement('div'); | ||
return _.find(['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'], function (key) { | ||
return el.style[key] !== void 0; | ||
}); | ||
}()); | ||
|
||
notify.directive('kbnNotifications', function () { | ||
return { | ||
restrict: 'A', | ||
scope: { | ||
list: '=list' | ||
}, | ||
template: require('text!./partials/toaster.html'), | ||
link: function ($scope, $el) { | ||
|
||
$el.addClass('toaster-container'); | ||
|
||
// handles recalculating positions and offsets, schedules | ||
// recalcs and waits for 100 seconds before running again. | ||
var layoutList = (function () { | ||
// lazy load the $nav element | ||
var navSelector = '.content > nav.navbar:first()'; | ||
var $nav; | ||
|
||
// pixels between the top of list and it's attachment(nav/window) | ||
var spacing = 10; | ||
// was the element set to postition: fixed last calc? | ||
|
||
var visible = false; | ||
|
||
var recalc = function () { | ||
// set $nav lazily | ||
if (!$nav || !$nav.length) $nav = $(navSelector); | ||
|
||
// if we can't find the nav, don't display the list | ||
if (!$nav.length) return; | ||
|
||
// the top point at which the list should be secured | ||
var fixedTop = $nav.height(); | ||
|
||
// height of the section at the top of the page that is hidden | ||
var hiddenBottom = document.body.scrollTop; | ||
|
||
var top, left, css = { | ||
visibility: 'visible' | ||
}; | ||
|
||
if (hiddenBottom > fixedTop) { | ||
// if we are already fixed, no reason to set the styles again | ||
css.position = 'fixed'; | ||
top = spacing; | ||
} else { | ||
css.position = 'absolute'; | ||
top = fixedTop + spacing; | ||
} | ||
|
||
// calculate the expected left value (keep it centered) | ||
left = Math.floor((document.body.scrollWidth - $el.width()) / 2); | ||
css[transformKey] = 'translateX(' + Math.round(left) + 'px) translateY(' + Math.round(top) + 'px)'; | ||
if (transformKey !== 'msTransform') { | ||
// The Z transform will keep this in the GPU (faster, and prevents artifacts), | ||
// but IE9 doesn't support 3d transforms and will choke. | ||
css[transformKey] += ' translateZ(0)'; | ||
} | ||
|
||
$el.css(css); | ||
}; | ||
|
||
// track the already scheduled recalcs | ||
var timeoutId; | ||
var clearSchedule = function () { | ||
timeoutId = null; | ||
}; | ||
|
||
var schedule = function () { | ||
if (timeoutId) return; | ||
else recalc(); | ||
timeoutId = setTimeout(clearSchedule, 25); | ||
}; | ||
|
||
// call to remove the $el from the view | ||
schedule.hide = function () { | ||
$el.css('visibility', 'hidden'); | ||
visible = false; | ||
}; | ||
|
||
return schedule; | ||
}()); | ||
|
||
function listen(off) { | ||
$(window)[off ? 'off' : 'on']('resize scroll', layoutList); | ||
} | ||
|
||
var wat = new MutableWatcher({ | ||
$scope: $scope, | ||
expression: 'list', | ||
type: 'collection' | ||
}, showList); | ||
|
||
function showList(list) { | ||
if (list && list.length) { | ||
listen(); | ||
wat.set(hideList); | ||
|
||
// delay so that angular has time to update the DOM | ||
nextTick(layoutList); | ||
} | ||
} | ||
|
||
function hideList(list) { | ||
if (!list || !list.length) { | ||
listen(true); | ||
wat.set(showList); | ||
layoutList.hide(); | ||
} | ||
} | ||
|
||
$scope.$on('$destoy', _.partial(listen, true)); | ||
} | ||
}; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
define(function (require) { | ||
var errors = {}; | ||
var _ = require('lodash'); | ||
var inherits = require('utils/inherits'); | ||
|
||
var canStack = (function () { | ||
var err = new Error(); | ||
return !!err.stack; | ||
}()); | ||
|
||
// abstract error class | ||
function KibanaError(msg, constructor) { | ||
this.message = msg; | ||
|
||
Error.call(this, this.message); | ||
if (!this.stack) { | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, constructor || KibanaError); | ||
} else if (canStack) { | ||
this.stack = (new Error()).stack; | ||
} else { | ||
this.stack = ''; | ||
} | ||
} | ||
} | ||
errors.KibanaError = KibanaError; | ||
inherits(KibanaError, Error); | ||
|
||
/** | ||
* Map of error text for different error types | ||
* @type {Object} | ||
*/ | ||
var requireTypeText = { | ||
timeout: 'a network timeout', | ||
nodefine: 'an invalid module definition', | ||
scripterror: 'a generic script error' | ||
}; | ||
|
||
/** | ||
* ScriptLoadFailure error class for handling requirejs load failures | ||
* @param {String} [msg] - | ||
*/ | ||
errors.ScriptLoadFailure = function ScriptLoadFailure(err) { | ||
var explain = requireTypeText[err.requireType] || err.requireType || 'an unknown error'; | ||
|
||
this.stack = err.stack; | ||
var modules = err.requireModules; | ||
if (_.isArray(modules) && modules.length > 0) { | ||
modules = modules.map(JSON.stringify); | ||
|
||
if (modules.length > 1) { | ||
modules = modules.slice(0, -1).join(', ') + ' and ' + modules.slice(-1)[0]; | ||
} else { | ||
modules = modules[0]; | ||
} | ||
|
||
modules += ' modules'; | ||
} | ||
|
||
if (!modules || !modules.length) { | ||
modules = 'unknown modules'; | ||
} | ||
|
||
|
||
KibanaError.call(this, | ||
'Unable to load ' + modules + ' because of ' + explain + '.', | ||
errors.ScriptLoadFailure); | ||
}; | ||
inherits(errors.ScriptLoadFailure, KibanaError); | ||
|
||
return errors; | ||
}); |
Oops, something went wrong.