Very first baby-steps into the land of modern web development.

Use `esbuild` to build TypeScript, and bundle components together
in a minified form for the `lts_node` website.

This is very much a work in progress, committing as a checkpoint.
This commit is contained in:
Herbert Wolverson 2023-04-21 18:52:53 +00:00
parent 6e36ab7161
commit a84f590393
11 changed files with 147 additions and 2 deletions

3
.gitignore vendored
View File

@ -59,6 +59,9 @@ src/rust/lqos_anonymous_stats_server/anonymous.sqlite
src/rust/long_term_stats/license_server/lqkeys.bin
src/rust/long_term_stats/lts_node/lqkeys.bin
src/rust/long_term_stats/pgdb/.env
src/rust/long_term_stats/site_build/node_modules
src/rust/long_term_stats/site_build/output
src/rust/long_term_stats/site_build/package-lock.json
# Ignore Rust build artifacts
src/rust/target

View File

@ -7,9 +7,21 @@ use axum::{
routing::get,
Router,
};
const JS_BUNDLE: &str = include_str!("../../../site_build/output/app.js");
const JS_MAP: &str = include_str!("../../../site_build/output/app.js.map");
const CSS: &str = include_str!("../../../site_build/output/style.css");
const CSS_MAP: &str = include_str!("../../../site_build/output/style.css.map");
const HTML_MAIN: &str = include_str!("../../../site_build/src/main.html");
pub async fn webserver() {
let app = Router::new()
.route("/", get(index_page));
.route("/", get(index_page))
.route("/app.js", get(js_bundle))
.route("/app.js.map", get(js_map))
.route("/style.css", get(css))
.route("/style.css.map", get(css_map))
;
log::info!("Listening for web traffic on 0.0.0.0:9127");
axum::Server::bind(&"0.0.0.0:9127".parse().unwrap())
@ -19,5 +31,33 @@ pub async fn webserver() {
}
async fn index_page() -> Html<String> {
Html("Hello, World!".to_string())
Html(HTML_MAIN.to_string())
}
async fn js_bundle() -> axum::response::Response<String> {
axum::response::Response::builder()
.header("Content-Type", "text/javascript")
.body(JS_BUNDLE.to_string())
.unwrap()
}
async fn js_map() -> axum::response::Response<String> {
axum::response::Response::builder()
.header("Content-Type", "text/json")
.body(JS_MAP.to_string())
.unwrap()
}
async fn css() -> axum::response::Response<String> {
axum::response::Response::builder()
.header("Content-Type", "text/css")
.body(CSS.to_string())
.unwrap()
}
async fn css_map() -> axum::response::Response<String> {
axum::response::Response::builder()
.header("Content-Type", "text/json")
.body(CSS_MAP.to_string())
.unwrap()
}

View File

@ -0,0 +1,20 @@
# Site Build
This folder compiles and packages the website used by `lts_node`. It
needs to be compiled and made available to the `lts_node` process.
Steps: TBA
## Requirements
To run the build (as opposed to shipping pre-built files), you need to
install `esbuild` and `npm` (ugh). You can do this with:
```bash
(change directory to site_build folder)
sudo apt-get install npm
npm install --save-exact esbuild
````
You can run the build manually by running `./esbuild.sh` in this
directory.

View File

@ -0,0 +1,12 @@
#!/usr/bin/env node
import * as esbuild from 'esbuild'
await esbuild.build({
entryPoints: ['src/app.ts', 'src/style.css'],
bundle: true,
minify: true,
sourcemap: true,
// target: ['chrome58', 'firefox57', 'safari11', 'edge16'],
outdir: 'output/',
loader: { '.html': 'text'}
})

View File

@ -0,0 +1,7 @@
{
"dependencies": {
"@types/bootstrap": "^5.2.6",
"bootstrap": "^5.2.3",
"esbuild": "0.17.17"
}
}

View File

@ -0,0 +1,4 @@
import 'bootstrap/dist/css/bootstrap.css';
import { LoginPage } from './login/login';
let loginPanel = new LoginPage();

View File

@ -0,0 +1,4 @@
declare module '*.html' {
const value: string;
export default value
}

View File

@ -0,0 +1,10 @@
import html from './template.html';
export class LoginPage {
constructor() {
document.body.innerHTML = html;
let button = document.getElementById('btnLogin');
if (button)
button.onclick = () => { alert('blah') };
}
}

View File

@ -0,0 +1,30 @@
<div id="container" class="pad4">
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm-4">
<div class="card bg-light">
<div class="card-body">
<h5 class="card-title">Login</h5>
<p>Please enter a username and password to access LibreQoS.</p>
<p>You can control access locally with <em>bin/lqusers</em> from the console.</p>
<table class="table">
<tr>
<td>License ID</td>
<td><input type="text" id="license" /></td>
</tr>
<tr>
<td>Username</td>
<td><input type="text" id="username" /></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" id="password" /></td>
</tr>
</table>
<a class="btn btn-primary" id="btnLogin">Login</a>
</div>
</div>
</div>
<div class="col-sm-4"></div>
</div>
</div>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>LibreWoS Long-Term Statistics</title>
<link rel="shortcut icon" href="#" />
<script type="module" src="/app.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>Hello</body>
</html>

View File

@ -0,0 +1 @@
@import 'bootstrap/dist/css/bootstrap.css';