Initial
This commit is contained in:
commit
d23055a0bf
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
package-lock.json
|
||||||
|
node_modules/
|
||||||
|
build/
|
1324
Cargo.lock
generated
Normal file
1324
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "persmgr-gui"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.99"
|
||||||
|
askama = "0.14.0"
|
||||||
|
axum = "0.8.4"
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.143"
|
||||||
|
tokio = { version = "1.47.1", features = ["full"] }
|
||||||
|
toml = "0.9.5"
|
||||||
|
tower = { version = "0.5.2", features = ["full"] }
|
||||||
|
tower-http = { version = "0.6.6", features = ["full"] }
|
||||||
|
tracing = "0.1.41"
|
||||||
|
tracing-subscriber = "0.3.20"
|
14
README.md
Normal file
14
README.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dashboard
|
||||||
|
Roster
|
||||||
|
Management (with the right permissions only)
|
||||||
|
Documents
|
||||||
|
User (something shorter than personal file)
|
||||||
|
|
||||||
|
|
||||||
|
(user icon) (dropdown)
|
||||||
|
- Account
|
||||||
|
- Preferences
|
||||||
|
- Logout
|
19
persmgr-gui-rs/Cargo.toml
Normal file
19
persmgr-gui-rs/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "persmgr-gui"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.99"
|
||||||
|
image = "0.25.7"
|
||||||
|
reqwest = { version = "0.12.23", features = ["json", "blocking"] }
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.143"
|
||||||
|
slint = { version = "1.12.1", features = ["gettext", "log", "serde", "image-default-formats"] }
|
||||||
|
tokio = "1.47.1"
|
||||||
|
toml = "0.9.5"
|
||||||
|
tracing = "0.1.41"
|
||||||
|
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
slint-build = "1.12.1"
|
3
persmgr-gui-rs/build.rs
Normal file
3
persmgr-gui-rs/build.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
slint_build::compile("ui/main.slint").unwrap();
|
||||||
|
}
|
12
persmgr-gui-rs/src/main.rs
Normal file
12
persmgr-gui-rs/src/main.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
slint::include_modules!();
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let app = MainWindow::new().unwrap();
|
||||||
|
|
||||||
|
// connect callback
|
||||||
|
app.on_clicked(|| {
|
||||||
|
println!("Button was clicked owo");
|
||||||
|
});
|
||||||
|
|
||||||
|
app.run().unwrap();
|
||||||
|
}
|
24
persmgr-gui-rs/ui/main.slint
Normal file
24
persmgr-gui-rs/ui/main.slint
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { Button } from "std-widgets.slint";
|
||||||
|
|
||||||
|
|
||||||
|
export component MainWindow inherits Window {
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
title: "My Slint App :3";
|
||||||
|
|
||||||
|
VerticalLayout {
|
||||||
|
Text {
|
||||||
|
text: "Hello nya~ from Slint!";
|
||||||
|
horizontal-alignment: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Click me!";
|
||||||
|
clicked => {
|
||||||
|
root.clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback clicked();
|
||||||
|
}
|
54
persmgr-gui-rs/ui/top_nav.slint
Normal file
54
persmgr-gui-rs/ui/top_nav.slint
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import { Button } from "std-widgets.slint";
|
||||||
|
export component TopNavBar inherits HorizontalLayout {
|
||||||
|
height: 50px;
|
||||||
|
spacing: 16px;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-right: 16px;
|
||||||
|
|
||||||
|
// Permission flag for Management tab
|
||||||
|
in property <bool> is_officer: false;
|
||||||
|
|
||||||
|
// callbacks for tabs
|
||||||
|
callback dashboard_clicked();
|
||||||
|
callback roster_clicked();
|
||||||
|
callback management_clicked();
|
||||||
|
callback documents_clicked();
|
||||||
|
callback profile_clicked();
|
||||||
|
callback user_account_clicked();
|
||||||
|
callback user_preferences_clicked();
|
||||||
|
callback user_logout_clicked();
|
||||||
|
Button {
|
||||||
|
text: "Dashboard";
|
||||||
|
clicked() => {
|
||||||
|
root.dashboard_clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Roster";
|
||||||
|
clicked() => {
|
||||||
|
root.roster_clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Management";
|
||||||
|
clicked() => {
|
||||||
|
root.management_clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Documents";
|
||||||
|
clicked() => {
|
||||||
|
root.documents_clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Your file";
|
||||||
|
clicked() => {
|
||||||
|
root.dashboard_clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
res/css/global.css
Normal file
38
res/css/global.css
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--bg-color-ll: #535353;
|
||||||
|
--bg-color-l: #434343;
|
||||||
|
--bg-color: #323232;
|
||||||
|
--bg-color-d: #292929;
|
||||||
|
--bg-color-dd: #212121;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--bg-color);
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#topnav {
|
||||||
|
width: 100%;
|
||||||
|
height: 10%;
|
||||||
|
background: var(--bg-color-l);
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.topnav_button {
|
||||||
|
padding: 1rem 3rem;
|
||||||
|
margin: 3px 10px;
|
||||||
|
background: var(--bg-color-ll);
|
||||||
|
border: 2px solid var(--bg-color);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topnav_button a {
|
||||||
|
text_decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topnav_button:hover {
|
||||||
|
cursor: pointer
|
||||||
|
}
|
BIN
res/favicon.ico
Normal file
BIN
res/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 274 KiB |
11
src/api/mod.rs
Normal file
11
src/api/mod.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
use axum::{Router, http::StatusCode, routing::get};
|
||||||
|
|
||||||
|
async fn root() -> (StatusCode, &'static str) {
|
||||||
|
(StatusCode::OK, "We Good twin :3c")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_routes() -> Router {
|
||||||
|
let router = Router::new().route("/", get(root));
|
||||||
|
|
||||||
|
Router::new().nest("/api", router)
|
||||||
|
}
|
30
src/main.rs
Normal file
30
src/main.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use axum::Router;
|
||||||
|
use tower::ServiceBuilder;
|
||||||
|
use tower_http::{services::ServeDir, trace::TraceLayer};
|
||||||
|
use tracing::{info, level_filters::LevelFilter};
|
||||||
|
use tracing_subscriber::FmtSubscriber;
|
||||||
|
|
||||||
|
mod api;
|
||||||
|
mod pages;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let sub = FmtSubscriber::builder()
|
||||||
|
.with_max_level(LevelFilter::DEBUG)
|
||||||
|
.finish();
|
||||||
|
tracing::subscriber::set_global_default(sub).unwrap();
|
||||||
|
|
||||||
|
info!("Server starting");
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.merge(pages::register_routes())
|
||||||
|
.merge(api::register_routes())
|
||||||
|
.fallback_service(ServiceBuilder::new().service(ServeDir::new("res")))
|
||||||
|
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));
|
||||||
|
|
||||||
|
let laddr = "0.0.0.0:8080";
|
||||||
|
|
||||||
|
let sock = tokio::net::TcpListener::bind(laddr).await.unwrap();
|
||||||
|
info!("Listening on http://{laddr}");
|
||||||
|
axum::serve(sock, app).await.unwrap();
|
||||||
|
}
|
12
src/pages/index.rs
Normal file
12
src/pages/index.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use askama::Template;
|
||||||
|
use axum::{http::StatusCode, response::Html};
|
||||||
|
|
||||||
|
#[derive(Debug, Template, Clone)]
|
||||||
|
#[template(path = "index.html")]
|
||||||
|
pub struct PageTemplate {}
|
||||||
|
|
||||||
|
pub async fn page() -> (StatusCode, Html<String>) {
|
||||||
|
let page = PageTemplate {};
|
||||||
|
|
||||||
|
(StatusCode::OK, Html(page.render().unwrap()))
|
||||||
|
}
|
8
src/pages/mod.rs
Normal file
8
src/pages/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use askama::Template;
|
||||||
|
use axum::{Router, routing::get};
|
||||||
|
|
||||||
|
pub mod index;
|
||||||
|
|
||||||
|
pub fn register_routes() -> Router {
|
||||||
|
Router::new().route("/", get(index::page))
|
||||||
|
}
|
27
templates/base.html
Normal file
27
templates/base.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{% block title %}{% endblock %}</title>
|
||||||
|
<link href="css/global.css" rel="stylesheet">
|
||||||
|
{% block headers %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="topnav">
|
||||||
|
<div class="topnav_button" onclick="location.href='/'">
|
||||||
|
Dashboard
|
||||||
|
</div>
|
||||||
|
<div class="topnav_button" onclick="location.href='/roster'">
|
||||||
|
Roster
|
||||||
|
</div>
|
||||||
|
<div class="topnav_button" onclick="location.href='/events'">
|
||||||
|
Events
|
||||||
|
</div>
|
||||||
|
<div class="topnav_button" onclick="location.href='/documents'">
|
||||||
|
Documents
|
||||||
|
</div>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
templates/index.html
Normal file
11
templates/index.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Dashboard{% endblock %}
|
||||||
|
{% block headers %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Hello!!!!!!!</h1>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user