Compare commits

..

No commits in common. "b167d6d586e16d55cdcebe7d82a3ffaecdc0235b" and "192502df18064bed12a34db78b31c0598c65b42b" have entirely different histories.

11 changed files with 109 additions and 30 deletions

45
dist/link.html vendored Normal file
View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/link.css" rel="stylesheet">
<script>
document.addEventListener("DOMContentLoaded", () => {
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
if (params.link !== null) {
let link = `${window.location.origin}/download/${params.link}`;
let link_el = document.getElementById("link");
link_el.href = link;
link_el.innerHTML = link;
}
});
function clipboard() {
let copyText = document.getElementById("link");
navigator.clipboard.writeText(copyText.href).then(() => alert("Copied: " + copyText.href));
}
</script>
</head>
<body>
<div class="link-wrapper">
<a id="link" href=""></a>
</div>
<button class="return-button" onclick="clipboard()">Copy to Clipboard</button>
<a href="/" class="return-button">Return to home</a>
</body>
</html>

5
dist/scripts/cat_fact_fetcher.js vendored Normal file
View File

@ -0,0 +1,5 @@
fetch("https://catfact.ninja/fact")
.then(data => data.json())
.then(data => {
document.getElementById("cat-fact").innerHTML = data.fact;
});

16
dist/scripts/link.js vendored
View File

@ -1,3 +1,19 @@
document.addEventListener("DOMContentLoaded", () => {
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
if (params.link !== null) {
let link = `${window.location.origin}/download/${params.link}`;
let link_el = document.getElementById("link");
link_el.href = link;
link_el.innerHTML = link;
}
});
function clipboard() { function clipboard() {
let copyText = document.getElementById("link"); let copyText = document.getElementById("link");

View File

@ -51,9 +51,9 @@ async fn main() -> io::Result<()> {
} }
async fn welcome() -> impl IntoResponse { async fn welcome() -> impl IntoResponse {
let fact = views::get_cat_fact().await; let cat_fact = views::get_cat_fact().await;
Html(ssr::render(move || { Html(ssr::render(move || {
leptos::view! { <WelcomePage fact /> } leptos::view! { <WelcomePage fact=cat_fact /> }
})) }))
} }

View File

@ -1,6 +1,7 @@
use axum::{ use axum::{
body::Body, body::Body,
extract::State, extract::State,
http::HeaderMap,
response::{IntoResponse, Redirect}, response::{IntoResponse, Redirect},
routing::get, routing::get,
Router, Router,
@ -16,10 +17,20 @@ pub fn get_download_router() -> Router<AppState> {
async fn download( async fn download(
axum::extract::Path(id): axum::extract::Path<String>, axum::extract::Path(id): axum::extract::Path<String>,
headers: HeaderMap,
State(state): State<AppState>, State(state): State<AppState>,
) -> Result<axum::response::Response, (StatusCode, String)> { ) -> Result<axum::response::Response, (StatusCode, String)> {
{ {
let mut records = state.records.lock().await; let mut records = state.records.lock().await;
if headers.get("hx-request").is_some() {
return Ok(axum::http::Response::builder()
.header("HX-Redirect", format!("/download/{id}"))
.status(204)
.body("".to_owned())
.unwrap()
.into_response());
}
if let Some(record) = records if let Some(record) = records
.get_mut(&id) .get_mut(&id)
.filter(|record| record.can_be_downloaded()) .filter(|record| record.can_be_downloaded())

View File

@ -28,7 +28,9 @@ async fn link(
{ {
return Ok(Html(ssr::render({ return Ok(Html(ssr::render({
let record = record.clone(); let record = record.clone();
|| leptos::view! { <DownloadLinkPage id record /> } || {
leptos::view! { <DownloadLinkPage id=id record=record /> }
}
}))); })));
} }
} }

View File

@ -4,7 +4,6 @@ use axum::{
routing::get, routing::get,
Json, Router, Json, Router,
}; };
use leptos::CollectView;
use crate::{util::ssr, AppState, HtmxPage}; use crate::{util::ssr, AppState, HtmxPage};
@ -23,32 +22,31 @@ pub(crate) async fn records(State(state): State<AppState>) -> impl IntoResponse
// this behind some kind of authentication // this behind some kind of authentication
pub async fn records_links(State(state): State<AppState>) -> impl IntoResponse { pub async fn records_links(State(state): State<AppState>) -> impl IntoResponse {
let records = state.records.lock().await.clone(); let records = state.records.lock().await.clone();
let records_list_view = records
.keys()
.map(|key| {
leptos::view! {
<li class="link-wrapper">
<a href="/link/{key}">{key}</a>
<button
style="margin-left: 1em;"
hx-target="closest .link-wrapper"
hx-swap="outerHTML"
hx-delete="/link/{key}"
>
"X"
</button>
</li>
}
})
.collect_view();
Html(ssr::render(move || { Html(ssr::render(move || {
leptos::view! { leptos::view! {
<HtmxPage> <HtmxPage>
<div class="form-wrapper"> <div class="form-wrapper">
<div class="column-container"> <div class="column-container">
<ul>{records_list_view}</ul> <ul>
{records
.keys()
.map(|key| {
leptos::view! {
<li class="link-wrapper">
<a href="/link/{key}">{key}</a>
<button
style="margin-left: 1em;"
hx-target="closest .link-wrapper"
hx-swap="outerHTML"
hx-delete="/link/{key}"
>
X
</button>
</li>
}
})
.collect::<Vec<_>>()}
</ul>
</div> </div>
</div> </div>
</HtmxPage> </HtmxPage>

View File

@ -92,7 +92,9 @@ async fn upload_to_zip(
.status(200) .status(200)
.header("Content-Type", "text/html") .header("Content-Type", "text/html")
.header("HX-Push-Url", format!("/link/{}", &id)) .header("HX-Push-Url", format!("/link/{}", &id))
.body(ssr::render(|| leptos::view! { <LinkView id record /> })) .body(ssr::render(|| {
leptos::view! { <LinkView id record /> }
}))
.unwrap(); .unwrap();
Ok(response) Ok(response)

View File

@ -19,7 +19,7 @@ pub fn HtmxPage(children: Children) -> impl IntoView {
</head> </head>
<body> <body>
<h1>"NyaZoom"<sup>"2"</sup></h1> <h1>NyaZoom<sup>2</sup></h1>
{children()} {children()}
</body> </body>
} }

View File

@ -24,7 +24,7 @@ pub fn LinkView(id: String, record: UploadRecord) -> impl IntoView {
<div class="column-container"> <div class="column-container">
<div class="link-wrapper"> <div class="link-wrapper">
<a id="link" href="/download/{id}"> <a id="link" href="/download/{id}">
"Download Now!" Download Now!
</a> </a>
</div> </div>
@ -40,7 +40,7 @@ pub fn LinkView(id: String, record: UploadRecord) -> impl IntoView {
</button> </button>
<a href="/" class="return-button"> <a href="/" class="return-button">
"Return to home" Return to home
</a> </a>
</div> </div>
} }

View File

@ -38,7 +38,7 @@ pub fn WelcomeView(fact: String) -> impl IntoView {
data-multiple-caption="{{count}} files selected" data-multiple-caption="{{count}} files selected"
multiple multiple
/> />
<label for="file">"Select Files"</label> <label for="file">Select Files</label>
<input type="submit" value="Get Link~" /> <input type="submit" value="Get Link~" />
<p id="cat-fact">{fact}</p> <p id="cat-fact">{fact}</p>