import { LitElement, html, css, nothing } from "lit"; import { property } from "lit/decorators.js"; import { wrapCss } from "./misc"; import { map } from "lit/directives/map.js"; import prettyBytes from "pretty-bytes"; import type { ItemType } from "./types"; import "./components/labeled-field"; import { dateTimeFormatter } from "./utils/dateTimeFormatter"; // =========================================================================== class ItemInfo extends LitElement { @property({ type: Object }) item: ItemType | Record | null = null; @property({ type: Boolean }) detailed = false; @property({ type: Boolean }) canDelete = false; static get styles() { return wrapCss(ItemInfo.compStyles); } static get compStyles() { return css` .columns { width: 100%; } .column { word-break: break-word; position: relative; } :host { width: 100%; height: 100%; min-width: 0px; } :host(.is-list) .columns { display: flex !important; flex-direction: column; } :host(.is-list) .column { width: 100% !important; flex: 1 1 auto; } .col-title:hover { } .col-title a { display: block; height: 100%; } .column:hover > .copy, .col-content:hover .copy, .copy:hover { color: inherit; } .copy { color: black; margin: 0px; margin: -4px 0 0; line-height: 0.4em; padding: 6px; border-radius: 10px; position: absolute; } .copy:active { background-color: lightgray; } .col-content { font-family: monospace; font-size: 14px; color: #1f2937; } .minihead { font-size: 12px; line-height: 16px; margin-bottom: 4px; } `; } renderSource(showItemID = true) { const item = this.item; return html` ${item!.sourceUrl && (item!.sourceUrl.startsWith("http://") || item!.sourceUrl.startsWith("https://")) ? html` ${item!.sourceUrl} ` : html` ${item!.sourceUrl}`} ${item!.sourceUrl && item!.sourceUrl.startsWith("googledrive://") ? html` (${item!.filename})` : nothing} ${showItemID ? html` ${item!.coll || "No ID"} ` : nothing} ${item!.ctime ? dateTimeFormatter.format(new Date(item!.ctime)) : nothing} ${prettyBytes(Number(item!.totalSize || item!.size || 0))} `; } renderSummaryView() { const item = this.item; return html`
${this.renderSource(false)}
`; } renderDetailed() { const item = this.item; const { numValid = 0, numInvalid = 0, domain, certFingerprint, datapackageHash, publicKey, software, } = this.item!.verify || {}; const certFingerprintUrl = certFingerprint ? `https://crt.sh/?q=${certFingerprint}` : ""; return html`
${item!.name || item!.title ? html` ${item!.name || item!.title} ` : nothing} ${item!.filename} ${item!.resources ? html`
    ${map( item!.resources, (resource) => html`
  1. ${resource.name + "\n"}
  2. `, )}
` : nothing} ${this.renderSource()} ${domain ? html`

${domain}

${certFingerprintUrl ? html` View Certificate` : nothing}
` : nothing} ${software ? html` ${software || "Unknown"} ` : nothing} ${numValid > 0 || numInvalid > 0 ? html`

${numValid} hashes verified${numInvalid ? html`, ${numInvalid} invalid` : nothing}

` : html` Not Available`}
${datapackageHash || "Not Available"} ${publicKey || "Not Available"} ${item!.onDemand ? "Download On-Demand" : "Fully Local"}
`; } render() { return this.detailed ? this.renderDetailed() : this.renderSummaryView(); } onCopy(event: Event, text: string | undefined) { event.preventDefault(); event.stopPropagation(); // TODO: Fix this the next time the file is edited. // eslint-disable-next-line @typescript-eslint/no-floating-promises if (text) navigator.clipboard.writeText(text); return false; } // @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'reload' implicitly has an 'any' type. onPurge(reload) { const detail = { reload }; this.dispatchEvent(new CustomEvent("item-purge", { detail })); } } customElements.define("wr-item-info", ItemInfo); export { ItemInfo };