aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/ui/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/routes/ui/node.rs')
-rw-r--r--server/src/routes/ui/node.rs52
1 files changed, 41 insertions, 11 deletions
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 3820b14..fc12db3 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -5,7 +5,7 @@
*/
use super::{
assets::{rocket_uri_macro_r_item_assets, rocket_uri_macro_r_node_thumbnail},
- error::MyError,
+ error::MyResult,
sort::{filter_and_sort_nodes, NodeFilterSort, NodeFilterSortForm},
};
use crate::{
@@ -14,7 +14,7 @@ use crate::{
api::AcceptJson,
ui::{
account::session::Session,
- assets::AssetRole,
+ assets::{rocket_uri_macro_r_person_asset, AssetRole},
layout::{DynLayoutPage, LayoutPage},
player::{rocket_uri_macro_r_player, PlayerConfig},
},
@@ -25,12 +25,12 @@ use crate::{
use anyhow::{anyhow, Result};
use chrono::NaiveDateTime;
use jellybase::{
- database::{TableExt, T_NODE, T_USER_NODE},
+ database::{TableExt, T_NODE, T_NODE_EXTENDED, T_USER_NODE},
permission::NodePermissionExt,
};
use jellycommon::{
user::{NodeUserData, WatchedState},
- Chapter, MediaInfo, NodeKind, NodePublic, Rating, SourceTrackKind,
+ Chapter, ExtendedNode, MediaInfo, NodeKind, NodePublic, PeopleGroup, Rating, SourceTrackKind,
};
use rocket::{get, serde::json::Json, Either, State};
@@ -40,6 +40,20 @@ pub fn r_library_node(id: String) {
drop(id)
}
+#[get("/n/<id>/extended")]
+pub async fn r_library_node_ext<'a>(
+ session: Session,
+ id: &'a str,
+ db: &'a State<DataAcid>,
+) -> MyResult<Json<ExtendedNode>> {
+ T_NODE
+ .get(&db, id)?
+ .only_if_permitted(&session.user.permissions)
+ .ok_or(anyhow!("node does not exist"))?;
+
+ Ok(Json(T_NODE_EXTENDED.get(db, id)?.unwrap_or_default()))
+}
+
#[get("/n/<id>?<filter..>")]
pub async fn r_library_node_filter<'a>(
session: Session,
@@ -47,12 +61,13 @@ pub async fn r_library_node_filter<'a>(
db: &'a State<DataAcid>,
aj: AcceptJson,
filter: NodeFilterSort,
-) -> Result<Either<DynLayoutPage<'a>, Json<NodePublic>>, MyError> {
+) -> MyResult<Either<DynLayoutPage<'a>, Json<NodePublic>>> {
let node = T_NODE
.get(&db, id)?
.only_if_permitted(&session.user.permissions)
.ok_or(anyhow!("node does not exist"))?
.public;
+ let node_ext = T_NODE_EXTENDED.get(db, id)?.unwrap_or_default();
let udata = T_USER_NODE
.get(&db, &(session.user.name.as_str(), id))?
@@ -75,7 +90,7 @@ pub async fn r_library_node_filter<'a>(
Ok(Either::Left(LayoutPage {
title: node.title.clone().unwrap_or_default(),
content: markup::new! {
- @NodePage { node: &node, id: &id, udata: &udata, children: &children, filter: &filter }
+ @NodePage { node: &node, id: &id, udata: &udata, children: &children, filter: &filter, node_ext: &node_ext }
},
..Default::default()
}))
@@ -87,7 +102,7 @@ markup::define! {
div[class=cls] {
.poster {
a[href=uri!(r_library_node(id))] {
- img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(1024)))];
+ img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(1024))), loading="lazy"];
}
.cardhover.item {
@if !(matches!(node.kind.unwrap_or_default(), NodeKind::Collection | NodeKind::Channel)) {
@@ -103,13 +118,13 @@ markup::define! {
}
}
}
- NodePage<'a>(id: &'a str, node: &'a NodePublic, udata: &'a NodeUserData, children: &'a Vec<(String, NodePublic, NodeUserData)>, filter: &'a NodeFilterSort) {
+ NodePage<'a>(id: &'a str, node: &'a NodePublic, node_ext: &'a ExtendedNode, udata: &'a NodeUserData, children: &'a Vec<(String, NodePublic, NodeUserData)>, filter: &'a NodeFilterSort) {
@if !matches!(node.kind.unwrap_or_default(), NodeKind::Collection) {
- img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop, Some(2048)))];
+ img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop, Some(2048))), loading="lazy"];
}
.page.node {
@if !matches!(node.kind.unwrap_or_default(), NodeKind::Collection) {
- div.bigposter { img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(2048)))]; }
+ div.bigposter { img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(2048))), loading="lazy"]; }
}
.title {
h1 { @node.title }
@@ -151,7 +166,7 @@ markup::define! {
li { .card."aspect-thumb" {
.poster {
a[href=&uri!(r_player(id, PlayerConfig::seek(chap.time_start.unwrap_or(0.))))] {
- img[src=&uri!(r_node_thumbnail(id, chapter_key_time(chap, media.duration), Some(1024)))];
+ img[src=&uri!(r_node_thumbnail(id, chapter_key_time(chap, media.duration), Some(1024))), loading="lazy"];
}
.cardhover { .props { p { @inl } } }
}
@@ -159,6 +174,21 @@ markup::define! {
}}
}}}
}
+ h2 { "Cast & Crew" }
+ @for (group, people) in &node_ext.people {
+ h3 { @format!("{:?}", group) }
+ .hlist { ul.children { @for (i, pe) in people.iter().enumerate() {
+ li { .card."aspect-port" {
+ .poster {
+ a[href="#"] {
+ img[src=&uri!(r_person_asset(id, i, group, Some(1024))), loading="lazy"];
+ }
+ // .cardhover { .props { p { @pe.person.name } } }
+ }
+ .title { @pe.person.name }
+ }}
+ }}}
+ }
details {
summary { "Tracks" }
ol { @for track in &media.tracks {