summaryrefslogtreecommitdiff
path: root/ambari-web
diff options
context:
space:
mode:
authorYusaku Sako <yusaku@apache.org>2012-12-09 14:42:31 +0000
committerYusaku Sako <yusaku@apache.org>2012-12-09 14:42:31 +0000
commit7ab2fbf4fbb083bc41b24bf361a2b0dae3eaad79 (patch)
treeda689ef889b14886fa21b72f26dd6edcc1ea6b0f /ambari-web
parentec1abe07667f65636846fc42e5e1bd91d552acb2 (diff)
AMBARI-1039. Improve Nagios alerts time display. (Srimanth Gunturi via yusaku)
git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/branches/AMBARI-666@1418981 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'ambari-web')
-rw-r--r--ambari-web/app/assets/licenses/NOTICE.txt5
-rw-r--r--ambari-web/app/mappers/alerts_mapper.js2
-rw-r--r--ambari-web/app/models/alert.js32
-rw-r--r--ambari-web/app/styles/application.less9
-rw-r--r--ambari-web/app/templates/main/service/info/client_summary.hbs2
-rw-r--r--ambari-web/app/templates/main/service/info/summary.hbs2
-rw-r--r--ambari-web/app/views/main/service/info/summary.js2
-rw-r--r--ambari-web/config.coffee1
-rw-r--r--ambari-web/vendor/scripts/jquery.timeago.js152
9 files changed, 197 insertions, 10 deletions
diff --git a/ambari-web/app/assets/licenses/NOTICE.txt b/ambari-web/app/assets/licenses/NOTICE.txt
index f238d78473..0606a2933a 100644
--- a/ambari-web/app/assets/licenses/NOTICE.txt
+++ b/ambari-web/app/assets/licenses/NOTICE.txt
@@ -33,4 +33,7 @@ Copyright (c) 2012 Stefan Petre
This product includes Font Awesome 2.0 (http://fortawesome.github.com/Font-Awesome - Creative Commons 3.0)
This product incudes Rickshaw 1.1.2 (http://code.shutterstock.com/rickshaw/ - MIT License)
-Copyright (C) 2011 by Shutterstock Images, LLC \ No newline at end of file
+Copyright (C) 2011 by Shutterstock Images, LLC
+
+This product includes Timeago (http://timeago.yarp.com/ - MIT License)
+Copyright (c) 2008-2012, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) \ No newline at end of file
diff --git a/ambari-web/app/mappers/alerts_mapper.js b/ambari-web/app/mappers/alerts_mapper.js
index 1577157fc4..fa64bd1d39 100644
--- a/ambari-web/app/mappers/alerts_mapper.js
+++ b/ambari-web/app/mappers/alerts_mapper.js
@@ -23,7 +23,7 @@ App.alertsMapper = App.QuickDataMapper.create({
$alert_id:'' ,
title: "service_description",
service_type: "service_type",
- date: "last_check",
+ date: "last_hard_state_change",
status: "current_state",
message: "plugin_output",
host_name: "host_name",
diff --git a/ambari-web/app/models/alert.js b/ambari-web/app/models/alert.js
index 77df655e56..8a570a6f4e 100644
--- a/ambari-web/app/models/alert.js
+++ b/ambari-web/app/models/alert.js
@@ -53,19 +53,41 @@ App.Alert = DS.Model.extend({
}.property('status'),
/**
- * Used to show appropriate date in UI
+ * Provides how long ago this alert happened.
+ *
+ * @type {String}
*/
- dateDisplay: function () {
+ timeSinceAlert: function () {
var d = this.get('date');
if (d) {
- var dateString = d.toDateString() + ". " + d.toLocaleTimeString();
- dateString = dateString.substr(dateString.indexOf(" ") + 1);
- return dateString;
+ return $.timeago(d);
}
return "";
}.property('date'),
/**
+ * Provides more details about when this alert happened.
+ *
+ * @type {String}
+ */
+ timeSinceAlertDetails: function () {
+ var details = "";
+ var date = this.get('date');
+ if (date) {
+ var dateString = date.toDateString();
+ dateString = dateString.substr(dateString.indexOf(" ") + 1);
+ dateString = "Occurred on " + dateString + ", " + date.toLocaleTimeString();
+ details += dateString;
+ }
+ var lastCheck = this.get('lastCheck');
+ if (lastCheck) {
+ lastCheck = new Date(lastCheck * 1000);
+ details = details + "<br>Last checked " + $.timeago(lastCheck);
+ }
+ return details;
+ }.property('lastCheck', 'date'),
+
+ /**
* Used to show appropriate service label in UI
*/
serviceName: function () {
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 5c7f7be75b..83bde02491 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -196,6 +196,10 @@ h1 {
color: #FF4B4B;
}
+.tooltip-inner {
+ text-align: left;
+}
+
#installer, #add-host, #add-service {
h2 {
margin-top: 0;
@@ -632,7 +636,10 @@ a:focus {
padding-top: 7px;
}
.date-time {
- color: #777;
+ color: #999;
+ font-style: italic;
+ font-size: small;
+ text-align: right;
}
.message {
font-size: 13px;
diff --git a/ambari-web/app/templates/main/service/info/client_summary.hbs b/ambari-web/app/templates/main/service/info/client_summary.hbs
index 07cfd89507..f2721315df 100644
--- a/ambari-web/app/templates/main/service/info/client_summary.hbs
+++ b/ambari-web/app/templates/main/service/info/client_summary.hbs
@@ -86,7 +86,7 @@
<div class="row-fluid">
<div class="span7 title">{{title}}
</div>
- <div class="span5 date-time">{{dateDisplay}}</div>
+ <div rel="tooltip" {{bindAttr data-title="timeSinceAlertDetails"}} data-placement="right" class="span5 date-time">{{timeSinceAlert}}</div>
</div>
<div class="row-fluid message">{{message}}</div>
</div>
diff --git a/ambari-web/app/templates/main/service/info/summary.hbs b/ambari-web/app/templates/main/service/info/summary.hbs
index 9f644cb21d..721ab9e798 100644
--- a/ambari-web/app/templates/main/service/info/summary.hbs
+++ b/ambari-web/app/templates/main/service/info/summary.hbs
@@ -149,7 +149,7 @@
<div class="row-fluid">
<div class="span7 title">{{title}}
</div>
- <div class="span5 date-time">{{dateDisplay}}</div>
+ <div rel="tooltip" {{bindAttr data-title="timeSinceAlertDetails"}} data-placement="right" class="span5 date-time">{{timeSinceAlert}}</div>
</div>
<div class="row-fluid message">{{message}}</div>
</div>
diff --git a/ambari-web/app/views/main/service/info/summary.js b/ambari-web/app/views/main/service/info/summary.js
index 8ec29a0353..f5f22d33ab 100644
--- a/ambari-web/app/views/main/service/info/summary.js
+++ b/ambari-web/app/views/main/service/info/summary.js
@@ -183,6 +183,8 @@ App.MainServiceInfoSummaryView = Em.View.extend({
$(summaryTable).attr('style', "height:" + alertsList.clientHeight + "px;");
}
}
+ // Tooltips for alerts need to be enabled.
+ $("div[rel=tooltip]").tooltip();
},
clientHosts:App.Host.find(),
diff --git a/ambari-web/config.coffee b/ambari-web/config.coffee
index f31f600ce1..8b1ef877de 100644
--- a/ambari-web/config.coffee
+++ b/ambari-web/config.coffee
@@ -52,6 +52,7 @@ exports.config =
'vendor/scripts/jquery.ui.sortable.js',
'vendor/scripts/jquery.ui.custom-effects.js',
'vendor/scripts/jquery.dataTables.js',
+ 'vendor/scripts/jquery.timeago.js',
'vendor/scripts/workflow_visualization.js',
'vendor/scripts/rickshaw.js'
]
diff --git a/ambari-web/vendor/scripts/jquery.timeago.js b/ambari-web/vendor/scripts/jquery.timeago.js
new file mode 100644
index 0000000000..2e8d29f536
--- /dev/null
+++ b/ambari-web/vendor/scripts/jquery.timeago.js
@@ -0,0 +1,152 @@
+/**
+ * Timeago is a jQuery plugin that makes it easy to support automatically
+ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
+ *
+ * @name timeago
+ * @version 0.11.4
+ * @requires jQuery v1.2.3+
+ * @author Ryan McGeary
+ * @license MIT License - http://www.opensource.org/licenses/mit-license.php
+ *
+ * For usage and examples, visit:
+ * http://timeago.yarp.com/
+ *
+ * Copyright (c) 2008-2012, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
+ */
+(function($) {
+ $.timeago = function(timestamp) {
+ if (timestamp instanceof Date) {
+ return inWords(timestamp);
+ } else if (typeof timestamp === "string") {
+ return inWords($.timeago.parse(timestamp));
+ } else if (typeof timestamp === "number") {
+ return inWords(new Date(timestamp));
+ } else {
+ return inWords($.timeago.datetime(timestamp));
+ }
+ };
+ var $t = $.timeago;
+
+ $.extend($.timeago, {
+ settings: {
+ refreshMillis: 60000,
+ allowFuture: false,
+ strings: {
+ prefixAgo: null,
+ prefixFromNow: null,
+ suffixAgo: "ago",
+ suffixFromNow: "from now",
+ seconds: "less than a minute",
+ minute: "about a minute",
+ minutes: "%d minutes",
+ hour: "about an hour",
+ hours: "about %d hours",
+ day: "a day",
+ days: "%d days",
+ month: "about a month",
+ months: "%d months",
+ year: "about a year",
+ years: "%d years",
+ wordSeparator: " ",
+ numbers: []
+ }
+ },
+ inWords: function(distanceMillis) {
+ var $l = this.settings.strings;
+ var prefix = $l.prefixAgo;
+ var suffix = $l.suffixAgo;
+ if (this.settings.allowFuture) {
+ if (distanceMillis < 0) {
+ prefix = $l.prefixFromNow;
+ suffix = $l.suffixFromNow;
+ }
+ }
+
+ var seconds = Math.abs(distanceMillis) / 1000;
+ var minutes = seconds / 60;
+ var hours = minutes / 60;
+ var days = hours / 24;
+ var years = days / 365;
+
+ function substitute(stringOrFunction, number) {
+ var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
+ var value = ($l.numbers && $l.numbers[number]) || number;
+ return string.replace(/%d/i, value);
+ }
+
+ var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
+ seconds < 90 && substitute($l.minute, 1) ||
+ minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
+ minutes < 90 && substitute($l.hour, 1) ||
+ hours < 24 && substitute($l.hours, Math.round(hours)) ||
+ hours < 42 && substitute($l.day, 1) ||
+ days < 30 && substitute($l.days, Math.round(days)) ||
+ days < 45 && substitute($l.month, 1) ||
+ days < 365 && substitute($l.months, Math.round(days / 30)) ||
+ years < 1.5 && substitute($l.year, 1) ||
+ substitute($l.years, Math.round(years));
+
+ var separator = $l.wordSeparator === undefined ? " " : $l.wordSeparator;
+ return $.trim([prefix, words, suffix].join(separator));
+ },
+ parse: function(iso8601) {
+ var s = $.trim(iso8601);
+ s = s.replace(/\.\d+/,""); // remove milliseconds
+ s = s.replace(/-/,"/").replace(/-/,"/");
+ s = s.replace(/T/," ").replace(/Z/," UTC");
+ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
+ return new Date(s);
+ },
+ datetime: function(elem) {
+ var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
+ return $t.parse(iso8601);
+ },
+ isTime: function(elem) {
+ // jQuery's `is()` doesn't play well with HTML5 in IE
+ return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
+ }
+ });
+
+ $.fn.timeago = function() {
+ var self = this;
+ self.each(refresh);
+
+ var $s = $t.settings;
+ if ($s.refreshMillis > 0) {
+ setInterval(function() { self.each(refresh); }, $s.refreshMillis);
+ }
+ return self;
+ };
+
+ function refresh() {
+ var data = prepareData(this);
+ if (!isNaN(data.datetime)) {
+ $(this).text(inWords(data.datetime));
+ }
+ return this;
+ }
+
+ function prepareData(element) {
+ element = $(element);
+ if (!element.data("timeago")) {
+ element.data("timeago", { datetime: $t.datetime(element) });
+ var text = $.trim(element.text());
+ if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
+ element.attr("title", text);
+ }
+ }
+ return element.data("timeago");
+ }
+
+ function inWords(date) {
+ return $t.inWords(distance(date));
+ }
+
+ function distance(date) {
+ return (new Date().getTime() - date.getTime());
+ }
+
+ // fix for IE6 suckage
+ document.createElement("abbr");
+ document.createElement("time");
+}(jQuery));