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