Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PARKED] Area chart light theme colours #318

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
13 changes: 11 additions & 2 deletions analysis/stack-trace/frames.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,17 @@ class Frame {
}

getModuleName (systemInfo) {
const filePath = this.fileName.split(systemInfo.pathSeparator)
if (!filePath.includes('node_modules')) return null
let filePath = this.fileName.split(systemInfo.pathSeparator)
// For eval frames, use the source file listed in the `evalOrigin`
if (this.fileName === '' && this.isEval) {
const m = this.evalOrigin.match(/\((.*?):\d+:\d+\)$/)
if (m) {
filePath = m[1].split(systemInfo.pathSeparator)
}
}
if (!filePath.includes('node_modules')) {
return null
}

// Find the last node_modules directory, and count how many were
// encountered.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@nearform/bubbleprof",
"description": "Programmable interface to Clinic.js Bubbleprof",
"repository": "nearform/node-clinic-bubbleprof",
"version": "2.1.0",
"version": "2.1.1",
"engines": {
"node": "^11.0.0 || ^10.0.0 || ^8.11.1"
},
Expand Down Expand Up @@ -40,7 +40,7 @@
"d3-ease": "^1.0.3",
"d3-format": "^1.3.0",
"d3-interpolate": "^1.2.0",
"d3-scale": "^2.1.0",
"d3-scale": "^3.0.0",
"d3-selection": "^1.3.0",
"d3-shape": "^1.2.0",
"d3-time": "^1.0.8",
Expand Down
19 changes: 18 additions & 1 deletion test/analysis-aggregate-mark-module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,23 @@ test('Aggregate Node - mark module', function (t) {
type: 'TickObject'
})

const aggregateNodeEval = new FakeAggregateNode({
aggregateId: 2,
parentAggregateId: 1,
children: [],
frames: [
{ fileName: '/node_modules/promise/lib/core.js' },
{ fileName: '', isEval: true, evalOrigin: 'eval at denodeifyWithoutCount (/node_modules/promise/lib/node-extensions.js:90:10)' }
],
mark: ['external', null, null],
type: 'TickObject'
})

const systemInfo = new FakeSystemInfo('/')
const aggregateNodesInput = [
aggregateNodeRoot, aggregateNodeNodecore,
aggregateNodeInternal, aggregateNodeExternal
aggregateNodeInternal, aggregateNodeExternal,
aggregateNodeEval
]

startpoint(aggregateNodesInput, { objectMode: true })
Expand All @@ -76,6 +89,10 @@ test('Aggregate Node - mark module', function (t) {
aggregateNodesOutput[3].mark.toJSON(),
['external', 'deep', null]
)
t.strictDeepEqual(
aggregateNodesOutput[4].mark.toJSON(),
['external', 'promise', null]
)
t.end()
}))
})
25 changes: 11 additions & 14 deletions visualizer/draw/area-chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

const d3 = require('./d3-subset.js')
const HtmlContent = require('./html-content.js')
const getCSSVarValue = require('./util/getCssVarValue.js')

const {
numberiseIfNumericString,
uniqueObjectKey
Expand All @@ -19,7 +21,7 @@ class AreaChart extends HtmlContent {
}
}, contentProperties))

this.cssVarValues = {}
this.cssVarValues = getCSSVarValue()

this.initialized = false
this.topmostUI = this.ui
Expand Down Expand Up @@ -48,10 +50,16 @@ class AreaChart extends HtmlContent {
this.draw()
}
})

this.ui.on('initializeFromData', () => {
this.initializeFromData()
})

this.ui.on('themeChanged', () => {
this.cssVarValues = getCSSVarValue(this.ui.currentTheme)
this.draw()
})

this.highlightedLayoutNode = null

this.hoverListener = layoutNode => {
Expand Down Expand Up @@ -81,17 +89,6 @@ class AreaChart extends HtmlContent {
})
}

/**
* Get the value of a CSS variable
* @param {String} varName
*/
getCSSVarValue (varName) {
if (!this.cssVarValues[varName]) {
this.cssVarValues[varName] = window.getComputedStyle(document.body).getPropertyValue(varName)
}
return this.cssVarValues[varName]
}

