Skip to content

Commit

Permalink
Merge pull request #5 from picture-pro/3-draft-a-gallery-view
Browse files Browse the repository at this point in the history
3 draft a gallery view
  • Loading branch information
johnbchron authored Feb 18, 2024
2 parents f04e380 + 80aa280 commit 7a1d48b
Show file tree
Hide file tree
Showing 17 changed files with 849 additions and 144 deletions.
713 changes: 598 additions & 115 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@ codegen-units = 1
[workspace.dependencies]
axum = { version = "0.7.4", features = ["macros"] }
axum-login = "0.13"
base64 = { version = "0.21" }
bytes = "1.5.0"
cfg-if = "1"
color-eyre = "0.6"
console_error_panic_hook = "0.1.7"
console_log = "1"
http = "1"
image = { version = "0.24", features = [ "avif-encoder" ] }
leptos = { version = "0.6", features = ["nightly", "experimental-islands"] }
leptos_axum = { version = "0.6", features = ["experimental-islands"] }
leptos_meta = { version = "0.6", features = ["nightly"] }
leptos_router = { version = "0.6", features = ["nightly"] }
server_fn = { version = "0.6", features = ["multipart"] }
log = "0.4"
server_fn = { version = "0.6", features = ["multipart"] }
serde = { version = "1", features = ["derive"] }
simple_logger = "4.2.0"
surrealdb = { version = "1" }
Expand Down
1 change: 1 addition & 0 deletions accreditations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Blanton Lewis** - for thoughtful design recommendations.
2 changes: 1 addition & 1 deletion crates/artifact/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Artifact for PublicArtifact {
id: id.clone(),
contents,
url: format!(
"s3.{}.amazonaws.com/{}/{}",
"https://s3.{}.amazonaws.com/{}/{}",
std::env::var("AWS_DEFAULT_REGION").unwrap(),
ARTIFACT_PUBLIC_LTS_BUCKET,
id.0
Expand Down
2 changes: 1 addition & 1 deletion crates/bl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ artifact = { path = "../artifact" }

bytes.workspace = true
color-eyre.workspace = true
image.workspace = true
thiserror.workspace = true
surrealdb.workspace = true
serde.workspace = true
ulid.workspace = true

image = "0.24.8"
25 changes: 21 additions & 4 deletions crates/bl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use core_types::{
AsThing, NewId, Photo, PhotoArtifacts, PhotoGroup, PhotoGroupUploadMeta,
PrivateArtifact, PublicArtifact,
};
use image::ImageEncoder;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize, thiserror::Error)]
Expand Down Expand Up @@ -47,7 +48,7 @@ pub async fn upload_single_photo(
))
})?;

// create a thumbnail and upload it as an artifact
// create a thumbnail image
let aspect_ratio =
original_image.width() as f32 / original_image.height() as f32;
let thumbnail_size = thumbnail_size(aspect_ratio);
Expand All @@ -57,7 +58,17 @@ pub async fn upload_single_photo(
thumbnail_size.1,
image::imageops::FilterType::Lanczos3,
);
let thumbnail_bytes: Bytes = thumbnail_image.as_bytes().to_vec().into();

// encode as png to bytes
let mut thumbnail_bytes = Vec::new();
let encoder = image::codecs::png::PngEncoder::new(&mut thumbnail_bytes);
thumbnail_image.write_with_encoder(encoder).map_err(|e| {
PhotoUploadError::InvalidImage(format!(
"Failed to encode thumbnail image: {e:?}"
))
})?;

