Skip to content

Commit

Permalink
Merge pull request #104 from picture-pro/100-overhaul-visual-style
Browse files Browse the repository at this point in the history
100 overhaul visual style
  • Loading branch information
johnbchron authored Mar 25, 2024
2 parents 4b0d0ba + 17ae77c commit dd23444
Show file tree
Hide file tree
Showing 15 changed files with 458 additions and 480 deletions.
547 changes: 211 additions & 336 deletions Cargo.lock

Large diffs are not rendered by default.

34 changes: 25 additions & 9 deletions crates/artifact/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,46 @@ pub fn object_store_from_env(
Ok(Box::new(object_store))
}

fn cache_dir() -> std::path::PathBuf { std::env::temp_dir() }
fn cache_path(id: &str) -> std::path::PathBuf { cache_dir().join(id) }
/// Get the cache directory for artifacts.
///
/// By default, this is the system's temporary directory. It can be overridden
/// by setting the `TMPDIR` environment variable. If the directory does not
/// exist, it will be created.
fn get_cache_dir() -> Result<std::path::PathBuf> {
let cache_dir = std::env::temp_dir();
if !cache_dir.exists() {
tracing::debug!("creating cache directory");
std::fs::create_dir_all(&cache_dir)
.wrap_err("Failed to create cache directory")?;
}
Ok(cache_dir)
}
/// Get the path to the cached artifact.
///
/// The parent directory will be created in [`get_cache_dir`] if it does not
/// exist.
fn cache_path(id: &str) -> Result<std::path::PathBuf> {
get_cache_dir().map(|d| d.join(id))
}

