Owows so many new files
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
/config.toml
|
/config.toml
|
||||||
|
/node_modules
|
||||||
1833
Cargo.lock
generated
1833
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
74
Cargo.toml
74
Cargo.toml
@@ -17,12 +17,14 @@ chrono = { version = "0.4.45", features = ["serde"] }
|
|||||||
console_error_panic_hook = "0.1.7"
|
console_error_panic_hook = "0.1.7"
|
||||||
diesel = { version = "2.3.13", features = ["postgres", "uuid", "chrono", "r2d2"] }
|
diesel = { version = "2.3.13", features = ["postgres", "uuid", "chrono", "r2d2"] }
|
||||||
diesel_migrations = "2.3.2"
|
diesel_migrations = "2.3.2"
|
||||||
leptos = "0.8.20"
|
leptos = { version = "0.8.20", features = ["hydration"] }
|
||||||
leptos_axum = "0.8.10"
|
leptos_axum = { version = "0.8.10", features = ["tracing", "wasm"]}
|
||||||
|
leptos_meta = "0.8.6"
|
||||||
|
leptos_router = { version = "0.8.15", features = ["tracing"] }
|
||||||
serde = { version = "1.0.229", features = ["derive"] }
|
serde = { version = "1.0.229", features = ["derive"] }
|
||||||
serde_json = "1.0.151"
|
serde_json = "1.0.151"
|
||||||
thiserror = "2.0.20"
|
thiserror = "2.0.20"
|
||||||
tokio = { version = "1.53.1", features = ["full"] }
|
tokio = { version = "1.53.1", features = ["rt-multi-thread","macros"] }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
tracing-subscriber = { version = "0.3.23", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.23", features = ["env-filter"] }
|
||||||
uuid = { version = "1.26.0", features = ["v4", "serde"] }
|
uuid = { version = "1.26.0", features = ["v4", "serde"] }
|
||||||
@@ -32,3 +34,69 @@ toml = "1.1.5"
|
|||||||
camino = { version = "1.2.5", features = ["serde1"]}
|
camino = { version = "1.2.5", features = ["serde1"]}
|
||||||
humantime = "2.4.0"
|
humantime = "2.4.0"
|
||||||
humantime-serde = "1.1.1"
|
humantime-serde = "1.1.1"
|
||||||
|
any_spawner = { version = "0.3", features = ["tokio"] }
|
||||||
|
|
||||||
|
|
||||||
|
[profile.wasm-release]
|
||||||
|
inherits = "release"
|
||||||
|
opt-level = 'z'
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[[workspace.metadata.leptos]]
|
||||||
|
name="erplt"
|
||||||
|
bin-package="erplt"
|
||||||
|
lib-package="erplt"
|
||||||
|
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
|
||||||
|
output-name = "erplt"
|
||||||
|
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
|
||||||
|
site-root = "target/site"
|
||||||
|
# The site-root relative folder where all compiled output (JS, WASM and CSS) is written
|
||||||
|
# Defaults to pkg
|
||||||
|
site-pkg-dir = "pkg"
|
||||||
|
# The tailwind input file.
|
||||||
|
#
|
||||||
|
# Optional, Activates the tailwind build
|
||||||
|
tailwind-input-file = "crates/erplt-api/style/tailwind.css"
|
||||||
|
|
||||||
|
# [Optional] Files in the asset-dir will be copied to the site-root directory
|
||||||
|
assets-dir = "public"
|
||||||
|
# The port to use for automatic reload monitoring
|
||||||
|
site-addr = "0.0.0.0:8080"
|
||||||
|
reload-port = 8081
|
||||||
|
|
||||||
|
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
|
||||||
|
# [Windows] for non-WSL use "npx.cmd playwright test"
|
||||||
|
# This binary name can be checked in Powershell with Get-Command npx
|
||||||
|
end2end-cmd = "npx playwright test"
|
||||||
|
end2end-dir = "end2end"
|
||||||
|
|
||||||
|
# The browserlist query used for optimizing the CSS.
|
||||||
|
browserquery = "defaults"
|
||||||
|
|
||||||
|
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
|
||||||
|
watch = false
|
||||||
|
|
||||||
|
# The environment Leptos will run in, usually either "DEV" or "PROD"
|
||||||
|
env = "DEV"
|
||||||
|
|
||||||
|
# The features to use when compiling the bin target
|
||||||
|
#
|
||||||
|
# Optional. Can be over-ridden with the command line parameter --bin-features
|
||||||
|
bin-features = ["ssr"]
|
||||||
|
|
||||||
|
# If the --no-default-features flag should be used when compiling the bin target
|
||||||
|
#
|
||||||
|
# Optional. Defaults to false.
|
||||||
|
bin-default-features = false
|
||||||
|
|
||||||
|
# The features to use when compiling the lib target
|
||||||
|
#
|
||||||
|
# Optional. Can be over-ridden with the command line parameter --lib-features
|
||||||
|
lib-features = ["hydrate"]
|
||||||
|
|
||||||
|
# If the --no-default-features flag should be used when compiling the lib target
|
||||||
|
#
|
||||||
|
# Optional. Defaults to false.
|
||||||
|
lib-default-features = false
|
||||||
@@ -3,10 +3,40 @@ name = "erplt-api"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
|
|
||||||
|
[features]
|
||||||
|
hydrate=["leptos/hydrate"]
|
||||||
|
ssr=[
|
||||||
|
"dep:erplt-db",
|
||||||
|
"dep:erplt-config",
|
||||||
|
"dep:leptos_axum",
|
||||||
|
"dep:tokio",
|
||||||
|
"dep:anyhow",
|
||||||
|
"dep:any_spawner",
|
||||||
|
"dep:tracing",
|
||||||
|
"dep:axum",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erplt-db.path="../erplt-db"
|
leptos.workspace = true
|
||||||
erplt-config.path = "../erplt-config"
|
leptos_meta.workspace = true
|
||||||
anyhow.workspace = true
|
leptos_router.workspace = true
|
||||||
axum.workspace = true
|
console_error_panic_hook.workspace = true
|
||||||
tokio.workspace = true
|
wasm-bindgen.workspace = true
|
||||||
tracing.workspace = true
|
|
||||||
|
axum = { workspace = true, optional = true }
|
||||||
|
erplt-db = { path = "../erplt-db", optional = true }
|
||||||
|
erplt-config = { path = "../erplt-config", optional = true }
|
||||||
|
leptos_axum = { workspace = true, optional = true }
|
||||||
|
tokio = { workspace = true, optional = true }
|
||||||
|
anyhow = { workspace = true, optional = true }
|
||||||
|
any_spawner = { workspace = true, optional = true }
|
||||||
|
tracing = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
[package.metadata.cargo-all-features]
|
||||||
|
denylist = ["axum", "tokio", "tower", "tower-http", "leptos_axum"]
|
||||||
|
skip_feature_sets = [["ssr", "hydrate"], []]
|
||||||
@@ -1,5 +1,21 @@
|
|||||||
mod routes;
|
mod routes;
|
||||||
|
#[cfg(feature="ssr")]
|
||||||
mod state;
|
mod state;
|
||||||
|
#[cfg(feature="ssr")]
|
||||||
mod server;
|
mod server;
|
||||||
|
#[cfg(feature="ssr")]
|
||||||
pub use server::start;
|
pub use server::start;
|
||||||
|
|
||||||
|
#[cfg(feature="ssr")]
|
||||||
|
use leptos::config::LeptosOptions;
|
||||||
|
|
||||||
|
#[cfg(feature="ssr")]
|
||||||
|
type Router = axum::Router<LeptosOptions>;
|
||||||
|
|
||||||
|
#[cfg(feature = "hydrate")]
|
||||||
|
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||||
|
pub fn hydrate() {
|
||||||
|
use routes::pages::App;
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
leptos::mount::hydrate_body(App);
|
||||||
|
}
|
||||||
8
crates/erplt-api/src/routes/api/mod.rs
Normal file
8
crates/erplt-api/src/routes/api/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
mod v1;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn router() -> crate::Router {
|
||||||
|
crate::Router::new()
|
||||||
|
.merge(v1::router())
|
||||||
|
.nest("/v1", v1::router())
|
||||||
|
}
|
||||||
9
crates/erplt-api/src/routes/api/v1/mod.rs
Normal file
9
crates/erplt-api/src/routes/api/v1/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use axum::routing::get;
|
||||||
|
|
||||||
|
mod health;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn router() -> crate::Router {
|
||||||
|
crate::Router::new()
|
||||||
|
.route("/health", get(health::get))
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
use axum::{routing::get, Router};
|
pub mod pages;
|
||||||
|
|
||||||
mod health;
|
#[cfg(feature="ssr")]
|
||||||
|
mod api;
|
||||||
|
|
||||||
pub fn router() -> Router {
|
#[cfg(feature="ssr")]
|
||||||
Router::new()
|
pub fn router() -> crate::Router {
|
||||||
.route("/health", get(health::get))
|
crate::Router::new()
|
||||||
|
.nest("/api", api::router())
|
||||||
}
|
}
|
||||||
11
crates/erplt-api/src/routes/pages/home.rs
Normal file
11
crates/erplt-api/src/routes/pages/home.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn HomePage() -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<main>
|
||||||
|
<h1>"ERPLT"</h1>
|
||||||
|
<p>"Welcome to ERPLT."</p>
|
||||||
|
</main>
|
||||||
|
}
|
||||||
|
}
|
||||||
32
crates/erplt-api/src/routes/pages/layout.rs
Normal file
32
crates/erplt-api/src/routes/pages/layout.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Layout(children: Children) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<div class="flex min-h-screen">
|
||||||
|
<aside class="w-64 border-r p-4">
|
||||||
|
<h1 class="mb-6 text-xl font-bold">
|
||||||
|
"ERPLT"
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<nav class="space-y-2">
|
||||||
|
<a href="/">"Dashboard"</a>
|
||||||
|
<a href="/sales">"Sales"</a>
|
||||||
|
<a href="/purchases">"Purchases"</a>
|
||||||
|
<a href="/inventory">"Inventory"</a>
|
||||||
|
<a href="/accounting">"Accounting"</a>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<div class="flex flex-1 flex-col">
|
||||||
|
<header class="border-b p-4">
|
||||||
|
"ERPLT"
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="flex-1 p-6">
|
||||||
|
{children()}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
50
crates/erplt-api/src/routes/pages/mod.rs
Normal file
50
crates/erplt-api/src/routes/pages/mod.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
use leptos_meta::*;
|
||||||
|
use leptos_router::{
|
||||||
|
SsrMode, StaticSegment, components::{FlatRoutes, Route, Router},
|
||||||
|
};
|
||||||
|
|
||||||
|
mod home;
|
||||||
|
mod layout;
|
||||||
|
|
||||||
|
#[cfg(feature="ssr")]
|
||||||
|
pub fn shell(options: LeptosOptions) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<AutoReload options=options.clone() />
|
||||||
|
<HydrationScripts options/>
|
||||||
|
<link rel="stylesheet" id="leptos" href="/pkg/erplt.css"/>
|
||||||
|
<link rel="shortcut icon" type="image/ico" href="/favicon.ico"/>
|
||||||
|
<MetaTags/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<App/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn App() -> impl IntoView {
|
||||||
|
provide_meta_context();
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<Router>
|
||||||
|
<FlatRoutes fallback=|| "Page not found.">
|
||||||
|
<Route
|
||||||
|
path=StaticSegment("")
|
||||||
|
view=|| view! {
|
||||||
|
<layout::Layout>
|
||||||
|
<home::HomePage/>
|
||||||
|
</layout::Layout>
|
||||||
|
}
|
||||||
|
ssr=SsrMode::Async
|
||||||
|
/>
|
||||||
|
</FlatRoutes>
|
||||||
|
</Router>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,41 @@
|
|||||||
|
use std::{net::{Ipv4Addr, SocketAddr, SocketAddrV4}, str::FromStr};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use axum::http::StatusCode;
|
use leptos::prelude::*;
|
||||||
|
use leptos_axum::{LeptosRoutes, generate_route_list};
|
||||||
|
|
||||||
use erplt_db::DbPool;
|
use erplt_db::DbPool;
|
||||||
|
|
||||||
#[axum::debug_handler]
|
use crate::routes;
|
||||||
async fn fallback() -> (StatusCode, &'static str) {
|
|
||||||
(StatusCode::NOT_FOUND, "Not Found")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub async fn start(db: DbPool) -> anyhow::Result<()> {
|
pub async fn start(db: DbPool) -> anyhow::Result<()> {
|
||||||
let config = erplt_config::get();
|
let config = erplt_config::get();
|
||||||
|
|
||||||
|
// Need this because tokio has threading panics otherwise
|
||||||
|
any_spawner::Executor::init_tokio().unwrap();
|
||||||
|
|
||||||
|
let leptos_options = LeptosOptions::builder()
|
||||||
|
.output_name("erplt")
|
||||||
|
.site_root("target/site")
|
||||||
|
.site_pkg_dir("pkg")
|
||||||
|
.reload_external_port(Some((config.web.port+1) as u32))
|
||||||
|
.site_addr(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from_str(&config.web.host)?, config.web.port)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let routes = generate_route_list(routes::pages::App);
|
||||||
|
|
||||||
let app = axum::Router::new()
|
let app = axum::Router::new()
|
||||||
.merge(crate::routes::router())
|
//.merge(crate::routes::router())
|
||||||
.fallback(fallback);
|
.merge(routes::router())
|
||||||
|
.leptos_routes(&leptos_options, routes, {
|
||||||
|
let leptos_options = leptos_options.clone();
|
||||||
|
move || routes::pages::shell(leptos_options.clone())
|
||||||
|
})
|
||||||
|
.fallback(leptos_axum::file_and_error_handler(routes::pages::shell))
|
||||||
|
.with_state(leptos_options)
|
||||||
|
.with_state(db);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +46,7 @@ pub async fn start(db: DbPool) -> anyhow::Result<()> {
|
|||||||
|
|
||||||
tracing::info!("Web server listening on http://{}", listener.local_addr()?);
|
tracing::info!("Web server listening on http://{}", listener.local_addr()?);
|
||||||
|
|
||||||
axum::serve(listener, app)
|
axum::serve(listener, app.into_make_service())
|
||||||
.await
|
.await
|
||||||
.context("Web server stopped unexpectedly")?;
|
.context("Web server stopped unexpectedly")?;
|
||||||
|
|
||||||
|
|||||||
1
crates/erplt-api/style/tailwind.css
Normal file
1
crates/erplt-api/style/tailwind.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
@@ -2,7 +2,6 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use camino::Utf8PathBuf;
|
use camino::Utf8PathBuf;
|
||||||
use serde::de;
|
|
||||||
|
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use diesel::r2d2::ConnectionManager;
|
use diesel::r2d2::ConnectionManager;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub type DbBackend = diesel::pg::Pg;
|
pub type DbBackend = diesel::pg::Pg;
|
||||||
pub type DbConnection = diesel::PgConnection;
|
pub type DbConnection = diesel::PgConnection;
|
||||||
pub type DbPool = diesel::r2d2::Pool<
|
pub type DbPool = diesel::r2d2::Pool<
|
||||||
@@ -25,6 +26,8 @@ pub fn connect(url: &str) -> anyhow::Result<DbPool> {
|
|||||||
|
|
||||||
pool.get()
|
pool.get()
|
||||||
.context("Failed to connect to PostgreSQL")?;
|
.context("Failed to connect to PostgreSQL")?;
|
||||||
|
|
||||||
tracing::info!("Connected to database");
|
tracing::info!("Connected to database");
|
||||||
|
// crate::migrations::run_migrations(&pool)?;
|
||||||
Ok(pool)
|
Ok(pool)
|
||||||
}
|
}
|
||||||
@@ -3,17 +3,39 @@ name = "erplt"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["ssr", "erplt-api/ssr"]
|
||||||
|
hydrate=["erplt-api/hydrate"]
|
||||||
|
ssr=[
|
||||||
|
"erplt-api/ssr",
|
||||||
|
"dep:erplt-db",
|
||||||
|
"dep:erplt-config",
|
||||||
|
"dep:camino",
|
||||||
|
"dep:clap",
|
||||||
|
"dep:serde",
|
||||||
|
"dep:toml",
|
||||||
|
"dep:anyhow",
|
||||||
|
"dep:tracing",
|
||||||
|
"dep:tracing-subscriber",
|
||||||
|
"dep:humantime",
|
||||||
|
"dep:humantime-serde",
|
||||||
|
"dep:tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erplt-db.path="../erplt-db"
|
|
||||||
erplt-api.path="../erplt-api"
|
erplt-api.path="../erplt-api"
|
||||||
erplt-config.path="../erplt-config"
|
erplt-db = { path="../erplt-db", optional = true }
|
||||||
camino.workspace = true
|
erplt-config = { path="../erplt-config", optional = true }
|
||||||
clap.workspace = true
|
camino = { workspace = true, optional = true }
|
||||||
serde.workspace = true
|
clap = { workspace = true, optional = true }
|
||||||
toml.workspace = true
|
serde = { workspace = true, optional = true }
|
||||||
anyhow.workspace = true
|
toml = { workspace = true, optional = true }
|
||||||
tracing-subscriber.workspace = true
|
anyhow = { workspace = true, optional = true }
|
||||||
tracing.workspace = true
|
tracing-subscriber = { workspace = true, optional = true }
|
||||||
humantime.workspace = true
|
tracing = { workspace = true, optional = true }
|
||||||
humantime-serde.workspace = true
|
humantime = { workspace = true, optional = true }
|
||||||
tokio.workspace = true
|
humantime-serde = { workspace = true, optional = true }
|
||||||
|
tokio = { workspace = true, optional = true }
|
||||||
|
|||||||
2
crates/erplt/src/lib.rs
Normal file
2
crates/erplt/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(feature = "hydrate")]
|
||||||
|
pub use erplt_api::hydrate;
|
||||||
1103
package-lock.json
generated
Normal file
1103
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
package.json
Normal file
6
package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@tailwindcss/cli": "^4.3.3",
|
||||||
|
"tailwindcss": "^4.3.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
2
scripts/cloc.sh
Normal file
2
scripts/cloc.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
cloc . --fullpath --not-match-d="\.hemttout|\.hemtt/presets|target|node_modules" --not-match-f="package-lock.json"
|
||||||
Reference in New Issue
Block a user