class PackageIndexEntry { name: string description: string | null website: string | null version: string | null report: boolean } function toHTML(entry: PackageIndexEntry): HTMLTableRowElement { let v = entry.version != null ? `${escapeHtml(entry.version)}` : "" let d = entry.description != null ? `

${escapeHtml(entry.description)}

` : "" let w = entry.website != null ? `Website` : "" let r = entry.report ? `Log (View | Download)` : "" let row = (document.createElement('tr')) row.innerHTML = `

${escapeHtml(entry.name)} ${v}

${d} ${w} ${r} ` return row } const API_VERSION = 1 const ENDPOINT = `/api/v${API_VERSION}` class InfoPayload { count: number hakurei_version: string } async function infoRequest(): Promise { const res = await fetch(`${ENDPOINT}/info`) const res_1 = await res.json() return res_1 as InfoPayload } class GetPayload { count: number values: PackageIndexEntry[] } enum SortOrders { DeclarationAscending = 0, DeclarationDescending, NameAscending, NameDescending } async function getRequest(limit: number, index: number, sort: SortOrders): Promise { const res = await fetch(`${ENDPOINT}/get?limit=${limit}&index=${index}&sort=${sort.valueOf()}`) const res_1 = await res.json() return res_1 as GetPayload } class State { entriesPerPage: number = 10 currentPage: number = 1 entryIndex: number = 0 maxEntries: number = 0 getEntriesPerPage(): number { return this.entriesPerPage } setEntriesPerPage(entriesPerPage: number) { this.entriesPerPage = entriesPerPage if (this.currentPage > this.getMaxPage()) { this.setCurrentPage(this.getMaxPage()) } } getCurrentPage(): number { return this.currentPage } setCurrentPage(page: number) { this.currentPage = page this.setEntryIndex((this.getCurrentPage() - 1) * this.getEntriesPerPage()) document.getElementById("page-number").innerText = String(this.getCurrentPage()) } getEntryIndex(): number { return this.entryIndex } setEntryIndex(entryIndex: number) { this.entryIndex = entryIndex this.updateRange() this.updateListings() } getMaxEntries(): number { return this.maxEntries } setMaxEntries(max: number) { this.maxEntries = max } getMaxPage(): number { return Math.ceil(this.getMaxEntries() / this.getEntriesPerPage()) } updateRange() { let max = Math.min(this.getEntryIndex() + this.getEntriesPerPage(), this.getMaxEntries()) document.getElementById("entry-counter").innerText = `${this.getEntryIndex() + 1}-${max} of ${this.getMaxEntries()}` } updateListings() { getRequest(this.getEntriesPerPage(), this.entryIndex, 0) .then(res => { let table = document.getElementById("pkg-list") table.innerHTML = '' for(let i = 0; i < res.count; i++) { table.appendChild(toHTML(res.values[i])) } }) } } let STATE: State function prevPage() { let current = STATE.getCurrentPage() if (current > 1) { STATE.setCurrentPage(STATE.getCurrentPage() - 1) } } function nextPage() { let current = STATE.getCurrentPage() if (current < STATE.getMaxPage()) { STATE.setCurrentPage(STATE.getCurrentPage() + 1) } } function escapeHtml(str: string): string { return str .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') } document.addEventListener("DOMContentLoaded", () => { STATE = new State() infoRequest() .then(res => { STATE.setMaxEntries(res.count) document.getElementById("hakurei-version").innerText = res.hakurei_version STATE.updateRange() STATE.updateListings() }) document.getElementById("count").addEventListener("change", (event) => { STATE.setEntriesPerPage(parseInt((event.target as HTMLSelectElement).value)) }) })