-
Notifications
You must be signed in to change notification settings - Fork 45
Building Chart Modules
Workbench lets your module output a custom HTML page.
We call these "chart modules" for brevity. The pythoncode
module uses the same system. A more accurate term is, "iframe modules".
Your chart becomes the module.html
in this diagram:
┏━━━━ Workbench ━━━━┓
┃ ┃
┃ ┌ module.html ┐ ┃
┃ │ │ ┃
┃ │ ▃ ▄ ▁ █ │ ┃
┃ └─────────────┘ ┃
┗━━━━━━━━━━━━━━━━━━━┛
Add html_output: true
to your module specification. This tells Workbench to render an iframe.
Supply an HTML file to render. Workbench will render an <iframe>
with this URL.
And there you have it! Workbench now renders your HTML.
Of course, you'll want to supply data. So you need:
Your render()
function must return a dictionary with at least dataframe
and json
keys. The json
can be any JSON dictionary.
Most charts output the exact dataframe
they use as input. They output Vega and Vega-Lite objects in their json
. (Today's only exception is Pythoncode.)
Workbench supplies a ?dataUrl=...
parameter for your HTML. It's either the empty string, or a complete URL.
If it's an empty string, that means Workbench is rendering.
Otherwise, you can pull it from JavaScript:
window.addEventListener('DOMContentLoaded', () => {
const dataUrl = new URL(window.location).searchParams.get('dataUrl')
if (dataUrl) {
fetch(dataUrl, { credentials: 'same-origin' }).then(/* ... */)
} else {
// ...
}
})
Workbench will respond at dataUrl
with:
- HTTP 403: This is a private workflow and you aren't permitted to access its data. (Ensure you are logged in and
credentials
is being used correctly.) - HTTP 404: The
render()
function did not return anyjson
. (Check therender()
function.) - HTTP 404: Workbench just rendered new values at a different
dataUrl
. (Workbench will update the iframe'ssrc
with a newdataUrl
; the user can refresh the page if it doesn't.) - HTTP 404: The Workflow or Step was deleted.
When users fiddle with chart parameters in the workflow editor, the chart's dataUrl
changes often. Normally, this would cause the whole iframe to reload with every change, since a new dataUrl
implies a new src
.
Workbench has an opt-in window.postMessage
-based system to supply a new dataUrl
without setting a new src
. To use it, check whether Workbench supplies the origin
query-string parameter:
let dataUrl = new URL(window.location).searchParams.get('dataUrl')
const messageOrigin = new URL(window.location).searchParams.get('origin')
if (messageOrigin) {
function handleMessage (ev) {
if (ev.source !== window.parent || ev.origin !== messageOrigin) {
return
}
if (ev.data.type === 'set-data-url') {
if (dataUrl !== ev.data.dataUrl) {
dataUrl = ev.data.dataUrl
startLoading()
}
}
}
window.addEventListener('message', handleMessage)
// Tell Workbench to send us these messages instead of changing iframe `src`
window.parent.postMessage({ type: 'subscribe-to-data-url' }, messageOrigin)
}
This feature is mainly for the workflow editor. As of 2021-03-19, the embed HTML doesn't open a Websockets connection to Workbench; so embedded charts won't refresh until the people viewing them click "Refresh". When subscription is disabled, Workbench won't supply an origin
query-string parameter.
By default, a chart in the workflow editor is full-height. And charts in reports and embeds always have a fixed height.
There's an exception: pythoncode
uses an experimental system for setting the height of the chart, only within the workflow editor. It uses the same origin
query parameter as the dataUrl
-subscription system:
function notifySize () {
if (!messageOrigin) {
return
}
// To be stable, make height always factor in scrollbar width
// Otherwise, making the scrollbar appear would change height,
// which would make the scrollbar disappear, which would change
// height, and we'd never be stable.
document.body.style.overflow = 'hidden scroll'
const height = pre.clientHeight || 0
document.body.style.overflow = 'hidden auto'
window.parent.postMessage({ type: 'resize', height }, messageOrigin)
}
When the workflow editor receives this message, it adjusts the height of the iframe. This can create a very-tall iframe. Workbench will supply the scrollbar such that the iframe and data table will both be visible.
As a special case, height: 0
hides the iframe altogether. It's still there, though. It can subscribe to dataUrl
changes and send a new height when desired.