/**
* Generic function to define the styles for the canvas based visualization
* For SVG we could do this with CSS - but for Canvas we don't have access to CSS
Expand All @@ -105,7 +102,7 @@ class AreaChart extends HtmlContent {
'type-other': '--type-colour-5'
}

const fillColour = this.getCSSVarValue(colourIds[type] || 'type-other')
const fillColour = this.cssVarValues(colourIds[type] || 'type-other')
let opacity = 0.8
if (isEven) opacity = 0.6
if (isHighlighted) opacity = 1
Expand Down Expand Up @@ -500,7 +497,7 @@ class AreaChart extends HtmlContent {
this.canvasContext.beginPath()
this.areaMaker.context(this.canvasContext)(d)
// Reset area's colour, so repeated hover in/out doesn't overlay colours increasing their intensity
this.canvasContext.fillStyle = this.getCSSVarValue('--main-bg-color')
this.canvasContext.fillStyle = this.cssVarValues('--main-bg-color')
this.canvasContext.fill()
this.canvasContext.fillStyle = d3Col.toString()
this.canvasContext.fill()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
'use strict'

const HtmlContent = require('./html-content.js')
const SvgNodeDiagram = require('./svg-node-diagram.js')
const BubbleNodeDiagram = require('./bubble-node-diagram.js')

class SvgContainer extends HtmlContent {
class BubbleNodeContainer extends HtmlContent {
constructor (parentContent, contentProperties = {}) {
const defaultProperties = {
htmlElementType: 'svg'
}
super(parentContent, Object.assign(defaultProperties, contentProperties))

// this.renderType =

if (contentProperties.svgBounds) {
const defaultBounds = {
minX: 0,
Expand All @@ -21,15 +23,19 @@ class SvgContainer extends HtmlContent {
}
this.svgBounds = Object.assign(defaultBounds, contentProperties.svgBounds)
}

this.svgNodeDiagram = new SvgNodeDiagram(this)
this.ui.nodeLinkContainer = this
this.svgNodeDiagram = new BubbleNodeDiagram(this)
this.ui.svgNodeDiagram = this.svgNodeDiagram

this.ui.on('setData', () => {
this.setData()
})
}

get renderType () {
return this.contentProperties.htmlElementType
}

setData () {
const {
minX,
Expand All @@ -39,9 +45,21 @@ class SvgContainer extends HtmlContent {
this.svgBounds.height = this.ui.layout.scale.finalSvgHeight || this.ui.layout.settings.svgHeight
this.svgBounds.width = this.ui.layout.settings.svgWidth

if (this.renderType === 'svg') {
this.d3Element
.attr('viewBox', `${minX} ${minY} ${this.svgBounds.width} ${this.svgBounds.height}`)
.attr('preserveAspectRatio', preserveAspectRatio)
}

if (this.renderType === 'canvas') {
this.initializeCanvas()
}
}

initializeCanvas () {
this.d3Element
.attr('viewBox', `${minX} ${minY} ${this.svgBounds.width} ${this.svgBounds.height}`)
.attr('preserveAspectRatio', preserveAspectRatio)
.attr('width', this.svgBounds.width)
.attr('height', this.svgBounds.height)
}

initializeElements () {
Expand All @@ -63,4 +81,4 @@ class SvgContainer extends HtmlContent {
}
}

module.exports = SvgContainer
module.exports = BubbleNodeContainer
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

const d3 = require('./d3-subset.js')
const LineCoordinates = require('../layout/line-coordinates.js')
const SvgNode = require('./svg-node.js')
const BubbleNode = require('./bubble-node.js')
const ShadowCanvas = require('./util/shadowCanvas.js')

class SvgNodeDiagram {
constructor (svgContainer) {
this.svgContainer = svgContainer
this.ui = svgContainer.ui
class BubbleNodeDiagram {
constructor (bubbleNodeContainer) {
this.bubbleNodeContainer = bubbleNodeContainer
this.ui = bubbleNodeContainer.ui

this.svgNodes = new Map()
this.canvasCtx = null
this.shadowCanvas = null

this.ui.on('initializeFromData', () => {
// Called once, creates group contents using d3's .append()
Expand All @@ -22,6 +25,7 @@ class SvgNodeDiagram {
})

this.ui.on('svgDraw', () => {
if (this.canvasCtx) this.shadowCanvas.clear()
// Called any time the SVG DOM elements need to be modified or redrawn
this.draw()
})
Expand All @@ -32,8 +36,19 @@ class SvgNodeDiagram {
}

initializeElements () {
this.d3Container = this.svgContainer.d3Element
if (this.bubbleNodeContainer.renderType === 'svg') {
this.d3Container = this.bubbleNodeContainer.d3Element
}

if (this.bubbleNodeContainer.renderType === 'canvas') {
this.canvasCtx = this.bubbleNodeContainer.d3Element.node().getContext('2d')
this.d3Container = d3.select(document.createElement('custom'))
}
if (this.canvasCtx) {
this.shadowCanvas = new ShadowCanvas()
// document.getElementById('node-link').append(this.shadowCanvas.canvasElement)
// this.shadowCanvas.canvasElement.style = 'position:absolute; top:0; left: 0; opacity: 1'
}
// Group to which one group for each node is appended
this.d3Element = this.d3Container.append('g')
.classed('node-links-wrapper', true)
Expand All @@ -46,9 +61,13 @@ class SvgNodeDiagram {
.enter()

this.dataArray.forEach(layoutNode => {
if (!this.svgNodes.has(layoutNode.id)) this.svgNodes.set(layoutNode.id, new SvgNode(this))
if (!this.svgNodes.has(layoutNode.id)) this.svgNodes.set(layoutNode.id, new BubbleNode(this))
this.svgNodes.get(layoutNode.id).setData(layoutNode)
})

if (this.shadowCanvas) {
this.shadowCanvas.setDimensions(this.ui.layout.settings.svgWidth, this.ui.layout.settings.svgHeight)
}
}

initializeFromData () {
Expand All @@ -59,44 +78,79 @@ class SvgNodeDiagram {
const d3NodeGroup = d3.select(nodes[i])
this.svgNodes.get(layoutNode.id).initializeFromData(d3NodeGroup)
})
.on('mouseenter', layoutNode => this.ui.highlightNode(layoutNode))
.on('mouseleave', () => this.ui.highlightNode(null))
.on('click', (layoutNode) => {
d3.event.stopPropagation()
this.ui.queueAnimation('selectGraphNode', (animationQueue) => {
this.ui.selectNode(layoutNode, animationQueue).then(targetUI => {
if (targetUI !== this.ui) {
this.ui.originalUI.emit('navigation', { from: this.ui, to: targetUI })

if (!this.canvasCtx) {
this.d3NodeGroups
.on('mouseenter', layoutNode => this.ui.highlightNode(layoutNode))
.on('mouseleave', () => this.ui.highlightNode(null))
.on('click', (layoutNode) => {
d3.event.stopPropagation()
this.ui.queueAnimation('selectGraphNode', (animationQueue) => {
this.ui.selectNode(layoutNode, animationQueue).then(targetUI => {
if (targetUI !== this.ui) {
this.ui.originalUI.emit('navigation', { from: this.ui, to: targetUI })
}
animationQueue.execute()
})
})
})
} else {
this.bubbleNodeContainer.d3Element
.on('mousemove', () => {
const layoutNode = this.shadowCanvas.getData(d3.event)
if (layoutNode) {
if (!this.ui.highlightedDataNode) {
this.ui.highlightNode(layoutNode)
}
animationQueue.execute()
} else {
this.ui.highlightNode(null)
}
})
.on('click', () => {
const layoutNode = this.shadowCanvas.getData(d3.event)
d3.event.stopPropagation()
if (!layoutNode) {
return
}
this.ui.queueAnimation('selectGraphNode', (animationQueue) => {
this.ui.selectNode(layoutNode, animationQueue).then(targetUI => {
if (targetUI !== this.ui) {
this.ui.originalUI.emit('navigation', { from: this.ui, to: targetUI })
}
animationQueue.execute()
})
})
})
})
}
}

animate (isExpanding, onComplete) {
this.ui.isAnimating = true

this.svgContainer.d3Element.classed('fade-elements-in', isExpanding)
this.svgContainer.d3Element.classed('fade-elements-out', !isExpanding)
this.svgContainer.d3Element.classed('complete-fade-out', false)
this.svgContainer.d3Element.classed('complete-fade-in', false)
this.bubbleNodeContainer.d3Element.classed('fade-elements-in', isExpanding)
this.bubbleNodeContainer.d3Element.classed('fade-elements-out', !isExpanding)
this.bubbleNodeContainer.d3Element.classed('complete-fade-out', false)
this.bubbleNodeContainer.d3Element.classed('complete-fade-in', false)

const parentContainer = this.ui.parentUI.svgNodeDiagram.svgContainer
const parentContainer = this.ui.parentUI.svgNodeDiagram.bubbleNodeContainer
parentContainer.d3Element.classed('fade-elements-in', false)
parentContainer.d3Element.classed('fade-elements-out', false)
parentContainer.d3Element.classed('complete-fade-out', isExpanding)
parentContainer.d3Element.classed('complete-fade-in', !isExpanding)

this.bbox = this.d3Container.node().getBoundingClientRect()

const svgNodeAnimations = []
this.svgNodes.forEach(svgNode => svgNode.animate(svgNodeAnimations, isExpanding))
if (this.canvasCtx) {
onComplete()
} else {
const svgNodeAnimations = []
this.svgNodes.forEach(svgNode => svgNode.animate(svgNodeAnimations, isExpanding))

Promise.all(svgNodeAnimations).then(() => {
this.ui.isAnimating = false
if (onComplete) onComplete()
})
Promise.all(svgNodeAnimations).then(() => {
this.ui.isAnimating = false
if (onComplete) onComplete()
})
}
}

deselectAll () {
Expand All @@ -105,6 +159,7 @@ class SvgNodeDiagram {

draw () {
if (this.ui.isAnimating) return
if (this.canvasCtx) this.shadowCanvas.clear()

this.bbox = this.d3Container.node().getBoundingClientRect()
this.svgNodes.forEach(svgNode => svgNode.draw())
Expand Down Expand Up @@ -145,4 +200,4 @@ class SvgNodeDiagram {
}
}

module.exports = SvgNodeDiagram
module.exports = BubbleNodeDiagram
Loading