This commit is contained in:
JMARyA 2024-09-16 13:07:03 +02:00
commit 14a9704249
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
10 changed files with 1837 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

1677
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

10
Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "umbrella"
version = "0.1.0"
edition = "2021"
[dependencies]
maud = "0.26.0"
rocket = "0.5.1"
serde = { version = "1.0.210", features = ["derive"] }
serde_yml = "0.0.12"

2
README.md Normal file
View file

@ -0,0 +1,2 @@
# Umbrella ☂️
Umbrella is a project overview application.

14
config.yml Normal file
View file

@ -0,0 +1,14 @@
projects:
root:
name: "Root Project"
description: "Root Project"
website: "https://example.com"
documentation: "https://docs.example.com"
since: 1999-00-00
contact:
email: "mail@example.com"
sub:
sub_project:
name: "Sub Project"
description: "Sub Project"

50
src/config.rs Normal file
View file

@ -0,0 +1,50 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct Config {
pub projects: HashMap<String, Project>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Project {
pub name: String,
pub description: String,
pub website: Option<String>,
pub documentation: Option<String>,
pub since: Option<String>,
pub contact: Option<ContactInfo>,
pub sub: HashMap<String, Project>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ContactInfo {
pub email: Option<String>,
}
impl Config {
pub fn load(path: &str) -> Self {
serde_yml::from_str(&std::fs::read_to_string(path).unwrap()).unwrap()
}
}
impl Project {
pub fn build(&self, card_id: &str) -> maud::PreEscaped<String> {
let subcard_id = format!("{card_id}_sub");
// todo : info
maud::html!(
div class="card" id=(card_id) {
h3 { (self.name) };
p { "Description" };
button class="expand-button" onclick=(format!("toggleSubcards('{subcard_id}')")) { "Expand" };
div class="subcards" id=(subcard_id) {
@for (id, prj) in &self.sub {
(prj.build(id))
}
};
};
)
}
}

20
src/main.rs Normal file
View file

@ -0,0 +1,20 @@
use config::Config;
use rocket::{get, launch, routes, State};
mod config;
mod site;
#[get("/")]
pub fn main_page(c: &State<Config>) -> String {
site::gen_site(c)
}
#[launch]
async fn rocket() -> _ {
let conf_path: String = std::env::args()
.next()
.unwrap_or("./config.yml".to_string());
let conf = config::Config::load(&conf_path);
rocket::build().mount("/", routes![main_page]).manage(conf)
}

8
src/script.js Normal file
View file

@ -0,0 +1,8 @@
function toggleSubcards(id) {
var subcards = document.getElementById(id);
if (subcards.style.display === "block") {
subcards.style.display = "none";
} else {
subcards.style.display = "block";
}
}

26
src/site.rs Normal file
View file

@ -0,0 +1,26 @@
use crate::config::Config;
pub fn gen_site(c: &Config) -> String {
maud::html!(
(maud::DOCTYPE)
html {
head {
meta charset="UTF-8";
meta name="viewport" content="width=device-width, initial-scale=1.0";
title { "Umbrella ☂️"};
link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css";
style { (include_str!("style.css")) };
};
body {
script { (include_str!("script.js")) };
main class="container" {
h1 { "Umbrella ☂️" };
@for (id, card) in &c.projects {
(card.build(id));
}
};
};
}
).into_string()
}

29
src/style.css Normal file
View file

@ -0,0 +1,29 @@
.card {
border: 1px solid #ccc;
padding: 1rem;
margin: 1rem 0;
position: relative;
transition: max-height 0.3s ease-in-out;
overflow: hidden;
}
.subcards {
display: none;
margin-left: 1rem;
}
.expand-button {
position: absolute;
top: 10px;
right: 10px;
background-color: #141414;
color: white;
border: none;
padding: 0.3rem 0.6rem;
cursor: pointer;
border-radius: 0.25rem;
}
.expand-button:hover {
background-color: #0056b3;
}