Published
Edited
Sep 6, 2021
Importers
Insert cell
Insert cell
Insert cell
terminusWidget = ({value = '', status = 'No Database Selected'} = {}) => {

const output = htl.html`<output>`;

const create = htl.html`<button onclick=${() => dbAction('create', node, value)}>CREATE</button>`
const clear = htl.html`<button onclick=${() => dbAction('clear', node, value)}>CLEAR</button>`
const del = htl.html`<button onclick=${() => dbAction('delete', node, value)}>DELETE</button>`

if (databases.length > 0) value = databases[databases.length-1].id

const node = htl.html`
<style>${style}</style>
<div class="terminus-widget">
<div class="terminus-header">
<img src="https://terminusdb.com//img/logos/logo.svg" alt="Terminus DB"/>
</div>
<div class='form'>
<label>Select or Create Database</label>
<div class="input">
<input placeholder="Database Name" value="${value}" type="text" autocomplete="off" list="terminus-db-list" oninput=${(e) => set(node, e.target.value)}></input>
<datalist id="terminus-db-list">
${databases.map(d => Object.assign(html`<option>${d.label}</option>`, { value: d.id }))}
</datalist>
</div>
<div>
${create}
${clear}
${del}
</div>
</div>
<div class="terminus-status">
${output}
</div>
</div>`;

// Update the display whenever the value changes
Object.defineProperty(node, "value", {
get() {
return value;
},
set(v) {
value = v;
if (!value) {
create.setAttribute('disabled', '')
clear.setAttribute('disabled', '')
del.setAttribute('disabled', '')
} else if (databases.find(({id}) => id === value) != null) {
create.setAttribute('disabled', '')
clear.removeAttribute('disabled')
del.removeAttribute('disabled')
} else {
create.removeAttribute('disabled')
clear.setAttribute('disabled', '')
del.setAttribute('disabled', '')
}
}
});

Object.defineProperty(node, "status", {
get() {
return status;
},
set(s) {
output.value = status = s;
}
});

// Set the initial value
node.value = value;
node.status = status;

if (databases.length > 0) set(node, databases[databases.length-1].id)
return node;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof refresh = html`<output value="0"/>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
createDB = async (db, comment) => {
await Client.createDatabase(db, {
label: db,
comment: comment || db,
schema: true
}, 'admin').then(() => {
console.log(`✔ created «${db}»`)
})
}
Insert cell
deleteDB = async (db) => {
await Client.deleteDatabase(db, 'admin').then(async () => {
console.log(`✔ deleted «${db}»`)
}).catch((err) => {
console.log(err.data)
})
}
Insert cell
forceRefresh = () => {
(viewof refresh).value ++
(viewof refresh).dispatchEvent(new Event("input"))
}
Insert cell
dbAction = async (action, input, value) => {
input.status = `${action} database`
if (action === 'clear' || action === 'delete') await deleteDB(value)
if (action === 'create' || action === 'clear') await createDB(value)
forceRefresh()
if (action === 'create' || action === 'clear') Client.database(value)
input.status = `waiting for instructions`
}
Insert cell
function set(input, value) {
input.value = value;
input.dispatchEvent(new Event("input", { bubbles: true })); // Native events bubble, so we should too
if (databases.find(({id}) => id === value) != null) {
input.status = `Selected «${value}»`
Client.db(value)
} else {
input.status = `No Database Selected`
}
}
Insert cell
databases = Client.databases()
Insert cell
dbExists = databases.find(({id}) => id === dbName) != null
Insert cell
Insert cell
Insert cell
Client.databases()
Insert cell
Client.databaseInfo('vvv')
Insert cell
{
const term = 'muscheln'
const doctype = 'scm:Material' // set to null to search across all doctypes
const res = await query(WOQL.and(
WOQL
.select('v:label', 'v:subject')
.limit(10)
.order_by('v:dist', 'desc')
.and(
WOQL.triple('v:subject', 'rdfs:label', 'v:label'),
WOQL.triple('v:subject', 'rdf:type', doctype || 'v:doctype'),
WOQL.like(term, 'v:label', 'v:dist')
)
))
return res.bindings
}
Insert cell
Insert cell
style = `
.terminus-widget {
--teal-0: #09120d;
--teal-1: #173125;
--teal-2: #1f523c;
--teal-3: #287355;
--teal-4: #37926d;
--teal-5: #4bae85;
--teal-6: #65c69b;
--teal-7: #82d8b1;
--teal-8: #a1e6c5;
--teal-9: #c1f1d9;
--teal-10: #e0f9ec;
--text: #fff;

--border-radius: 5px;
width: 100%;
/* min-height: 320px; */
font: 13px/1.2 var(--sans-serif);
color: var(--text);
background: var(--teal-3);
border-radius: var(--border-radius);
box-sizing: border-box;

display: flex;
flex-direction: column;
justify-content: space-between;
}

.terminus-widget > * {
padding: 1em;
}

.terminus-widget .terminus-header {
background: var(--teal-1);
border-radius: var(--border-radius) var(--border-radius) 0 0;
}
.terminus-widget .terminus-header img {
height: 25px;
display: block;
}

.terminus-widget .terminus-status {
background: var(--teal-5);
border-radius: 0 0 var(--border-radius) var(--border-radius);
}

.terminus-widget .form {
padding: 2em 1em;
}

.terminus-widget .form > * + * {
margin-top: 0.5em;
}

.terminus-widget .form input {
line-height: normal;
width: 280px;
color: var(--teal-3);
font: inherit;
box-sizing: border-box;
}

.terminus-widget .form button {
line-height: normal;
width: 80px;
/* height: 40px; */
color: var(--teal-3);
font: inherit;
box-sizing: border-box;
}
`
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

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