Published unlisted
Edited
Sep 3, 2022
4 stars
Insert cell
Insert cell
Insert cell
proxyKey = new URL(document.baseURI).pathname
Insert cell
Insert cell
import {initBridge} from '@mootari/api-bridge@629'
Insert cell
Insert cell
viewof query = initBridge({key: proxyKey, routes: [
// A public route that does not require authentication.
'documents/public',
'documents/public/trending',
// Privileged routes that require authentication.
{route: 'user', credentials: true},
{route: 'document/{notebook}/history', credentials: true},
]})
Insert cell
Insert cell
Insert cell
Insert cell
query('ping')
Insert cell
Insert cell
query('info')
Insert cell
Insert cell
Insert cell
query('query', {route: 'documents/public/trending'})
Insert cell
Insert cell
query('query', {route: 'user', credentials: true})
Insert cell
Insert cell
viewof notebookData = notebookInput()
Insert cell
query('query', {route: `document/${notebookData.id}/history`, credentials: true})
Insert cell
Insert cell
Insert cell
recent_notebooks = {
// 30 results per page.
const pages = 2;
const results = new Map;
for(let i = 1; i <= pages; i++) {
const t = Date.now();
const r = await query('query', {route: `documents/public?page=${i}`});
for(const entry of r.data.results) results.set(entry.id, mapEntry(entry, t));
}
return Array.from(results.values());
}
Insert cell
md`---
## Creating a Changelog
`
Insert cell
viewof logNotebook = notebookInput()
Insert cell
logNotebook
Insert cell
md`Event properties:
~~~
"type": one of ["create", "modify_node", "modify_title", "remove_node", "unpin_node", "move_node", "pin_node", "revert"]
"version"
"node_id": node ID or revert version
"user_id"
"time"
"is_new": true or undefined; only if "type" is "modify_node"
"node_value_start": up to 39 leading chars of the cell content; only present if node_name is undefined; only present if "type" is "modify_node"?
"title": new title; only if "type" is "modify_title"
"node_name":
"publish_time"
"publish_user_id"
"publish_type"
~~~
"type" values:

`
Insert cell
{
// type = revert -> node_id refers to revert version!
const res = await query('query', {route: `document/${logNotebook.id}/history`, credentials: true}),
events = res.data.events,
changesets = [];
return new Set(events
.filter(e => e.node_name)
.map(e => e.type)
.flat())
function split(n, n2) {
return n.publish_type != null;
}
function merge(events) {
const log = new Map();
const nodes = events.reduce((map, e) => {
const id = e.node_id;
if(!map.has(id)) map.push(id, {});
const state = map.get(id);
switch(e.type) {
//'create', 'modify_node', 'modify_title', 'remove_node', 'unpin_node', 'move_node', 'pin_node', 'revert'
case 'pin_node':
case 'unpin_node':
case 'modify_node':
case 'remove_node':
case 'modify_title':
case 'revert':
case 'create':
break; // todo: handle
case '':
}
}, new Map());
return events;
}
let offset = 0, i = 0;
while(i < events.length) {
if(split(events[i], events[++i])) {
changesets.push(merge(events.slice(offset, i)));
offset = i;
}
}
return changesets;
}
Insert cell
viewof createChangelog = {
// A confirmation "modal" in the broadest sense. Attaches itself to $parent and returns a promise.
// Note: Cancellation causes the promise to get rejected.
const confirm = async($parent, prompt) => new Promise((resolve, reject) => {
const $confirm = html`<button>confirm`,
$cancel = html`<button>cancel`,
$modal = $parent.appendChild(html`${[DOM.text(prompt), $confirm, $cancel]}`),
clear = () => { $modal.parentElement && $modal.parentElement.removeChild($modal) };
$confirm.onclick = () => { clear(); resolve() };
$cancel.onclick = () => { clear(); reject() };
});
const $view = html``;
return $view;
}
Insert cell
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