Initial
This commit is contained in:
commit
d6be7111f9
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
1205
Cargo.lock
generated
Normal file
1205
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "fuck_microsoft_access"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
askama = "0.15.1"
|
||||
axum = { version = "0.8.8", features = ["macros", "ws"] }
|
||||
clap = "4.5.54"
|
||||
env_logger = "0.11.8"
|
||||
log = "0.4.29"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
tokio = { version = "1.49.0", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] }
|
||||
toml = "0.9.11"
|
||||
14
src/main.rs
Normal file
14
src/main.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use log::LevelFilter;
|
||||
|
||||
mod web;
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
env_logger::builder()
|
||||
.filter_module("fuck_microsoft_access", LevelFilter::Debug)
|
||||
.init();
|
||||
|
||||
web::start().await?;
|
||||
Ok(())
|
||||
}
|
||||
17
src/web/mod.rs
Normal file
17
src/web/mod.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use axum::{Router, routing::get};
|
||||
|
||||
pub mod pages;
|
||||
|
||||
|
||||
|
||||
|
||||
pub async fn start() -> anyhow::Result<()> {
|
||||
let addr = "0.0.0.0:3000";
|
||||
let app = Router::new()
|
||||
.route("/", get(pages::home::get_page));
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||
log::info!("Listening on http://{addr}");
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
31
src/web/pages/error.rs
Normal file
31
src/web/pages/error.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use askama::Template;
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "error.html")]
|
||||
pub struct ErrorTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
pub error: String
|
||||
}
|
||||
|
||||
impl BaseTemplate for ErrorTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_error_page(e: String) -> String {
|
||||
let mut template = ErrorTemplate {
|
||||
ctx: Default::default(),
|
||||
error: e.to_string()
|
||||
};
|
||||
|
||||
template.set_title("Error");
|
||||
|
||||
template.render().unwrap()
|
||||
}
|
||||
50
src/web/pages/home.rs
Normal file
50
src/web/pages/home.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
pub struct HomeTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for HomeTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = HomeTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
template.set_title("Home");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
match inner() {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/web/pages/mod.rs
Normal file
33
src/web/pages/mod.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
|
||||
pub mod home;
|
||||
pub mod error;
|
||||
|
||||
|
||||
pub struct BaseTemplateCtx {
|
||||
pub title: String
|
||||
}
|
||||
|
||||
impl Default for BaseTemplateCtx {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
title: String::from("Default Title")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BaseTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx;
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx;
|
||||
|
||||
|
||||
fn set_title(&mut self, title: &str) {
|
||||
self.ctx_mut().title = title.to_string();
|
||||
}
|
||||
|
||||
|
||||
fn title(&self) -> &String {
|
||||
&self.ctx().title
|
||||
}
|
||||
|
||||
}
|
||||
16
templates/base.html
Normal file
16
templates/base.html
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ self.title() }}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% include "header.html" %}
|
||||
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
{% include "footer.html" %}
|
||||
</body>
|
||||
</html>
|
||||
5
templates/error.html
Normal file
5
templates/error.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
A server error happened: {{ error }}
|
||||
{% endblock %}
|
||||
3
templates/footer.html
Normal file
3
templates/footer.html
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<footer>
|
||||
<small>© 2026 MCorange. Licensed under the GNU GPL v3 or later.</small>
|
||||
</footer>
|
||||
2
templates/header.html
Normal file
2
templates/header.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<header>
|
||||
</header>
|
||||
4
templates/home.html
Normal file
4
templates/home.html
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
Loading…
Reference in New Issue
Block a user