ui work:
- show favicon in location bar, if available - editable mode: experimental allow editing collection title from pages view, update using new api - editable mode: disable selected only downloads if nothing is selected - pageentry: simplify, use passed in date wabac.js: update to latest dev wabac.js 2.1.0-beta.2, including improved fuzzy matching system, new rules for fb and twitter (beta)
This commit is contained in:
+45
-3
@@ -65,6 +65,8 @@ class Coll extends LitElement
|
|||||||
this.splitter = null;
|
this.splitter = null;
|
||||||
|
|
||||||
this.isVisible = true;
|
this.isVisible = true;
|
||||||
|
|
||||||
|
this.favIconUrl = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties() {
|
static get properties() {
|
||||||
@@ -93,12 +95,13 @@ class Coll extends LitElement
|
|||||||
embed: { type: String },
|
embed: { type: String },
|
||||||
editable: { type: Boolean },
|
editable: { type: Boolean },
|
||||||
|
|
||||||
isVisible: { type: Boolean }
|
isVisible: { type: Boolean },
|
||||||
|
|
||||||
|
favIconUrl: {type: String }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
//this.doUpdateInfo();
|
|
||||||
this.inited = true;
|
this.inited = true;
|
||||||
window.addEventListener("hashchange", (event) => this.onHashChange(event));
|
window.addEventListener("hashchange", (event) => this.onHashChange(event));
|
||||||
|
|
||||||
@@ -127,6 +130,13 @@ class Coll extends LitElement
|
|||||||
if (changedProperties.has("sourceUrl")) {
|
if (changedProperties.has("sourceUrl")) {
|
||||||
this.doUpdateInfo();
|
this.doUpdateInfo();
|
||||||
}
|
}
|
||||||
|
if (changedProperties.has("editable")) {
|
||||||
|
if (this.editable) {
|
||||||
|
this._pollColl = setInterval(() => this.doUpdateInfo(), 10000);
|
||||||
|
} else if (this._pollColl) {
|
||||||
|
clearInterval(this._pollColl);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (changedProperties.has("tabData")) {
|
if (changedProperties.has("tabData")) {
|
||||||
if (!this.collInfo || !this.collInfo.coll) {
|
if (!this.collInfo || !this.collInfo.coll) {
|
||||||
return;
|
return;
|
||||||
@@ -257,6 +267,14 @@ class Coll extends LitElement
|
|||||||
}}));
|
}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCollUpdate(event) {
|
||||||
|
if (!this.editable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.collInfo = {...this.collInfo, ...event.detail};
|
||||||
|
}
|
||||||
|
|
||||||
onHashChange(event) {
|
onHashChange(event) {
|
||||||
const hash = window.location.hash;
|
const hash = window.location.hash;
|
||||||
if (hash && hash !== this._locationHash) {
|
if (hash && hash !== this._locationHash) {
|
||||||
@@ -418,6 +436,12 @@ class Coll extends LitElement
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.favicon img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
filter: drop-shadow(1px 1px 2px grey);
|
||||||
|
}
|
||||||
|
|
||||||
#datetime {
|
#datetime {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1em;
|
right: 1em;
|
||||||
@@ -570,6 +594,7 @@ class Coll extends LitElement
|
|||||||
ts="${this.tabData.ts || ""}"
|
ts="${this.tabData.ts || ""}"
|
||||||
@coll-tab-nav="${this.onCollTabNav}" id="replay"
|
@coll-tab-nav="${this.onCollTabNav}" id="replay"
|
||||||
@replay-loading="${(e) => this.isLoading = e.detail.loading}"
|
@replay-loading="${(e) => this.isLoading = e.detail.loading}"
|
||||||
|
@replay-favicons="${this.onFavIcons}"
|
||||||
>
|
>
|
||||||
</wr-coll-replay>
|
</wr-coll-replay>
|
||||||
` : ``}
|
` : ``}
|
||||||
@@ -640,6 +665,8 @@ class Coll extends LitElement
|
|||||||
|
|
||||||
const isReplay = !!this.tabData.url;
|
const isReplay = !!this.tabData.url;
|
||||||
|
|
||||||
|
const showFavIcon = isReplay && this.favIconUrl;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<a class="skip-link" href="#skip-replay-target" @click="${this.skipMenu}">Skip replay navigation</a>
|
<a class="skip-link" href="#skip-replay-target" @click="${this.skipMenu}">Skip replay navigation</a>
|
||||||
<nav class="replay-bar" aria-label="replay">
|
<nav class="replay-bar" aria-label="replay">
|
||||||
@@ -677,9 +704,13 @@ class Coll extends LitElement
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<form @submit="${this.onSubmit}">
|
<form @submit="${this.onSubmit}">
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded ${showFavIcon ? 'has-icons-left' : ''}">
|
||||||
<input id="url" class="input" type="search" @keydown="${this.onKeyDown}" .value="${this.url}" placeholder="Enter text to search or a URL to replay"/>
|
<input id="url" class="input" type="search" @keydown="${this.onKeyDown}" .value="${this.url}" placeholder="Enter text to search or a URL to replay"/>
|
||||||
${isReplay ? html`<p id="datetime" class="control is-hidden-mobile">${dateStr}</p>` : html``}
|
${isReplay ? html`<p id="datetime" class="control is-hidden-mobile">${dateStr}</p>` : html``}
|
||||||
|
${showFavIcon ? html`
|
||||||
|
<span class="favicon icon is-small is-left">
|
||||||
|
<img src="${this.favIconUrl}"/>
|
||||||
|
</span>` : html``}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@@ -803,6 +834,7 @@ class Coll extends LitElement
|
|||||||
.url="${this.tabData.url || ""}"
|
.url="${this.tabData.url || ""}"
|
||||||
.ts="${this.tabData.ts || ""}"
|
.ts="${this.tabData.ts || ""}"
|
||||||
@coll-tab-nav="${this.onCollTabNav}" id="pages"
|
@coll-tab-nav="${this.onCollTabNav}" id="pages"
|
||||||
|
@coll-update="${this.onCollUpdate}"
|
||||||
class="${isPages ? '' : 'is-hidden'} ${isSidebar ? 'sidebar' : ''}"
|
class="${isPages ? '' : 'is-hidden'} ${isSidebar ? 'sidebar' : ''}"
|
||||||
role="${isSidebar ? '' : 'main'}"
|
role="${isSidebar ? '' : 'main'}"
|
||||||
>
|
>
|
||||||
@@ -878,6 +910,16 @@ class Coll extends LitElement
|
|||||||
this.showSidebar = false;
|
this.showSidebar = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFavIcons(event) {
|
||||||
|
this.favIconUrl = "";
|
||||||
|
event.detail.icons.map(async (icon) => {
|
||||||
|
const res = await fetch(icon.href);
|
||||||
|
if (res.status === 200) {
|
||||||
|
this.favIconUrl = icon.href;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onReAuthed(event) {
|
onReAuthed(event) {
|
||||||
this.reauthWait = (async () => {
|
this.reauthWait = (async () => {
|
||||||
const headers = event.detail.headers;
|
const headers = event.detail.headers;
|
||||||
|
|||||||
+6
-16
@@ -4,7 +4,7 @@ import { LitElement, html, css, unsafeCSS } from 'lit-element';
|
|||||||
|
|
||||||
import "keyword-mark-element/lib/keyword-mark.js";
|
import "keyword-mark-element/lib/keyword-mark.js";
|
||||||
|
|
||||||
import { getPageDateTS, getReplayLink } from './pageutils';
|
import { getReplayLink } from './pageutils';
|
||||||
|
|
||||||
import { wrapCss } from './misc';
|
import { wrapCss } from './misc';
|
||||||
|
|
||||||
@@ -24,9 +24,6 @@ class PageEntry extends LitElement
|
|||||||
this.index = 0;
|
this.index = 0;
|
||||||
this.isCurrent = false;
|
this.isCurrent = false;
|
||||||
this.isSidebar = false;
|
this.isSidebar = false;
|
||||||
|
|
||||||
this.timestamp = "";
|
|
||||||
this.date = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties() {
|
static get properties() {
|
||||||
@@ -42,8 +39,6 @@ class PageEntry extends LitElement
|
|||||||
index: { type: Number },
|
index: { type: Number },
|
||||||
isCurrent: { type: Boolean },
|
isCurrent: { type: Boolean },
|
||||||
isSidebar: { type: Boolean },
|
isSidebar: { type: Boolean },
|
||||||
timestamp: { type: String },
|
|
||||||
date: { type: Object }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,16 +165,12 @@ class PageEntry extends LitElement
|
|||||||
this.iconValid = !!this.page.favIconUrl;
|
this.iconValid = !!this.page.favIconUrl;
|
||||||
//this.updateFavIcon();
|
//this.updateFavIcon();
|
||||||
this.deleting = false;
|
this.deleting = false;
|
||||||
|
|
||||||
const res = getPageDateTS(this.page);
|
|
||||||
this.timestamp = res.timestamp;
|
|
||||||
this.date = res.date;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const p = this.page;
|
const p = this.page;
|
||||||
const date = this.date;
|
const date = this.page.date;
|
||||||
|
|
||||||
const hasSize = typeof(p.size) === "number";
|
const hasSize = typeof(p.size) === "number";
|
||||||
|
|
||||||
@@ -204,14 +195,13 @@ class PageEntry extends LitElement
|
|||||||
<figure class="media-left">
|
<figure class="media-left">
|
||||||
<p class="">
|
<p class="">
|
||||||
${this.iconValid ? html`
|
${this.iconValid ? html`
|
||||||
<img class="favicon" @error="${(e) => this.iconValid = false}" src="${this.replayPrefix}/${this.timestamp}id_/${p.favIconUrl}"/>` : html`
|
<img class="favicon" @error="${(e) => this.iconValid = false}" src="${this.replayPrefix}/${this.page.timestamp}id_/${p.favIconUrl}"/>` : html`
|
||||||
<span class="favicon"></span>`}
|
<span class="favicon"></span>`}
|
||||||
</p>
|
</p>
|
||||||
</figure>
|
</figure>
|
||||||
<div class="media-content ${this.isCurrent ? 'current' : ''}">
|
<div class="media-content ${this.isCurrent ? 'current' : ''}">
|
||||||
<div role="heading" aria-level="${this.isSidebar ? "4": "3"}">
|
<div role="heading" aria-level="${this.isSidebar ? "4": "3"}">
|
||||||
<a @click="${this.onReplay}" href="${getReplayLink("pages", this.page.url, this.timestamp)}">
|
<a @click="${this.onReplay}" href="${getReplayLink("pages", this.page.url, this.page.timestamp)}">
|
||||||
${this.isCurrent ? html`<p class="curr-page is-pulled-right">Current Page</p>` : ``}
|
|
||||||
<p class="is-size-6 has-text-weight-bold has-text-link text">
|
<p class="is-size-6 has-text-weight-bold has-text-link text">
|
||||||
<keyword-mark keywords="${this.query}">${p.title || p.url}</keyword-mark>
|
<keyword-mark keywords="${this.query}">${p.title || p.url}</keyword-mark>
|
||||||
</p>
|
</p>
|
||||||
@@ -245,7 +235,7 @@ class PageEntry extends LitElement
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resp = await fetch(`${this.replayPrefix}/${this.timestamp}id_/${this.page.favIconUrl}`);
|
const resp = await fetch(`${this.replayPrefix}/${this.page.timestamp}id_/${this.page.favIconUrl}`);
|
||||||
|
|
||||||
if (resp.status != 200) {
|
if (resp.status != 200) {
|
||||||
this.favIconData = null;
|
this.favIconData = null;
|
||||||
@@ -313,7 +303,7 @@ class PageEntry extends LitElement
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
url: this.page.url,
|
url: this.page.url,
|
||||||
ts: this.timestamp,
|
ts: this.page.timestamp,
|
||||||
};
|
};
|
||||||
this.sendChangeEvent(data);
|
this.sendChangeEvent(data);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+72
-7
@@ -11,6 +11,8 @@ import { getTS, getPageDateTS } from './pageutils';
|
|||||||
import fasSearch from '@fortawesome/fontawesome-free/svgs/solid/search.svg';
|
import fasSearch from '@fortawesome/fontawesome-free/svgs/solid/search.svg';
|
||||||
import fasAngleDown from '@fortawesome/fontawesome-free/svgs/solid/angle-down.svg';
|
import fasAngleDown from '@fortawesome/fontawesome-free/svgs/solid/angle-down.svg';
|
||||||
|
|
||||||
|
import fasEdit from '@fortawesome/fontawesome-free/svgs/solid/edit.svg';
|
||||||
|
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class Pages extends LitElement
|
class Pages extends LitElement
|
||||||
@@ -41,6 +43,8 @@ class Pages extends LitElement
|
|||||||
this.isSidebar = false;
|
this.isSidebar = false;
|
||||||
this.url = "";
|
this.url = "";
|
||||||
this.ts = "";
|
this.ts = "";
|
||||||
|
|
||||||
|
this.editing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get sortKeys() {
|
static get sortKeys() {
|
||||||
@@ -85,7 +89,9 @@ class Pages extends LitElement
|
|||||||
|
|
||||||
isSidebar: { type: Boolean },
|
isSidebar: { type: Boolean },
|
||||||
url: { type: String },
|
url: { type: String },
|
||||||
ts: { type: String }
|
ts: { type: String },
|
||||||
|
|
||||||
|
editing: { type: Boolean }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,6 +328,7 @@ class Pages extends LitElement
|
|||||||
border-right: 3px solid rgb(237, 237, 237);
|
border-right: 3px solid rgb(237, 237, 237);
|
||||||
background-color: whitesmoke;
|
background-color: whitesmoke;
|
||||||
padding-right: 0px;
|
padding-right: 0px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.index-bar-title {
|
.index-bar-title {
|
||||||
@@ -331,6 +338,17 @@ class Pages extends LitElement
|
|||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.index-bar-title:hover + .editIcon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editIcon {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.index-bar-status {
|
.index-bar-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -413,6 +431,11 @@ class Pages extends LitElement
|
|||||||
background-color: rgb(207, 243, 255);
|
background-color: rgb(207, 243, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: .65;
|
||||||
|
}
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -509,7 +532,13 @@ class Pages extends LitElement
|
|||||||
</div>
|
</div>
|
||||||
<div class="main columns">
|
<div class="main columns">
|
||||||
<div class="column index-bar is-one-fifth is-hidden-mobile">
|
<div class="column index-bar is-one-fifth is-hidden-mobile">
|
||||||
<div class="index-bar-title">${this.collInfo.title}</div>
|
|
||||||
|
${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>`}
|
||||||
|
|
||||||
|
${this.editable ? html`<fa-icon class="editIcon" .svg="${fasEdit}"></fa-icon>` : html``}
|
||||||
|
|
||||||
<span class="num-results" aria-live="polite" aria-atomic="true">${this.formatResults()}</span>
|
<span class="num-results" aria-live="polite" aria-atomic="true">${this.formatResults()}</span>
|
||||||
|
|
||||||
@@ -556,17 +585,29 @@ class Pages extends LitElement
|
|||||||
</div>
|
</div>
|
||||||
<div class="dropdown-menu" id="dropdown-menu">
|
<div class="dropdown-menu" id="dropdown-menu">
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<a role="button" href="#" @click="${(e) => this.onDownload(e, "wacz", true)}" @keyup="${clickOnSpacebarPress}" class="dropdown-item">
|
<a role="button" href="#"
|
||||||
|
@click="${(e) => this.onDownload(e, "wacz", true)}"
|
||||||
|
@keyup="${clickOnSpacebarPress}"
|
||||||
|
class="dropdown-item ${this.selectedPages.size === 0 ? 'is-disabled' : ''}">
|
||||||
Download Selected as WACZ (Web Archive Collection)
|
Download Selected as WACZ (Web Archive Collection)
|
||||||
</a>
|
</a>
|
||||||
<a role="button" href="#" @click="${(e) => this.onDownload(e, "warc", true)}" @keyup="${clickOnSpacebarPress}" class="dropdown-item">
|
<a role="button" href="#"
|
||||||
|
@click="${(e) => this.onDownload(e, "warc", true)}"
|
||||||
|
@keyup="${clickOnSpacebarPress}"
|
||||||
|
class="dropdown-item ${this.selectedPages.size === 0 ? 'is-disabled' : ''}">
|
||||||
Download Selected as WARC Only
|
Download Selected as WARC Only
|
||||||
</a>
|
</a>
|
||||||
<hr class="dropdown-divider">
|
<hr class="dropdown-divider">
|
||||||
<a role="button" href="#" @click="${(e) => this.onDownload(e, "wacz", false)}" @keyup="${clickOnSpacebarPress}" class="dropdown-item">
|
<a role="button" href="#"
|
||||||
|
@click="${(e) => this.onDownload(e, "wacz", false)}"
|
||||||
|
@keyup="${clickOnSpacebarPress}"
|
||||||
|
class="dropdown-item">
|
||||||
Download All as WACZ (Web Archive Collection)
|
Download All as WACZ (Web Archive Collection)
|
||||||
</a>
|
</a>
|
||||||
<a role="button" href="#" @click="${(e) => this.onDownload(e, "warc", false)}" @keyup="${clickOnSpacebarPress}" class="dropdown-item">
|
<a role="button" href="#"
|
||||||
|
@click="${(e) => this.onDownload(e, "warc", false)}"
|
||||||
|
@keyup="${clickOnSpacebarPress}"
|
||||||
|
class="dropdown-item">
|
||||||
Download All as WARC Only
|
Download All as WARC Only
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -576,7 +617,7 @@ class Pages extends LitElement
|
|||||||
|
|
||||||
renderPageHeader() {
|
renderPageHeader() {
|
||||||
return html`
|
return html`
|
||||||
${this.editable ? html`
|
${this.editable && this.filteredPages.length ? html`
|
||||||
<div class="check-select">
|
<div class="check-select">
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input @change=${this.onSelectAll} type="checkbox" .checked="${this.allSelected}">
|
<input @change=${this.onSelectAll} type="checkbox" .checked="${this.allSelected}">
|
||||||
@@ -656,6 +697,30 @@ class Pages extends LitElement
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUpdateTitle(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.editing = false;
|
||||||
|
|
||||||
|
if (!this.editable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const input = this.renderRoot.querySelector("#titleEdit");
|
||||||
|
if (!input || !input.value.trim()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = input.value;
|
||||||
|
|
||||||
|
const body = JSON.stringify({title});
|
||||||
|
|
||||||
|
fetch(`${this.collInfo.apiPrefix}/metadata`, {method: 'POST', body}).then((res) => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
this.dispatchEvent(new CustomEvent("coll-update", {detail: {title}}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onMenu(event) {
|
onMenu(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.menuActive = !this.menuActive;
|
this.menuActive = !this.menuActive;
|
||||||
|
|||||||
@@ -292,8 +292,8 @@
|
|||||||
"@xtuc/long" "4.2.2"
|
"@xtuc/long" "4.2.2"
|
||||||
|
|
||||||
"@webrecorder/wabac@github:webrecorder/wabac.js#develop":
|
"@webrecorder/wabac@github:webrecorder/wabac.js#develop":
|
||||||
version "2.1.0-beta.1"
|
version "2.1.0-beta.2"
|
||||||
resolved "https://codeload.github.com/webrecorder/wabac.js/tar.gz/aecb66112cf5b2df38a3a444b19ee149d91c7a63"
|
resolved "https://codeload.github.com/webrecorder/wabac.js/tar.gz/2851cb9ddf44dfd1616b9f127f3f659e49e9cc19"
|
||||||
dependencies:
|
dependencies:
|
||||||
brotli "github:foliojs/brotli.js"
|
brotli "github:foliojs/brotli.js"
|
||||||
fast-xml-parser "^3.15.1"
|
fast-xml-parser "^3.15.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user