#[instrument(skip(object_store))]
pub async fn download_artifact(
object_store: ObjectStoreGenerator,
id: &str,
) -> Result<bytes::Bytes> {
let cache_path = cache_path(id);
let cache_path = cache_path(id)?;
if cache_path.exists() {
tracing::debug!("using cached artifact instead of downloading");
let contents = tokio::fs::read(cache_path)
.await
.wrap_err("Failed to read cached artifact")?;
return Ok(contents.into());
}

let object_store = object_store()?;
tracing::debug!("downloading uncached artifact");
let contents = inner_download_artifact(&*object_store, id).await?;

if !cache_dir().exists() {
tokio::fs::create_dir_all(cache_dir())
.await
.wrap_err("Failed to create cache directory")?;
}
tokio::fs::write(&cache_path, &contents)
.await
.wrap_err("Failed to write cached artifact")?;
Expand Down Expand Up @@ -73,7 +89,7 @@ pub async fn upload_artifact(
id: &str,
contents: bytes::Bytes,
) -> Result<()> {
let cache_path = cache_path(id);
let cache_path = cache_path(id)?;
tokio::fs::write(&cache_path, &contents)
.await
.wrap_err("Failed to write cached artifact")?;
Expand Down
4 changes: 2 additions & 2 deletions crates/bl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ edition = "2021"
[dependencies]
core_types = { path = "../core_types" }
leptos.workspace = true
bytes.workspace = true
serde.workspace = true
thiserror.workspace = true
http.workspace = true
Expand All @@ -19,6 +18,7 @@ artifact = { path = "../artifact", optional = true }
rmp-serde = "1.1.2"

base64 = { workspace = true, optional = true }
bytes = { workspace = true, optional = true }
chrono = { workspace = true, optional = true }
color-eyre = { workspace = true, optional = true }
image = { workspace = true, optional = true }
Expand All @@ -37,5 +37,5 @@ hydrate = [ "leptos/hydrate" ]
ssr = [
"core_types/ssr", "leptos/ssr", "dep:clients", "dep:artifact", "dep:base64",
"dep:color-eyre", "dep:image", "dep:qrcode", "dep:rayon", "dep:surrealdb",
"dep:tokio", "dep:tracing", "dep:kamadak-exif", "dep:chrono",
"dep:tokio", "dep:tracing", "dep:kamadak-exif", "dep:chrono", "dep:bytes",
]
4 changes: 2 additions & 2 deletions crates/site-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ serde.workspace = true
bytes = { workspace = true, optional = true }
time = { workspace = true, optional = true }
chrono = { workspace = true }
timeago = { workspace = true }
timeago = { workspace = true, optional = true }
tower-sessions = { workspace = true, optional = true }
tracing = { workspace = true, optional = true }

Expand All @@ -39,6 +39,6 @@ hydrate = ["bl/hydrate", "leptos/hydrate", "leptos_meta/hydrate", "leptos_router
ssr = [
"bl/ssr", "leptos/ssr", "leptos/tracing", "leptos_meta/ssr", "leptos_router/ssr",
"dep:leptos_axum", "dep:auth", "dep:bytes", "dep:tracing", "dep:tower-sessions",
"dep:time",
"dep:time", "dep:timeago",
]

22 changes: 19 additions & 3 deletions crates/site-app/src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,27 @@ pub mod basic {

#[component]
pub fn TimeAgo(time: chrono::DateTime<chrono::Utc>) -> impl IntoView {
let formatter = timeago::Formatter::new();
let formatted = formatter.convert_chrono(time, chrono::Utc::now());
let formatted_time = create_blocking_resource(move || time, format_timeago);

view! {
<span>{ formatted }</span>
<Suspense fallback=|| view!{}>
{ move || match formatted_time() {
Some(Ok(time)) => view! {
<span>{ time }</span>
}.into_view(),
_ => view! {
<span>...</span>
}.into_view()
}}
</Suspense>
}
}

#[server]
async fn format_timeago(
date: chrono::DateTime<chrono::Utc>,
) -> Result<String, ServerFnError> {
let formatter = timeago::Formatter::new();
Ok(formatter.convert_chrono(date, chrono::Utc::now()))
}
}
9 changes: 7 additions & 2 deletions crates/site-app/src/components/photo_deck.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
use leptos::*;

use crate::components::photo::PhotoSize;

#[component]
pub fn PhotoDeck(ids: Vec<core_types::PhotoRecordId>) -> impl IntoView {
pub fn PhotoDeck(
ids: Vec<core_types::PhotoRecordId>,
#[prop(default = PhotoSize::Regular)] size: PhotoSize,
) -> impl IntoView {
view! {
{ ids.into_iter().map(|photo_id| {
view! {
<crate::components::photo::Photo photo_id=photo_id />
<crate::components::photo::Photo photo_id=photo_id size=size />
}
.into_view()
}).collect::<Vec<_>>() }
Expand Down
72 changes: 34 additions & 38 deletions crates/site-app/src/components/photo_upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ fn round_with_scale(input: f32, scale: f32) -> f32 {
}

/// Converts a price to a reasonable multiple.
#[allow(illegal_floating_point_literal_pattern)]
fn sensible_price(input: f32) -> f32 {
match input {
0.0..=1.0 => round_with_scale(input, 0.05),
Expand Down Expand Up @@ -72,47 +71,44 @@ pub fn PhotoUpload() -> impl IntoView {
});

view! {
<div class="d-card bg-base-100 shadow max-w-sm">
<div class="d-card-body gap-4">
<p class="text-2xl font-semibold tracking-tight">"Upload Photo"</p>

// price input
<div class="flex flex-row gap-4 items-center">
<label for="price">"Price"</label>
<input
type="range" class="d-range" id="price" name="price"
min={MIN_PRICE.log10()} max={MAX_PRICE.log10()} step=0.01
on:input=move |e: Event| {
set_logarithmic_price(event_target_value(&e).parse::<f32>().unwrap());
}
value={DEFAULT_PRICE.log10()}
prop:value=logarithmic_price
/>
<p class="min-w-[4rem] text-right">{move || format!("${:.2}", price())}</p>
</div>

// file input
<div class="flex flex-col p-8 gap-4 rounded-box bg-base-100 shadow max-w-sm">
<p class="text-2xl font-semibold tracking-tight">"Upload Photo"</p>

// price input
<div class="flex flex-row gap-4 items-center">
<label for="price">"Price"</label>
<input
type="file" class="d-file-input d-file-input-bordered w-full"
name="photo" accept="image/*" capture="camera" multiple="multiple"
required=true on:input=move |e: Event| {
let target = e.target().unwrap().dyn_into::<HtmlInputElement>().unwrap();
set_files(target.files());
type="range" class="d-range" id="price" name="price"
min={MIN_PRICE.log10()} max={MAX_PRICE.log10()} step=0.01
on:input=move |e: Event| {
set_logarithmic_price(event_target_value(&e).parse::<f32>().unwrap());
}
value={DEFAULT_PRICE.log10()}
prop:value=logarithmic_price
/>
<p class="min-w-[4rem] text-right">{move || format!("${:.2}", price())}</p>
</div>

// upload button
<div class="d-form-control mt-6">
<button
class="d-btn d-btn-primary w-full"
disabled=move || pending() || files().is_none()
on:click=move |_| upload_action.dispatch((files().unwrap(), price()))
>
{ move || if pending() { view!{ <span class="d-loading d-loading-spinner" /> }.into_view() } else { view! {}.into_view() } }
"Upload"
</button>
</div>

// file input
<input
type="file" class="d-file-input d-file-input-bordered w-full"
name="photo" accept="image/*" capture="camera" multiple="multiple"
required=true on:input=move |e: Event| {
let target = e.target().unwrap().dyn_into::<HtmlInputElement>().unwrap();
set_files(target.files());
}
/>

// upload button
<div class="d-form-control mt-6">
<button
class="d-btn d-btn-primary w-full"
disabled=move || pending() || files().is_none()
on:click=move |_| upload_action.dispatch((files().unwrap(), price()))
>
{ move || if pending() { view!{ <span class="d-loading d-loading-spinner" /> }.into_view() } else { view! {}.into_view() } }
"Upload"
</button>
</div>
</div>
}
Expand Down
20 changes: 8 additions & 12 deletions crates/site-app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ pub fn App() -> impl IntoView {
view! {
<Style>{include_str!("../style/fonts.css")}</Style>
<Stylesheet id="leptos" href="/pkg/site.css"/>
<Link rel="preload" href="fonts/inter.ttf" as_="font" type_="font/ttf" crossorigin="anonymous" />
<Link rel="preload" href="/fonts/inter.ttf" as_="font" type_="font/ttf" crossorigin="anonymous" />

<Html lang="en" attr:data-theme="wireframe" />
<Html lang="en" attr:data-theme="dark" />

// set the metadata
<Title text="PicturePro"/>
Expand Down Expand Up @@ -59,21 +59,17 @@ pub fn App() -> impl IntoView {
#[component]
pub fn Navbar() -> impl IntoView {
let current_user = authenticated_user();
let home_url = if current_user.is_some() {
"/dashboard"
} else {
"/"
};
let button_class = "d-btn d-btn-neutral d-btn-sm";

let user_area = match current_user {
Some(_user) => view! {
<a class="d-btn d-btn-neutral d-btn-sm" href="/dashboard">Dashboard</a>
<LogoutButton class={Some("d-btn d-btn-neutral d-btn-sm".into())} />
<a class={button_class} href="/dashboard">Dashboard</a>
<LogoutButton class={Some(button_class.into())} />
}
.into_view(),
None => view! {
<a class="d-btn d-btn-neutral d-btn-sm" href="/login">Login</a>
<a class="d-btn d-btn-neutral d-btn-sm" href="/signup">Sign Up</a>
<a class={button_class} href="/login">Login</a>
<a class={button_class} href="/signup">Sign Up</a>
}
.into_view(),
};
Expand All @@ -82,7 +78,7 @@ pub fn Navbar() -> impl IntoView {
<div class="bg-base-100 w-full shadow">
<div class="d-navbar md:container md:mx-auto">
<div class="flex-1">
<a class="d-btn d-btn-ghost text-xl d-btn-sm" href={home_url}>PicturePro</a>
<a class="d-btn d-btn-ghost text-xl d-btn-sm" href="/">PicturePro</a>
</div>
<div class="flex-none flex flex-row items-center gap-2">
{user_area}
Expand Down
Loading

0 comments on commit dd23444

Please sign in to comment.