Archive verification info + Embed improvements + Embed Receipts UI (#125)

info panel verification/integrity additions, (fixes on #113)
- info panel: display number of hashes verified valid (and invalid), observer domain (if any), and certificate fingerprint, creation software, and package digest
- info: ensure replayTS is updated, not just replayUrl, to ensure correct stats

404 page: improved formatting on 404 page (via wabac.js)

embeds:
- new embed 'replay-with-info mode, displays replay-only with dropdown showing archival 'receipt, which includes condensed info and verification (hashes valid/invalid, observer domain, cert fingerprint)
- support 'newWindowBase' attribute for specifying base replay URL for opening new window. default: use current url if deepLink enabled, otherwise use https://replayweb.page/
use transparent for embeds
- embed dropdown/receipt styling from @Shrinks99 
- automatically setting noCache and noWebWorker for older browsers (eg. safari < 16)
- add 'hideOffscreen' attribute to enable unloading embed when offscreen

dependencies: update to wabac.js 2.13.0-beta.0

bump version to 1.7.0-beta.0

Embed receipt styling co-authored-by: @Shrinks99
This commit is contained in:
Ilya Kreymer
2022-10-01 18:22:30 -07:00
committed by GitHub
parent 4cb52b4480
commit 27a8524aac
18 changed files with 1225 additions and 315 deletions
+67 -33
View File
@@ -404,44 +404,88 @@ class CollInfo extends LitElement
`;
}
render() {
renderSource(coll) {
return html`
<div class="column is-4">
<span class="source-text"><p class="minihead">Source</p>
${coll.sourceUrl && (coll.sourceUrl.startsWith("http://") || coll.sourceUrl.startsWith("https://")) ? html`
<a href="${coll.sourceUrl}">${coll.sourceUrl}&nbsp;</a>` : html`
${coll.sourceUrl}&nbsp;`}
</span>
<a @click="${(e) => this.onCopy(e, coll.sourceUrl)}" class="copy"><fa-icon .svg="${fasCopy}"/></a>
${coll.sourceUrl && coll.sourceUrl.startsWith("googledrive://") ? html`
<p><i>(${coll.filename})</i></p>` : ""}
</div>
<div class="column is-2"><p class="minihead">Date Loaded</p>${coll.ctime ? new Date(coll.ctime).toLocaleString() : ""}</div>
<div class="column is-2"><p class="minihead">Total Size</p>${prettyBytes(Number(coll.size || 0))}</div>
`;
}
renderSummaryView() {
const coll = this.coll;
const detailed = this.detailed;
return html`
<div class="columns">
<div class="column col-title is-4">
<span class="subtitle has-text-weight-bold">
<a href="?source=${encodeURIComponent(coll.sourceUrl)}">${coll.title || coll.filename}</a>
</span>
</div>
${this.renderSource(coll)}
</div>`;
}
renderDetailed() {
const coll = this.coll;
let {numValid, numInvalid, domain, certFingerprint, datapackageHash, software} = this.coll.verify || {};
numValid = numValid || 0;
numInvalid = numInvalid || 0;
const certFingerprintUrl = certFingerprint ? `https://search.censys.io/certificates/${certFingerprint}` : "";
return html`
<div class="columns">
<div class="column col-title is-4">
<span class="subtitle has-text-weight-bold">
${detailed ? html`
${coll.title || coll.filename}
` : html`
<a href="?source=${encodeURIComponent(coll.sourceUrl)}">${coll.title || coll.filename}</a>`}
</span>
</div>
${detailed && coll.desc ? html`
${coll.desc ? html`
<div class="column">
<p class="minihead">Description</p>
${coll.desc}
</div>` : html`
`}
<div class="column is-4">
<span class="source-text"><p class="minihead">Source</p>
${coll.sourceUrl && (coll.sourceUrl.startsWith("http://") || coll.sourceUrl.startsWith("https://")) ? html`
<a href="${coll.sourceUrl}">${coll.sourceUrl}&nbsp;</a>` : html`
${coll.sourceUrl}&nbsp;`}
</span>
<div class="column"><p class="minihead">Filename</p>${coll.filename}</div>
${this.renderSource(coll)}
<a @click="${(e) => this.onCopy(e, coll.sourceUrl)}" class="copy"><fa-icon .svg="${fasCopy}"/></a>
${coll.sourceUrl && coll.sourceUrl.startsWith("googledrive://") ? html`
<p><i>(${coll.filename})</i></p>` : ""}
${domain ? html`
<div class="column">
<p class="minihead">Observed By</p>
<p>${domain}</p>
${certFingerprintUrl ? html`<span><a target="_blank" href="${certFingerprintUrl}">View Certificate</a></span>` : ""}
</div>
${detailed ? html`
<div class="column"><p class="minihead">Filename</p>${coll.filename}</div>` : html``}
` : software ? html`
<div class="column">
<p class="minihead">Created With</p>
${software || "Unknown"}
</div>
` : ""}
<div class="column is-2"><p class="minihead">Date Loaded</p>${coll.ctime ? new Date(coll.ctime).toLocaleString() : ""}</div>
<div class="column is-2"><p class="minihead">Total Size</p>${prettyBytes(Number(coll.size || 0))}</div>
<div class="column">
<p class="minihead">Validation</p>
${numValid > 0 || numInvalid > 0 ? html`
<p>${numValid} hashes verified${numInvalid ? html`, ${numInvalid} invalid` : ""}</p>` : html`
Not Available`}
</div>
<div class="column">
<p class="minihead">Package Hash</p>
${datapackageHash || "Not Available"}
</div>
${detailed ? html`
<div class="column">
<p class="minihead">Loading Mode</p>
${coll.onDemand ? "Download On-Demand" : "Fully Local"}
@@ -450,22 +494,12 @@ class CollInfo extends LitElement
<p class="minihead">Collection id</p>
${coll.coll}
</div>
` : html``}
</div>`;
}
// purge + delete buttons
//
// <div class="column">
// <button @click="${(e) => this.onPurge(true)}" class="button">Purge Cache + Full Reload</button>
// </div>
// ${this.canDelete ? html`
// <div class="column">
// <button @click="${(e) => this.onPurge(false)}" class="button is-outlined is-danger">Delete Archive</button>
// </div>` : html``}
//
render() {
return this.detailed ? this.renderDetailed() : this.renderSummaryView();
}
onCopy(event, sourceUrl) {
event.preventDefault();