let thumbnail_bytes: Bytes = thumbnail_bytes.into();
let thumbnail_artifact = PublicArtifact::new(Some(thumbnail_bytes));
thumbnail_artifact.upload_and_push().await.map_err(|e| {
PhotoUploadError::ArtifactCreationError(format!(
Expand All @@ -71,8 +82,14 @@ pub async fn upload_single_photo(
photographer: user_id.clone(),
owner: user_id.clone(),
artifacts: PhotoArtifacts {
original: original_artifact,
thumbnail: thumbnail_artifact,
original: core_types::PrivateImageArtifact {
artifact_id: original_artifact.id,
size: (original_image.width(), original_image.height()),
},
thumbnail: core_types::PublicImageArtifact {
artifact_id: thumbnail_artifact.id,
size: (thumbnail_image.width(), thumbnail_image.height()),
},
},
};

Expand Down
4 changes: 2 additions & 2 deletions crates/core_types/src/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
pub const PRIVATE_ARTIFACT_TABLE: &str = "private_artifact";
pub const PUBLIC_ARTIFACT_TABLE: &str = "public_artifact";

#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize, Copy)]
#[cfg_attr(feature = "ssr", serde(from = "crate::conv::UlidOrThing"))]
pub struct PrivateArtifactRecordId(pub ulid::Ulid);

Expand All @@ -14,7 +14,7 @@ pub struct PrivateArtifact {
pub contents: Option<bytes::Bytes>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize, Copy)]
#[cfg_attr(feature = "ssr", serde(from = "crate::conv::UlidOrThing"))]
pub struct PublicArtifactRecordId(pub ulid::Ulid);

Expand Down
2 changes: 1 addition & 1 deletion crates/core_types/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};

pub const USER_TABLE: &str = "user";

#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[cfg_attr(feature = "ssr", serde(from = "crate::conv::UlidOrThing"))]
pub struct UserRecordId(pub ulid::Ulid);

Expand Down
22 changes: 20 additions & 2 deletions crates/core_types/src/conv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use serde::Deserialize;
use surreal_id::NewId;
use surrealdb::sql::{Id, Thing};
use surrealdb::{
opt::{IntoResource, Resource},
sql::{Id, Thing},
};

use crate::{
PhotoGroupRecordId, PhotoRecordId, PrivateArtifactRecordId,
Expand Down Expand Up @@ -57,10 +60,25 @@ pub trait AsThing {

impl<T: NewId> AsThing for T {
fn as_thing(&self) -> Thing {
println!("converting to thing: {:?}", self.get_inner_string());
Thing {
tb: T::TABLE.to_string(),
id: Id::String(self.get_inner_string()),
}
}
}

macro_rules! impl_into_resource {
($type:ty) => {
impl<R> IntoResource<Option<R>> for $type {
fn into_resource(self) -> Result<Resource, surrealdb::Error> {
Ok(Resource::RecordId(self.as_thing()))
}
}
};
}

impl_into_resource!(UserRecordId);
impl_into_resource!(PhotoRecordId);
impl_into_resource!(PhotoGroupRecordId);
impl_into_resource!(PrivateArtifactRecordId);
impl_into_resource!(PublicArtifactRecordId);
21 changes: 16 additions & 5 deletions crates/core_types/src/photo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ pub const PHOTO_TABLE: &str = "photo";
pub const PHOTO_GROUP_TABLE: &str = "photo_group";

use crate::{
artifact::{PrivateArtifact, PublicArtifact},
auth::UserRecordId,
auth::UserRecordId, PrivateArtifactRecordId, PublicArtifactRecordId,
};

#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize, Copy)]
#[cfg_attr(feature = "ssr", serde(from = "crate::conv::UlidOrThing"))]
pub struct PhotoRecordId(pub ulid::Ulid);

Expand All @@ -22,11 +21,23 @@ pub struct Photo {

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PhotoArtifacts {
pub original: PrivateArtifact,
pub thumbnail: PublicArtifact,
pub original: PrivateImageArtifact,
pub thumbnail: PublicImageArtifact,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PublicImageArtifact {
pub artifact_id: PublicArtifactRecordId,
pub size: (u32, u32),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PrivateImageArtifact {
pub artifact_id: PrivateArtifactRecordId,
pub size: (u32, u32),
}

#[derive(Clone, Debug, Deserialize, Serialize, Copy)]
#[cfg_attr(feature = "ssr", serde(from = "crate::conv::UlidOrThing"))]
pub struct PhotoGroupRecordId(pub ulid::Ulid);

Expand Down
6 changes: 5 additions & 1 deletion crates/site-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,25 @@ cfg-if.workspace = true
thiserror.workspace = true
serde.workspace = true
bytes = { workspace = true, optional = true }
base64 = { workspace = true, optional = true }
image = { workspace = true, optional = true }

validator = "0.16.1"
web-sys = { version = "0.3", features = [ "Window", "EventTarget" ] }

core_types = { path = "../core_types" }
validation = { path = "../validation" }

artifact = { path = "../artifact", optional = true }
auth = { path = "../auth", optional = true }
clients = { path = "../clients", optional = true }
bl = { path = "../bl", optional = true }

[features]
default = []
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"leptos/ssr", "leptos_meta/ssr", "leptos_router/ssr", "dep:leptos_axum",
"auth", "bl", "bytes"
"artifact", "auth", "base64", "bl", "bytes", "clients", "image"
]

60 changes: 50 additions & 10 deletions crates/site-app/src/components/gallery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,65 @@ pub fn Gallery() -> impl IntoView {

let photo_groups = create_resource(
move || (),
move |_| get_user_photo_groups(user.id.clone()),
move |_| fetch_user_photo_groups(user.id.clone()),
);

view! {
<Suspense fallback=|| view!{<p>"Loading..."</p>}>
{ move || photo_groups.map(|groups| view! {
<pre class="text-sm leading-6 flex ligatures-none overflow-auto whitespace-pre-wrap">
<code class="bg-base-200 rounded-box p-2">
{format!("Photo Groups: {:#?}", groups)}
</code>
</pre>
})}
<Suspense fallback=|| view!{ }>
{ move || photo_groups.map(|groups| {
match groups {
Ok(groups) => {
view! {
<PhotoGroupList groups=groups.clone() />
}
.into_view()
}
Err(e) => {
view! {
<p>"Failed to load photo groups: {e}"</p>
}
.into_view()
}
}
}) }
</Suspense>
}
.into_view()
}

#[component]
fn PhotoGroupList(groups: Vec<core_types::PhotoGroup>) -> impl IntoView {
view! {
<div class="flex flex-row flex-wrap gap-4">
{ groups.into_iter().map(|group| {
view! {
<PhotoGroup group=group />
}
.into_view()
}).collect::<Vec<_>>() }
</div>
}
.into_view()
}

#[component]
fn PhotoGroup(group: core_types::PhotoGroup) -> impl IntoView {
view! {
<div class="flex p-4 bg-base-200 rounded-box border">
<div class="flex gap-4">
{ group.photos.into_iter().map(|photo_id| {
view! {
<crate::components::photo::Photo photo_id=photo_id />
}
.into_view()
}).collect::<Vec<_>>() }
</div>
</div>
}
}

#[server]
pub async fn get_user_photo_groups(
pub async fn fetch_user_photo_groups(
user_id: core_types::UserRecordId,
) -> Result<Vec<core_types::PhotoGroup>, ServerFnError> {
bl::get_user_photo_groups(user_id).await.map_err(|e| {
Expand Down
1 change: 1 addition & 0 deletions crates/site-app/src/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod form;
pub mod gallery;
pub mod navigation;
pub mod photo;
pub mod photo_upload;
Loading

0 comments on commit 7a1d48b

Please sign in to comment.