import { TextField } from "@material/mwc-textfield"; import debug from "debug"; import { css, html, LitElement, PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { NamedNode } from "n3"; import { getTopGraph } from "./RdfdbSyncedGraph"; import { SyncedGraph } from "./SyncedGraph"; export { Button } from "@material/mwc-button"; export { Dialog } from "@material/mwc-dialog"; export { TextField } from "@material/mwc-textfield"; const log = debug("rdisplay"); @customElement("resource-display") export class ResourceDisplay extends LitElement { graph!: SyncedGraph; static styles = [ css` :host { display: inline-block; } a.resource { color: inherit; text-decoration: none; } .resource { border: 1px solid #545454; border-radius: 5px; padding: 1px; margin: 2px; background: rgb(49, 49, 49); display: inline-block; text-shadow: 1px 1px 2px black; } .resource.minor { background: none; border: none; } .resource a { color: rgb(150, 150, 255); padding: 1px; display: inline-block; } .resource.minor a { text-decoration: none; color: rgb(155, 155, 193); padding: 0; } `, ]; render() { let renameDialog = html``; if (this.renameDialogOpen) { renameDialog = html`

New label:

Cancel OK
`; } return html` ${this.label} ${this.rename ? html`` : ""} ${renameDialog}`; // } @property() uri?: NamedNode; @state() label: string = ""; @state() renameDialogOpen = false; @state() renameTo = ""; @property({ type: Boolean }) rename: boolean = false; @property({ type: Boolean }) noclick: boolean = false; @property({ type: Boolean }) minor: boolean = false; constructor() { super(); getTopGraph().then((g) => { this.graph = g; this.onUri(); }); } updated(changedProperties: PropertyValues) { if (changedProperties.has("uri")) { this.onUri(); } } private onUri() { if (!this.graph) { return; /*too soon, but getTopGraph will call us again*/ } if (this.uri === undefined) { this.label = "(unset)"; } else if (this.uri === null) { throw 'use undefined please' } else { this.graph.runHandler(this.compile.bind(this, this.graph), `label for ${this.uri.id}`); } } private compile(graph: SyncedGraph) { if (this.uri === undefined) { return; } else { this.label = this.graph.labelOrTail(this.uri); } } private href(): string { if (!this.uri || this.noclick) { return "javascript:;"; } return this.uri.value; } private resClasses() { return this.minor ? "resource minor" : "resource"; } private onRename() { this.renameTo = this.label; this.renameDialogOpen = true; setTimeout(() => { // I! 👏 know! 👏 the! 👏 element! 👏 I! 👏 want! const inputEl = this.shadowRoot!.querySelector("#renameField")!.shadowRoot!.querySelector("input")! as HTMLInputElement; inputEl.setSelectionRange(0, -1); }, 100); } // move to SyncedGraph private whatCtxHeldTheObj(subj: NamedNode, pred: NamedNode): NamedNode { var ctxs = this.graph.contextsWithPattern(subj, pred, null); if (ctxs.length != 1) { throw new Error(`${ctxs.length} ${pred.id} stmts for ${subj.id}`); } return ctxs[0]; } private onRenameClosing(ev: CustomEvent) { this.renameTo = (this.shadowRoot!.querySelector("#renameField")! as TextField).value; } private onRenameClosed(ev: CustomEvent) { this.renameDialogOpen = false; if (ev.detail.action == "ok") { var label = this.graph.Uri("rdfs:label"); if (this.uri === undefined) { throw "lost uri"; } const ctx = this.whatCtxHeldTheObj(this.uri, label); this.graph.patchObject(this.uri, label, this.graph.Literal(this.renameTo), ctx); } this.renameTo = ""; } }