├── .babelrc ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── bower.json ├── bundle.map.json ├── demo ├── data.js ├── index.html ├── script.js └── style.css ├── package.json ├── scripts └── publish.sh ├── src ├── config.js ├── drawer │ ├── axes.js │ ├── context.js │ ├── drops.js │ ├── index.js │ ├── labels.js │ ├── line.js │ └── marker.js ├── filters │ └── index.js ├── timeline.js ├── xAxis.js └── zoom.js ├── style.css ├── test └── karma │ ├── drawer │ └── drops.js │ ├── karma.conf.js │ └── timeline.js ├── webpack.config.js └── webpack ├── entries.js └── plugins.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb/base", 3 | "rules": { 4 | "indent": [2, 4], 5 | "id-length": [2, { "min": 1 }] 6 | }, 7 | "env": { 8 | "jasmine": true 9 | }, 10 | "globals": { 11 | "d3": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "5" 4 | 5 | env: 6 | - CXX=g++-4.8 7 | 8 | addons: 9 | apt: 10 | sources: 11 | - ubuntu-toolchain-r-test 12 | packages: 13 | - g++-4.8 14 | 15 | before_install: 16 | - 'git checkout -B $TRAVIS_BRANCH' # Reconcile detached HEAD 17 | - 'if [[ `npm -v` != 3* ]]; then npm i -g npm@3; fi' 18 | 19 | script: 20 | - 'npm run build' 21 | - 'npm run test' 22 | 23 | after_success: 24 | - sh -x ./scripts/publish.sh -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 marmelab 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | patternfly-timeline 2 | ========== 3 | 4 | A time based/event series interactive visualization using d3.js. Use drag and zoom to navigate in time. [View the demo here.](https://rawgit.com/patternfly/patternfly-timeline/master-dist/demo/) 5 | 6 | Based on the [EventDrops](https://github.com/marmelab/EventDrops) timeline. 7 | ## Usage 8 | 9 | Include the `src/timeline.js` script in your page after d3: 10 | 11 | ```html 12 | 13 | 14 | ``` 15 | 16 | 17 | 18 | In the HTML source, create a new timeline chart, bind data to a DOM element, then call the chart on the element. **Important:** In order for the zoom slider to work correctly, the placeholder element must have `position: relative` or `position: absolute` styling. 19 | 20 | ```js 21 | var timelineChart = d3.chart.timeline(); 22 | d3.select('#chart_placeholder') 23 | .datum(data) 24 | .call(timelineChart); 25 | ``` 26 | 27 | The data must be an array of named time series with an optional details payload. For instance: 28 | 29 | ```js 30 | var json = [ 31 | { 32 | "name":"Power Activity", 33 | "data":[ 34 | {"date": "2016-04-08T15:07:37.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 35 | {"date": "2016-04-08T15:07:37.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 36 | {"date": "2016-04-15T21:04:16.247Z", "details": {"event": "vmPowerOn", "object": "vmName"}} 37 | ] 38 | }, 39 | { 40 | "name":"Alarm/Error", 41 | "data":[ 42 | {"date": "2016-04-21T01:06:19.126Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 43 | {"date": "2016-04-16T13:07:15.205Z", "details": {"event": "vmPowerOff", "object": "hostName"}}, 44 | {"date": "2016-04-07T22:35:41.145Z", "details": {"event": "vmPowerOff", "object": "hostName"}} 45 | ] 46 | } 47 | ]; 48 | ``` 49 | 50 | ## Configuration 51 | 52 | Patternfly-timeline follows the [d3.js reusable charts pattern](http://bost.ocks.org/mike/chart/) to let you customize the chart at will: 53 | 54 | ```js 55 | var timelineChart = d3.chart.timeline() 56 | .width(1200) 57 | .context(false) 58 | ``` 59 | 60 | Configurable values: 61 | 62 | - `start`: start date of the scale. Defaults to `new Date(0)`. 63 | - `end`: end date of the scale. Defaults to `new Date()` 64 | - `minScale`: The minimum scaling (zoom out), default to `0`. 65 | - `maxScale`: The maximum scaling (zoom in), default to `Infinity`. 66 | - `width`: width of the chart in pixels. Responsive by default. 67 | - `padding`: paddings of the graph in pixels. Defaults to `{ top: 30, left: 40, bottom: 40, right: 40 }` 68 | - `lineHeight`: The height of each row in the chart, default to `40`. 69 | - `contextHeight`: The height of the context viewport below the char, default to `50`. 70 | - `locale`: locale used for the X axis labels. See [d3.locale](https://github.com/mbostock/d3/wiki/Localization#locale) for the expected format. Defaults to `null` (i.e. d3 default locale). 71 | - `axisFormat`: function receiving the d3 axis object, to customize tick number and size. 72 | - `tickFormat`: tickFormat for the X axis. See [d3.timeFormat.multi()](https://github.com/mbostock/d3/wiki/Time-Formatting#format_multi) for expected format. 73 | - `eventHover`: function to be called when hovering an event in the chart. Receives the DOM element hovered (uses event delegation). 74 | - `eventZoom`: function to be called when done zooming on the chart. Receives the d3 scale at the end of the zoom. 75 | - `eventClick`: function to be called on click event of data-point (circle). Receives the DOM element hovered (uses event delegation). 76 | - `eventLineColor`: The color of the event line. Accepts a color (color name or `#ffffff` notation), or a function receiving the eventData and returning a color. 77 | - `eventColor`: The color of the event. Accepts a color (color name or `#ffffff` notation), or a function receiving the eventData and returning a color. Defaults to null. EventLineColor will be ignored if this is used. 78 | - `eventShape`: The shape of the event. Accepts unicode characters, including icon fonts. 79 | - `eventPopover`: The contents of the event's popover. 80 | - `marker`: `true` by default. Enable current time/date marker under mouse pointer. 81 | - `context`: `true` by default. Enable context viewport beneath chart. 82 | - `slider`: `true` by default. Enable zoom slider and buttons to right of chart. 83 | - `eventGrouping`: `60000`(one minute) by default. The number of milliseconds within which events will be considered to have happened at the same time. 84 | 85 | ## Styling 86 | 87 | You can style all elements of the chart in CSS. Check the source to see the available selectors. 88 | 89 | ## Extending / Development 90 | 91 | First, install the dependencies: 92 | 93 | ```sh 94 | npm install 95 | ``` 96 | 97 | For development purpose, you can use the following command: 98 | 99 | ``` sh 100 | npm start 101 | ``` 102 | 103 | It serves the demo at http://localhost:8080. 104 | 105 | When your changes are done, ensure that all tests pass with: 106 | 107 | ``` sh 108 | npm test 109 | ``` 110 | 111 | Finally, if everything is fine, you can rebuild the library using: 112 | 113 | ``` sh 114 | npm run build 115 | ``` 116 | 117 | ## License 118 | 119 | Patternfly Timeline is released under the MIT License 120 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "patternfly-timeline", 3 | "description": "A time based/event series interactive visualization using d3.js. Use drag and zoom to navigate in time.", 4 | "main": "dist/timeline.js", 5 | "version": "1.0.7", 6 | "authors": [ 7 | "Red Hat" 8 | ], 9 | "license": "MIT", 10 | "homepage": "https://github.com/patternfly/patternfly-timeline", 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /bundle.map.json: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bundle.js","sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","src/main.js","src/timeline.js","src/util/configurable.js","src/eventLine.js","src/delimiter.js","src/filterData.js"],"names":["timeline","require","define","amd","d3","chart","window","module","exports","configurable","eventLine","delimiter","defaultConfig","start","Date","end","width","padding","top","left","bottom","right","locale","axisFormat","tickFormat","d","getMilliseconds","getSeconds","getMinutes","getHours","getDay","getDate","getMonth","eventHover","hasDelimiter","hasTopAxis","hasBottomAxis","data","length","eventColor","config","eventDropGraph","selection","each","updateZoom","event","sourceEvent","toString","zoom","translate","scale","redraw","redrawDelimiter","svg","select","remove","append","classed","attr","graphWidth","call","xScale","dateFormat","timeFormat","time","format","drawXAxis","where","tickFormatData","forEach","item","tick","slice","push","multi","xAxis","axis","orient","y","parseInt","graphHeight","graph","size","height","graphBody","lines","selectAll","enter","yScale","name","style","exit","behavior","center","on","this","yDomain","yRange","index","domain","range","yAxisEl","yTick","curx","cury","zoomRect","clientX","clientY","el","document","elementFromPoint","tagName","x","ordinal","key","targetFunction","listeners","value","arguments","hasOwnProperty","filterData","text","count","dates","circle","limits","filteredData","boundary","min","max","datum"],"mappings":"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","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 10;\n },\n eventColor: 'black'\n };\n\n return function timeline(config) {\n var xScale = d3.time.scale();\n var yScale = d3.scale.ordinal();\n config = config || {};\n for (var key in defaultConfig) {\n config[key] = config[key] || defaultConfig[key];\n }\n\n function eventDropGraph(selection) {\n selection.each(function (data) {\n var zoom = d3.behavior.zoom().center(null).on(\"zoom\", updateZoom);\n\n if (config.hasDelimiter) {\n zoom.on(\"zoomend\", redrawDelimiter);\n }\n var graphWidth = config.width - config.padding.right - config.padding.left;\n var graphHeight = data.length * 40;\n var height = graphHeight + config.padding.top + config.padding.bottom;\n\n d3.select(this).select('svg').remove();\n\n var svg = d3.select(this)\n .append('svg')\n .attr('width', config.width)\n .attr('height', height)\n ;\n\n var graph = svg.append('g')\n .attr('transform', 'translate(0, 25)');\n\n var yDomain = [];\n var yRange = [];\n\n data.forEach(function (event, index) {\n yDomain.push(event.name);\n yRange.push(index * 40);\n });\n\n yScale.domain(yDomain).range(yRange);\n\n var yAxisEl = graph.append('g')\n .classed('y-axis', true)\n .attr('transform', 'translate(0, 60)');\n\n var yTick = yAxisEl.append('g').selectAll('g').data(yDomain);\n\n yTick.enter()\n .append('g')\n .attr('transform', function(d) {\n return 'translate(0, ' + yScale(d) + ')';\n })\n .append('line')\n .classed('y-tick', true)\n .attr('x1', config.padding.left)\n .attr('x2', config.padding.left + graphWidth);\n\n yTick.exit().remove();\n\n var curx, cury;\n var zoomRect = svg\n .append('rect')\n .call(zoom)\n .classed('zoom', true)\n .attr('width', graphWidth)\n .attr('height', height )\n .attr('transform', 'translate(' + config.padding.left + ', 35)')\n ;\n\n if (typeof config.eventHover === 'function') {\n zoomRect.on('mousemove', function(d, e) {\n var event = d3.event;\n if (curx == event.clientX && cury == event.clientY) return;\n curx = event.clientX;\n cury = event.clientY;\n zoomRect.attr('display', 'none');\n var el = document.elementFromPoint(d3.event.clientX, d3.event.clientY);\n zoomRect.attr('display', 'block');\n if (el.tagName !== 'circle') return;\n config.eventHover(el);\n });\n }\n\n xScale.range([0, graphWidth]).domain([config.start, config.end]);\n\n zoom.x(xScale);\n\n function updateZoom() {\n if (d3.event.sourceEvent.toString() === '[object MouseEvent]') {\n zoom.translate([d3.event.translate[0], 0]);\n }\n\n if (d3.event.sourceEvent.toString() === '[object WheelEvent]') {\n zoom.scale(d3.event.scale);\n }\n\n redraw();\n }\n\n function redrawDelimiter() {\n svg.select('.delimiter').remove();\n var delimiterEl = svg\n .append('g')\n .classed('delimiter', true)\n .attr('width', graphWidth)\n .attr('height', 10)\n .attr('transform', 'translate(' + config.padding.left + ', ' + (config.padding.top - 45) + ')')\n .call(delimiter({\n xScale: xScale,\n dateFormat: config.locale ? config.locale.timeFormat(\"%d %B %Y\") : d3.time.format(\"%d %B %Y\")\n }))\n ;\n }\n\n function drawXAxis(where) {\n\n // copy config.tickFormat because d3 format.multi edit its given tickFormat data\n var tickFormatData = [];\n\n config.tickFormat.forEach(function (item) {\n var tick = item.slice(0);\n tickFormatData.push(tick);\n });\n\n var tickFormat = config.locale ? config.locale.timeFormat.multi(tickFormatData) : d3.time.format.multi(tickFormatData);\n var xAxis = d3.svg.axis()\n .scale(xScale)\n .orient(where)\n .tickFormat(tickFormat);\n ;\n\n if (typeof config.axisFormat === 'function') {\n config.axisFormat(xAxis);\n }\n\n var y = (where == 'bottom' ? parseInt(graphHeight) : 0) + config.padding.top - 40;\n\n graph.select('.x-axis.' + where).remove();\n var xAxisEl = graph\n .append('g')\n .classed('x-axis', true)\n .classed(where, true)\n .attr('transform', 'translate(' + config.padding.left + ', ' + y + ')')\n .call(xAxis)\n ;\n }\n\n function redraw() {\n\n var hasTopAxis = typeof config.hasTopAxis === 'function' ? config.hasTopAxis(data) : config.hasTopAxis;\n if (hasTopAxis) {\n drawXAxis('top');\n }\n\n var hasBottomAxis = typeof config.hasBottomAxis === 'function' ? config.hasBottomAxis(data) : config.hasBottomAxis;\n if (hasBottomAxis) {\n drawXAxis('bottom');\n }\n\n zoom.size([config.width, height]);\n\n graph.select('.graph-body').remove();\n var graphBody = graph\n .append('g')\n .classed('graph-body', true)\n .attr('transform', 'translate(' + config.padding.left + ', ' + (config.padding.top - 15) + ')');\n\n var lines = graphBody.selectAll('g').data(data);\n\n lines.enter()\n .append('g')\n .classed('line', true)\n .attr('transform', function(d) {\n return 'translate(0,' + yScale(d.name) + ')';\n })\n .style('fill', config.eventColor)\n .call(eventLine({ xScale: xScale }))\n ;\n\n lines.exit().remove();\n }\n\n redraw();\n if (config.hasDelimiter) {\n redrawDelimiter();\n }\n });\n }\n\n configurable(eventDropGraph, config);\n\n return eventDropGraph;\n };\n};\n","module.exports = function configurable(targetFunction, config, listeners) {\n listeners = listeners || {};\n for (var item in config) {\n (function(item) {\n targetFunction[item] = function(value) {\n if (!arguments.length) return config[item];\n config[item] = value;\n if (listeners.hasOwnProperty(item)) {\n listeners[item](value);\n }\n\n return targetFunction;\n };\n })(item); // for doesn't create a closure, forcing it\n }\n};\n","\"use strict\";\n/* global require, module, d3 */\n\nvar configurable = require('./util/configurable');\nvar filterData = require('./filterData');\n\nvar defaultConfig = {\n xScale: null\n};\n\nmodule.exports = function (config) {\n\n config = config || {};\n for (var key in defaultConfig) {\n config[key] = config[key] || defaultConfig[key];\n }\n\n var eventLine = function eventLine(selection) {\n selection.each(function (data) {\n d3.select(this).selectAll('text').remove();\n\n d3.select(this).append('text')\n .text(function(d) {\n var count = filterData(d.dates, config.xScale).length;\n return d.name + (count > 0 ? ' (' + count + ')' : '');\n })\n .attr('text-anchor', 'end')\n .attr('transform', 'translate(-20)')\n .style('fill', 'black')\n ;\n\n d3.select(this).selectAll('circle').remove();\n\n var circle = d3.select(this).selectAll('circle')\n .data(function(d) {\n // filter value outside of range\n return filterData(d.dates, config.xScale);\n });\n\n circle.enter()\n .append('circle')\n .attr('cx', function(d) {\n return config.xScale(d);\n })\n .attr('cy', -5)\n .attr('r', 10)\n ;\n\n circle.exit().remove();\n\n });\n };\n\n configurable(eventLine, config);\n\n return eventLine;\n};\n","\"use strict\";\n/* global require, module, d3 */\n\nvar configurable = require('./util/configurable');\n\nvar defaultConfig = {\n xScale: null,\n dateFormat: null\n};\n\nmodule.exports = function (config) {\n\n config = config || {};\n for (var key in defaultConfig) {\n config[key] = config[key] || defaultConfig[key];\n }\n\n function delimiter(selection) {\n selection.each(function (data) {\n d3.select(this).selectAll('text').remove();\n\n var limits = config.xScale.domain();\n\n d3.select(this).append('text')\n .text(function () {\n\n return config.dateFormat(limits[0]);\n })\n .classed('start', true)\n ;\n\n d3.select(this).append('text')\n .text(function () {\n\n return config.dateFormat(limits[1]);\n })\n .attr('text-anchor', 'end')\n .attr('transform', 'translate(' + config.xScale.range()[1] + ')')\n .classed('end', true)\n ;\n });\n }\n\n configurable(delimiter, config);\n\n return delimiter;\n};\n","\"use strict\";\n/* global module */\n\nmodule.exports = function filterDate(data, scale) {\n data = data || [];\n var filteredData = [];\n var boundary = scale.range();\n var min = boundary[0];\n var max = boundary[1];\n data.forEach(function (datum) {\n var value = scale(datum);\n if (value < min || value > max) {\n return;\n }\n filteredData.push(datum);\n });\n\n return filteredData;\n};\n"]} 2 | -------------------------------------------------------------------------------- /demo/data.js: -------------------------------------------------------------------------------- 1 | var json = [ 2 | { 3 | "name":"Power Activity", 4 | "data":[ 5 | {"date": "2016-04-08T15:07:37.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 6 | {"date": "2016-04-08T15:07:37.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 7 | {"date": "2016-04-15T21:04:16.247Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 8 | {"date": "2016-04-22T09:39:26.155Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 9 | {"date": "2016-04-06T09:56:00.311Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 10 | {"date": "2016-04-28T02:49:19.957Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 11 | {"date": "2016-04-07T02:20:34.234Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 12 | {"date": "2016-04-16T09:46:14.901Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 13 | {"date": "2016-04-27T07:26:28.700Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 14 | {"date": "2016-04-16T17:40:33.439Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 15 | {"date": "2016-04-22T02:15:24.387Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 16 | {"date": "2016-05-02T17:59:06.134Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 17 | {"date": "2016-05-01T08:20:05.500Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 18 | {"date": "2016-05-02T11:38:00.112Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 19 | {"date": "2016-04-25T06:54:07.920Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 20 | {"date": "2016-04-06T13:06:38.328Z", "details": {"event": "vmPowerOff", "object": "hostName"}}, 21 | {"date": "2016-04-09T11:53:26.678Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 22 | {"date": "2016-04-03T01:09:27.405Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 23 | {"date": "2016-04-28T16:42:53.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 24 | {"date": "2016-04-05T23:49:26.308Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 25 | {"date": "2016-04-04T01:46:50.852Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 26 | {"date": "2016-04-06T18:29:16.542Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 27 | {"date": "2016-04-04T08:45:45.998Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 28 | {"date": "2016-04-27T18:56:10.822Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 29 | {"date": "2016-05-01T09:21:34.462Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 30 | {"date": "2016-04-13T00:39:22.679Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 31 | {"date": "2016-04-29T12:31:23.536Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 32 | {"date": "2016-04-16T19:26:19.408Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 33 | {"date": "2016-04-16T19:17:48.878Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 34 | {"date": "2016-04-03T13:35:23.846Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 35 | {"date": "2016-04-22T13:11:25.771Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 36 | {"date": "2016-04-05T11:56:44.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 37 | {"date": "2016-04-26T19:22:53.675Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 38 | {"date": "2016-04-22T00:01:05.057Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 39 | {"date": "2016-04-21T22:17:29.427Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 40 | {"date": "2016-04-06T09:23:30.735Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 41 | {"date": "2016-04-05T09:06:10.970Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 42 | {"date": "2016-04-13T06:46:48.832Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 43 | {"date": "2016-04-18T22:24:22.229Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 44 | {"date": "2016-04-04T07:33:23.064Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 45 | {"date": "2016-05-02T01:37:31.176Z", "details": {"event": "vmPowerOff", "object": "hostName"}} 46 | ] 47 | }, 48 | { 49 | "name":"Alarm/Error", 50 | "data":[ 51 | {"date": "2016-04-21T01:06:19.126Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 52 | {"date": "2016-04-16T13:07:15.205Z", "details": {"event": "This is a link", "object": "hostName"}}, 53 | {"date": "2016-04-30T20:02:25.693Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 54 | {"date": "2016-04-30T20:02:26.664Z", "details": {"event": "vmPowerUp", "object": "vmNorm"}}, 55 | {"date": "2016-04-30T20:02:27.627Z", "details": {"event": "vmPowerDown", "object": "vmGnome"}}, 56 | {"date": "2016-04-30T20:02:28.694Z", "details": {"event": "vmPowerIn", "object": "vmNone"}}, 57 | {"date": "2016-04-30T20:02:28.628Z", "details": {"event": "vmPowerOut", "object": "vmNoon"}}, 58 | {"date": "2016-04-30T20:02:29.618Z", "details": {"event": "vmPowerOutage", "object": "vmName"}}, 59 | {"date": "2016-04-30T20:02:25.693Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 60 | {"date": "2016-04-07T22:35:41.145Z", "details": {"event": "vmPowerOff", "object": "hostName"}} 61 | ] 62 | }, 63 | { 64 | "name":"Storage", 65 | "data":[ 66 | {"date": "2016-04-13T21:06:27.205Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 67 | {"date": "2016-04-13T05:48:37.174Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 68 | {"date": "2016-04-12T01:13:02.594Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 69 | {"date": "2016-04-03T12:30:24.813Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 70 | {"date": "2016-04-28T02:56:16.627Z", "details": {"event": "vmPowerOff", "object": "hostName"}}, 71 | {"date": "2016-04-03T20:42:55.008Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 72 | {"date": "2016-04-28T21:18:16.319Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 73 | {"date": "2016-04-24T00:49:22.314Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 74 | {"date": "2016-05-02T15:56:59.659Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 75 | {"date": "2016-04-07T10:32:05.466Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 76 | {"date": "2016-04-05T09:00:47.328Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 77 | {"date": "2016-04-20T16:28:46.861Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 78 | {"date": "2016-04-27T04:50:46.041Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 79 | {"date": "2016-04-16T05:32:26.241Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 80 | {"date": "2016-04-10T02:45:12.749Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 81 | {"date": "2016-04-20T20:15:58.904Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 82 | {"date": "2016-04-20T13:40:02.328Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 83 | {"date": "2016-04-18T12:58:45.645Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 84 | {"date": "2016-04-13T16:14:01.939Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 85 | {"date": "2016-04-11T14:00:17.371Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 86 | {"date": "2016-04-21T14:07:26.108Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 87 | {"date": "2016-04-15T14:04:45.937Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 88 | {"date": "2016-04-20T21:14:44.922Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 89 | {"date": "2016-04-07T23:35:58.435Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 90 | {"date": "2016-04-22T11:42:05.508Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 91 | {"date": "2016-04-12T14:41:34.224Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 92 | {"date": "2016-04-20T16:47:20.726Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 93 | {"date": "2016-04-10T18:22:19.052Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 94 | {"date": "2016-04-11T00:30:43.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 95 | {"date": "2016-04-15T19:08:40.581Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 96 | {"date": "2016-05-02T02:10:26.622Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 97 | {"date": "2016-04-12T11:41:48.869Z", "details": {"event": "vmPowerOff", "object": "hostName"}}, 98 | {"date": "2016-04-25T21:33:10.589Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 99 | {"date": "2016-04-20T13:01:34.038Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 100 | {"date": "2016-04-14T09:18:05.570Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 101 | {"date": "2016-04-19T09:48:19.709Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 102 | {"date": "2016-04-22T01:54:56.041Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 103 | {"date": "2016-04-24T15:45:19.787Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 104 | {"date": "2016-04-10T18:02:29.479Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 105 | {"date": "2016-04-07T01:57:38.033Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 106 | {"date": "2016-05-01T15:13:11.563Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 107 | {"date": "2016-04-21T05:45:24.835Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 108 | {"date": "2016-04-19T10:33:50.364Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 109 | {"date": "2016-04-20T15:35:33.712Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 110 | {"date": "2016-04-16T05:28:57.049Z", "details": {"event": "vmPowerOff", "object": "hostName"}}, 111 | {"date": "2016-04-18T02:51:23.469Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 112 | {"date": "2016-04-04T17:27:17.072Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 113 | {"date": "2016-04-15T12:57:09.793Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 114 | {"date": "2016-04-30T18:18:49.469Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 115 | {"date": "2016-04-27T21:25:49.676Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 116 | {"date": "2016-04-25T17:24:20.083Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 117 | {"date": "2016-04-06T00:44:34.012Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 118 | {"date": "2016-04-14T17:17:37.767Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 119 | {"date": "2016-04-20T00:39:49.944Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 120 | {"date": "2016-04-22T09:46:50.385Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 121 | {"date": "2016-04-08T22:21:42.485Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 122 | {"date": "2016-04-05T23:09:28.517Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 123 | {"date": "2016-04-05T01:44:47.189Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 124 | {"date": "2016-04-09T17:39:20.472Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 125 | {"date": "2016-04-23T12:30:57.622Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 126 | {"date": "2016-04-03T11:50:55.063Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 127 | {"date": "2016-04-21T19:21:25.933Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 128 | {"date": "2016-04-12T05:36:15.173Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 129 | {"date": "2016-04-02T20:14:22.691Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 130 | {"date": "2016-04-27T08:22:39.841Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 131 | {"date": "2016-04-11T00:01:38.733Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 132 | {"date": "2016-05-01T07:10:37.498Z", "details": {"event": "vmPowerOff", "object": "hostName"}}, 133 | {"date": "2016-04-13T03:12:28.206Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 134 | {"date": "2016-04-26T18:41:55.007Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 135 | {"date": "2016-04-18T21:56:30.547Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 136 | {"date": "2016-04-03T03:30:30.553Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 137 | {"date": "2016-04-08T05:06:20.615Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 138 | {"date": "2016-04-15T03:48:36.117Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 139 | {"date": "2016-04-21T09:56:03.914Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 140 | {"date": "2016-04-29T16:41:28.482Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 141 | {"date": "2016-04-05T05:32:02.416Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 142 | {"date": "2016-04-26T23:04:05.259Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 143 | {"date": "2016-04-26T23:20:31.241Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 144 | {"date": "2016-04-19T00:51:05.587Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 145 | {"date": "2016-04-09T07:51:52.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 146 | {"date": "2016-04-16T00:22:27.364Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 147 | {"date": "2016-04-27T18:38:23.804Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 148 | {"date": "2016-04-06T05:38:45.812Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 149 | {"date": "2016-04-11T16:50:42.233Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 150 | {"date": "2016-04-21T08:38:42.204Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 151 | {"date": "2016-04-08T10:28:46.149Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 152 | {"date": "2016-04-15T07:00:51.630Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 153 | {"date": "2016-04-07T15:16:17.303Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 154 | {"date": "2016-04-21T22:48:56.080Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 155 | {"date": "2016-04-15T12:59:07.148Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 156 | {"date": "2016-04-29T03:02:29.678Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 157 | {"date": "2016-04-06T09:56:53.814Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 158 | {"date": "2016-04-21T22:34:40.755Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 159 | {"date": "2016-04-28T14:29:19.874Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 160 | {"date": "2016-04-07T16:25:52.033Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 161 | {"date": "2016-04-30T06:08:12.663Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 162 | {"date": "2016-04-05T11:57:06.963Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 163 | {"date": "2016-04-07T06:05:57.970Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 164 | {"date": "2016-04-22T11:47:49.098Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 165 | {"date": "2016-04-30T06:12:33.073Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 166 | {"date": "2016-04-17T08:17:07.875Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 167 | {"date": "2016-04-03T16:05:04.803Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 168 | {"date": "2016-04-17T09:57:29.941Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 169 | {"date": "2016-04-27T00:19:33.632Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 170 | {"date": "2016-04-08T14:37:15.273Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 171 | {"date": "2016-04-15T00:44:17.868Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 172 | {"date": "2016-04-30T11:30:19.284Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 173 | {"date": "2016-04-29T09:58:38.471Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 174 | {"date": "2016-04-07T13:36:47.868Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 175 | {"date": "2016-04-18T21:20:07.209Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 176 | {"date": "2016-04-27T07:08:58.978Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 177 | {"date": "2016-04-09T14:25:48.869Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 178 | {"date": "2016-04-19T02:16:44.743Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 179 | {"date": "2016-04-14T15:58:12.574Z", "details": {"event": "vmPowerOn", "object": "vmName"}} 180 | ] 181 | }, 182 | { 183 | "name":"Network", 184 | "data":[ 185 | {"date": "2016-04-09T06:42:50.582Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 186 | {"date": "2016-04-22T21:02:05.862Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 187 | {"date": "2016-04-26T14:12:57.818Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 188 | {"date": "2016-04-04T05:50:13.526Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 189 | {"date": "2016-04-23T12:24:32.260Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 190 | {"date": "2016-04-23T19:50:49.191Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 191 | {"date": "2016-04-15T15:46:03.502Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 192 | {"date": "2016-04-11T03:38:07.292Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 193 | {"date": "2016-04-06T07:02:24.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 194 | {"date": "2016-04-17T00:39:49.275Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 195 | {"date": "2016-04-15T09:07:04.699Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 196 | {"date": "2016-04-11T19:07:21.330Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 197 | {"date": "2016-04-06T01:55:29.366Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 198 | {"date": "2016-04-07T23:51:24.755Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 199 | {"date": "2016-04-08T07:36:44.810Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 200 | {"date": "2016-04-11T17:13:39.874Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 201 | {"date": "2016-04-14T19:22:56.325Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 202 | {"date": "2016-04-18T05:33:52.666Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 203 | {"date": "2016-04-16T04:21:18.599Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 204 | {"date": "2016-04-24T22:15:55.925Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 205 | {"date": "2016-05-02T07:20:50.300Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 206 | {"date": "2016-04-13T02:32:00.741Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 207 | {"date": "2016-04-14T14:58:51.563Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 208 | {"date": "2016-04-12T07:00:10.308Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 209 | {"date": "2016-04-14T04:25:27.663Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 210 | {"date": "2016-04-06T12:21:28.742Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 211 | {"date": "2016-04-06T08:12:35.229Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 212 | {"date": "2016-04-22T13:01:01.073Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 213 | {"date": "2016-04-15T02:14:40.188Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 214 | {"date": "2016-04-19T08:55:48.568Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 215 | {"date": "2016-04-26T06:14:58.639Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 216 | {"date": "2016-04-12T01:50:00.954Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 217 | {"date": "2016-04-08T16:02:43.251Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 218 | {"date": "2016-04-28T02:11:53.283Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 219 | {"date": "2016-05-01T06:20:51.064Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 220 | {"date": "2016-04-08T07:36:11.607Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 221 | {"date": "2016-04-14T18:05:42.223Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 222 | {"date": "2016-05-02T10:10:56.179Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 223 | {"date": "2016-04-12T20:40:57.299Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 224 | {"date": "2016-04-25T18:39:01.018Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 225 | {"date": "2016-04-17T05:23:32.993Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 226 | {"date": "2016-05-01T01:30:42.800Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 227 | {"date": "2016-04-06T16:20:58.887Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 228 | {"date": "2016-04-17T15:47:34.932Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 229 | {"date": "2016-04-08T11:36:40.961Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 230 | {"date": "2016-05-01T10:56:36.822Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 231 | {"date": "2016-04-14T12:48:04.832Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 232 | {"date": "2016-04-27T06:01:14.175Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 233 | {"date": "2016-04-13T18:30:00.920Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 234 | {"date": "2016-04-08T12:21:20.616Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 235 | {"date": "2016-04-15T13:46:08.037Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 236 | {"date": "2016-04-09T06:07:34.036Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 237 | {"date": "2016-04-19T20:03:44.024Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 238 | {"date": "2016-05-01T17:47:49.481Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 239 | {"date": "2016-04-07T07:34:58.568Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 240 | {"date": "2016-04-26T10:01:43.668Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 241 | {"date": "2016-04-12T20:55:55.433Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 242 | {"date": "2016-04-22T03:20:55.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 243 | {"date": "2016-04-07T05:13:17.834Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 244 | {"date": "2016-04-25T22:04:50.316Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 245 | {"date": "2016-04-23T09:59:23.846Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 246 | {"date": "2016-04-26T09:41:56.447Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 247 | {"date": "2016-04-23T12:59:02.852Z", "details": {"event": "vmPowerOn", "object": "vmName"}} 248 | ] 249 | }, 250 | { 251 | "name":"Deletion/Removal", 252 | "data":[ 253 | {"date": "2016-04-10T02:47:22.214Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 254 | {"date": "2016-05-02T01:55:40.478Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 255 | {"date": "2016-04-10T15:23:35.542Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 256 | {"date": "2016-04-15T17:18:05.597Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 257 | {"date": "2016-04-09T17:03:28.422Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 258 | {"date": "2016-04-05T06:32:38.593Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 259 | {"date": "2016-04-03T22:53:24.855Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 260 | {"date": "2016-04-29T02:11:24.694Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 261 | {"date": "2016-04-16T11:10:06.399Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 262 | {"date": "2016-04-08T17:55:53.148Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 263 | {"date": "2016-04-24T03:49:00.715Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 264 | {"date": "2016-04-09T08:26:06.263Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 265 | {"date": "2016-04-26T16:38:56.212Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 266 | {"date": "2016-04-11T22:42:28.279Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 267 | {"date": "2016-04-05T22:53:05.869Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 268 | {"date": "2016-04-06T17:39:43.432Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 269 | {"date": "2016-04-14T16:18:47.626Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 270 | {"date": "2016-04-11T08:17:28.600Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 271 | {"date": "2016-04-26T14:51:42.827Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 272 | {"date": "2016-04-22T14:43:04.642Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 273 | {"date": "2016-04-05T09:04:53.266Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 274 | {"date": "2016-04-04T13:49:33.930Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 275 | {"date": "2016-04-16T08:34:21.318Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 276 | {"date": "2016-04-06T08:28:32.547Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 277 | {"date": "2016-04-05T08:40:44.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 278 | {"date": "2016-04-07T01:04:02.615Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 279 | {"date": "2016-04-18T12:56:25.362Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 280 | {"date": "2016-04-21T10:45:49.222Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 281 | {"date": "2016-04-24T05:51:51.814Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 282 | {"date": "2016-04-05T09:25:43.782Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 283 | {"date": "2016-04-17T06:37:18.457Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 284 | {"date": "2016-04-28T16:19:59.479Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 285 | {"date": "2016-04-19T03:33:38.645Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 286 | {"date": "2016-04-24T04:30:15.313Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 287 | {"date": "2016-05-02T00:22:36.669Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 288 | {"date": "2016-04-18T16:18:14.326Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 289 | {"date": "2016-04-12T05:42:08.066Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 290 | {"date": "2016-04-15T20:45:22.213Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 291 | {"date": "2016-04-24T04:46:24.524Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 292 | {"date": "2016-04-16T04:48:01.953Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 293 | {"date": "2016-04-05T12:09:29.733Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 294 | {"date": "2016-04-03T16:32:17.637Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 295 | {"date": "2016-04-22T19:55:34.269Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 296 | {"date": "2016-04-28T05:40:57.606Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 297 | {"date": "2016-04-15T09:06:34.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 298 | {"date": "2016-04-27T15:08:26.528Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 299 | {"date": "2016-04-03T12:54:13.001Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 300 | {"date": "2016-04-21T12:43:53.579Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 301 | {"date": "2016-04-08T10:08:28.031Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 302 | {"date": "2016-04-22T10:46:44.215Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 303 | {"date": "2016-04-27T19:13:50.013Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 304 | {"date": "2016-04-21T08:07:16.774Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 305 | {"date": "2016-04-28T06:27:08.958Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 306 | {"date": "2016-04-18T16:51:41.099Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 307 | {"date": "2016-04-07T22:08:26.738Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 308 | {"date": "2016-04-03T04:17:33.916Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 309 | {"date": "2016-04-12T14:34:33.613Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 310 | {"date": "2016-04-16T13:05:32.181Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 311 | {"date": "2016-05-02T17:16:58.639Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 312 | {"date": "2016-05-02T00:04:56.556Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 313 | {"date": "2016-04-12T03:56:51.858Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 314 | {"date": "2016-04-26T13:09:24.519Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 315 | {"date": "2016-04-11T04:59:59.431Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 316 | {"date": "2016-04-05T15:47:29.306Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 317 | {"date": "2016-04-10T20:53:13.603Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 318 | {"date": "2016-04-03T10:25:43.555Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 319 | {"date": "2016-04-13T19:33:26.080Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 320 | {"date": "2016-05-01T16:02:47.607Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 321 | {"date": "2016-05-02T00:37:50.533Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 322 | {"date": "2016-04-11T16:46:23.007Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 323 | {"date": "2016-04-23T23:45:03.144Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 324 | {"date": "2016-05-01T06:34:01.499Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 325 | {"date": "2016-04-04T13:10:33.387Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 326 | {"date": "2016-04-10T21:20:58.069Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 327 | {"date": "2016-04-24T03:36:22.763Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 328 | {"date": "2016-04-28T21:40:03.871Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 329 | {"date": "2016-04-28T17:24:16.746Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 330 | {"date": "2016-04-23T13:50:19.766Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 331 | {"date": "2016-04-07T06:29:55.698Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 332 | {"date": "2016-04-22T14:25:25.723Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 333 | {"date": "2016-04-22T23:01:24.415Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 334 | {"date": "2016-04-05T20:45:00.713Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 335 | {"date": "2016-04-09T10:39:26.159Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 336 | {"date": "2016-04-29T15:51:10.790Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 337 | {"date": "2016-04-14T08:02:59.526Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 338 | {"date": "2016-04-18T03:09:06.430Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 339 | {"date": "2016-04-12T10:29:43.571Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 340 | {"date": "2016-04-29T03:22:38.136Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 341 | {"date": "2016-04-30T02:51:20.347Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 342 | {"date": "2016-04-29T02:31:38.570Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 343 | {"date": "2016-04-13T00:22:12.390Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 344 | {"date": "2016-04-26T10:39:03.141Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 345 | {"date": "2016-04-11T10:23:30.005Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 346 | {"date": "2016-05-02T06:27:57.139Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 347 | {"date": "2016-04-27T16:52:35.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 348 | {"date": "2016-04-20T09:02:25.066Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 349 | {"date": "2016-04-08T02:04:42.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 350 | {"date": "2016-04-10T20:59:33.056Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 351 | {"date": "2016-04-08T23:37:41.471Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 352 | {"date": "2016-04-10T07:29:39.302Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 353 | {"date": "2016-04-03T10:17:00.476Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 354 | {"date": "2016-04-08T11:28:25.963Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 355 | {"date": "2016-04-14T18:46:17.142Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 356 | {"date": "2016-04-09T22:40:40.881Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 357 | {"date": "2016-04-14T16:48:32.946Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 358 | {"date": "2016-04-10T16:13:52.225Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 359 | {"date": "2016-04-26T06:59:57.293Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 360 | {"date": "2016-04-26T11:26:59.337Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 361 | {"date": "2016-04-23T04:13:26.267Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 362 | {"date": "2016-04-04T03:51:56.546Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 363 | {"date": "2016-04-13T05:58:37.851Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 364 | {"date": "2016-04-23T10:24:39.973Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 365 | {"date": "2016-04-11T15:17:31.364Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 366 | {"date": "2016-04-16T16:55:18.685Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 367 | {"date": "2016-05-01T02:03:49.953Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 368 | {"date": "2016-04-17T04:24:12.854Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 369 | {"date": "2016-04-16T11:56:47.852Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 370 | {"date": "2016-05-01T18:27:23.475Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 371 | {"date": "2016-04-17T02:20:25.994Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 372 | {"date": "2016-04-20T01:34:43.002Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 373 | {"date": "2016-04-14T17:24:46.776Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 374 | {"date": "2016-04-29T01:46:41.438Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 375 | {"date": "2016-04-21T21:09:56.366Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 376 | {"date": "2016-04-23T17:08:03.801Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 377 | {"date": "2016-04-18T14:00:20.959Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 378 | {"date": "2016-04-21T07:08:33.441Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 379 | {"date": "2016-04-06T16:32:51.049Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 380 | {"date": "2016-04-12T04:56:58.508Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 381 | {"date": "2016-04-07T12:59:45.464Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 382 | {"date": "2016-04-04T06:14:50.426Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 383 | {"date": "2016-04-09T11:44:50.749Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 384 | {"date": "2016-04-25T02:17:31.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 385 | {"date": "2016-04-13T17:30:48.817Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 386 | {"date": "2016-04-27T17:00:23.043Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 387 | {"date": "2016-05-01T17:44:45.574Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 388 | {"date": "2016-04-14T06:18:18.987Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 389 | {"date": "2016-04-12T22:34:13.804Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 390 | {"date": "2016-04-05T23:58:41.553Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 391 | {"date": "2016-04-21T04:24:44.700Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 392 | {"date": "2016-04-27T21:58:36.924Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 393 | {"date": "2016-04-21T20:22:16.145Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 394 | {"date": "2016-04-30T01:46:58.261Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 395 | {"date": "2016-04-22T21:34:26.861Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 396 | {"date": "2016-04-18T09:14:50.048Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 397 | {"date": "2016-04-29T08:10:50.184Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 398 | {"date": "2016-04-19T06:41:27.433Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 399 | {"date": "2016-04-08T00:23:17.796Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 400 | {"date": "2016-04-26T17:27:10.417Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 401 | {"date": "2016-04-16T10:33:14.549Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 402 | {"date": "2016-04-21T14:50:11.535Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 403 | {"date": "2016-04-24T12:15:11.307Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 404 | {"date": "2016-04-29T19:56:43.346Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 405 | {"date": "2016-04-21T18:58:43.241Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 406 | {"date": "2016-04-03T01:29:43.699Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 407 | {"date": "2016-04-04T12:29:41.538Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 408 | {"date": "2016-04-27T22:34:43.324Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 409 | {"date": "2016-04-26T15:54:55.926Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 410 | {"date": "2016-04-19T15:29:47.106Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 411 | {"date": "2016-04-10T00:39:47.385Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 412 | {"date": "2016-04-18T13:59:51.548Z", "details": {"event": "vmPowerOn", "object": "vmName"}} 413 | ] 414 | } 415 | , 416 | { 417 | "name":"Creation/Addition", 418 | "data":[ 419 | {"date": "2016-04-10T02:47:22.214Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 420 | {"date": "2016-05-02T01:55:40.478Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 421 | {"date": "2016-04-10T15:23:35.542Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 422 | {"date": "2016-04-15T17:18:05.597Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 423 | {"date": "2016-04-09T17:03:28.422Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 424 | {"date": "2016-04-05T06:32:38.593Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 425 | {"date": "2016-04-03T22:53:24.855Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 426 | {"date": "2016-04-29T02:11:24.694Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 427 | {"date": "2016-04-16T11:10:06.399Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 428 | {"date": "2016-04-08T17:55:53.148Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 429 | {"date": "2016-04-24T03:49:00.715Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 430 | {"date": "2016-04-09T08:26:06.263Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 431 | {"date": "2016-04-26T16:38:56.212Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 432 | {"date": "2016-04-11T22:42:28.279Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 433 | {"date": "2016-04-05T22:53:05.869Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 434 | {"date": "2016-04-06T17:39:43.432Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 435 | {"date": "2016-04-14T16:18:47.626Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 436 | {"date": "2016-04-11T08:17:28.600Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 437 | {"date": "2016-04-26T14:51:42.827Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 438 | {"date": "2016-04-22T14:43:04.642Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 439 | {"date": "2016-04-05T09:04:53.266Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 440 | {"date": "2016-04-04T13:49:33.930Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 441 | {"date": "2016-04-16T08:34:21.318Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 442 | {"date": "2016-04-06T08:28:32.547Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 443 | {"date": "2016-04-05T08:40:44.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 444 | {"date": "2016-04-07T01:04:02.615Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 445 | {"date": "2016-04-18T12:56:25.362Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 446 | {"date": "2016-04-21T10:45:49.222Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 447 | {"date": "2016-04-24T05:51:51.814Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 448 | {"date": "2016-04-05T09:25:43.782Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 449 | {"date": "2016-04-17T06:37:18.457Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 450 | {"date": "2016-04-28T16:19:59.479Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 451 | {"date": "2016-04-19T03:33:38.645Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 452 | {"date": "2016-04-24T04:30:15.313Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 453 | {"date": "2016-05-02T00:22:36.669Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 454 | {"date": "2016-04-18T16:18:14.326Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 455 | {"date": "2016-04-12T05:42:08.066Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 456 | {"date": "2016-04-15T20:45:22.213Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 457 | {"date": "2016-04-24T04:46:24.524Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 458 | {"date": "2016-04-16T04:48:01.953Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 459 | {"date": "2016-04-05T12:09:29.733Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 460 | {"date": "2016-04-03T16:32:17.637Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 461 | {"date": "2016-04-22T19:55:34.269Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 462 | {"date": "2016-04-28T05:40:57.606Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 463 | {"date": "2016-04-15T09:06:34.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 464 | {"date": "2016-04-27T15:08:26.528Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 465 | {"date": "2016-04-03T12:54:13.001Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 466 | {"date": "2016-04-21T12:43:53.579Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 467 | {"date": "2016-04-08T10:08:28.031Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 468 | {"date": "2016-04-22T10:46:44.215Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 469 | {"date": "2016-04-27T19:13:50.013Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 470 | {"date": "2016-04-21T08:07:16.774Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 471 | {"date": "2016-04-28T06:27:08.958Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 472 | {"date": "2016-04-18T16:51:41.099Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 473 | {"date": "2016-04-07T22:08:26.738Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 474 | {"date": "2016-04-03T04:17:33.916Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 475 | {"date": "2016-04-12T14:34:33.613Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 476 | {"date": "2016-04-16T13:05:32.181Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 477 | {"date": "2016-05-02T17:16:58.639Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 478 | {"date": "2016-05-02T00:04:56.556Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 479 | {"date": "2016-04-12T03:56:51.858Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 480 | {"date": "2016-04-26T13:09:24.519Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 481 | {"date": "2016-04-11T04:59:59.431Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 482 | {"date": "2016-04-05T15:47:29.306Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 483 | {"date": "2016-04-10T20:53:13.603Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 484 | {"date": "2016-04-03T10:25:43.555Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 485 | {"date": "2016-04-13T19:33:26.080Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 486 | {"date": "2016-05-01T16:02:47.607Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 487 | {"date": "2016-05-02T00:37:50.533Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 488 | {"date": "2016-04-11T16:46:23.007Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 489 | {"date": "2016-04-23T23:45:03.144Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 490 | {"date": "2016-05-01T06:34:01.499Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 491 | {"date": "2016-04-04T13:10:33.387Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 492 | {"date": "2016-04-10T21:20:58.069Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 493 | {"date": "2016-04-24T03:36:22.763Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 494 | {"date": "2016-04-28T21:40:03.871Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 495 | {"date": "2016-04-28T17:24:16.746Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 496 | {"date": "2016-04-23T13:50:19.766Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 497 | {"date": "2016-04-07T06:29:55.698Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 498 | {"date": "2016-04-22T14:25:25.723Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 499 | {"date": "2016-04-22T23:01:24.415Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 500 | {"date": "2016-04-05T20:45:00.713Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 501 | {"date": "2016-04-09T10:39:26.159Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 502 | {"date": "2016-04-29T15:51:10.790Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 503 | {"date": "2016-04-14T08:02:59.526Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 504 | {"date": "2016-04-18T03:09:06.430Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 505 | {"date": "2016-04-12T10:29:43.571Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 506 | {"date": "2016-04-29T03:22:38.136Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 507 | {"date": "2016-04-30T02:51:20.347Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 508 | {"date": "2016-04-29T02:31:38.570Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 509 | {"date": "2016-04-13T00:22:12.390Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 510 | {"date": "2016-04-26T10:39:03.141Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 511 | {"date": "2016-04-11T10:23:30.005Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 512 | {"date": "2016-05-02T06:27:57.139Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 513 | {"date": "2016-04-27T16:52:35.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 514 | {"date": "2016-04-20T09:02:25.066Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 515 | {"date": "2016-04-08T02:04:42.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 516 | {"date": "2016-04-10T20:59:33.056Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 517 | {"date": "2016-04-08T23:37:41.471Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 518 | {"date": "2016-04-10T07:29:39.302Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 519 | {"date": "2016-04-03T10:17:00.476Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 520 | {"date": "2016-04-08T11:28:25.963Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 521 | {"date": "2016-04-14T18:46:17.142Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 522 | {"date": "2016-04-09T22:40:40.881Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 523 | {"date": "2016-04-14T16:48:32.946Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 524 | {"date": "2016-04-10T16:13:52.225Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 525 | {"date": "2016-04-26T06:59:57.293Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 526 | {"date": "2016-04-26T11:26:59.337Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 527 | {"date": "2016-04-23T04:13:26.267Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 528 | {"date": "2016-04-04T03:51:56.546Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 529 | {"date": "2016-04-13T05:58:37.851Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 530 | {"date": "2016-04-23T10:24:39.973Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 531 | {"date": "2016-04-11T15:17:31.364Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 532 | {"date": "2016-04-16T16:55:18.685Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 533 | {"date": "2016-05-01T02:03:49.953Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 534 | {"date": "2016-04-17T04:24:12.854Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 535 | {"date": "2016-04-16T11:56:47.852Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 536 | {"date": "2016-05-01T18:27:23.475Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 537 | {"date": "2016-04-17T02:20:25.994Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 538 | {"date": "2016-04-20T01:34:43.002Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 539 | {"date": "2016-04-14T17:24:46.776Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 540 | {"date": "2016-04-29T01:46:41.438Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 541 | {"date": "2016-04-21T21:09:56.366Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 542 | {"date": "2016-04-23T17:08:03.801Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 543 | {"date": "2016-04-18T14:00:20.959Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 544 | {"date": "2016-04-21T07:08:33.441Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 545 | {"date": "2016-04-06T16:32:51.049Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 546 | {"date": "2016-04-12T04:56:58.508Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 547 | {"date": "2016-04-07T12:59:45.464Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 548 | {"date": "2016-04-04T06:14:50.426Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 549 | {"date": "2016-04-09T11:44:50.749Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 550 | {"date": "2016-04-25T02:17:31.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 551 | {"date": "2016-04-13T17:30:48.817Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 552 | {"date": "2016-04-27T17:00:23.043Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 553 | {"date": "2016-05-01T17:44:45.574Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 554 | {"date": "2016-04-14T06:18:18.987Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 555 | {"date": "2016-04-12T22:34:13.804Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 556 | {"date": "2016-04-05T23:58:41.553Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 557 | {"date": "2016-04-21T04:24:44.700Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 558 | {"date": "2016-04-27T21:58:36.924Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 559 | {"date": "2016-04-21T20:22:16.145Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 560 | {"date": "2016-04-30T01:46:58.261Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 561 | {"date": "2016-04-22T21:34:26.861Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 562 | {"date": "2016-04-18T09:14:50.048Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 563 | {"date": "2016-04-29T08:10:50.184Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 564 | {"date": "2016-04-19T06:41:27.433Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 565 | {"date": "2016-04-08T00:23:17.796Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 566 | {"date": "2016-04-26T17:27:10.417Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 567 | {"date": "2016-04-16T10:33:14.549Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 568 | {"date": "2016-04-21T14:50:11.535Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 569 | {"date": "2016-04-24T12:15:11.307Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 570 | {"date": "2016-04-29T19:56:43.346Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 571 | {"date": "2016-04-21T18:58:43.241Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 572 | {"date": "2016-04-03T01:29:43.699Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 573 | {"date": "2016-04-04T12:29:41.538Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 574 | {"date": "2016-04-27T22:34:43.324Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 575 | {"date": "2016-04-26T15:54:55.926Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 576 | {"date": "2016-04-19T15:29:47.106Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 577 | {"date": "2016-04-10T00:39:47.385Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 578 | {"date": "2016-04-18T13:59:51.548Z", "details": {"event": "vmPowerOn", "object": "vmName"}} 579 | ] 580 | }, 581 | { 582 | "name":"Migration/VMotion", 583 | "data":[ 584 | {"date": "2016-04-10T02:47:22.214Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 585 | {"date": "2016-05-02T01:55:40.478Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 586 | {"date": "2016-04-10T15:23:35.542Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 587 | {"date": "2016-04-15T17:18:05.597Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 588 | {"date": "2016-04-09T17:03:28.422Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 589 | {"date": "2016-04-05T06:32:38.593Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 590 | {"date": "2016-04-03T22:53:24.855Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 591 | {"date": "2016-04-29T02:11:24.694Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 592 | {"date": "2016-04-16T11:10:06.399Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 593 | {"date": "2016-04-08T17:55:53.148Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 594 | {"date": "2016-04-24T03:49:00.715Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 595 | {"date": "2016-04-09T08:26:06.263Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 596 | {"date": "2016-04-26T16:38:56.212Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 597 | {"date": "2016-04-11T22:42:28.279Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 598 | {"date": "2016-04-05T22:53:05.869Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 599 | {"date": "2016-04-06T17:39:43.432Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 600 | {"date": "2016-04-14T16:18:47.626Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 601 | {"date": "2016-04-11T08:17:28.600Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 602 | {"date": "2016-04-26T14:51:42.827Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 603 | {"date": "2016-04-22T14:43:04.642Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 604 | {"date": "2016-04-05T09:04:53.266Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 605 | {"date": "2016-04-04T13:49:33.930Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 606 | {"date": "2016-04-16T08:34:21.318Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 607 | {"date": "2016-04-06T08:28:32.547Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 608 | {"date": "2016-04-05T08:40:44.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 609 | {"date": "2016-04-07T01:04:02.615Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 610 | {"date": "2016-04-18T12:56:25.362Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 611 | {"date": "2016-04-21T10:45:49.222Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 612 | {"date": "2016-04-24T05:51:51.814Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 613 | {"date": "2016-04-05T09:25:43.782Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 614 | {"date": "2016-04-17T06:37:18.457Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 615 | {"date": "2016-04-28T16:19:59.479Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 616 | {"date": "2016-04-19T03:33:38.645Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 617 | {"date": "2016-04-24T04:30:15.313Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 618 | {"date": "2016-05-02T00:22:36.669Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 619 | {"date": "2016-04-18T16:18:14.326Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 620 | {"date": "2016-04-12T05:42:08.066Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 621 | {"date": "2016-04-15T20:45:22.213Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 622 | {"date": "2016-04-24T04:46:24.524Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 623 | {"date": "2016-04-16T04:48:01.953Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 624 | {"date": "2016-04-05T12:09:29.733Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 625 | {"date": "2016-04-03T16:32:17.637Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 626 | {"date": "2016-04-22T19:55:34.269Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 627 | {"date": "2016-04-28T05:40:57.606Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 628 | {"date": "2016-04-15T09:06:34.374Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 629 | {"date": "2016-04-27T15:08:26.528Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 630 | {"date": "2016-04-03T12:54:13.001Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 631 | {"date": "2016-04-21T12:43:53.579Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 632 | {"date": "2016-04-08T10:08:28.031Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 633 | {"date": "2016-04-22T10:46:44.215Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 634 | {"date": "2016-04-27T19:13:50.013Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 635 | {"date": "2016-04-21T08:07:16.774Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 636 | {"date": "2016-04-28T06:27:08.958Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 637 | {"date": "2016-04-18T16:51:41.099Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 638 | {"date": "2016-04-07T22:08:26.738Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 639 | {"date": "2016-04-03T04:17:33.916Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 640 | {"date": "2016-04-12T14:34:33.613Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 641 | {"date": "2016-04-16T13:05:32.181Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 642 | {"date": "2016-05-02T17:16:58.639Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 643 | {"date": "2016-05-02T00:04:56.556Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 644 | {"date": "2016-04-12T03:56:51.858Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 645 | {"date": "2016-04-26T13:09:24.519Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 646 | {"date": "2016-04-11T04:59:59.431Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 647 | {"date": "2016-04-05T15:47:29.306Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 648 | {"date": "2016-04-10T20:53:13.603Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 649 | {"date": "2016-04-03T10:25:43.555Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 650 | {"date": "2016-04-13T19:33:26.080Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 651 | {"date": "2016-05-01T16:02:47.607Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 652 | {"date": "2016-05-02T00:37:50.533Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 653 | {"date": "2016-04-11T16:46:23.007Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 654 | {"date": "2016-04-23T23:45:03.144Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 655 | {"date": "2016-05-01T06:34:01.499Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 656 | {"date": "2016-04-04T13:10:33.387Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 657 | {"date": "2016-04-10T21:20:58.069Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 658 | {"date": "2016-04-24T03:36:22.763Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 659 | {"date": "2016-04-28T21:40:03.871Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 660 | {"date": "2016-04-28T17:24:16.746Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 661 | {"date": "2016-04-23T13:50:19.766Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 662 | {"date": "2016-04-07T06:29:55.698Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 663 | {"date": "2016-04-22T14:25:25.723Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 664 | {"date": "2016-04-22T23:01:24.415Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 665 | {"date": "2016-04-05T20:45:00.713Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 666 | {"date": "2016-04-09T10:39:26.159Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 667 | {"date": "2016-04-29T15:51:10.790Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 668 | {"date": "2016-04-14T08:02:59.526Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 669 | {"date": "2016-04-18T03:09:06.430Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 670 | {"date": "2016-04-12T10:29:43.571Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 671 | {"date": "2016-04-29T03:22:38.136Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 672 | {"date": "2016-04-30T02:51:20.347Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 673 | {"date": "2016-04-29T02:31:38.570Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 674 | {"date": "2016-04-13T00:22:12.390Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 675 | {"date": "2016-04-26T10:39:03.141Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 676 | {"date": "2016-04-11T10:23:30.005Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 677 | {"date": "2016-05-02T06:27:57.139Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 678 | {"date": "2016-04-27T16:52:35.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 679 | {"date": "2016-04-20T09:02:25.066Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 680 | {"date": "2016-04-08T02:04:42.391Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 681 | {"date": "2016-04-10T20:59:33.056Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 682 | {"date": "2016-04-08T23:37:41.471Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 683 | {"date": "2016-04-10T07:29:39.302Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 684 | {"date": "2016-04-03T10:17:00.476Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 685 | {"date": "2016-04-08T11:28:25.963Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 686 | {"date": "2016-04-14T18:46:17.142Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 687 | {"date": "2016-04-09T22:40:40.881Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 688 | {"date": "2016-04-14T16:48:32.946Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 689 | {"date": "2016-04-10T16:13:52.225Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 690 | {"date": "2016-04-26T06:59:57.293Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 691 | {"date": "2016-04-26T11:26:59.337Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 692 | {"date": "2016-04-23T04:13:26.267Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 693 | {"date": "2016-04-04T03:51:56.546Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 694 | {"date": "2016-04-13T05:58:37.851Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 695 | {"date": "2016-04-23T10:24:39.973Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 696 | {"date": "2016-04-11T15:17:31.364Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 697 | {"date": "2016-04-16T16:55:18.685Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 698 | {"date": "2016-05-01T02:03:49.953Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 699 | {"date": "2016-04-17T04:24:12.854Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 700 | {"date": "2016-04-16T11:56:47.852Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 701 | {"date": "2016-05-01T18:27:23.475Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 702 | {"date": "2016-04-17T02:20:25.994Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 703 | {"date": "2016-04-20T01:34:43.002Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 704 | {"date": "2016-04-14T17:24:46.776Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 705 | {"date": "2016-04-29T01:46:41.438Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 706 | {"date": "2016-04-21T21:09:56.366Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 707 | {"date": "2016-04-23T17:08:03.801Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 708 | {"date": "2016-04-18T14:00:20.959Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 709 | {"date": "2016-04-21T07:08:33.441Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 710 | {"date": "2016-04-06T16:32:51.049Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 711 | {"date": "2016-04-12T04:56:58.508Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 712 | {"date": "2016-04-07T12:59:45.464Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 713 | {"date": "2016-04-04T06:14:50.426Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 714 | {"date": "2016-04-09T11:44:50.749Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 715 | {"date": "2016-04-25T02:17:31.150Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 716 | {"date": "2016-04-13T17:30:48.817Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 717 | {"date": "2016-04-27T17:00:23.043Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 718 | {"date": "2016-05-01T17:44:45.574Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 719 | {"date": "2016-04-14T06:18:18.987Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 720 | {"date": "2016-04-12T22:34:13.804Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 721 | {"date": "2016-04-05T23:58:41.553Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 722 | {"date": "2016-04-21T04:24:44.700Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 723 | {"date": "2016-04-27T21:58:36.924Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 724 | {"date": "2016-04-21T20:22:16.145Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 725 | {"date": "2016-04-30T01:46:58.261Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 726 | {"date": "2016-04-22T21:34:26.861Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 727 | {"date": "2016-04-18T09:14:50.048Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 728 | {"date": "2016-04-29T08:10:50.184Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 729 | {"date": "2016-04-19T06:41:27.433Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 730 | {"date": "2016-04-08T00:23:17.796Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 731 | {"date": "2016-04-26T17:27:10.417Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 732 | {"date": "2016-04-16T10:33:14.549Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 733 | {"date": "2016-04-21T14:50:11.535Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 734 | {"date": "2016-04-24T12:15:11.307Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 735 | {"date": "2016-04-29T19:56:43.346Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 736 | {"date": "2016-04-21T18:58:43.241Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 737 | {"date": "2016-04-03T01:29:43.699Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 738 | {"date": "2016-04-04T12:29:41.538Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 739 | {"date": "2016-04-27T22:34:43.324Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 740 | {"date": "2016-04-26T15:54:55.926Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 741 | {"date": "2016-04-19T15:29:47.106Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 742 | {"date": "2016-04-10T00:39:47.385Z", "details": {"event": "vmPowerOn", "object": "vmName"}}, 743 | {"date": "2016-04-18T13:59:51.548Z", "details": {"event": "vmPowerOn", "object": "vmName"}} 744 | ] 745 | } 746 | ] 747 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Patternfly timeline test page 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 1 week 26 | 27 | 28 | 29 | 1 hour 30 | 1 day 31 | 1 week 32 | 1 month 33 | 34 | 35 | 36 | 37 | ending 38 | 39 | 40 | 41 | centered on 42 | starting 43 | ending 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Reset Zoom 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /demo/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('[data-toggle="popover"]').popover({ 3 | 'container': '#pf-timeline', 4 | 'placement': 'top' 5 | }); 6 | }); 7 | 8 | $(document).on('click', '.drop', function () {$(this).popover('show'); }); 9 | 10 | $(document).on('click', '.grid', function () {$('[data-toggle="popover"]').popover('hide');}); 11 | 12 | const ONE_HOUR = 60 * 60 * 1000, 13 | ONE_DAY = 24 * ONE_HOUR, 14 | ONE_WEEK = 7 * ONE_DAY, 15 | ONE_MONTH = 30 * ONE_DAY, 16 | SIX_MONTHS = 6 * ONE_MONTH; 17 | 18 | var data = [], 19 | start = new Date('2016-04-02T20:14:22.691Z'), 20 | today = new Date('2016-05-02T17:59:06.134Z'); 21 | 22 | for (var x in json) { //json lives in external file for testing 23 | data[x] = {}; 24 | data[x].name = json[x].name; 25 | data[x].data = []; 26 | for (var y in json[x].data) { 27 | data[x].data.push({}); 28 | data[x].data[y].date = new Date(json[x].data[y].date); 29 | data[x].data[y].details = json[x].data[y].details; 30 | } 31 | $('#timeline-selectpicker').append("" + data[x].name + ""); 32 | data[x].display = true; 33 | } 34 | $('#timeline-selectpicker').selectpicker('selectAll'); 35 | 36 | var timeline = d3.chart.timeline() 37 | .end(today) 38 | .start(today - ONE_WEEK) 39 | .minScale(ONE_WEEK / ONE_MONTH) 40 | .maxScale(ONE_WEEK / ONE_HOUR) 41 | .eventClick(function(el) { 42 | var table = ''; 43 | if(el.hasOwnProperty("events")) { 44 | table = table + 'This is a group of ' + el.events.length + ' events starting on '+ el.date + ''; 45 | table = table + 'DateEventObject'; 46 | for (var i = 0; i < el.events.length; i++) { 47 | table = table + '' + el.events[i].date + ' '; 48 | for (var j in el.events[i].details) { 49 | table = table +' ' + el.events[i].details[j] + ' '; 50 | } 51 | table = table + ''; 52 | } 53 | table = table + ''; 54 | } else { 55 | table = table + 'Date: ' + el.date + ''; 56 | for (i in el.details) { 57 | table = table + i.charAt(0).toUpperCase() + i.slice(1) + ': ' + el.details[i] + ''; 58 | } 59 | } 60 | $('#legend').html(table); 61 | 62 | }); 63 | if(countNames(data) <= 0) { 64 | timeline.labelWidth(60); 65 | } 66 | 67 | 68 | 69 | var element = d3.select('#pf-timeline').append('div').datum(data.filter(function(eventGroup) { 70 | return eventGroup.display === true; 71 | })); 72 | timeline(element); 73 | 74 | $('#timeline-selectpicker').on('changed.bs.select', function(event, clickedIndex, newValue, oldValue) { 75 | data[clickedIndex].display = !data[clickedIndex].display; 76 | element.datum(data.filter(function(eventGroup) { 77 | return eventGroup.display === true; 78 | })); 79 | timeline(element); 80 | $('[data-toggle="popover"]').popover({ 81 | 'container': '#pf-timeline', 82 | 'placement': 'top' 83 | }); 84 | }); 85 | 86 | $(window).on('resize', function() { 87 | timeline(element); 88 | $('[data-toggle="popover"]').popover({ 89 | 'container': '#pf-timeline', 90 | 'placement': 'top' 91 | }); 92 | }); 93 | 94 | 95 | $('#datepicker').datepicker({ 96 | autoclose: true, 97 | todayBtn: "linked", 98 | todayHighlight: true 99 | }); 100 | 101 | $('#datepicker').datepicker('setDate', today); 102 | 103 | $('#datepicker').on('changeDate', zoomFilter); 104 | 105 | $( document.body ).on( 'click', '.dropdown-menu li', function( event ) { 106 | var $target = $( event.currentTarget ); 107 | $target.closest( '.dropdown' ) 108 | .find( '[data-bind="label"]' ).text( $target.text() ) 109 | .end() 110 | .children( '.dropdown-toggle' ).dropdown( 'toggle' ); 111 | 112 | zoomFilter(); 113 | 114 | return false; 115 | }); 116 | 117 | function countNames(data) { 118 | var count = 0; 119 | for (var i = 0; i < data.length; i++) { 120 | if (data[i].name !== undefined && data[i].name !=='') { 121 | count++; 122 | } 123 | } 124 | return count; 125 | } 126 | 127 | function zoomFilter() { 128 | var range = $('#range-dropdown').find('[data-bind="label"]' ).text(), 129 | position = $('#position-dropdown').find('[data-bind="label"]' ).text(), 130 | date = $('#datepicker').datepicker('getDate'), 131 | startDate, 132 | endDate; 133 | 134 | switch (range) { 135 | case '1 hour': 136 | range = ONE_HOUR; 137 | break; 138 | 139 | case '1 day': 140 | range = ONE_DAY; 141 | break; 142 | 143 | case '1 week': 144 | range = ONE_WEEK; 145 | break; 146 | 147 | case '1 month': 148 | range = ONE_MONTH; 149 | break; 150 | } 151 | switch (position) { 152 | case 'centered on': 153 | startDate = new Date(date.getTime() - range/2); 154 | endDate = new Date(date.getTime() + range/2); 155 | break; 156 | 157 | case 'starting': 158 | startDate = date; 159 | endDate = new Date(date.getTime() + range); 160 | break; 161 | 162 | case 'ending': 163 | startDate = new Date(date.getTime() - range); 164 | endDate = date; 165 | break; 166 | } 167 | timeline.Zoom.zoomFilter(startDate, endDate); 168 | } 169 | 170 | $('#reset-button').click(function() { 171 | timeline(element); 172 | $('[data-toggle="popover"]').popover({ 173 | 'container': '#pf-timeline', 174 | 'placement': 'top' 175 | }); 176 | }); 177 | -------------------------------------------------------------------------------- /demo/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | } 4 | 5 | #pf-timeline { 6 | width: 100%; 7 | margin-left: auto; 8 | margin-right: auto; 9 | position: relative; 10 | } 11 | 12 | #pf-timeline .popover { 13 | white-space: pre; 14 | max-width: none; 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "patternfly-timeline", 3 | "version": "1.0.7", 4 | "description": "A time based / event series interactive visualization using d3.js. Use drag and zoom to navigate in time.", 5 | "main": "dist/timeline.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/patternfly/patternfly-timeline" 9 | }, 10 | "dependencies": { 11 | "d3": "~3.5.17", 12 | "patternfly": "~3.25.0" 13 | }, 14 | "devDependencies": { 15 | "babel-core": "6.4.5", 16 | "babel-eslint": "^4.1.8", 17 | "babel-loader": "6.2.1", 18 | "babel-preset-es2015": "6.3.13", 19 | "babel-preset-stage-0": "^6.3.13", 20 | "bower": "^1.7.9", 21 | "configurable.js": "0.1.0", 22 | "css-loader": "0.19.0", 23 | "eslint": "1.6.0", 24 | "eslint-config-airbnb": "0.1.0", 25 | "extract-text-webpack-plugin": "1.0.1", 26 | "html-loader": "0.3.0", 27 | "html-webpack-plugin": "1.6.1", 28 | "jasmine-core": "2.4.1", 29 | "jsdom": "1.0.0-pre.6", 30 | "karma": "^0.13.19", 31 | "karma-firefox-launcher": "0.1.7", 32 | "karma-jasmine": "^0.3.6", 33 | "karma-phantomjs-launcher": "^1.0.1", 34 | "karma-webpack": "^1.7.0", 35 | "mocha": "1.21.4", 36 | "mocha-traceur": "2.1.0", 37 | "scss-loader": "0.0.1", 38 | "style-loader": "0.12.4", 39 | "webpack": "1.12.2", 40 | "webpack-dev-server": "1.11.0" 41 | }, 42 | "bugs": { 43 | "url": "https://github.com/cshinn/patternfly-timeline/issues" 44 | }, 45 | "homepage": "https://github.com/cshinn/patternfly-timeline", 46 | "directories": { 47 | "example": "example", 48 | "test": "test" 49 | }, 50 | "scripts": { 51 | "test": "karma start test/karma/karma.conf.js --single-run", 52 | "build": "webpack -p --optimize-minimize --optimize-occurence-order --optimize-dedupe --progress --devtool source-map", 53 | "start": "webpack-dev-server --colors --inline --devtool source-map --host=0.0.0.0" 54 | }, 55 | "author": "Chris Shinn (https://github.com/cshinn)", 56 | "license": "MIT" 57 | } 58 | -------------------------------------------------------------------------------- /scripts/publish.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | set -o errexit -o nounset 4 | 5 | if [ "$TRAVIS_REPO_SLUG" = "patternfly/patternfly-timeline" ] 6 | then 7 | echo "This build is running against patternfly/patternfly-timeline." 8 | if [ -z "$TRAVIS_TAG" -a "$TRAVIS_BRANCH" != "master" ] 9 | then 10 | echo "This commit was made against $TRAVIS_BRANCH and not the master or tag! Do not deploy!" 11 | exit 1 12 | fi 13 | fi 14 | 15 | # User info 16 | git config user.name "Admin" 17 | git config user.email "patternfly-build@redhat.com" 18 | git config --global push.default simple 19 | 20 | # Add upstream authentication token 21 | git remote add upstream https://$AUTH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git 22 | 23 | # Commit generated files 24 | git add dist --force 25 | git commit -m "Added files generated by Travis build" 26 | 27 | # Push to dist branch 28 | EXISTING=`git ls-remote --heads https://github.com/"$TRAVIS_REPO_SLUG".git "$TRAVIS_BRANCH"-dist` 29 | 30 | if [ -n "$EXISTING" ] 31 | then 32 | git fetch upstream $TRAVIS_BRANCH-dist:$TRAVIS_BRANCH-dist 33 | git checkout $TRAVIS_BRANCH-dist 34 | git merge -Xtheirs $TRAVIS_BRANCH --no-edit --ff 35 | git push upstream $TRAVIS_BRANCH-dist --force -v 36 | else 37 | git push upstream $TRAVIS_BRANCH:$TRAVIS_BRANCH-dist --force -v 38 | fi 39 | 40 | exit $? 41 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | 3 | const config = { 4 | start: new Date(0), 5 | end: new Date(), 6 | contextStart: null, 7 | contextEnd: null, 8 | minScale: 0, 9 | maxScale: Infinity, 10 | width: null, 11 | padding: { 12 | top: 30, //must be at least 24 for marker to display properly 13 | left: 40, 14 | bottom: 40, 15 | right: 40 16 | }, 17 | lineHeight: 40, 18 | labelWidth: 140, 19 | sliderWidth: 30, 20 | contextHeight: 50, 21 | locale: null, 22 | axisFormat: null, 23 | tickFormat: [ 24 | ['.%L', (d) => d.getMilliseconds()], 25 | [':%S', (d) => d.getSeconds()], 26 | ['%I:%M', (d) => d.getMinutes()], 27 | ['%I %p', (d) => d.getHours()], 28 | ['%b %d', (d) => d.getMonth() && d.getDate()], 29 | ['%b', (d) => d.getMonth()], 30 | ['%Y', () => true] 31 | ], 32 | eventHover: null, 33 | eventZoom: null, 34 | eventClick: null, 35 | eventLineColor: (d, i) => { 36 | switch (i % 5) { 37 | case 0: 38 | return "#00659c"; 39 | case 1: 40 | return "#0088ce"; 41 | case 2: 42 | return "#3f9c35"; 43 | case 3: 44 | return "#ec7a08"; 45 | case 4: 46 | return "#cc0000"; 47 | } 48 | }, 49 | eventColor: null, 50 | eventShape: (d) => { 51 | if(d.hasOwnProperty("events")) { 52 | return '\uf140'; 53 | } else { 54 | return '\uf111'; 55 | } 56 | }, 57 | eventPopover: (d) => { 58 | var popover = ''; 59 | if(d.hasOwnProperty("events")) { 60 | popover = `Group of ${d.events.length} events` 61 | } else { 62 | for (var i in d.details) { 63 | popover = popover + i.charAt(0).toUpperCase() + i.slice(1) + ': ' + d.details[i] + ''; 64 | } 65 | popover = popover + 'Date: ' + d.date; 66 | } 67 | return popover; 68 | }, 69 | marker: true, 70 | context: true, 71 | slider: true, 72 | eventGrouping: 60000, //one minute 73 | }; 74 | 75 | config.dateFormat = config.locale ? config.locale.timeFormat('%a %x %I:%M %p') : d3.time.format('%a %x %I:%M %p'); 76 | 77 | module.exports = config; 78 | -------------------------------------------------------------------------------- /src/drawer/axes.js: -------------------------------------------------------------------------------- 1 | import xAxis from '../xAxis'; 2 | 3 | export default (axesContainer, scales, configuration, dimensions) => data => { 4 | const axis = (scope, scale) => { 5 | const selection = axesContainer.selectAll(`.timeline-pf-x-axis.${scope}`).data([{}]); 6 | 7 | selection.enter() 8 | .append('g') 9 | .classed('timeline-pf-x-axis', true) 10 | .classed(scope, true) 11 | .call(xAxis(scale, configuration)) 12 | .attr('transform', `translate(0,${scope === 'focus' ? dimensions.height : dimensions.height + dimensions.ctxHeight + 40})`); 13 | 14 | selection.call(xAxis(scale, configuration, dimensions.width)); 15 | 16 | selection.exit().remove(); 17 | }; 18 | 19 | axis('focus', scales.x); 20 | 21 | if (configuration.context) { 22 | axis('context', scales.ctx); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/drawer/context.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | 3 | export default (svg, scales, dimensions, configuration, data) => { 4 | 5 | const contextContainer = svg.append("g") 6 | .classed('timeline-pf-context', true) 7 | .attr('width', dimensions.width) 8 | .attr('height', dimensions.ctxHeight) 9 | .attr('clip-path', 'url(#timeline-pf-context-brush-clipper)') 10 | .attr("transform", `translate(${configuration.padding.left + configuration.labelWidth},${configuration.padding.top + dimensions.height + 40})`); 11 | 12 | let counts = []; 13 | let roundTo = 3600000;//one hour 14 | let barWidth = Math.ceil((roundTo / (scales.ctx.domain()[1] - scales.ctx.domain()[0])) * dimensions.width); 15 | 16 | countEvents(data, roundTo, counts); 17 | counts.sort((a,b) => { 18 | if(a.date < b.date) { 19 | return -1; 20 | } 21 | if(a.date > b.date) { 22 | return 1; 23 | } 24 | return 0; 25 | }); 26 | scales.cty.domain([0, d3.max(counts, (d) => {return d.count;})]); 27 | 28 | contextContainer.selectAll(".timeline-pf-bar") 29 | .data(counts) 30 | .enter().append("rect") 31 | .attr("class", "timeline-pf-bar") 32 | .attr("x", d => {return scales.ctx(d.date); }) 33 | .attr("y", d => {return scales.cty(d.count); }) 34 | .attr("width", barWidth) 35 | .attr("height", d => { return dimensions.ctxHeight - scales.cty(d.count); }); 36 | 37 | contextContainer.append("g") 38 | .attr("class", "timeline-pf-brush"); 39 | 40 | }; 41 | 42 | function countEvents(data, toRoundTo, counts) { 43 | let temp = {}; 44 | for(let i in data) { 45 | for (let j in data[i].data) { 46 | let rounded = Math.floor(data[i].data[j].date / toRoundTo) * toRoundTo; 47 | temp[rounded] = temp[rounded] + 1 || 1; 48 | } 49 | } 50 | for(let k in temp) { 51 | let tempDate = new Date(); 52 | tempDate.setTime(+k); 53 | counts.push({'date': tempDate, 'count': temp[k]}); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /src/drawer/drops.js: -------------------------------------------------------------------------------- 1 | export default (svg, scales, configuration) => function dropsSelector(data) { 2 | const dropLines = svg.selectAll('.timeline-pf-drop-line').data(data); 3 | 4 | dropLines.enter() 5 | .append('g') 6 | .classed('timeline-pf-drop-line', true) 7 | .attr('transform', (d, idx) => `translate(0, ${scales.y(idx) + (configuration.lineHeight/2)})`) 8 | .attr('fill', configuration.eventLineColor); 9 | 10 | dropLines.each(function dropLineDraw(drop) { 11 | 12 | const drops = d3.select(this).selectAll('.timeline-pf-drop').data(drop.data); 13 | 14 | drops.attr('transform', (d) => `translate(${scales.x(d.date)})`); 15 | 16 | const shape = drops.enter() 17 | .append('text') 18 | .classed('timeline-pf-drop', true) 19 | .classed('timeline-pf-event-group', (d) => {return d.hasOwnProperty("events") ? true : false}) 20 | .attr('transform', (d) => `translate(${scales.x(d.date)})`) 21 | .attr('fill', configuration.eventColor) 22 | .attr('text-anchor', 'middle') 23 | .attr('data-toggle', 'popover') 24 | .attr('data-html', 'true') 25 | .attr('data-content', configuration.eventPopover) 26 | .attr('dominant-baseline', 'central') 27 | .text(configuration.eventShape); 28 | 29 | if (configuration.eventClick) { 30 | shape.on('click', configuration.eventClick); 31 | } 32 | 33 | if (configuration.eventHover) { 34 | shape.on('mouseover', configuration.eventHover); 35 | } 36 | 37 | // unregister previous event handlers to prevent from memory leaks 38 | drops.exit() 39 | .on('click', null) 40 | .on('mouseover', null); 41 | 42 | drops.exit().remove(); 43 | }); 44 | 45 | dropLines.exit().remove(); 46 | }; 47 | -------------------------------------------------------------------------------- /src/drawer/index.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | import axesFactory from './axes'; 3 | import dropsFactory from './drops'; 4 | import labelsFactory from './labels'; 5 | import markerFactory from './marker'; 6 | 7 | export default (svg, dimensions, scales, configuration) => { 8 | const defs = svg.append('defs'); 9 | defs.append('clipPath') 10 | .attr('id', 'timeline-pf-drops-container-clipper') 11 | .append('rect') 12 | .attr('id', 'timeline-pf-drops-container-rect') 13 | .attr('x', 0) 14 | .attr('y', 0) 15 | .attr('width', dimensions.width) 16 | .attr('height', dimensions.height); 17 | 18 | if(configuration.context) { 19 | defs.append('clipPath') 20 | .attr('id', 'timeline-pf-context-brush-clipper') 21 | .append('polygon') 22 | .attr('points', `0,0 ${dimensions.width},0 ${dimensions.width + configuration.sliderWidth},${dimensions.ctxHeight/2} ${dimensions.width},${dimensions.ctxHeight} 0,${dimensions.ctxHeight} ${-configuration.sliderWidth},${dimensions.ctxHeight/2}`); 23 | } 24 | 25 | const pattern = defs.append('pattern') 26 | .attr('class', 'timeline-pf-grid-stripes') 27 | .attr('id', 'timeline-pf-grid-stripes') 28 | .attr('width', dimensions.width) 29 | .attr('height', (configuration.lineHeight) * 2) 30 | .attr('patternUnits', 'userSpaceOnUse'); 31 | pattern.append('rect') 32 | .attr('width', dimensions.width) 33 | .attr('height', configuration.lineHeight); 34 | pattern.append('line') 35 | .attr('x1', 0) 36 | .attr('x2', dimensions.width) 37 | .attr('y1', configuration.lineHeight) 38 | .attr('y2', configuration.lineHeight); 39 | pattern.append('line') 40 | .attr('x1', 0) 41 | .attr('x2', dimensions.width) 42 | .attr('y1', '1px') 43 | .attr('y2', '1px'); 44 | 45 | const gridContainer = svg.append('g') 46 | .classed('timeline-pf-grid', true) 47 | .attr('fill', 'url(#timeline-pf-grid-stripes)') 48 | .attr('transform', `translate(${configuration.padding.left + configuration.labelWidth}, ${configuration.padding.top})`); 49 | 50 | const labelsContainer = svg.append('g') 51 | .classed('timeline-pf-labels', true) 52 | .attr('transform', `translate(${configuration.padding.left}, ${configuration.padding.top})`); 53 | 54 | const axesContainer = svg.append('g') 55 | .classed('timeline-pf-axes', true) 56 | .attr('transform', `translate(${configuration.padding.left + configuration.labelWidth}, ${configuration.padding.top})`); 57 | 58 | const dropsContainer = svg.append('g') 59 | .classed('timeline-pf-drops-container', true) 60 | .attr('clip-path', 'url(#timeline-pf-drops-container-clipper)') 61 | .attr('transform', `translate(${configuration.padding.left + configuration.labelWidth}, ${configuration.padding.top})`); 62 | 63 | if (configuration.marker) { 64 | const stampContainer = svg.append('g') 65 | .classed('timeline-pf-timestamp', true) 66 | .attr('height', 30) 67 | .attr('transform', `translate(${configuration.padding.left + configuration.labelWidth}, ${configuration.padding.top})`); 68 | 69 | markerFactory(gridContainer, stampContainer, scales, dimensions, configuration.dateFormat); 70 | } 71 | 72 | const axes = axesFactory(axesContainer, scales, configuration, dimensions); 73 | const labels = labelsFactory(labelsContainer, scales, configuration); 74 | const drops = dropsFactory(dropsContainer, scales, configuration); 75 | 76 | 77 | return data => { 78 | drops(data); 79 | labels(data); 80 | axes(data); 81 | }; 82 | }; 83 | -------------------------------------------------------------------------------- /src/drawer/labels.js: -------------------------------------------------------------------------------- 1 | export default (container, scales, config) => data => { 2 | const labels = container.selectAll('.timeline-pf-label').data(data); 3 | 4 | const countEvents = data => { 5 | let count = 0; 6 | for (let i = 0; i < data.length; i++) { 7 | if (data[i].hasOwnProperty("events")) { 8 | count += data[i].events.length; 9 | } else { 10 | count++; 11 | } 12 | } 13 | return count 14 | } 15 | const text = d => { 16 | const count = countEvents(d.data); 17 | if (d.name === undefined || d.name ===''){ 18 | return `${count} Events`; 19 | } 20 | return d.name + (count >= 0 ? ` (${count})` : ''); 21 | }; 22 | 23 | labels.text(text); 24 | 25 | labels.enter() 26 | .append('text') 27 | .classed('timeline-pf-label', true) 28 | .attr('transform', (d, idx) => `translate(${config.labelWidth - 20} ${scales.y(idx) + (config.lineHeight/2)})`) 29 | .attr('dominant-baseline', 'central') 30 | .attr('text-anchor', 'end') 31 | .text(text); 32 | 33 | labels.exit().remove(); 34 | }; 35 | -------------------------------------------------------------------------------- /src/drawer/line.js: -------------------------------------------------------------------------------- 1 | import { drops } from './drops'; 2 | import { labels } from './labels'; 3 | 4 | export const line = (svg, xScale, yScale, data, eventColor = '#000') => { 5 | let dropElements = svg.selectAll('g').data(data); 6 | 7 | dropElements.enter() 8 | .append('g') 9 | .classed('timeline-pf-line', true) 10 | .attr('transform', (d) => `translate(0, ${yScale(d.name)})`) 11 | .call(drops(xScale, eventColor)); 12 | 13 | dropElements.exit().remove(); 14 | }; 15 | -------------------------------------------------------------------------------- /src/drawer/marker.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | 3 | export default (gridContainer, stampContainer, scales, dimensions, dateFormat) => { 4 | gridContainer.append('rect') 5 | .attr('width', dimensions.width) 6 | .attr('height', dimensions.height) 7 | .on("mouseover", function() { 8 | marker.style("display", null); 9 | timeStamp.style("display", null); 10 | timeBox.style("display", null); 11 | }) 12 | .on("mouseout", function() { 13 | marker.style("display", "none"); 14 | timeStamp.style("display", "none"); 15 | timeBox.style("display", "none"); 16 | }) 17 | .on('mousemove', moveMarker); 18 | 19 | 20 | var marker = gridContainer.append('line') 21 | .classed('timeline-pf-marker', true) 22 | .attr('y1', 0) 23 | .attr('y2', dimensions.height); 24 | 25 | const domain = scales.x.domain(); 26 | 27 | var timeBox = stampContainer.append('rect') 28 | .attr('height', '24') 29 | .attr('width', '150') 30 | .style('display', 'none'); 31 | 32 | var timeStamp = stampContainer.append('text') 33 | .text(dateFormat(domain[1])) 34 | .attr('transform', `translate(${scales.x.range()[1]})`) 35 | .attr('text-anchor', 'middle'); 36 | 37 | function moveMarker() { 38 | var pos = d3.mouse(gridContainer[0][0])[0] 39 | marker.attr('transform', `translate(${pos})`); 40 | timeBox.attr('transform', `translate(${pos - 75}, -25)`); 41 | timeStamp.attr('transform', `translate(${pos}, -9)`) 42 | .text(dateFormat(scales.x.invert(pos))); 43 | 44 | } 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /src/filters/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patternfly/patternfly-timeline/7400c2ce27864d07c3f04e1f437e18c612c1012b/src/filters/index.js -------------------------------------------------------------------------------- /src/timeline.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | 3 | import configurable from 'configurable.js'; 4 | import defaultConfig from './config'; 5 | import drawer from './drawer'; 6 | import context from './drawer/context'; 7 | import Zoom from './zoom'; 8 | 9 | 10 | function timeline(config = {}) { 11 | const finalConfiguration = {...defaultConfig, ...config}; 12 | let zoomInstance = new Zoom(); 13 | 14 | const yScale = (data) => { 15 | return d3.scale.ordinal() 16 | .domain(data.map((d) => d.name)) 17 | .range(data.map((d, i) => i * finalConfiguration.lineHeight)); 18 | }; 19 | 20 | const xScale = (width, timeBounds) => { 21 | return d3.time.scale() 22 | .range([0, width]) 23 | .domain(timeBounds); 24 | }; 25 | 26 | function timelineGraph(selection) { 27 | selection.each(function selector(data) { 28 | 29 | let ungroupedData = data; 30 | data = groupEvents(data, finalConfiguration.eventGrouping); 31 | 32 | finalConfiguration.lineHeight = (data.length <= 3) ? 80 : 40; 33 | finalConfiguration.contextStart = finalConfiguration.contextStart || d3.min(getDates(data)); 34 | finalConfiguration.contextEnd = finalConfiguration.contextEnd || finalConfiguration.end; 35 | 36 | d3.select(this).select('.timeline-pf-chart').remove(); 37 | d3.select(this).selectAll('.timeline-pf-zoom').remove(); 38 | 39 | const SCALEHEIGHT = 40; 40 | let outer_width = finalConfiguration.width || selection.node().clientWidth; 41 | const height = data.length * finalConfiguration.lineHeight; 42 | 43 | const dimensions = { 44 | width: outer_width - finalConfiguration.padding.right - finalConfiguration.padding.left - finalConfiguration.labelWidth - ((finalConfiguration.slider) ? finalConfiguration.sliderWidth : 0), 45 | height, 46 | ctxHeight: finalConfiguration.contextHeight, 47 | outer_height: height + finalConfiguration.padding.top + finalConfiguration.padding.bottom + ((finalConfiguration.context) ? finalConfiguration.contextHeight + SCALEHEIGHT: 0) 48 | }; 49 | const scales = { 50 | x: xScale(dimensions.width, [finalConfiguration.start, finalConfiguration.end]), 51 | y: yScale(data), 52 | ctx: xScale(dimensions.width, [finalConfiguration.contextStart, finalConfiguration.contextEnd]), 53 | cty: d3.scale.linear().range([dimensions.ctxHeight, 0]) 54 | }; 55 | 56 | const svg = d3.select(this).append('svg') 57 | .classed('timeline-pf-chart', true) 58 | .attr({ 59 | width: outer_width, 60 | height: dimensions.outer_height, 61 | }); 62 | const draw = drawer(svg, dimensions, scales, finalConfiguration).bind(selection); 63 | 64 | draw(data); 65 | 66 | if (finalConfiguration.context) { 67 | context(svg, scales, dimensions, finalConfiguration, ungroupedData); 68 | } 69 | 70 | zoomInstance.updateZoom(d3.select(this), dimensions, scales, finalConfiguration, data, draw); 71 | 72 | }); 73 | } 74 | 75 | configurable(timelineGraph, finalConfiguration); 76 | timelineGraph.Zoom = zoomInstance; 77 | return timelineGraph; 78 | } 79 | 80 | d3.chart = d3.chart || {}; 81 | d3.chart.timeline = timeline; 82 | 83 | module.exports = timeline; 84 | 85 | function getDates(data) { 86 | let toReturn = []; 87 | for (let i = 0; i < data.length; i++){ 88 | for (let j = 0; j < data[i].data.length; j++){ 89 | toReturn.push(data[i].data[j].date); 90 | } 91 | } 92 | return toReturn; 93 | } 94 | 95 | function groupEvents(data, toRoundTo) { 96 | let rounded, 97 | temp = {}, 98 | toReturn = []; 99 | 100 | for (let i = 0; i < data.length; i++) { 101 | toReturn[i] = {}; 102 | toReturn[i].name = data[i].name; 103 | toReturn[i].data = []; 104 | for (let j = 0; j < data[i].data.length; j++) { 105 | rounded = Math.round(data[i].data[j].date / toRoundTo) * toRoundTo; 106 | if (temp[rounded] === undefined) { 107 | temp[rounded] = []; 108 | } 109 | temp[rounded].push(data[i].data[j]); 110 | } 111 | for (let k in temp) { 112 | if (temp[k].length === 1) { 113 | toReturn[i].data.push(temp[k][0]); 114 | } else { 115 | let tempDate = new Date(); 116 | tempDate.setTime(+k); 117 | toReturn[i].data.push({'date': tempDate,'events': temp[k]}); 118 | } 119 | } 120 | temp = {}; 121 | } 122 | return toReturn; 123 | } 124 | -------------------------------------------------------------------------------- /src/xAxis.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | 3 | export default function(xScale, configuration, width) { 4 | const tickFormatData = configuration.tickFormat.map(t => t.slice(0)); 5 | const tickFormat = configuration.locale ? configuration.locale.timeFormat.multi(tickFormatData) : d3.time.format.multi(tickFormatData); 6 | let numTicks = Math.round(width / 70); 7 | const axis = d3.svg.axis() 8 | .scale(xScale) 9 | .orient('bottom') 10 | .ticks(numTicks) 11 | .tickFormat(tickFormat); 12 | 13 | if (typeof configuration.axisFormat === 'function') { 14 | configuration.axisFormat(axis); 15 | } 16 | 17 | return axis; 18 | } 19 | -------------------------------------------------------------------------------- /src/zoom.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3'; 2 | 3 | export default class zoom { 4 | 5 | constructor() { 6 | } 7 | 8 | updateZoom(container, dimensions, scales, configuration, data, callback) { 9 | this.ONE_MINUTE = 60 * 1000; 10 | this.ONE_HOUR = this.ONE_MINUTE * 60; 11 | this.ONE_DAY = this.ONE_HOUR * 24; 12 | this.ONE_WEEK = this.ONE_DAY * 7; 13 | this.ONE_MONTH = this.ONE_DAY * 30; 14 | 15 | this.grid = d3.select('.timeline-pf-grid'); 16 | this.dimensions = dimensions; 17 | this.scales = scales; 18 | this.configuration = configuration; 19 | this.data = data; 20 | this.callback = callback; 21 | this.sliderScale = d3.scale.log() 22 | .domain([configuration.minScale, configuration.maxScale]) 23 | .range([configuration.minScale, configuration.maxScale]) 24 | .base(2); 25 | this.zoom = d3.behavior.zoom() 26 | .size([dimensions.width, dimensions.height]) 27 | .scaleExtent([configuration.minScale, configuration.maxScale]) 28 | .x(scales.x); 29 | this.brush = null; 30 | 31 | if (configuration.slider) { 32 | const zoomIn = container.append('button') 33 | .attr('type', 'button') 34 | .attr('class', 'btn btn-default timeline-pf-zoom timeline-pf-zoom-in') 35 | .attr('id', 'timeline-pf-zoom-in') 36 | .style('top', `${configuration.padding.top}px`) 37 | .on('click', () => {this.zoomClick()}); 38 | zoomIn 39 | .style('left', `${configuration.padding.left + configuration.labelWidth + dimensions.width + (configuration.sliderWidth - zoomIn.node().offsetWidth)}px`) 40 | .append('i') 41 | .attr('class', 'fa fa-plus') 42 | .attr('id', 'timeline-pf-zoom-in-icon'); 43 | 44 | const zoomOut = container.append('button') 45 | .attr('type', 'button') 46 | .attr('class', 'btn btn-default timeline-pf-zoom') 47 | .attr('id', 'timeline-pf-zoom-out') 48 | .style('top', `${configuration.padding.top + dimensions.height - 26}px`) 49 | .on('click', () => {this.zoomClick()}); 50 | zoomOut 51 | .style('left', `${configuration.padding.left + configuration.labelWidth + dimensions.width + (configuration.sliderWidth - zoomOut.node().offsetWidth)}px`) 52 | .append('i') 53 | .attr('class', 'fa fa-minus') 54 | .attr('id', 'timeline-pf-zoom-out-icon'); 55 | 56 | const zoomSlider = container.append('input') 57 | .attr('type', 'range') 58 | .attr('class', 'timeline-pf-zoom timeline-pf-slider') 59 | .attr('id', 'timeline-pf-slider') 60 | .style('width', `${dimensions.height - (zoomIn.node().offsetHeight * 2)}px`) 61 | .attr('value', this.sliderScale(this.zoom.scale())) 62 | .attr('min', configuration.minScale) 63 | .attr('max', configuration.maxScale) 64 | .attr('step', 0.1) 65 | .on('input', () => {this.zoomClick()}) 66 | .on('change', () => {this.zoomClick()}); 67 | zoomSlider 68 | .style('top', `${configuration.padding.top + ((dimensions.height - (zoomIn.node().offsetHeight) * 2) / 2) + zoomIn.node().offsetHeight - (zoomSlider.node().offsetHeight / 2)}px`) 69 | .style('left', `${configuration.padding.left + configuration.labelWidth + dimensions.width + 70 | configuration.sliderWidth - ((zoomIn.node().offsetWidth - zoomSlider.node().offsetHeight) / 2) - (zoomSlider.node().offsetWidth / 2)}px`); 71 | } 72 | 73 | if(configuration.context) { 74 | this.brush = d3.svg.brush() 75 | .x(scales.ctx) 76 | .extent(scales.x.domain()) 77 | .on("brush", () => {this.brushed()}); 78 | 79 | container.select('.timeline-pf-brush') 80 | .call(this.brush) 81 | .selectAll("rect") 82 | .attr("height", dimensions.ctxHeight); 83 | } 84 | 85 | 86 | if (configuration.eventZoom) { 87 | this.zoom.on('zoomend', configuration.eventZoom); 88 | } 89 | 90 | this.zoom.on('zoom', () => { 91 | requestAnimationFrame(() => callback(data)); 92 | if(configuration.slider) { 93 | container.select('#timeline-pf-slider').property('value', this.sliderScale(this.zoom.scale())); 94 | } 95 | if(configuration.context) { 96 | this.brush.extent(this.scales.x.domain()); 97 | container.select('.timeline-pf-brush').call(this.brush); 98 | } 99 | }); 100 | return this.grid.call(this.zoom) 101 | .on("dblclick.zoom", null); 102 | } 103 | 104 | brushed() { 105 | if(this.brush.empty() !== true) { 106 | let extent = this.brush.extent(); 107 | this.zoomFilter(extent[0], extent[1], 0); 108 | } 109 | } 110 | 111 | zoomClick() { 112 | let factor = 0.5, 113 | target_zoom = 1, 114 | duration = 0, 115 | center = this.dimensions.width / 2, 116 | extent = this.zoom.scaleExtent(), 117 | translate0, 118 | l, 119 | view = { 120 | x: this.zoom.translate()[0], 121 | k: this.zoom.scale() 122 | }; 123 | switch (d3.event.target.id) { 124 | case 'timeline-pf-zoom-in-icon': 125 | case 'timeline-pf-zoom-in': 126 | target_zoom = this.zoom.scale() * (1 + factor); 127 | duration = 100; 128 | break; 129 | case 'timeline-pf-zoom-out-icon': 130 | case 'timeline-pf-zoom-out': 131 | target_zoom = this.zoom.scale() * (1 + factor * -1); 132 | duration = 100; 133 | break; 134 | case 'timeline-pf-slider': 135 | target_zoom = this.sliderScale.invert(d3.event.target.value); 136 | break; 137 | default: 138 | target_zoom = this.zoom.scale(); 139 | } 140 | 141 | if (target_zoom < extent[0]) { 142 | target_zoom = extent[0]; 143 | } else if (target_zoom > extent[1]) { 144 | target_zoom = extent[1]; 145 | } 146 | 147 | translate0 = (center - view.x) / view.k; 148 | view.k = target_zoom; 149 | l = translate0 * view.k + view.x; 150 | 151 | view.x += center - l; 152 | this.interpolateZoom([view.x, 0], view.k, duration); 153 | } 154 | 155 | interpolateZoom(translate, scale, duration) { 156 | return d3.transition().duration(duration).tween("zoom", () => { 157 | if(this.zoom) { 158 | let iTranslate = d3.interpolate(this.zoom.translate(), translate), 159 | iScale = d3.interpolate(this.zoom.scale(), scale); 160 | return (t) => { 161 | this.zoom 162 | .scale(iScale(t)) 163 | .translate(iTranslate(t)); 164 | this.zoom.event(this.grid); 165 | }; 166 | } 167 | }); 168 | } 169 | 170 | getRange(Extent) { 171 | return Extent[1].getTime() - Extent[0].getTime(); 172 | } 173 | 174 | getScale(oldRange, newRange) { 175 | return oldRange / newRange; 176 | } 177 | 178 | zoomFilter(fromTime, toTime, duration = 100) { 179 | let range = toTime - fromTime, 180 | width = this.dimensions.width, 181 | extent = this.zoom.scaleExtent(), 182 | translate = this.zoom.translate()[0], 183 | curZoom = this.zoom.scale(), 184 | target_zoom = this.zoom.scale(), 185 | cur_width = this.getRange(this.scales.x.domain()), 186 | startDiff; 187 | 188 | target_zoom = target_zoom * this.getScale(this.getRange(this.scales.x.domain()), range); // new scale is ratio between old and new date ranges 189 | 190 | if (target_zoom < extent[0]) { 191 | target_zoom = extent[0]; 192 | } else if (target_zoom > extent[1]) { 193 | target_zoom = extent[1]; 194 | } 195 | 196 | startDiff = (this.scales.x.domain()[0] - fromTime) * (width / cur_width); // difference between leftmost dates in px 197 | 198 | translate += startDiff; 199 | 200 | translate = translate * (target_zoom / curZoom); // scale translate value (in px) to new zoom scale 201 | 202 | this.interpolateZoom([translate, 0], target_zoom, duration) 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .timeline-pf-zoom-area { 2 | cursor: pointer; 3 | fill: transparent; 4 | } 5 | 6 | .timeline-pf-y-tick { 7 | fill: none; 8 | stroke: black; 9 | stroke-width: 1px; 10 | } 11 | 12 | .timeline-pf-axes { 13 | fill: #fafafa; 14 | } 15 | 16 | .timeline-pf-x-axis { 17 | fill: none; 18 | position: absolute; 19 | shape-rendering: crispEdges; 20 | stroke: #d1d1d1; 21 | stroke-width: 1px; 22 | z-index: 50; 23 | } 24 | 25 | .timeline-pf-x-axis text { 26 | fill: black; 27 | font-family: 'Open Sans'; 28 | font-size: 12px; 29 | stroke: none; 30 | } 31 | 32 | .timeline-pf-label { 33 | font-weight: 400; 34 | } 35 | 36 | text.timeline-pf-drop { 37 | cursor: pointer; 38 | font-family: 'FontAwesome'; 39 | font-size: 10px; 40 | opacity: .7; 41 | stroke: none; 42 | text-rendering: auto; 43 | } 44 | 45 | text.timeline-pf-drop:hover { 46 | font-size: 21px; 47 | font-weight: bold; 48 | paint-order: stroke; 49 | } 50 | 51 | text.timeline-pf-event-group { 52 | font-size: 18px; 53 | } 54 | 55 | .timeline-pf-grid { 56 | cursor: all-scroll; 57 | shape-rendering: crispEdges; 58 | stroke: #d1d1d1; 59 | } 60 | 61 | .timeline-pf-graph-body .timeline-pf-line { 62 | height: 20px; 63 | padding: 10px; 64 | } 65 | 66 | .timeline-pf-timestamp text { 67 | fill: #fff; 68 | } 69 | 70 | .timeline-pf-timestamp rect { 71 | fill: #000; 72 | opacity: .7; 73 | } 74 | 75 | .timeline-pf-marker { 76 | pointer-events: none; 77 | } 78 | 79 | .timeline-pf-brush .extent { 80 | fill: #0088ce; 81 | fill-opacity: .25; 82 | shape-rendering: crispEdges; 83 | stroke: none; 84 | } 85 | 86 | .timeline-pf-graph-body .timeline-pf-line { 87 | height: 20px; 88 | padding: 10px; 89 | } 90 | 91 | .timeline-pf-zoom { 92 | position:absolute; 93 | } 94 | 95 | .timeline-pf-context .timeline-pf-bar { 96 | fill: #bbbbbb; 97 | shape-rendering: crispEdges; 98 | } 99 | 100 | .timeline-pf-slider { 101 | padding: 0; 102 | -webkit-transform: rotate(-90deg); 103 | transform: rotate(-90deg); 104 | } 105 | 106 | .timeline-pf-grid-stripes rect { 107 | fill: #fafafa; 108 | shape-rendering: crispEdges; 109 | } 110 | 111 | .timeline-pf-grid-stripes line { 112 | shape-rendering: crispEdges; 113 | stroke: #d1d1d1; 114 | stroke-width: 1px; 115 | } 116 | -------------------------------------------------------------------------------- /test/karma/drawer/drops.js: -------------------------------------------------------------------------------- 1 | describe('Drops drawer', () => { 2 | let wrapper; 3 | beforeEach(() => { 4 | wrapper = document.createElement('div'); 5 | document.body.appendChild(wrapper); 6 | }); 7 | 8 | it('should add click handler if specified in configuration', () => { 9 | const data = [{ name: 'foo', data: [{date: new Date('2014-04-03')}] }]; 10 | 11 | const clickSpy = jasmine.createSpy(); 12 | const chart = d3.chart.timeline().eventClick(clickSpy); 13 | d3.select(wrapper).datum(data).call(chart); 14 | 15 | const drop = d3.select('.timeline-pf-drop'); 16 | 17 | const event = document.createEvent('UIEvents'); 18 | event.initUIEvent('click', true, true, null, null); 19 | drop.node().dispatchEvent(event); 20 | 21 | expect(clickSpy.calls.any()).toBe(true); 22 | }); 23 | 24 | it('should add hover handler if specified in configuration', () => { 25 | const data = [{ name: 'foo', data: [{date: new Date('2014-04-03')}] }]; 26 | 27 | const hoverSpy = jasmine.createSpy(); 28 | const chart = d3.chart.timeline().eventHover(hoverSpy); 29 | d3.select(wrapper).datum(data).call(chart); 30 | 31 | const drop = d3.select('.timeline-pf-drop'); 32 | 33 | const event = document.createEvent('UIEvents'); 34 | event.initUIEvent('mouseover', true, true, null, null); 35 | drop.node().dispatchEvent(event); 36 | 37 | expect(hoverSpy.calls.any()).toBe(true); 38 | }); 39 | 40 | afterEach(() => { 41 | document.body.removeChild(wrapper); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/karma/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function (config) { 2 | // Retrieve a Webpack config specialized in tests 3 | var webpackConfig = require('../../webpack.config.js'); 4 | webpackConfig.context = __dirname + '/../..'; 5 | delete webpackConfig.entry; 6 | delete webpackConfig.output; 7 | 8 | config.set({ 9 | basePath: '../..', 10 | browserNoActivityTimeout: 30000, 11 | frameworks: ['jasmine'], 12 | browsers: ['PhantomJS'], 13 | files: [ 14 | './node_modules/d3/d3.js', 15 | './test/karma/*', 16 | './test/karma/**/*.js' 17 | ], 18 | plugins: ['karma-webpack', 'karma-jasmine', 'karma-firefox-launcher', 'karma-phantomjs-launcher'], 19 | preprocessors: { 20 | 'src/**/*.js': 'webpack', 21 | 'test/karma/**/*.js': 'webpack' 22 | }, 23 | webpackMiddleware: { 24 | noInfo: true, 25 | devtool: 'inline-source-map' 26 | }, 27 | webpack: webpackConfig 28 | }); 29 | }; 30 | -------------------------------------------------------------------------------- /test/karma/timeline.js: -------------------------------------------------------------------------------- 1 | require('../../src/timeline'); 2 | 3 | describe('d3.chart.timeline', () => { 4 | it('should append a SVG element to given selection', () => { 5 | const div = document.createElement('div'); 6 | const data = [{ name: 'foo', data: [{date: new Date()}] }]; 7 | 8 | const chart = d3.chart.timeline(); 9 | d3.select(div).datum(data).call(chart); 10 | 11 | expect(div.querySelectorAll('svg.timeline-pf-chart').length).toBe(1); 12 | }); 13 | 14 | it('should remove all previously created charts in current selection to prevent duplicates', () => { 15 | const div = document.createElement('div'); 16 | const data = [{ name: 'foo', data: [{date: new Date()}] }]; 17 | 18 | const chart = d3.chart.timeline(); 19 | d3.select(div).datum(data).call(chart); 20 | d3.select(div).datum(data).call(chart); 21 | 22 | expect(div.querySelectorAll('svg.timeline-pf-chart').length).toBe(1); 23 | }); 24 | 25 | it('should have as many lines as events', () => { 26 | const div = document.createElement('div'); 27 | const data = [ 28 | { name: 'foo', data: [{date: new Date()}] }, 29 | { name: 'bar', data: [{date: new Date()}] }, 30 | { name: 'quz', data: [{date: new Date()}] }, 31 | ]; 32 | 33 | const chart = d3.chart.timeline().start(new Date('2010-01-25')); 34 | d3.select(div).datum(data).call(chart); 35 | 36 | expect(div.querySelectorAll('.timeline-pf-drop-line').length).toBe(3); 37 | }); 38 | 39 | it('should have as many drops as given dates', () => { 40 | const div = document.createElement('div'); 41 | const data = [ 42 | { name: 'foo', data: [ {date: new Date('2010-01-01')} ] }, 43 | { name: 'bar', data: [] }, 44 | { name: 'quz', data: [ { date: new Date('2011-01-04')},{date: new Date('2012-08-09')}] }, 45 | ]; 46 | 47 | const chart = d3.chart.timeline().start(new Date('2010-01-25')); 48 | d3.select(div).datum(data).call(chart); 49 | 50 | expect(div.querySelectorAll('.timeline-pf-drop').length).toBe(3); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 2 | var PRODUCTION = process.argv[2] === '-p'; 3 | 4 | module.exports = { 5 | entry: require('./webpack/entries')(PRODUCTION), 6 | output: { 7 | publicPath: '', 8 | path: 'dist/', 9 | filename: '[name].js', 10 | library: 'timeline', 11 | libraryTarget: 'umd' 12 | }, 13 | module: { 14 | loaders: [ 15 | { test: /\.js$/, exclude: /node_modules/, loader: 'babel' }, 16 | { test: /\.css$/, include: __dirname + '/style.css', loader: ExtractTextPlugin.extract('css') }, 17 | ], 18 | }, 19 | externals: { 20 | d3: 'd3', 21 | }, 22 | plugins: require('./webpack/plugins')(PRODUCTION), 23 | }; 24 | -------------------------------------------------------------------------------- /webpack/entries.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = function (production) { 4 | var entries = { 5 | timeline: [ 6 | path.join(__dirname, '../src/timeline'), 7 | path.join(__dirname, '../style.css'), 8 | ] 9 | }; 10 | 11 | if (!production) { 12 | /* D3 is defined as an external, but we need it for the demo. So, let's 13 | include it using the full path to trick Webpack. */ 14 | entries['demo-d3'] = path.join(__dirname, '../node_modules/d3/d3.min.js'); 15 | entries.demo = [ 16 | path.join(__dirname, '../demo/script.js') 17 | ]; 18 | 19 | entries.timeline.push('webpack-dev-server/client?http://localhost:8080'); 20 | } 21 | 22 | return entries; 23 | }; 24 | -------------------------------------------------------------------------------- /webpack/plugins.js: -------------------------------------------------------------------------------- 1 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var ProvidePlugin = require('webpack').ProvidePlugin; 4 | 5 | var path = require('path'); 6 | 7 | module.exports = function (production) { 8 | var plugins = [ 9 | new ExtractTextPlugin('timeline.css', { 10 | allChunks: true 11 | }), 12 | ]; 13 | 14 | if (!production) { 15 | plugins.push(new HtmlWebpackPlugin({ 16 | template: path.join(__dirname, '../demo/index.html'), 17 | hash: true 18 | })); 19 | } 20 | 21 | return plugins; 22 | }; 23 | --------------------------------------------------------------------------------