mirror of
https://github.com/atom/atom.git
synced 2026-01-22 13:28:01 -05:00
Add d3 treemap of command logger data
This commit is contained in:
@@ -38,13 +38,3 @@ describe "CommandLogger", ->
|
||||
expect(commandLogger.eventLog['core:backspace'].count).toBe 1
|
||||
rootView.trigger 'command-logger:clear-data'
|
||||
expect(commandLogger.eventLog['core:backspace']).toBeUndefined()
|
||||
|
||||
describe "when the command logger is toggled", ->
|
||||
it "displays all the commands triggered", ->
|
||||
editor.trigger 'core:backspace'
|
||||
editor.trigger 'core:backspace'
|
||||
rootView.trigger 'command-logger:toggle'
|
||||
expect(rootView.find('.command-logger > li > .event-count:eq(0)')).toHaveText '2'
|
||||
expect(rootView.find('.command-logger > li > .event-description:eq(0)')).toHaveText 'Core: Backspace'
|
||||
expect(rootView.find('.command-logger > li > .event-count:eq(1)')).toHaveText '1'
|
||||
expect(rootView.find('.command-logger > li > .event-description:eq(1)')).toHaveText 'Command Logger: Toggle'
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
ScrollView = require 'scroll-view'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
d3 = require 'd3.v3'
|
||||
|
||||
module.exports =
|
||||
class CommandLogger extends ScrollView
|
||||
@@ -9,7 +10,9 @@ class CommandLogger extends ScrollView
|
||||
@instance = new CommandLogger(rootView, state?.eventLog)
|
||||
|
||||
@content: (rootView) ->
|
||||
@ol class: 'command-logger', tabindex: -1
|
||||
@div class: 'command-logger', tabindex: -1, =>
|
||||
@h1 class: 'category-header', outlet: 'categoryHeader'
|
||||
@div class: 'tree-map', outlet: 'treeMap'
|
||||
|
||||
@serialize: ->
|
||||
@instance.serialize()
|
||||
@@ -45,18 +48,105 @@ class CommandLogger extends ScrollView
|
||||
else
|
||||
@attach()
|
||||
|
||||
getHtml: ->
|
||||
sorted = _.sortBy(@eventLog, (event) => -event.count)
|
||||
$$$ ->
|
||||
for eventName, details of sorted
|
||||
@li =>
|
||||
@span "#{details.count}", class: 'event-count'
|
||||
@span "#{_.humanizeEventName(details.name)}", class: 'event-description'
|
||||
@span "Last run on #{new Date(details.lastRun).toString()}", class: 'event-last-run'
|
||||
createRootChildren: ->
|
||||
categories = {}
|
||||
for eventName, details of @eventLog
|
||||
categoryStart = eventName.indexOf(':')
|
||||
categoryName = _.humanizeEventName(eventName.substring(0, categoryStart))
|
||||
category = categories[categoryName]
|
||||
unless category
|
||||
category = name: _.humanizeEventName(categoryName), children: []
|
||||
categories[categoryName] = category
|
||||
category.children.push
|
||||
name: "#{_.humanizeEventName(eventName.substring(categoryStart + 1))} (#{details.count})"
|
||||
size: details.count
|
||||
_.toArray(categories)
|
||||
|
||||
addTreeMap: ->
|
||||
root = {}
|
||||
root.name = "All"
|
||||
root.children = @createRootChildren()
|
||||
node = root
|
||||
|
||||
@treeMap.empty()
|
||||
|
||||
w = @treeMap.width()
|
||||
h = @treeMap.height()
|
||||
x = d3.scale.linear().range([0, w])
|
||||
y = d3.scale.linear().range([0, h])
|
||||
color = d3.scale.category20()
|
||||
|
||||
setCategoryHeader = (node) =>
|
||||
@categoryHeader.text("#{node.name} Commands")
|
||||
setCategoryHeader(root)
|
||||
|
||||
zoom = (d) ->
|
||||
setCategoryHeader(d)
|
||||
kx = w / d.dx
|
||||
ky = h / d.dy
|
||||
x.domain([d.x, d.x + d.dx])
|
||||
y.domain([d.y, d.y + d.dy])
|
||||
|
||||
t = svg.selectAll('g.node').transition()
|
||||
.duration(750)
|
||||
.attr('transform', (d) -> "translate(#{x(d.x)},#{y(d.y)})")
|
||||
|
||||
t.select('rect')
|
||||
.attr('width', (d) -> kx * d.dx - 1)
|
||||
.attr('height', (d) -> ky * d.dy - 1)
|
||||
|
||||
t.select('text')
|
||||
.attr('x', (d) -> kx * d.dx / 2)
|
||||
.attr('y', (d) -> ky * d.dy / 2)
|
||||
.style('opacity', (d) -> if kx * d.dx > d.w then 1 else 0)
|
||||
|
||||
node = d
|
||||
d3.event.stopPropagation()
|
||||
|
||||
treemap = d3.layout.treemap()
|
||||
.round(false)
|
||||
.size([w, h])
|
||||
.sticky(true)
|
||||
.value((d) -> d.size)
|
||||
|
||||
svg = d3.select('.command-logger .tree-map')
|
||||
.append('div')
|
||||
.style('width', "#{w}px")
|
||||
.style('height', "#{h}px")
|
||||
.append('svg:svg')
|
||||
.attr('width', w)
|
||||
.attr('height', h)
|
||||
.append('svg:g')
|
||||
.attr('transform', 'translate(.5,.5)')
|
||||
|
||||
nodes = treemap.nodes(root).filter((d) -> not d.children)
|
||||
|
||||
cell = svg.selectAll('g')
|
||||
.data(nodes)
|
||||
.enter()
|
||||
.append('svg:g')
|
||||
.attr('class', 'node')
|
||||
.attr('transform', (d) -> "translate(#{d.x},#{d.y})")
|
||||
.on('click', (d) -> if node is d.parent then zoom(root) else zoom(d.parent))
|
||||
|
||||
cell.append('svg:rect')
|
||||
.attr('width', (d) -> d.dx - 1)
|
||||
.attr('height', (d) -> d.dy - 1)
|
||||
.style('fill', (d) -> color(d.parent.name))
|
||||
|
||||
cell.append('svg:text')
|
||||
.attr('x', (d) -> d.dx / 2)
|
||||
.attr('y', (d) -> d.dy / 2)
|
||||
.attr('dy', '.35em')
|
||||
.attr('text-anchor', 'middle')
|
||||
.text((d) -> d.name)
|
||||
.style('opacity', (d) -> d.w = this.getComputedTextLength(); if d.dx > d.w then 1 else 0)
|
||||
|
||||
d3.select('.command-logger').on('click', -> zoom(root))
|
||||
|
||||
attach: ->
|
||||
@rootView.append(this)
|
||||
@html(@getHtml())
|
||||
@addTreeMap()
|
||||
@focus()
|
||||
|
||||
detach: ->
|
||||
|
||||
@@ -5,21 +5,26 @@
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background: #1e1e1e;
|
||||
color: #d2d2d2;
|
||||
color: #eee;
|
||||
overflow: auto;
|
||||
opacity: 0.85;
|
||||
z-index: 99;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.command-logger li {
|
||||
padding: 5px;
|
||||
.command-logger .category-header {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.command-logger .event-count {
|
||||
padding-right: 10px;
|
||||
.command-logger .tree-map {
|
||||
margin: auto;
|
||||
position: relative;
|
||||
width: 960px;
|
||||
height: 700px;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
.command-logger .event-description {
|
||||
padding-right: 10px;
|
||||
.command-logger .node text {
|
||||
font-size: 10px;
|
||||
fill: #111;
|
||||
}
|
||||
|
||||
7812
vendor/d3.v3.js
vendored
Normal file
7812
vendor/d3.v3.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user