This commit is contained in:
JMARyA 2025-01-26 10:52:02 +01:00
parent 5ae9b80302
commit 8daef6920c
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
9 changed files with 158 additions and 135 deletions

48
Cargo.lock generated
View file

@ -202,7 +202,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "based" name = "based"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.hydrar.de/jmarya/based?branch=ui#79f08fd202abcfbc52cbab09be7dccc02f4c7c01" source = "git+https://git.hydrar.de/jmarya/based?branch=ui#3f411e071fd4d47ff0e2d7e7eeab4f638bd35799"
dependencies = [ dependencies = [
"bcrypt", "bcrypt",
"chrono", "chrono",
@ -403,9 +403,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.16" version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -1350,9 +1350,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.7.0" version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.15.2", "hashbrown 0.15.2",
@ -1376,19 +1376,19 @@ dependencies = [
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.10.1" version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]] [[package]]
name = "is-terminal" name = "is-terminal"
version = "0.4.13" version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
dependencies = [ dependencies = [
"hermit-abi 0.4.0", "hermit-abi 0.4.0",
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -1601,9 +1601,9 @@ dependencies = [
[[package]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.12" version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
@ -1706,9 +1706,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.68" version = "0.10.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" checksum = "f5e534d133a060a3c19daec1eb3e98ec6f4685978834f2dbadfe2ec215bab64e"
dependencies = [ dependencies = [
"bitflags 2.8.0", "bitflags 2.8.0",
"cfg-if", "cfg-if",
@ -1732,9 +1732,9 @@ dependencies = [
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
version = "0.1.5" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
@ -2313,9 +2313,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.43" version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [ dependencies = [
"bitflags 2.8.0", "bitflags 2.8.0",
"errno", "errno",
@ -2459,9 +2459,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.135" version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
@ -3286,9 +3286,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.14" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@ -3354,9 +3354,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.12.0" version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"serde", "serde",

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
based = { git = "https://git.hydrar.de/jmarya/based", features = ["htmx"], branch = "ui" } based = { git = "https://git.hydrar.de/jmarya/based", branch = "ui" }
bytesize = "1.3.0" bytesize = "1.3.0"
chrono = "0.4.39" chrono = "0.4.39"
env_logger = "0.11.6" env_logger = "0.11.6"

View file

@ -1,5 +1,8 @@
use based::asset::AssetRoutes;
use based::auth::User; use based::auth::User;
use based::get_pg; use based::get_pg;
use based::ui::components::Shell;
use based::ui::prelude::*;
use config::Config; use config::Config;
use rocket::routes; use rocket::routes;
@ -19,9 +22,20 @@ async fn launch() -> _ {
let _ = User::create("admin".to_string(), "admin", based::auth::UserRole::Admin).await; let _ = User::create("admin".to_string(), "admin", based::auth::UserRole::Admin).await;
let shell = Shell::new(
Nothing(),
Nothing(),
Background(MinHeight(
ScreenValue::screen,
Padding(Text("").color(&Gray::_200)).all(ScreenValue::_10),
))
.color(Gray::_900),
)
.use_ui();
rocket::build() rocket::build()
.mount_assets()
.mount("/", routes![ .mount("/", routes![
based::htmx::htmx_script_route,
routes::index_page, routes::index_page,
routes::pkg_route, routes::pkg_route,
routes::push::upload_pkg, routes::push::upload_pkg,
@ -36,4 +50,5 @@ async fn launch() -> _ {
routes::user::change_password_post routes::user::change_password_post
]) ])
.manage(config) .manage(config)
.manage(shell)
} }

View file

@ -91,7 +91,7 @@ impl Package {
} }
} }
let mut ret: Vec<_> = ret.into_iter().map(|x| (x.0, x.1.join(" "))).collect(); let mut ret: Vec<_> = ret.into_iter().map(|x| (x.0, x.1.join(";"))).collect();
ret.sort_by(|a, b| a.0.cmp(&b.0)); ret.sort_by(|a, b| a.0.cmp(&b.0));
ret ret
@ -218,6 +218,15 @@ impl Package {
.collect() .collect()
} }
pub fn fonts(&self) -> Vec<String> {
let files = self.file_list();
files
.into_iter()
.filter(|x| x.starts_with("usr/share/fonts"))
.map(|x| x.trim_start_matches("usr/share/fonts/").to_string())
.collect()
}
pub fn firmware(&self) -> Vec<String> { pub fn firmware(&self) -> Vec<String> {
let files = self.file_list(); let files = self.file_list();
files files

View file

@ -1,8 +1,8 @@
use based::auth::MaybeUser; use based::auth::MaybeUser;
use based::request::{RawResponse, RequestContext, StringResponse, respond_with}; use based::request::{RawResponse, RequestContext, StringResponse, respond_with};
use based::ui::components::Shell; use based::ui::components::Shell;
use based::ui::{prelude::*, render_page}; use based::ui::prelude::*;
use maud::{PreEscaped, Render, html}; use maud::{Render, html};
use pacco::pkg::mirror::MirrorRepository; use pacco::pkg::mirror::MirrorRepository;
use rocket::http::{ContentType, Status}; use rocket::http::{ContentType, Status};
use rocket::{State, get}; use rocket::{State, get};
@ -21,6 +21,7 @@ pub async fn index_page(
ctx: RequestContext, ctx: RequestContext,
user: MaybeUser, user: MaybeUser,
config: &State<Config>, config: &State<Config>,
shell: &State<Shell>,
) -> StringResponse { ) -> StringResponse {
let repos: Vec<String> = Repository::list(); let repos: Vec<String> = Repository::list();
@ -40,8 +41,8 @@ pub async fn index_page(
Padding( Padding(
Shadow::medium( Shadow::medium(
Flex(Hover( Flex(Hover(
Background(Gray::_600, Nothing())).on( Background(Nothing()).color(Gray::_600)).on(
Background(Gray::_700, Background(
Link( Link(
&format!("/{repo}"), &format!("/{repo}"),
Div().vanish().push(Text(&repo).medium().color(&Gray::_100)) Div().vanish().push(Text(&repo).medium().color(&Gray::_100))
@ -49,8 +50,8 @@ pub async fn index_page(
if config.is_mirrored_repo(&repo) { if config.is_mirrored_repo(&repo) {
Some(&()) Some(&())
} else { None }, } else { None },
|_: &()| Context(Padding(Rounded(Background(Blue::_500, Text("Mirrored").white().medium().sm())).size(Size::Full)).x(ScreenValue::_3).y(ScreenValue::_1)))).use_htmx() |_: &()| Context(Padding(Rounded(Background(Text("Mirrored").white().medium().sm()).color(Blue::_500)).size(Size::Full)).x(ScreenValue::_3).y(ScreenValue::_1)))).use_htmx()
))).items_center().gap(ScreenValue::_4) ).color(Gray::_700))).items_center().gap(ScreenValue::_4)
)).all(ScreenValue::_4)) )).all(ScreenValue::_4))
.size(Size::Large))) .size(Size::Large)))
} }
@ -58,7 +59,7 @@ pub async fn index_page(
) )
).render(); ).render();
render(content, "Repositories", ctx).await shell.render_page(content, "Repositories", ctx).await
} }
#[get("/pkg/<repo>/<arch>/<pkg_name>")] #[get("/pkg/<repo>/<arch>/<pkg_name>")]
@ -159,28 +160,6 @@ pub async fn pkg_route(
) )
} }
pub async fn render(
content: PreEscaped<String>,
title: &str,
ctx: RequestContext,
) -> StringResponse {
render_page(
content,
title,
ctx,
&Shell::new(
html! {
script src="https://cdn.tailwindcss.com" {};
script src="/assets/htmx.min.js" {};
meta name="viewport" content="width=device-width, initial-scale=1.0";
},
html! {},
Some("bg-gray-900 text-gray-200 min-h-screen p-10".to_string()),
),
)
.await
}
pub fn is_repo_db(pkg_name: &str) -> bool { pub fn is_repo_db(pkg_name: &str) -> bool {
pkg_name.ends_with("db.tar.gz") pkg_name.ends_with("db.tar.gz")
|| pkg_name.ends_with("db") || pkg_name.ends_with("db")

View file

@ -1,8 +1,6 @@
use based::ui::prelude::*; use based::ui::prelude::*;
use maud::{PreEscaped, Render}; use maud::{PreEscaped, Render};
use super::render;
// TODO : API // TODO : API
pub mod pkg; pub mod pkg;
@ -21,9 +19,9 @@ pub fn arch_card(a: &str, repo_name: &str, current: bool) -> PreEscaped<String>
Rounded( Rounded(
Padding(if current { Padding(if current {
Background(Blue::_500, link) Background(link).color(Blue::_500)
} else { } else {
Background(Gray::_700, link) Background(link).color(Gray::_700)
}) })
.x(ScreenValue::_3) .x(ScreenValue::_3)
.y(ScreenValue::_1), .y(ScreenValue::_1),

View file

@ -1,15 +1,14 @@
use based::request::{RequestContext, StringResponse}; use based::request::{RequestContext, StringResponse};
use based::ui::components::Shell;
use based::ui::primitives::flex::Strategy; use based::ui::primitives::flex::Strategy;
use based::ui::primitives::space::SpaceBetweenWidget; use based::ui::primitives::space::SpaceBetweenWidget;
use based::ui::primitives::text::{Code, TextWidget}; use based::ui::primitives::text::{Code, TextWidget};
use based::ui::{UIWidget, prelude::*}; use based::ui::{UIWidget, prelude::*};
use maud::{PreEscaped, Render, html}; use maud::{PreEscaped, Render, html};
use rocket::get; use rocket::{State, get};
use pacco::pkg::{Package, Repository, arch::Architecture, find_package_by_name}; use pacco::pkg::{Package, Repository, arch::Architecture, find_package_by_name};
use crate::routes::render;
use super::take_out; use super::take_out;
#[get("/<repo>/<pkg_name>?<ver>")] #[get("/<repo>/<pkg_name>?<ver>")]
@ -18,6 +17,7 @@ pub async fn pkg_ui(
pkg_name: &str, pkg_name: &str,
ctx: RequestContext, ctx: RequestContext,
ver: Option<&str>, ver: Option<&str>,
shell: &State<Shell>,
) -> Option<StringResponse> { ) -> Option<StringResponse> {
let repo = Repository::new(repo).unwrap(); let repo = Repository::new(repo).unwrap();
let mut pkg = repo.get_pkg_by_name(pkg_name)?; let mut pkg = repo.get_pkg_by_name(pkg_name)?;
@ -42,6 +42,7 @@ pub async fn pkg_ui(
let shared_objects = pkg.shared_objects(); let shared_objects = pkg.shared_objects();
let icons = pkg.icons(); let icons = pkg.icons();
let readmes = pkg.readmes(); let readmes = pkg.readmes();
let fonts = pkg.fonts();
let mut pkginfo = pkg.pkginfo(); let mut pkginfo = pkg.pkginfo();
let pkg_info_header = Flex( let pkg_info_header = Flex(
@ -69,15 +70,15 @@ pub async fn pkg_ui(
.push_for_each(&arch, |arch: &Architecture| { .push_for_each(&arch, |arch: &Architecture| {
Rounded( Rounded(
Padding( Padding(
Background(Gray::_700, Background(
Span(&arch.to_string()).medium().sm()) Span(&arch.to_string()).medium().sm()).color(Gray::_700)
).x(ScreenValue::_3).y(ScreenValue::_1) ).x(ScreenValue::_3).y(ScreenValue::_1)
).size(Size::Full) ).size(Size::Full)
}) })
.push(Margin( .push(Margin(
Flex( Flex(
Padding( Padding(
Hover(Background(Gray::_300, Nothing())).on(Background(Gray::_200, Hover(Background(Nothing()).color(Gray::_300)).on(Background(
Rounded(Shadow::medium( Rounded(Shadow::medium(
Link(&format!("/pkg/{}/{}/{}", pkg.repo, pkg.arch.to_string(), pkg.file_name()), Link(&format!("/pkg/{}/{}/{}", pkg.repo, pkg.arch.to_string(), pkg.file_name()),
Paragraph( Paragraph(
@ -88,7 +89,7 @@ pub async fn pkg_ui(
p class="ml-2 text-black" { "Download" }; p class="ml-2 text-black" { "Download" };
} }
).black().xs()))).size(Size::Large) ).black().xs()))).size(Size::Large)
)) ).color(Gray::_200))
).x(ScreenValue::_2).y(ScreenValue::_2) ).x(ScreenValue::_2).y(ScreenValue::_2)
).items_center() ).items_center()
).left(ScreenValue::_4) ).left(ScreenValue::_4)
@ -101,9 +102,8 @@ pub async fn pkg_ui(
.vanish() .vanish()
.push(Context(FlexGrow( .push(Context(FlexGrow(
Strategy::Grow, Strategy::Grow,
Animated(Background( Animated(
Gray::_800, Background(Shadow::large(
Shadow::large(
Rounded( Rounded(
Margin( Margin(
Padding( Padding(
@ -143,14 +143,14 @@ pub async fn pkg_ui(
.all(ScreenValue::_2), .all(ScreenValue::_2),
) )
.size(Size::Large), .size(Size::Large),
))
.color(Gray::_800),
), ),
)),
))) )))
.push( .push(
SpaceBetween( SpaceBetween(
Padding(Background( Padding(
Gray::_800, Background(Shadow::large(
Shadow::large(
Rounded( Rounded(
Margin( Margin(
Screen::medium(FlexGrow(Strategy::NoGrow, Nothing())).on( Screen::medium(FlexGrow(Strategy::NoGrow, Nothing())).on(
@ -210,8 +210,9 @@ pub async fn pkg_ui(
.all(ScreenValue::_2), .all(ScreenValue::_2),
) )
.size(Size::Large), .size(Size::Large),
),
)) ))
.color(Gray::_800),
)
.all(ScreenValue::_4), .all(ScreenValue::_4),
) )
.y(ScreenValue::_2), .y(ScreenValue::_2),
@ -257,12 +258,14 @@ pub async fn pkg_ui(
) )
.push( .push(
Padding( Padding(
Rounded(Background( Rounded(
Gray::_700, Background(
Code(&hook.1) Code(&hook.1)
.sm() .sm()
.color(&Gray::_100), .color(&Gray::_100),
)) )
.color(Gray::_700),
)
.size(Size::Large), .size(Size::Large),
) )
.all(ScreenValue::_4), .all(ScreenValue::_4),
@ -293,12 +296,14 @@ pub async fn pkg_ui(
) )
.push( .push(
Padding( Padding(
Rounded(Background( Rounded(
Gray::_700, Background(
Code(&readme.1) Code(&readme.1)
.sm() .sm()
.color(&Gray::_100), .color(&Gray::_100),
)) )
.color(Gray::_700),
)
.size(Size::Large), .size(Size::Large),
) )
.all(ScreenValue::_4), .all(ScreenValue::_4),
@ -336,6 +341,14 @@ pub async fn pkg_ui(
.push(ListElements(&shared_objects)), .push(ListElements(&shared_objects)),
) )
}) })
.push_if(!fonts.is_empty(), || {
InfoCard(
Div()
.vanish()
.push(CardTitle("Fonts"))
.push(ListElements(&fonts)),
)
})
.push_if(!firmware.is_empty(), || { .push_if(!firmware.is_empty(), || {
InfoCard( InfoCard(
Div() Div()
@ -412,13 +425,15 @@ pub async fn pkg_ui(
) )
.push( .push(
Rounded( Rounded(
Padding(Background( Padding(
Gray::_700, Background(
Code(install_script.trim()) Code(install_script.trim())
.color(&Gray::_100) .color(&Gray::_100)
.sm() .sm()
.indentation(ScreenValue::_0), .indentation(ScreenValue::_0),
)) )
.color(Gray::_700),
)
.all(ScreenValue::_2), .all(ScreenValue::_2),
) )
.size(Size::Large), .size(Size::Large),
@ -430,16 +445,18 @@ pub async fn pkg_ui(
}) })
.render(); .render();
Some(render(content, pkg_name, ctx).await) Some(shell.render_page(content, pkg_name, ctx).await)
} }
pub fn build_info(key: String, value: String) -> PreEscaped<String> { pub fn build_info(key: String, value: String) -> PreEscaped<String> {
match key.as_str() { match key.as_str() {
"pkgname" => {} "pkgname" => {}
"pkgbase" => {}
"xdata" => {} "xdata" => {}
"arch" => {} "arch" => {}
"pkbase" => {} "pkbase" => {}
"pkgver" => {} "pkgver" => {}
"provides" => {}
"pkgdesc" => { "pkgdesc" => {
return key_value("Description".to_string(), value); return key_value("Description".to_string(), value);
} }
@ -522,13 +539,13 @@ pub fn CardTitle(title: &str) -> PreEscaped<String> {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn InfoCard<T: UIWidget + 'static>(inner: T) -> SpaceBetweenWidget { pub fn InfoCard<T: UIWidget + 'static>(inner: T) -> SpaceBetweenWidget {
SpaceBetween( SpaceBetween(
Padding(Background( Padding(
Gray::_800, Background(Shadow::large(
Shadow::large(
Rounded(Margin(FlexGrow(Strategy::Grow, inner)).all(ScreenValue::_2)) Rounded(Margin(FlexGrow(Strategy::Grow, inner)).all(ScreenValue::_2))
.size(Size::Large), .size(Size::Large),
),
)) ))
.color(Gray::_800),
)
.all(ScreenValue::_4), .all(ScreenValue::_4),
) )
.y(ScreenValue::_2) .y(ScreenValue::_2)

View file

@ -1,4 +1,5 @@
use based::request::{RequestContext, StringResponse}; use based::request::{RequestContext, StringResponse};
use based::ui::components::Shell;
use based::ui::prelude::*; use based::ui::prelude::*;
use maud::{PreEscaped, Render, html}; use maud::{PreEscaped, Render, html};
use rocket::{State, get}; use rocket::{State, get};
@ -8,14 +9,13 @@ use pacco::pkg::{Repository, arch::Architecture};
use crate::config::Config; use crate::config::Config;
use crate::routes::ui::arch_card; use crate::routes::ui::arch_card;
use super::render;
#[get("/<repo>?<arch>")] #[get("/<repo>?<arch>")]
pub async fn repo_ui( pub async fn repo_ui(
repo: &str, repo: &str,
ctx: RequestContext, ctx: RequestContext,
arch: Option<&str>, arch: Option<&str>,
config: &State<Config>, config: &State<Config>,
shell: &State<Shell>,
) -> StringResponse { ) -> StringResponse {
let arch = arch.map(|x| Architecture::parse(x).unwrap_or(Architecture::any)); let arch = arch.map(|x| Architecture::parse(x).unwrap_or(Architecture::any));
@ -35,7 +35,6 @@ pub async fn repo_ui(
.push(Text(&repo.name)._3xl().bold().color(&Gray::_100)) .push(Text(&repo.name)._3xl().bold().color(&Gray::_100))
.push_if(config.is_mirrored_repo(&repo.name), || { .push_if(config.is_mirrored_repo(&repo.name), || {
Background( Background(
Blue::_500,
Rounded(Margin( Rounded(Margin(
Padding(Text("Mirrored").sm().medium().white()) Padding(Text("Mirrored").sm().medium().white())
.x(ScreenValue::_3) .x(ScreenValue::_3)
@ -43,6 +42,7 @@ pub async fn repo_ui(
)) ))
.size(Size::Full), .size(Size::Full),
) )
.color(Blue::_500)
}) })
.push( .push(
Screen::medium(Margin(Nothing()).top(ScreenValue::_0)).on(Margin( Screen::medium(Margin(Nothing()).top(ScreenValue::_0)).on(Margin(
@ -81,8 +81,7 @@ pub async fn repo_ui(
Animated( Animated(
Flex( Flex(
Padding( Padding(
Hover(Background(Gray::_600, Nothing())).on(Background( Hover(Background(Nothing()).color(Gray::_600)).on(Background(
Gray::_700,
Rounded(Shadow::medium( Rounded(Shadow::medium(
Link( Link(
&format!("/{}/{pkg}", repo.name), &format!("/{}/{pkg}", repo.name),
@ -103,7 +102,8 @@ pub async fn repo_ui(
.use_htmx(), .use_htmx(),
)) ))
.size(Size::Large), .size(Size::Large),
)), )
.color(Gray::_700)),
) )
.all(ScreenValue::_4), .all(ScreenValue::_4),
) )
@ -115,7 +115,7 @@ pub async fn repo_ui(
let content = Div().vanish().push(repo_info).push(package_list).render(); let content = Div().vanish().push(repo_info).push(package_list).render();
render(content, &repo.name, ctx).await shell.render_page(content, &repo.name, ctx).await
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -123,8 +123,8 @@ pub fn FirstLetterCircle(name: &str) -> PreEscaped<String> {
Sized( Sized(
ScreenValue::_10, ScreenValue::_10,
ScreenValue::_10, ScreenValue::_10,
Rounded(Background( Rounded(
Blue::_500, Background(
Flex( Flex(
Text( Text(
&name &name
@ -139,7 +139,9 @@ pub fn FirstLetterCircle(name: &str) -> PreEscaped<String> {
) )
.full_center() .full_center()
.group(), .group(),
)) )
.color(Blue::_500),
)
.size(Size::Full), .size(Size::Full),
) )
.render() .render()

View file

@ -1,11 +1,11 @@
use based::{ use based::{
auth::{Session, Sessions, User, csrf::CSRF}, auth::{Session, Sessions, User, csrf::CSRF},
request::{RequestContext, StringResponse, api::to_uuid, respond_html}, request::{RequestContext, StringResponse, api::to_uuid, respond_html},
ui::AttrExtendable, ui::{AttrExtendable, components::Shell},
}; };
use maud::{PreEscaped, html}; use maud::{PreEscaped, html};
use rocket::{ use rocket::{
FromForm, FromForm, State,
form::Form, form::Form,
get, get,
http::{Cookie, CookieJar}, http::{Cookie, CookieJar},
@ -13,11 +13,10 @@ use rocket::{
response::Redirect, response::Redirect,
}; };
use super::render;
use based::ui::prelude::*; use based::ui::prelude::*;
#[get("/login")] #[get("/login")]
pub async fn login(ctx: RequestContext) -> StringResponse { pub async fn login(ctx: RequestContext, shell: &State<Shell>) -> StringResponse {
let content = html! { let content = html! {
div class="min-w-screen justify-center flex items-center" { div class="min-w-screen justify-center flex items-center" {
div class="bg-gray-800 shadow-lg rounded-lg p-8 max-w-sm w-full" { div class="bg-gray-800 shadow-lg rounded-lg p-8 max-w-sm w-full" {
@ -37,7 +36,7 @@ pub async fn login(ctx: RequestContext) -> StringResponse {
}; };
}; };
render(content, "Login", ctx).await shell.render_page(content, "Login", ctx).await
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -116,7 +115,7 @@ pub async fn new_api_key(user: User, csrf: &str, session_name: &str) -> StringRe
} }
#[get("/account")] #[get("/account")]
pub async fn account_page(user: User, ctx: RequestContext) -> StringResponse { pub async fn account_page(user: User, ctx: RequestContext, shell: &State<Shell>) -> StringResponse {
let sessions = user.list_sessions().await; let sessions = user.list_sessions().await;
let content = html! { let content = html! {
@ -128,8 +127,8 @@ pub async fn account_page(user: User, ctx: RequestContext) -> StringResponse {
(Link("/passwd", Margin( (Link("/passwd", Margin(
Rounded(Padding( Rounded(Padding(
Hover( Hover(
Background(Green::_600, Nothing())).on( Background(Nothing()).color(Green::_600)).on(
Background(Green::_500, Text("Change Password").white()) Background(Text("Change Password").white()).color(Green::_500)
) )
).x(ScreenValue::_6).y(ScreenValue::_2)) ).x(ScreenValue::_6).y(ScreenValue::_2))
).bottom(ScreenValue::_6)).use_htmx()) ).bottom(ScreenValue::_6)).use_htmx())
@ -155,7 +154,7 @@ pub async fn account_page(user: User, ctx: RequestContext) -> StringResponse {
}; };
}; };
render(content, "Account", ctx).await shell.render_page(content, "Account", ctx).await
} }
pub async fn build_session_block(ses: &Session, user: &User) -> PreEscaped<String> { pub async fn build_session_block(ses: &Session, user: &User) -> PreEscaped<String> {
@ -198,7 +197,11 @@ pub async fn change_password_post(form: Form<PasswordChangeForm>, user: User) ->
} }
#[get("/passwd")] #[get("/passwd")]
pub async fn change_password(ctx: RequestContext, user: User) -> StringResponse { pub async fn change_password(
ctx: RequestContext,
user: User,
shell: &State<Shell>,
) -> StringResponse {
let content = html! { let content = html! {
div class="min-w-screen justify-center flex items-center" { div class="min-w-screen justify-center flex items-center" {
div class="bg-gray-800 shadow-lg rounded-lg p-8 max-w-sm w-full" { div class="bg-gray-800 shadow-lg rounded-lg p-8 max-w-sm w-full" {
@ -223,5 +226,5 @@ pub async fn change_password(ctx: RequestContext, user: User) -> StringResponse
}; };
}; };
render(content, "Change Password", ctx).await shell.render_page(content, "Change Password", ctx).await
} }