1.4.0 Release (#45)

* customizations for chooser, coll-index and appmain to support usage in archiveweb.page
- chooser: support panel/message view
- move apiPrefix to misc
- make coll-index extensible, overridable styles, filtering

* api changes: make configurable in coll-index, now using '/w/' instead of '/wabac/', '/c/' prefix for coll apis

* lint pass!

* bulma: update to 0.9.2, fix delete spinner with latest bulma

* ui fixes:
- show 'Loading Archives...' on initial load until first api response succeeds
- fix typo in oncontrollerchange not actually resolving the promise!

* embed sandbox: add other allow options, except top-nav
- first api load: keep loading message until first successful api load
- don't reset hash on purge to keep current page
- sw config: fix typo with latest wabac.js
- embed: add 'noSandbox' option to avoid adding sandbox to iframe, needed to show PDFs, add more allow rules (all except top-navigation)

* ui improvements:
- refresh: ensure location refresh from hitting enter in location bar always resets url
- pageentry doubleclick: ensure double-clicking on page in sidebar always triggers reload, even if current page
- pageentry typo fix: fix missing var causing selection error (fixes webrecorder/archivewebpage#25)
- lint: don't include 'event' as global
- use latest wabac.js 2.7.0-beta.1

* add CHANGES for 1.4.0, add 'noSandbox' to embedding options
- electron app: fix path to 'w/'
- bump electron to 11.4.3

* docs: autoload current version from package.json
- chooser: support .json files for multiwacz (experimental)
- update CHANGES.md
- add missing .eslintrc.js file

* bump version to 1.4.0
This commit is contained in:
Ilya Kreymer
2021-04-25 16:45:40 -07:00
committed by GitHub
parent 36ae1aefda
commit 0ef8f955db
29 changed files with 832 additions and 663 deletions
+47 -42
View File
@@ -1,18 +1,18 @@
"use strict";
import { LitElement, html, css, unsafeCSS } from 'lit-element';
import { wrapCss, clickOnSpacebarPress } from './misc';
import ndjson from 'fetch-ndjson';
import { LitElement, html, css, unsafeCSS } from "lit-element";
import { wrapCss, clickOnSpacebarPress } from "./misc";
import ndjson from "fetch-ndjson";
import FlexSearch from 'flexsearch';
import prettyBytes from 'pretty-bytes';
import FlexSearch from "flexsearch";
import prettyBytes from "pretty-bytes";
import { getTS, getPageDateTS } from './pageutils';
import { getTS, getPageDateTS } from "./pageutils";
import fasSearch from '@fortawesome/fontawesome-free/svgs/solid/search.svg';
import fasAngleDown from '@fortawesome/fontawesome-free/svgs/solid/angle-down.svg';
import fasSearch from "@fortawesome/fontawesome-free/svgs/solid/search.svg";
import fasAngleDown from "@fortawesome/fontawesome-free/svgs/solid/angle-down.svg";
import fasEdit from '@fortawesome/fontawesome-free/svgs/solid/edit.svg';
import fasEdit from "@fortawesome/fontawesome-free/svgs/solid/edit.svg";
// ===========================================================================
@@ -99,7 +99,7 @@ class Pages extends LitElement
toDeletePages: { type: Object },
toDeletePage: { type: Object }
}
};
}
_timedUpdate() {
@@ -131,7 +131,7 @@ class Pages extends LitElement
this.sortKey = "";
this.sortDesc = false;
} else {
this.sortKey = "date"
this.sortKey = "date";
this.sortDesc = true;
}
const sorter = this.renderRoot.querySelector("wr-sorter");
@@ -143,11 +143,11 @@ class Pages extends LitElement
if (changedProperties.has("sortedPages") && this.isSidebar) {
//if (await this.updateComplete) {
const selected = this.renderRoot.querySelector(".current");
if (selected) {
const opts = {behavior: "smooth", block: "nearest", inline: "nearest"};
setTimeout(() => selected.scrollIntoView(opts), 100);
}
const selected = this.renderRoot.querySelector(".current");
if (selected) {
const opts = {behavior: "smooth", block: "nearest", inline: "nearest"};
setTimeout(() => selected.scrollIntoView(opts), 100);
}
//}
}
}
@@ -241,13 +241,13 @@ class Pages extends LitElement
let lines = [];
async function flush() {
const flush = async () => {
let curr = lines;
lines = [];
await flex.add(curr);
console.log("added " + count + " " + curr.length);
console.log(flex.info());
}
};
for await (const line of ndjson(resp.body.getReader())) {
if (!line.text) {
@@ -516,9 +516,9 @@ class Pages extends LitElement
Pages in ${this.collInfo.title}
</div>
<div class="search-bar notification is-marginless">
${this.isSidebar ? html `<h3 class="is-sr-only">Search and Filter Pages</h3>` : ``}
${this.isSidebar ? html `<h3 class="is-sr-only">Search and Filter Pages</h3>` : ""}
<div class="field flex-auto">
<div class="control has-icons-left ${this.loading ? 'is-loading' : ''}">
<div class="control has-icons-left ${this.loading ? "is-loading" : ""}">
<input type="search" class="input" @input="${this.onChangeQuery}" .value="${this.query}" type="text"
placeholder="Search by Page URL, Title or Text">
<span class="icon is-left"><fa-icon .svg="${fasSearch}" aria-hidden="true"></fa-icon></span>
@@ -531,7 +531,7 @@ class Pages extends LitElement
${this.editable && this.editing ? html`
<form @submit="${this.onUpdateTitle}"><input id="titleEdit" class="input" value="${this.collInfo.title}" @blur="${this.onUpdateTitle}"></form>
` : html`
<div class="index-bar-title" @dblclick="${(e) => this.editing = true}">${this.collInfo.title}</div>`}
<div class="index-bar-title" @dblclick="${() => this.editing = true}">${this.collInfo.title}</div>`}
${this.editable ? html`<fa-icon class="editIcon" .svg="${fasEdit}"></fa-icon>` : html``}
@@ -540,25 +540,25 @@ class Pages extends LitElement
${this.editable ? html`
<div class="index-bar-actions">
${this.renderDownloadMenu()}
</div>` : ``}
</div>` : ""}
${this.collInfo.lists.length ? html`
<p id="filter-label" class="menu-label">Filter By List:</p>
<div class="index-bar-menu menu">
<ul class="menu-list">
<li>
<a href="#list-0" data-list="0" class="${currList === 0 ? 'is-active' : ''}"
<a href="#list-0" data-list="0" class="${currList === 0 ? "is-active" : ""}"
@click=${this.onSelectList}><i>All Pages</i></a>
</li>
${this.collInfo.lists.map(list => html`
<li>
<a @click=${this.onSelectList} href="#list-${list.id}"
data-list="${list.id}"
class="${currList === list.id ? 'is-active' : ''}">${list.title}</a>
class="${currList === list.id ? "is-active" : ""}">${list.title}</a>
</li>`)}
</ul>
</div>
` : ``}
` : ""}
</div>
<div class="column main-content">
<div class="is-sr-only" role="heading" aria-level="${this.isSidebar ? "3": "2"}">Page List</div>
@@ -571,7 +571,7 @@ class Pages extends LitElement
renderDownloadMenu() {
return html`
<div class="dropdown ${this.menuActive ? 'is-active' : ''}">
<div class="dropdown ${this.menuActive ? "is-active" : ""}">
<div class="dropdown-trigger">
<button @click="${this.onMenu}" class="button is-small" aria-haspopup="true" aria-expanded="${this.menuActive}" aria-controls="dropdown-menu">
<span>Download</span>
@@ -585,13 +585,13 @@ class Pages extends LitElement
<a role="button" href="#"
@click="${(e) => this.onDownload(e, "wacz", true)}"
@keyup="${clickOnSpacebarPress}"
class="dropdown-item ${this.selectedPages.size === 0 ? 'is-disabled' : ''}">
class="dropdown-item ${this.selectedPages.size === 0 ? "is-disabled" : ""}">
Download Selected as WACZ (Web Archive Collection)
</a>
<a role="button" href="#"
@click="${(e) => this.onDownload(e, "warc", true)}"
@keyup="${clickOnSpacebarPress}"
class="dropdown-item ${this.selectedPages.size === 0 ? 'is-disabled' : ''}">
class="dropdown-item ${this.selectedPages.size === 0 ? "is-disabled" : ""}">
Download Selected as WARC Only
</a>
<hr class="dropdown-divider">
@@ -623,10 +623,10 @@ class Pages extends LitElement
<div class="header columns is-hidden-mobile">
${this.query ? html`
<a role="button" href="#" @click="${this.onSort}" @keyup="${clickOnSpacebarPress}" data-key="" class="column is-1 ${this.sortKey === "" ? (this.sortDesc ? "desc" : "asc") : ''}">Match</a>` : ``}
<a role="button" href="#" @click="${this.onSort}" @keyup="${clickOnSpacebarPress}" data-key="" class="column is-1 ${this.sortKey === "" ? (this.sortDesc ? "desc" : "asc") : ""}">Match</a>` : ""}
<a role="button" href="#" @click="${this.onSort}" @keyup="${clickOnSpacebarPress}" data-key="date" class="column is-2 ${this.sortKey === "date" ? (this.sortDesc ? "desc" : "asc") : ''}">Date</a>
<a role="button" href="#" @click="${this.onSort}" @keyup="${clickOnSpacebarPress}" data-key="title" class="column is-6 pagetitle ${this.sortKey === "title" ? (this.sortDesc ? "desc" : "asc") : ''}">Page Title</a>
<a role="button" href="#" @click="${this.onSort}" @keyup="${clickOnSpacebarPress}" data-key="date" class="column is-2 ${this.sortKey === "date" ? (this.sortDesc ? "desc" : "asc") : ""}">Date</a>
<a role="button" href="#" @click="${this.onSort}" @keyup="${clickOnSpacebarPress}" data-key="title" class="column is-6 pagetitle ${this.sortKey === "title" ? (this.sortDesc ? "desc" : "asc") : ""}">Page Title</a>
</div>
<div class="is-hidden-tablet mobile-header">
@@ -638,7 +638,7 @@ class Pages extends LitElement
.data="${this.filteredPages}"
pageResults="100"
@sort-changed="${this.onSortChanged}"
class="${this.filteredPages.length ? '' : 'is-hidden'}">
class="${this.filteredPages.length ? "" : "is-hidden"}">
</wr-sorter>
</div>
`;
@@ -650,7 +650,7 @@ class Pages extends LitElement
}
return html`
<wr-modal bgClass="has-background-grey-lighter" @modal-closed="${(e) => this.toDeletePages = this.toDeletePage = null}" title="Confirm Delete">
<wr-modal bgClass="has-background-grey-lighter" @modal-closed="${() => this.toDeletePages = this.toDeletePage = null}" title="Confirm Delete">
${this.toDeletePage ? html`
<p>Are you sure you want to delete the page <b>${this.toDeletePage.title}</b>?
(Size: <b>${prettyBytes(this.toDeletePage.size)}</b>)</p>` : html`
@@ -659,7 +659,7 @@ class Pages extends LitElement
<p>This operation can not be undone.</p>
<button @click="${this.onDeletePages}"class="button is-danger">Delete</button>
<button @click="${(e) => this.toDeletePages = this.toDeletePage = null}" class="button">Cancel</button>
<button @click="${() => this.toDeletePages = this.toDeletePage = null}" class="button">Cancel</button>
</wr-modal>`;
}
@@ -688,10 +688,10 @@ class Pages extends LitElement
<ul class="scroller" @scroll="${this.onScroll}">
${this.sortedPages.length ? html`
${this.sortedPages.map((p, i) => {
const selected = this.selectedPages.has(p.id);
const selected = this.selectedPages.has(p.id);
return html`
<li class="page-entry ${selected ? 'selected' : ''}">
return html`
<li class="page-entry ${selected ? "selected" : ""}">
<wr-page-entry
.index="${this.query || this.isSidebar ? i + 1 : 0}"
.editable="${this.editable}"
@@ -704,10 +704,10 @@ class Pages extends LitElement
@delete-page="${this.onDeleteConfirm}"
replayPrefix="${this.collInfo.replayPrefix}"
query="${this.query}"
class="${this.isSidebar ? 'sidebar' : ''}"
class="${this.isSidebar ? "sidebar" : ""}"
>
</wr-page-entry>
</li>` })}` : html`<p class="mobile-header">${this.getNoResultsMessage()}</p>`}
</li>`; })}` : html`<p class="mobile-header">${this.getNoResultsMessage()}</p>`}
</ul>
`;
}
@@ -729,7 +729,7 @@ class Pages extends LitElement
const body = JSON.stringify({title});
fetch(`${this.collInfo.apiPrefix}/metadata`, {method: 'POST', body}).then((res) => {
fetch(`${this.collInfo.apiPrefix}/metadata`, {method: "POST", body}).then((res) => {
if (res.status === 200) {
this.dispatchEvent(new CustomEvent("coll-update", {detail: {title}}));
}
@@ -828,9 +828,14 @@ class Pages extends LitElement
}
for (const id of this.toDeletePages) {
const resp = await fetch(`${this.collInfo.apiPrefix}/page/${id}`, {method: 'DELETE'});
const resp = await fetch(`${this.collInfo.apiPrefix}/page/${id}`, {method: "DELETE"});
const json = await resp.json();
if (json.error) {
console.warn(json.error);
continue;
}
const page = pageMap[id];
if (!page) {
@@ -866,7 +871,7 @@ class Pages extends LitElement
}
if (this.updatingSearch) {
return "Initializing Search..."
return "Initializing Search...";
}
if (this.loading) {