init
This commit is contained in:
commit
14a9704249
10 changed files with 1837 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
1677
Cargo.lock
generated
Normal file
1677
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
10
Cargo.toml
Normal file
10
Cargo.toml
Normal 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
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Umbrella ☂️
|
||||||
|
Umbrella is a project overview application.
|
14
config.yml
Normal file
14
config.yml
Normal 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
50
src/config.rs
Normal 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
20
src/main.rs
Normal 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
8
src/script.js
Normal 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
26
src/site.rs
Normal 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
29
src/style.css
Normal 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;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue