Files @ 7578f855d18b
Branch filter:

Location: light9/web/ResourceDisplay.ts

drewp@bigasterisk.com
deps fix
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` <mwc-dialog id="renameDialog" open @closing=${this.onRenameClosing} @closed=${this.onRenameClosed}>
        <p>
          New label:
          <mwc-textfield id="renameField" dialogInitialFocus .value=${this.renameTo}></mwc-textfield>
        </p>
        <mwc-button dialogAction="cancel" slot="secondaryAction">Cancel</mwc-button>
        <mwc-button dialogAction="ok" slot="primaryAction">OK</mwc-button>
      </mwc-dialog>`;
    }

    return html` <span class="${this.resClasses()}">
        <a href="${this.href()}" id="uri"> <!-- type icon goes here -->${this.label}</a>
        ${this.rename ? html`<button @click=${this.onRename}>Rename</button>` : ""} </span
      >${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 = "";
  }
}