move archive info into a dialog in dropdown menu (#235)

using sl-dialog and sl-button for components

show error message when coll info is missing

rework info popup to better match 2.0 design

remove extra comment i forgot
This commit is contained in:
emma
2023-11-29 15:52:12 -05:00
parent 4d55efa341
commit e7b86626df
3 changed files with 141 additions and 117 deletions
+87 -69
View File
@@ -189,7 +189,6 @@ class CollIndex extends LitElement {
line-height: 0.4em; line-height: 0.4em;
padding: 6px; padding: 6px;
border-radius: 10px; border-radius: 10px;
display: none;
position: absolute; position: absolute;
} }
.copy:active { .copy:active {
@@ -346,7 +345,7 @@ class CollIndex extends LitElement {
`; `;
} }
renderCollInfo(coll) { renderCollInfo(coll: Coll) {
return html`<wr-coll-info .coll=${coll}></wr-coll-info>`; return html`<wr-coll-info .coll=${coll}></wr-coll-info>`;
} }
@@ -405,56 +404,74 @@ class CollInfo extends LitElement {
height: 100%; height: 100%;
} }
.column:hover > .copy, .column:hover > .copy,
.source-text:hover + .copy, .col-content:hover .copy,
.copy:hover { .copy:hover {
display: inline; color: inherit;
} }
.copy { .copy {
color: black; color: black;
margin: 0px; margin: 0px;
margin: 0; margin: -4px 0 0;
line-height: 0.4em; line-height: 0.4em;
padding: 6px; padding: 6px;
border-radius: 10px; border-radius: 10px;
display: none;
position: absolute; position: absolute;
} }
.copy:active { .copy:active {
background-color: lightgray; background-color: lightgray;
} }
.col-content {
font-family: monospace;
font-size: 14px;
color: #1f2937;
}
.minihead { .minihead {
font-size: 10px; font-size: 12px;
font-weight: bold; line-height: 16px;
margin-bottom: 4px;
} }
`; `;
} }
renderSource(coll) { renderSource() {
const coll = this.coll;
return html` return html`
<div class="column is-4"> <div class="column is-4">
<span class="source-text" <p class="minihead">Source</p>
><p class="minihead">Source</p> <div class="col-content">
${coll.sourceUrl && ${coll.sourceUrl &&
(coll.sourceUrl.startsWith("http://") || (coll.sourceUrl.startsWith("http://") ||
coll.sourceUrl.startsWith("https://")) coll.sourceUrl.startsWith("https://"))
? html` <a href="${coll.sourceUrl}">${coll.sourceUrl}&nbsp;</a>` ? html` <a href="${coll.sourceUrl}">${coll.sourceUrl}</a> `
: html` ${coll.sourceUrl}&nbsp;`} : html` ${coll.sourceUrl}`}
</span> ${coll.sourceUrl && coll.sourceUrl.startsWith("googledrive://")
? html` <i>(${coll.filename})</i>`
<a @click="${(e) => this.onCopy(e, coll.sourceUrl)}" class="copy"> : ""}
<fa-icon .svg="${fasCopy}"></fa-icon> <a @click="${(e) => this.onCopy(e, coll.sourceUrl)}" class="copy">
</a> <fa-icon .svg="${fasCopy}"></fa-icon>
${coll.sourceUrl && coll.sourceUrl.startsWith("googledrive://") </a>
? html` <p><i>(${coll.filename})</i></p>` </div>
: ""} </div>
<div class="column">
<p class="minihead">Collection id</p>
<div class="col-content">
${coll.coll}
<a @click="${(e) => this.onCopy(e, coll.coll)}" class="copy">
<fa-icon .svg="${fasCopy}"></fa-icon>
</a>
</div>
</div> </div>
<div class="column is-2"> <div class="column is-2">
<p class="minihead">Date Loaded</p> <p class="minihead">Date Loaded</p>
${coll.ctime ? new Date(coll.ctime).toLocaleString() : ""} <div class="col-content">
${coll.ctime ? new Date(coll.ctime).toLocaleString() : ""}
</div>
</div> </div>
<div class="column is-2"> <div class="column is-2">
<p class="minihead">Total Size</p> <p class="minihead">Total Size</p>
${prettyBytes(Number(coll.totalSize || coll.size || 0))} <div class="col-content">
${prettyBytes(Number(coll.totalSize || coll.size || 0))}
</div>
</div> </div>
`; `;
} }
@@ -470,7 +487,7 @@ class CollInfo extends LitElement {
> >
</span> </span>
</div> </div>
${this.renderSource(coll)} ${this.renderSource()}
</div>`; </div>`;
} }
@@ -494,24 +511,16 @@ class CollInfo extends LitElement {
: ""; : "";
return html` <div class="columns"> return html` <div class="columns">
<div class="column col-title is-4"> ${coll.name || coll.title
<span class="subtitle has-text-weight-bold">
${coll.name || coll.title || coll.filename}
</span>
</div>
${coll.desc
? html` <div class="column">
<p class="minihead">Description</p>
${coll.desc}
</div>`
: html``}
${coll.description
? html`<div class="column"> ? html`<div class="column">
<p class="minihead">Description</p> <p class="minihead">Title</p>
${coll.description} <div class="col-content">${coll.name || coll.title}</div>
</div>` </div>`
: html``} : ""}
<!-- Only show filename if coll.resources doesn't exist --> <div class="column">
<p class="minihead">Filename</p>
<div class="col-content">${coll.filename}</div>
</div>
${coll.resources ${coll.resources
? html`<div class="column"> ? html`<div class="column">
<p class="minihead">Files</p> <p class="minihead">Files</p>
@@ -525,61 +534,70 @@ class CollInfo extends LitElement {
)} )}
</ol> </ol>
</div>` </div>`
: html`<div class="column"> : ""}
<p class="minihead">Filename</p> ${this.renderSource()}
${coll.filename}
</div>`}
${this.renderSource(coll)}
${domain ${domain
? html` ? html`
<div class="column"> <div class="column">
<p class="minihead">Observed By</p> <p class="minihead">Observed By</p>
<p>${domain}</p> <span class="col-content">
${certFingerprintUrl <p>${domain}</p>
? html`<span ${certFingerprintUrl
><a target="_blank" href="${certFingerprintUrl}" ? html`<span
>View Certificate</a ><a target="_blank" href="${certFingerprintUrl}"
></span >View Certificate</a
>` ></span
: ""} >`
: ""}
</span>
</div> </div>
` `
: software : software
? html` ? html`
<div class="column"> <div class="column">
<p class="minihead">Created With</p> <p class="minihead">Created With</p>
${software || "Unknown"} <div class="col-content">${software || "Unknown"}</div>
</div> </div>
` `
: ""} : ""}
<div class="column"> <div class="column">
<p class="minihead">Validation</p> <p class="minihead">Validation</p>
${numValid > 0 || numInvalid > 0 <div class="col-content">
? html` <p> ${numValid > 0 || numInvalid > 0
${numValid} hashes ? html` <p>
verified${numInvalid ? html`, ${numInvalid} invalid` : ""} ${numValid} hashes
</p>` verified${numInvalid ? html`, ${numInvalid} invalid` : ""}
: html` Not Available`} </p>`
: html` Not Available`}
</div>
</div> </div>
<div class="column"> <div class="column">
<p class="minihead">Package Hash</p> <p class="minihead">Package Hash</p>
${datapackageHash || "Not Available"} <div class="col-content">
${datapackageHash || "Not Available"}
<a @click="${(e) => this.onCopy(e, datapackageHash)}" class="copy">
<fa-icon .svg="${fasCopy}"></fa-icon>
</a>
</div>
</div> </div>
<div class="column"> <div class="column">
<p class="minihead">Observer Public Key</p> <p class="minihead">Observer Public Key</p>
${publicKey || "Not Available"} <div class="col-content">
${publicKey || "Not Available"}
<a @click="${(e) => this.onCopy(e, publicKey)}" class="copy">
<fa-icon .svg="${fasCopy}"></fa-icon>
</a>
</div>
</div> </div>
<div class="column"> <div class="column">
<p class="minihead">Loading Mode</p> <p class="minihead">Loading Mode</p>
${coll.onDemand ? "Download On-Demand" : "Fully Local"} <div class="col-content">
</div> ${coll.onDemand ? "Download On-Demand" : "Fully Local"}
<div class="column"> </div>
<p class="minihead">Collection id</p>
${coll.coll}
</div> </div>
</div>`; </div>`;
} }
@@ -588,10 +606,10 @@ class CollInfo extends LitElement {
return this.detailed ? this.renderDetailed() : this.renderSummaryView(); return this.detailed ? this.renderDetailed() : this.renderSummaryView();
} }
onCopy(event, sourceUrl) { onCopy(event: Event, text: string | undefined) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
navigator.clipboard.writeText(sourceUrl); if (text) navigator.clipboard.writeText(text);
return false; return false;
} }
+51 -48
View File
@@ -1,10 +1,15 @@
import { LitElement, html, css } from "lit"; import { LitElement, html, css } from "lit";
import { property, state } from "lit/decorators.js"; import { property, state } from "lit/decorators.js";
import { ref, createRef, type Ref } from "lit/directives/ref.js";
import type { import type {
SlDialog,
SlDropdown, SlDropdown,
SlMenu, SlMenu,
SlSelectEvent, SlSelectEvent,
} from "@shoelace-style/shoelace"; } from "@shoelace-style/shoelace";
import "@shoelace-style/shoelace/dist/components/alert/alert.js";
import "@shoelace-style/shoelace/dist/components/button/button.js";
import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
import { import {
wrapCss, wrapCss,
rwpLogo, rwpLogo,
@@ -80,7 +85,7 @@ class Coll extends LitElement {
@property({ type: Object, attribute: false }) @property({ type: Object, attribute: false })
tabData: { tabData: {
view?: string; view?: "story" | "pages" | "resources";
url?: string; url?: string;
ts?: string; ts?: string;
multiTs?: string[]; multiTs?: string[];
@@ -149,6 +154,8 @@ class Coll extends LitElement {
private observer?: IntersectionObserver; private observer?: IntersectionObserver;
private archiveInfoDialog: Ref<SlDialog> = createRef();
private readonly tabNames = ["pages", "story", "resources", "info"]; private readonly tabNames = ["pages", "story", "resources", "info"];
private readonly tabLabels = { private readonly tabLabels = {
pages: "Pages", pages: "Pages",
@@ -776,17 +783,7 @@ class Coll extends LitElement {
width: 100%; width: 100%;
} }
.info-bg {
background-color: whitesmoke;
width: 100%;
height: 100%;
display: flex;
overflow: auto;
}
.is-list { .is-list {
margin: 1em;
background-color: whitesmoke;
height: fit-content; height: fit-content;
} }
@@ -876,6 +873,15 @@ class Coll extends LitElement {
} else if (this.collInfo) { } else if (this.collInfo) {
return html` return html`
${this.renderLocationBar()} ${this.renderVerifyInfo()} ${this.renderLocationBar()} ${this.renderVerifyInfo()}
<sl-dialog label="Archive Info" ${ref(this.archiveInfoDialog)}>
${this.renderCollInfo()}
<sl-button
slot="footer"
variant="primary"
@click="${this.onHideInfoDialog}"
>Close</sl-button
>
</sl-dialog>
<div id="tabContents"> <div id="tabContents">
<div <div
id="contents" id="contents"
@@ -1022,31 +1028,6 @@ class Coll extends LitElement {
</a> </a>
</li> </li>
<li class="${this.tabData.view === "info" ? "is-active" : ""}">
<a
@click="${this.onTabClick}"
href="#info"
class="is-size-6"
aria-label="Archive Info"
aria-current="${(this.tabData.view === "info"
? "location"
: "") as any}"
>
<span class="icon"
><fa-icon
.svg="${fasInfoIcon}"
aria-hidden="true"
title="Archive Info"
></fa-icon
></span>
<span
class="tab-label ${isSidebar ? "is-hidden" : ""}"
title="Archive Info"
>Info</span
>
</a>
</li>
${isSidebar ${isSidebar
? html` <li class="sidebar-nav right"> ? html` <li class="sidebar-nav right">
<a <a
@@ -1379,6 +1360,21 @@ class Coll extends LitElement {
<span class="menu-head">Capture Date</span>${dateStr} <span class="menu-head">Capture Date</span>${dateStr}
</div>` </div>`
: ""} : ""}
<a
href="#"
role="button"
class="dropdown-item"
@click="${this.onShowInfoDialog}"
>
<span class="icon is-small">
<fa-icon
class="has-text-grey"
aria-hidden="true"
.svg="${fasInfoIcon}"
></fa-icon>
</span>
<span>Archive Info</span>
</a>
<hr class="dropdown-divider" /> <hr class="dropdown-divider" />
<a <a
href="#" href="#"
@@ -1480,16 +1476,19 @@ class Coll extends LitElement {
} }
renderCollInfo() { renderCollInfo() {
if (!this.collInfo) return; if (!this.collInfo)
return html` <div class="info-bg"> return html`<sl-alert open variant="warning">
<wr-coll-info <sl-icon slot="icon" name="exclamation-triangle"></sl-icon>
class="is-list" <strong>Archive info is not available</strong><br />
.coll="${this.collInfo}" Please reload and try again.
?detailed="${true}" </sl-alert>`;
?canDelete="${!this.embed}" return html`<wr-coll-info
@coll-purge="${this.onPurgeCache}" class="is-list"
></wr-coll-info> .coll="${this.collInfo}"
</div>`; ?detailed="${true}"
?canDelete="${!this.embed}"
@coll-purge="${this.onPurgeCache}"
></wr-coll-info>`;
} }
renderExtraToolbar(/*isDropdown = false*/) { renderExtraToolbar(/*isDropdown = false*/) {
@@ -1500,10 +1499,8 @@ class Coll extends LitElement {
const isStory = this.hasStory && this.tabData.view === "story"; const isStory = this.hasStory && this.tabData.view === "story";
const isPages = this.tabData.view === "pages"; const isPages = this.tabData.view === "pages";
const isResources = this.tabData.view === "resources"; const isResources = this.tabData.view === "resources";
const isInfo = this.tabData.view === "info";
return html` return html`
${isInfo ? this.renderCollInfo() : html``}
${isStory ${isStory
? html` <wr-coll-story ? html` <wr-coll-story
.collInfo="${this.collInfo || {}}" .collInfo="${this.collInfo || {}}"
@@ -1796,6 +1793,12 @@ class Coll extends LitElement {
onAbout() { onAbout() {
this.dispatchEvent(new CustomEvent("about-show")); this.dispatchEvent(new CustomEvent("about-show"));
} }
onShowInfoDialog() {
this.archiveInfoDialog.value?.show();
}
onHideInfoDialog() {
this.archiveInfoDialog.value?.hide();
}
} }
customElements.define("wr-coll", Coll); customElements.define("wr-coll", Coll);
+3
View File
@@ -14,4 +14,7 @@ export interface Coll {
onDemand?: any; onDemand?: any;
pages?: any[]; pages?: any[];
lists?: any[]; lists?: any[];
ctime?: string;
totalSize?: unknown;
size?: unknown;
} }