"use strict"; import { LitElement, html, css } from 'lit-element'; import { wrapCss } from './misc'; import { getTS } from './pageutils'; import FlexSearch from 'flexsearch'; import "keyword-mark-element/lib/keyword-mark.js"; //const FlexSearch = Object; import fasSearch from '@fortawesome/fontawesome-free/svgs/solid/search.svg'; // =========================================================================== class Pages extends LitElement { constructor() { super(); this.pages = []; this.filteredPages = []; this.sortedPages = []; this.query = ""; this.flex = null; this.newQuery = null; this.loading = false; this.active = false; this.changeNeeded = false; } static get sortKeys() { return [ { "key": "title", "name": "Title" }, { "key": "ts", "name": "Date" } ]; } static get properties() { return { active: { type: Boolean}, collInfo: { type: Object }, pages: { type: Array }, filteredPages: { type: Array }, sortedPages: { type: Array }, query: { type: String }, loading: { type: Boolean }, } } firstUpdated() { //this._ival = window.setInterval(() => { //}, 10000); } _timedUpdate() { if (this.newQuery !== null) { this.query = this.newQuery; this.newQuery = null; this.filter(); } } updated(changedProperties) { if (changedProperties.has("collInfo")) { this.doUpdate(); } else if (changedProperties.has("query")) { this.filter(); } if (changedProperties.has("active") && this.active) { if (this.changeNeeded) { this.filter(); } } } async doUpdate() { const result = await fetch(`${this.collInfo.apiPrefix}/pages`); const json = await result.json(); this.pages = json.pages || []; this.updateTextSearch(); this.filter(); } onChangeQuery(event) { this.newQuery = event.currentTarget.value; //this.loading = true; if (this._ival) { window.clearTimeout(this._ival); } this._ival = window.setTimeout(() => this._timedUpdate(), 250); } async filter() { if (this.loading) { return; } if (!this.active) { this.changeNeeded = true; } this.loading = true; if (this.flex && this.query) { const result = await this.flex.search(this.query); this.filteredPages = result; } else { this.filteredPages = this.pages; } this.loading = false; this.changeNeeded = false; const data = {query: this.query}; this.sendChangeEvent(data); } sendChangeEvent(data) { this.dispatchEvent(new CustomEvent("coll-tab-nav", {detail: {data}})); } updateTextSearch() { this.flex = new FlexSearch({ doc: { id: "id", field: ["url", "title", "text"], }, async: true }); this.flex.add(this.pages); } static get styles() { return wrapCss(css` :host { width: 100%; height: 100%; display: flex; flex-direction: column; padding: 0 0.75rem 0.75rem 0; } .scroller { overflow-y: auto; display: flex; flex-direction: column; flex: auto; height: 100%; } .panel-block:last-child { border-bottom: 1px solid rgb(237, 237, 237); } .panel-block { border-left: 1px solid rgb(237, 237, 237); border-right: 1px solid rgb(237, 237, 237); } .panel-block.status { justify-content: space-between; } nav.panel { box-shadow: none; display: flex; flex-direction: column; flex: 1; height: 100%; } .light-blue { background-color: #43daff; } `); } render() { return html` `; } formatResults() { if (!this.collInfo || !this.collInfo.numPages) { return html`No Pages defined this archive. Check out Page Resources to search by URL.`; } if (this.loading) { return "Searching..."; } if (!this.sortedPages.length) { return "No Pages Found." } else if (this.sortedPages.length === 1) { return "1 Page"; } else { return `${this.sortedPages.length} Pages`; } } onScroll(event) { const element = event.currentTarget; const diff = (element.scrollHeight - element.scrollTop) - element.clientHeight; if (diff < 40) { const sorter = this.renderRoot.querySelector("wr-sorter"); if (sorter) { sorter.getMore(); } } } } // =========================================================================== class PageEntry extends LitElement { constructor() { super(); this.query = ""; this.textSnippet = ""; this.page = null; } static get properties() { return { query: { type: String }, textSnippet: { type: String }, page: { type: Object } } } static get styles() { return wrapCss(css` :host { min-height: min-content; width: 100%; word-break: break-all; } a { word-break: break-all; } @media screen and (max-width: 767px) { .col-date div { display: inline; } .columns { display: flex; flex-direction: column-reverse; } } `); } updated(changedProperties) { if (changedProperties.has("page") || changedProperties.has("query")) { this.updateSnippet(); } } render() { const p = this.page; let date = null; try { date = new Date(p.ts); } catch (e) { } return html`