Notebooks 2.0 is here.

Published
Edited
Nov 1, 2021
1 fork
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
/** Initialize Flo.w
*
* apiKey: string - a valid Flo.w API key (uuid)
* version: string (optional) - Flo.w RDF version number (e.g. '0.4.10'). If omitted, the latest version
* is used.
* host: string (optional) - Flo.w host URL (defaults to https://flow.emu-analytics.net)
*
* Returns the Flo.w context
*/
initializeFlow = async function (
apiKey,
version,
host = "https://flow.emu-analytics.net",
state = {}
) {
version = version ? "@" + version : "";

// Add Flo.w RDF script tag to register custom web components
const script = document.createElement("script");
script.type = "module";
script.src = `https://cdn.jsdelivr.net/npm/flow-rdf${version}/dist/flow-rdf/flow-rdf.esm.js`;
document.getElementsByTagName("head")[0].appendChild(script);

// Inject Flow core CSS
const coreStyles = document.createElement("link");
coreStyles.rel = "stylesheet";
coreStyles.href = `https://cdn.jsdelivr.net/npm/flow-rdf${version}/dist/flow-rdf/css/core.css`;
document.getElementsByTagName("head")[0].appendChild(coreStyles);

const flowLib = await import(
`https://cdn.jsdelivr.net/npm/flow-rdf${version}/dist/flow-rdf/index.esm.js`
);

// Initialize the context
const ctx = flowLib.flow.initializeContext({
host,
apiKey,
enableDebug: true,
initialState: state
});

// Wait for custom elements to be registered
await customElements.whenDefined("flow-context");

return ctx;
}
Insert cell
Insert cell
/**
* Display a table of datasets defined in supplied context
*/
datasetTable = async function (context, options) {
const datasets = await context.flowClient.datasets.list({ sort: "id" });

if (datasets.length) {
const idFilter = options?.ignoreUnderscore
? (ds) => !ds.id.startsWith("_")
: (ds) => true;

const dsInfo = datasets.filter(idFilter).map((ds) => ({
"Dataset ID": ds.id,
Name: ds.name,
Description: ds.description,
Type: ds.type
}));

return Inputs.table(dsInfo, { layout: "auto" });
} else {
return md`No datasets`;
}
}
Insert cell
Insert cell
/**
* Display a table of tile sources defined in the current context
*/
tileSourceTable = async function(context) {
const tileSources = await context.flowClient.tileSources.list();

if (tileSources.length) {
const tsInfo = tileSources.map(ts => ({
'TileSource ID': ts.id,
Type: ts.type,
Source: ts.source
}));

return Inputs.table(tsInfo, {layout: 'auto'});
} else {
return md`No tile sources`;
}
}
Insert cell
Insert cell
/**
* Display dataset source with SQL syntax highlighting
*/
datasetSource = async function (datasetIdOrObj, context) {
const dataset = await getDataset(datasetIdOrObj, context);

if (dataset) {
return md`
~~~SQL
${dataset.source}
~~~
`;
} else {
return md`Dataset not found`;
}
}
Insert cell
Insert cell
/**
* Display table of dataset attributes
*/
datasetAttributes = async function (datasetIdOrObj, context) {
const dataset = await getDataset(datasetIdOrObj, context);

if (dataset) {
const attrs = dataset.attributes;

return Inputs.table(
attrs.map((a) => ({
attribute: a.attribute,
type: a.type,
"DB Type": a.dbType,
description: a.description || "-"
})),
{ layout: "auto" }
);
} else {
return md`Dataset not found`;
}
}
Insert cell
/**
* Display full summary of supplied dataset
*/
datasetSummary = async function (datasetIdOrObj, context, options) {
options = {
headingLevel: 2,
...options
};

const paramRegex = /{{([a-zA-Z_\-\d]+)}}/gm;
const dataset = await getDataset(datasetIdOrObj, context);

if (dataset) {
const heading = md`${"#".repeat(options.headingLevel)} Dataset \`${
dataset.id
}\``;

const description = md`${dataset.description || "No description"}`;

const propertyTable = table(
[
{ property: "Name", value: dataset.name },
{ property: "Type", value: dataset.type },
{
property: "Created",
value: humanDate.prettyPrint(dataset.createdAt)
},
{
property: "Updated",
value: humanDate.relativeTime(dataset.updatedAt)
}
],
{ header: false }
);

const params = Array.from(
new Set(
dataset.type === "sql"
? (dataset.source || "")
.match(paramRegex)
.map((p) => p.replace(/[{}]/g, ""))
: []
)
);

const parameterTable = params.length
? table(params.map((p) => ({ Parameters: p })))
: "";

const source = await datasetSource(dataset);
const attributeTable = await datasetAttributes(dataset);

return htl.html`
${heading}
${description}
${propertyTable}
${parameterTable}
<h5 style="font-family: sans-serif;">SOURCE</h5>
${source}
${attributeTable}
`;
} else {
return md`Dataset not found`;
}
}
Insert cell
getDataset = async function (datasetIdOrObject, context) {
return typeof datasetIdOrObject === "string"
? context.flowClient.datasets.get(datasetIdOrObject)
: datasetIdOrObject;
}
Insert cell
Insert cell
Insert cell
Insert cell
context = initializeFlow("b6b77cc4-904a-46d1-aa0f-3bf3848ce4c7", "2")
Insert cell
html`
<flow-timer
minor-step="1 minute"
major-step="1 hour"
update-interval="10 seconds"
timer-state="$time"
style="--flow-color-text: #f2f2f2; --flow-color-background: #303030;"
>
</flow-timer>
`
Insert cell
html`<flow-value value="$time"></flow-value>`
Insert cell
datasetTable(context)
Insert cell
tileSourceTable(context)
Insert cell
Insert cell
datasetAttributes('landfill', context)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
humanDate = require("human-date")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more