Skip to content

Commit

Permalink
Add ability to upload files.
Browse files Browse the repository at this point in the history
  • Loading branch information
ibz committed Feb 24, 2024
1 parent 877972f commit 42e33ee
Show file tree
Hide file tree
Showing 4 changed files with 389 additions and 378 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@ edition = "2021"
async-std = { version = "1", features = ["attributes"] }
base64 = { version = "0.21" }
bitcoin_hashes = { version = "0.12", features = ["serde"] }
bytes = "1.5"
chrono = { version = "0", features = ["serde"] }
clap = { version = "4", features = ["derive"] }
femme = "2"
futures-util = "0.3"
http-types = "2"
lazy_static = "1.4"
markdown = "1.0.0-alpha.3"
mime_guess = "2.0.4"
multer = "3.0.0"
phf = { version = "0.11.2", features = ["macros"] }
regex = "1"
secp256k1 = { version = "0.27", features = ["serde", "bitcoin_hashes"] }
serde = "1"
serde_json = "1"
serde_yaml = "0.9"
sha256 = "1.5"
tera = "1"
tide = "0"
tide-acme = "0"
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,13 @@ Each of these "sites" has the following structure:
│ ├── <EVENT_ID>.md
│ └── ...
├── favicon.ico
├── index.md
```

Files and directories starting with "." are ignored.

Files and directories starting with "_" have special meaning: `_config.toml`, `_data`, `_layouts`, `_events`.

Anything else is considered a "resource" that will be served to the clients requesting it - regardless of the name.
Anything else will be directly served to the clients requesting it.

## _config.toml

Expand Down
46 changes: 36 additions & 10 deletions admin/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
return await window.nostr.signEvent(event);
}

async function getNostrAuthHeader(url, method) {
let authEvent = await getEvent(27235, "", [['u', url], ['method', method]]);
return `Nostr ${btoa(JSON.stringify(authEvent))}`;
}

async function getSites(sites) {
let endpoint = `${API_BASE_URL}/api/sites`;
sites.length = 0;
let authEvent = await getEvent(27235, "", [['u', window.location.protocol + endpoint], ['method', 'GET']]);
let response = await fetch(endpoint, {
headers: {'Authorization': `Nostr ${btoa(JSON.stringify(authEvent))}`},
headers: {'Authorization': await getNostrAuthHeader(window.location.protocol + endpoint, 'GET')},
});
for (const s of await response.json()) {
sites.push(s);
Expand All @@ -30,13 +34,12 @@

async function saveSite(site) {
let endpoint = `${API_BASE_URL}/api/sites`;
let authEvent = await getEvent(27235, "", [['u', window.location.protocol + endpoint], ['method', 'POST']]);
let response = await fetch(endpoint, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Nostr ${btoa(JSON.stringify(authEvent))}`,
'Authorization': await getNostrAuthHeader(window.location.protocol + endpoint, 'POST'),
},
body: JSON.stringify({
domain: site.domain,
Expand Down Expand Up @@ -96,17 +99,33 @@
};
}

function deletePost(post, event_id) {
function deletePost(post, event_id) {
let ws = new WebSocket(`${WS_PROTOCOL}//${post.site.domain}`);
ws.onopen = async (e) => {
ws.send(JSON.stringify(['EVENT', await getEvent(5, "", [['e', event_id]])]));
post.persisted = false;
};
}

async function uploadFile(site) {
const endpoint = `${window.location.protocol}//${site.domain}/api/files`;
const request = new XMLHttpRequest();
const formData = new FormData();
request.open("POST", endpoint, true);
request.setRequestHeader('Authorization', await getNostrAuthHeader(endpoint, 'POST'));
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 201) {
alert("Upload successful!");
}
};
let fileInput = document.querySelector('#fileInput');
formData.append('file', fileInput.files[0])
request.send(formData);
}
</script>
</head>
<body>
<div class="w-full mx-auto" x-data="{site: null, post: null, sites: [], posts: []}" x-init="await getSites(sites); await getPosts(sites, posts)">
<div class="w-full mx-auto" x-data="{site: null, post: null, fileManager: false, sites: [], posts: []}" x-init="await getSites(sites); await getPosts(sites, posts)">
<div class="navbar bg-base-200">
<div class="navbar-start">
<a class="btn btn-ghost normal-case text-xl">Servus</a>
Expand All @@ -118,7 +137,7 @@
<div class="drawer md:drawer-open">
<input id="admin-drawer" type="checkbox" class="drawer-toggle" />
<div class="drawer-content flex flex-col items-center justify-center">
<template x-if="post">
<template x-if="site && post">
<div class="w-3/4 mt-24">
<div class="form-control w-full max-w-full">
<label class="label" for="title">
Expand Down Expand Up @@ -158,7 +177,7 @@
</div>
</div>
</template>
<template x-if="!post && site">
<template x-if="site && !post && !fileManager">
<div class="w-3/4 mt-24">
<div class="form-control w-full max-w-full">
<label class="label" for="domain">
Expand All @@ -174,6 +193,12 @@
</div>
</div>
</template>
<template x-if="site && !post && fileManager">
<div>
<input type="file" id="fileInput" />
<button x-on:click="await uploadFile(site);" class="btn btn-primary">Upload</button>
</div>
</template>
</div>
<div class="drawer-side">
<label for="admin-drawer" class="drawer-overlay"></label>
Expand All @@ -193,13 +218,14 @@
<template x-if="p.draft">
<span class="badge badge-primary">draft</span>
</template>
<a x-text="p.title" x-on:click="post = p; site = s;"></a>
<a x-text="p.title" x-on:click="site = s; post = p; fileManager = false;"></a>
</span>
</li>
</template>
</template>
</ul>
<a class="btn btn-outline btn-primary" x-on:click="post = {'id': undefined, 'title': 'New post', 'content': 'New content', 'site': s, 'persisted': false}; posts = posts.concat(post); site = s;">New post</a>
<a class="btn btn-outline btn-primary" x-on:click="site = s; post = {'id': undefined, 'title': 'New post', 'content': 'New content', 'site': s, 'persisted': false}; posts = posts.concat(post); fileManager = false;">New post</a>
<a class="btn btn-outline btn-primary" x-on:click="site = s; post = null; fileManager = true;">Files</a>
</div>
</div>
</template>
Expand Down
Loading

0 comments on commit 42e33ee

Please sign in to comment.