From 76019071bf1add8c273a6ea4d3c94177bf4e9288 Mon Sep 17 00:00:00 2001 From: Ronald Roskens Date: Fri, 20 Sep 2013 11:20:53 -0500 Subject: [PATCH] nms-6023/6127 fix --- LICENSE | 1 + .../web/src/main/resources/nrt/realtime.template | 1 + opennms-webapp/src/main/webapp/js/rrdgraph.js | 45 ++- .../src/main/webapp/js/simpledateformat.js | 312 +++++++++++++++++++++ 4 files changed, 356 insertions(+), 3 deletions(-) create mode 100644 opennms-webapp/src/main/webapp/js/simpledateformat.js diff --git a/LICENSE b/LICENSE index 9c8cb0c..19c2a18 100644 --- a/LICENSE +++ b/LICENSE @@ -32,3 +32,4 @@ core/test-api/dns/src/main/java/org/opennms/core/test/dns/DNSServer.java opennms-services/src/main/java/org/opennms/netmgt/xmlrpcd/TimeoutSecureXmlRpcClient.java opennms-services/src/test/java/org/opennms/netmgt/syslogd/SyslogClient.java opennms-tools/OpenNMSXMLClient/* +opennms-webapp/src/main/webapp/js/simpledateformat.js diff --git a/features/nrtg/web/src/main/resources/nrt/realtime.template b/features/nrtg/web/src/main/resources/nrt/realtime.template index a9b720c..1449f51 100644 --- a/features/nrtg/web/src/main/resources/nrt/realtime.template +++ b/features/nrtg/web/src/main/resources/nrt/realtime.template @@ -15,6 +15,7 @@ + diff --git a/opennms-webapp/src/main/webapp/js/rrdgraph.js b/opennms-webapp/src/main/webapp/js/rrdgraph.js index 289e7c9..a7f3b69 100644 --- a/opennms-webapp/src/main/webapp/js/rrdgraph.js +++ b/opennms-webapp/src/main/webapp/js/rrdgraph.js @@ -94,7 +94,7 @@ var RRDGraph = window['RRDGraph'] = {}; var parse = function (config_string) { var result = { options: { - 'start' : +new Date() - 120000, + 'start' : +new Date(), 'end' : +new Date(), 'step' : 1, 'title' : '', @@ -1051,6 +1051,7 @@ var RRDGraph = window['RRDGraph'] = {}; this.extremes.x.max = Number.NEGATIVE_INFINITY; this.extremes.y.min = Number.POSITIVE_INFINITY; this.extremes.y.max = Number.NEGATIVE_INFINITY; + this.config.options.end = +new Date(); var temp_defs = {}; var n_defs = 0; @@ -1080,6 +1081,13 @@ var RRDGraph = window['RRDGraph'] = {}; } var temp_cdefs = {}; + var special_elements = { + '{diffTime}': Number((this.config.options.end - this.config.options.start)/1000).toFixed(0), + '{startTime}': Number(this.config.options.start/1000).toFixed(0), + '{endTime}': Number(this.config.options.end/1000).toFixed(0), + '{startTimeDate}': new Date(this.config.options.start).toLocaleString(), + '{endTimeDate}': new Date(this.config.options.end).toLocaleString(), + }; for (var cdef in this.config.defs.calc) { var rpn = this.config.defs.calc[cdef].split(','); @@ -1092,6 +1100,8 @@ var RRDGraph = window['RRDGraph'] = {}; stack.push(temp_defs[element]); } else if (element in temp_cdefs) { // CDEF stack.push(temp_cdefs[element]); + } else if (element in special_elements) { // custom elements + stack.push(special_elements[element]); } else { // operator RPN[element](stack); } @@ -1422,8 +1432,9 @@ var RRDGraph = window['RRDGraph'] = {}; for (var j = 0; j < line.content.length; ++j) { var element = line.content[j]; if (typeof element === 'string') { - text.append('svg:tspan').text(element). - attr('xml:space', 'preserve'); + text.append('svg:tspan'). + attr('xml:space', 'preserve'). + attr('id', 'cspan_' + i + '_' + j); } else { if (element.type === 'box') { text.append('svg:tspan').text("\u25A0 "). @@ -1816,6 +1827,14 @@ var RRDGraph = window['RRDGraph'] = {}; } } + var special_elements = { + '{diffTime}': Number((this.config.options.end - this.config.options.start)/1000).toFixed(0), + '{startTime}': Number(this.config.options.start/1000).toFixed(0), + '{endTime}': Number(this.config.options.end/1000).toFixed(0), + '{startTimeDate}': new Date(this.config.options.start).toLocaleString(), + '{endTimeDate}': new Date(this.config.options.end).toLocaleString(), + }; + for (var i = 0; i < this.config.legend.length; ++i) { var line = this.config.legend[i]; for (var j = 0; j < line.content.length; ++j) { @@ -1843,6 +1862,26 @@ var RRDGraph = window['RRDGraph'] = {}; this.svg.container.select('#tspan_' + i + '_' + j). text(text); } + } else if (typeof element === 'string') { + var text = element; + for (var k in special_elements) { + if (text.indexOf(k, 0) > -1) { + text = text.replace(k, special_elements[k]); + } + } + var matches = text.match(/(\{startTime:([^\{\}]+)\})/); + if (matches !== null) { + var sdf = new SimpleDateFormat(matches[2]); + text = text.replace(matches[1], sdf.format(new Date(this.config.options.start))); + } + var matches = text.match(/(\{endTime:([^\{\}]+)\})/); + if (matches !== null) { + var sdf = new SimpleDateFormat(matches[2]); + text = text.replace(matches[1], sdf.format(new Date(this.config.options.end))); + } + + this.svg.container.select('#cspan_' + i + '_' + j). + text(text); } } } diff --git a/opennms-webapp/src/main/webapp/js/simpledateformat.js b/opennms-webapp/src/main/webapp/js/simpledateformat.js new file mode 100644 index 0000000..d205d53 --- /dev/null +++ b/opennms-webapp/src/main/webapp/js/simpledateformat.js @@ -0,0 +1,312 @@ +/** + * Copyright 2007 Tim Down. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * simpledateformat.js + * + * A faithful JavaScript implementation of Java's SimpleDateFormat's format + * method. All pattern layouts present in the Java implementation are + * implemented here except for z, the text version of the date's time zone. + * + * Thanks to Ash Searle (http://hexmen.com/blog/) for his fix to my + * misinterpretation of pattern letters h and k. + * + * See the official Sun documentation for the Java version: + * http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html + * + * Author: Tim Down + * Last modified: 6/2/2007 + * Website: http://www.timdown.co.uk/code/simpledateformat.php + */ + +/* ------------------------------------------------------------------------- */ + +var SimpleDateFormat; + +(function() { + function isUndefined(obj) { + return typeof obj == "undefined"; + } + + var regex = /('[^']*')|(G+|y+|M+|w+|W+|D+|d+|F+|E+|a+|H+|k+|K+|h+|m+|s+|S+|Z+)|([a-zA-Z]+)|([^a-zA-Z']+)/; + var monthNames = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"]; + var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + var TEXT2 = 0, TEXT3 = 1, NUMBER = 2, YEAR = 3, MONTH = 4, TIMEZONE = 5; + var types = { + G : TEXT2, + y : YEAR, + M : MONTH, + w : NUMBER, + W : NUMBER, + D : NUMBER, + d : NUMBER, + F : NUMBER, + E : TEXT3, + a : TEXT2, + H : NUMBER, + k : NUMBER, + K : NUMBER, + h : NUMBER, + m : NUMBER, + s : NUMBER, + S : NUMBER, + Z : TIMEZONE + }; + var ONE_DAY = 24 * 60 * 60 * 1000; + var ONE_WEEK = 7 * ONE_DAY; + var DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK = 1; + + var newDateAtMidnight = function(year, month, day) { + var d = new Date(year, month, day, 0, 0, 0); + d.setMilliseconds(0); + return d; + } + + Date.prototype.getDifference = function(date) { + return this.getTime() - date.getTime(); + }; + + Date.prototype.isBefore = function(d) { + return this.getTime() < d.getTime(); + }; + + Date.prototype.getUTCTime = function() { + return Date.UTC(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), + this.getSeconds(), this.getMilliseconds()); + }; + + Date.prototype.getTimeSince = function(d) { + return this.getUTCTime() - d.getUTCTime(); + }; + + Date.prototype.getPreviousSunday = function() { + // Using midday avoids any possibility of DST messing things up + var midday = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 12, 0, 0); + var previousSunday = new Date(midday.getTime() - this.getDay() * ONE_DAY); + return newDateAtMidnight(previousSunday.getFullYear(), previousSunday.getMonth(), + previousSunday.getDate()); + } + + Date.prototype.getWeekInYear = function(minimalDaysInFirstWeek) { + if (isUndefined(this.minimalDaysInFirstWeek)) { + minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK; + } + var previousSunday = this.getPreviousSunday(); + var startOfYear = newDateAtMidnight(this.getFullYear(), 0, 1); + var numberOfSundays = previousSunday.isBefore(startOfYear) ? + 0 : 1 + Math.floor(previousSunday.getTimeSince(startOfYear) / ONE_WEEK); + var numberOfDaysInFirstWeek = 7 - startOfYear.getDay(); + var weekInYear = numberOfSundays; + if (numberOfDaysInFirstWeek < minimalDaysInFirstWeek) { + weekInYear--; + } + return weekInYear; + }; + + Date.prototype.getWeekInMonth = function(minimalDaysInFirstWeek) { + if (isUndefined(this.minimalDaysInFirstWeek)) { + minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK; + } + var previousSunday = this.getPreviousSunday(); + var startOfMonth = newDateAtMidnight(this.getFullYear(), this.getMonth(), 1); + var numberOfSundays = previousSunday.isBefore(startOfMonth) ? + 0 : 1 + Math.floor((previousSunday.getTimeSince(startOfMonth)) / ONE_WEEK); + var numberOfDaysInFirstWeek = 7 - startOfMonth.getDay(); + var weekInMonth = numberOfSundays; + if (numberOfDaysInFirstWeek >= minimalDaysInFirstWeek) { + weekInMonth++; + } + return weekInMonth; + }; + + Date.prototype.getDayInYear = function() { + var startOfYear = newDateAtMidnight(this.getFullYear(), 0, 1); + return 1 + Math.floor(this.getTimeSince(startOfYear) / ONE_DAY); + }; + + /* ----------------------------------------------------------------- */ + + SimpleDateFormat = function(formatString) { + this.formatString = formatString; + }; + + /** + * Sets the minimum number of days in a week in order for that week to + * be considered as belonging to a particular month or year + */ + SimpleDateFormat.prototype.setMinimalDaysInFirstWeek = function(days) { + this.minimalDaysInFirstWeek = days; + }; + + SimpleDateFormat.prototype.getMinimalDaysInFirstWeek = function(days) { + return isUndefined(this.minimalDaysInFirstWeek) ? + DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK : this.minimalDaysInFirstWeek; + }; + + SimpleDateFormat.prototype.format = function(date) { + var formattedString = ""; + var result; + + var padWithZeroes = function(str, len) { + while (str.length < len) { + str = "0" + str; + } + return str; + }; + + var formatText = function(data, numberOfLetters, minLength) { + return (numberOfLetters >= 4) ? data : data.substr(0, Math.max(minLength, numberOfLetters)); + }; + + var formatNumber = function(data, numberOfLetters) { + var dataString = "" + data; + // Pad with 0s as necessary + return padWithZeroes(dataString, numberOfLetters); + }; + + var searchString = this.formatString; + while ((result = regex.exec(searchString))) { + var matchedString = result[0]; + var quotedString = result[1]; + var patternLetters = result[2]; + var otherLetters = result[3]; + var otherCharacters = result[4]; + + // If the pattern matched is quoted string, output the text between the quotes + if (quotedString) { + if (quotedString == "''") { + formattedString += "'"; + } else { + formattedString += quotedString.substring(1, quotedString.length - 1); + } + } else if (otherLetters) { + // Swallow non-pattern letters by doing nothing here + } else if (otherCharacters) { + // Simply output other characters + formattedString += otherCharacters; + } else if (patternLetters) { + // Replace pattern letters + var patternLetter = patternLetters.charAt(0); + var numberOfLetters = patternLetters.length; + var rawData = ""; + switch (patternLetter) { + case "G": + rawData = "AD"; + break; + case "y": + rawData = date.getFullYear(); + break; + case "M": + rawData = date.getMonth(); + break; + case "w": + rawData = date.getWeekInYear(this.getMinimalDaysInFirstWeek()); + break; + case "W": + rawData = date.getWeekInMonth(this.getMinimalDaysInFirstWeek()); + break; + case "D": + rawData = date.getDayInYear(); + break; + case "d": + rawData = date.getDate(); + break; + case "F": + rawData = 1 + Math.floor((date.getDate() - 1) / 7); + break; + case "E": + rawData = dayNames[date.getDay()]; + break; + case "a": + rawData = (date.getHours() >= 12) ? "PM" : "AM"; + break; + case "H": + rawData = date.getHours(); + break; + case "k": + rawData = date.getHours() || 24; + break; + case "K": + rawData = date.getHours() % 12; + break; + case "h": + rawData = (date.getHours() % 12) || 12; + break; + case "m": + rawData = date.getMinutes(); + break; + case "s": + rawData = date.getSeconds(); + break; + case "S": + rawData = date.getMilliseconds(); + break; + case "Z": + rawData = date.getTimezoneOffset(); // This is returns the number of minutes since GMT was this time. + break; + } + // Format the raw data depending on the type + switch (types[patternLetter]) { + case TEXT2: + formattedString += formatText(rawData, numberOfLetters, 2); + break; + case TEXT3: + formattedString += formatText(rawData, numberOfLetters, 3); + break; + case NUMBER: + formattedString += formatNumber(rawData, numberOfLetters); + break; + case YEAR: + if (numberOfLetters <= 3) { + // Output a 2-digit year + var dataString = "" + rawData; + formattedString += dataString.substr(2, 2); + } else { + formattedString += formatNumber(rawData, numberOfLetters); + } + break; + case MONTH: + if (numberOfLetters >= 3) { + formattedString += formatText(monthNames[rawData], numberOfLetters, numberOfLetters); + } else { + // NB. Months returned by getMonth are zero-based + formattedString += formatNumber(rawData + 1, numberOfLetters); + } + break; + case TIMEZONE: + var isPositive = (rawData > 0); + // The following line looks like a mistake but isn't + // because of the way getTimezoneOffset measures. + var prefix = isPositive ? "-" : "+"; + var absData = Math.abs(rawData); + + // Hours + var hours = "" + Math.floor(absData / 60); + hours = padWithZeroes(hours, 2); + // Minutes + var minutes = "" + (absData % 60); + minutes = padWithZeroes(minutes, 2); + + formattedString += prefix + hours + minutes; + break; + } + } + searchString = searchString.substr(result.index + result[0].length); + } + return formattedString; + }; +})(); -- 1.8.3.1