blossom-cloudron/public/list-blobs.js
2024-11-04 16:09:32 +01:00

182 lines
5.2 KiB
JavaScript

import { html, LitElement } from "./lib/lit.min.js";
import { unixNow, newExpirationValue, formatBytes } from "./utils.js";
export class ListForm extends LitElement {
static properties = {
pubkey: { state: true },
blobs: { state: true },
status: { state: true, type: String },
};
createRenderRoot() {
return this;
}
_auth = null;
async submit(e) {
e.preventDefault();
const formData = new FormData(e.target);
this.pubkey = formData.get("pubkey") || (await window.nostr?.getPublicKey());
if (!this.pubkey) return;
this.status = "Signing...";
this._auth = await window.nostr.signEvent({
kind: 24242,
content: "List Blobs",
created_at: unixNow(),
tags: [
["t", "list"],
["expiration", newExpirationValue()],
["server", new URL(location.protocol + "//" + location.hostname).toString()],
],
});
this.status = "Fetching...";
this.blobs = await fetch("/list/" + this.pubkey, {
headers: { authorization: "Nostr " + btoa(JSON.stringify(this._auth)) },
}).then((res) => res.json());
this.status = undefined;
}
async refresh() {
this.blobs = await fetch("/list/" + this.pubkey, {
headers: { authorization: "Nostr " + btoa(JSON.stringify(this._auth)) },
}).then((res) => res.json());
}
inputChange(e) {
this.pubkey = e.target.files[0];
}
async pubkeyFromExtension(e) {
e.preventDefault();
this.pubkey = await window.nostr.getPublicKey();
}
async deleteBlob(blob) {
const auth = await window.nostr.signEvent({
kind: 24242,
content: "Delete Item",
created_at: unixNow(),
tags: [
["t", "delete"],
["x", blob.sha256],
["expiration", newExpirationValue()],
],
});
await fetch("/" + blob.sha256, {
method: "DELETE",
headers: { authorization: "Nostr " + btoa(JSON.stringify(auth)) },
}).then(async (res) => {
if (res.ok) {
alert("Blob deleted");
await this.refresh();
} else alert(await res.text());
});
}
renderResults() {
return html`<table class="table-auto overflow-hidden">
<thead>
<tr>
<th class="px-2">sha256</th>
<th class="px-2 text-right">Type</th>
<th class="px-2 text-right">Size</th>
<th class="px-2"></th>
</tr>
</thead>
<tbody class="overflow-auto">
${this.blobs.map(
(blob) => html`
<tr class="whitespace-nowrap">
<td class="px-2 overflow-hidden truncate font-mono" style="max-width: 10em">
<a href=${blob.url} class="hover:underline" target="_blank">${blob.sha256}</a>
</td>
<td class="px-2 text-right" style="max-width: 5em">${blob.type}</td>
<td class="px-2 text-right">${formatBytes(blob.size)}</td>
<td class="px-2 text-right">
<a
href="#"
class="text-red-500 hover:underline"
@click="${(e) => {
e.preventDefault();
this.deleteBlob(blob);
}}"
>
Delete
</a>
</td>
</tr>
`,
)}
</tbody>
</table>`;
}
renderForm() {
return html`<form class="space-y-4 ml-auto" @submit="${this.submit}">
<label class="text-sm font-bold text-gray-500 tracking-wide flex flex-col">
<div class="flex gap-2">
<input
name="pubkey"
type="text"
class="rounded-md border-2 w-full p-2 h-10 min-w-20"
@change="${this.inputChange}"
.value="${this.pubkey || ""}"
placeholder="Pubkey"
style="min-width: 18rem;"
/>
<button
type="submit"
class="flex bg-blue-500 text-gray-100 py-2 px-4 rounded-md tracking-wide font-semibold hover:bg-blue-600 cursor-pointer transition ease-in duration-300"
>
${this.status || "List"}
</button>
</div>
${window.nostr &&
html`<a href="#" class="text-blue-500 ml-auto" @click="${this.pubkeyFromExtension}">From Extension</a>`}
</label>
</form>`;
}
renderContent() {
if (this.status) {
return html`<p class="my-5 text-center text-lg">${this.status}</p>`;
} else if (this.blobs) {
if (this.blobs.length === 0) return html`<p class="text-gray-500 text-md text-center p-10">Set pubkey</p>`;
return this.renderResults();
}
return html`<p class="text-gray-500 text-md text-center p-10">Set pubkey</p>`;
}
render() {
if (this.status) {
return html`<p class="my-5 text-center text-lg">${this.status}</p>`;
}
return html`<div class="w-full p-4 bg-white rounded-xl flex flex-col overflow-hidden">
<div class="flex gap-4 w-full items-flex-start flex-wrap">
<h1 class="text-xl">List blobs</h1>
${this.renderForm()}
</div>
${this.renderContent()}
<div class="flex mt-4 text-sm text-blue-400">
<a href="#">back to upload</a>
<a class="ml-auto" href="https://github.com/hzrd149/blossom">🌸 Blossom Spec</a>
</div>
</div>`;
}
}
customElements.define("list-blobs", ListForm);