feat(mse): minijinja template engine, shared header partial
- tmpl.rs: OnceLock ile build-time compile edilmiş minijinja env
- _header.html: ortak header partial — logo, nav (active_page değişkeni), mode-toggle, çıkış
- index.html, bots.html, positions.html: hardcoded header → {% include "_header.html" %}
- bots.html: + Yeni Bot butonu header'dan page-toolbar'a taşındı
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5db9332157
commit
64806dd32e
7 changed files with 55 additions and 49 deletions
|
|
@ -70,7 +70,7 @@ async fn bots_handler(
|
||||||
Some(t) => { let db = state.db.lock().await; db.session_exists(&t).unwrap_or(false) }
|
Some(t) => { let db = state.db.lock().await; db.session_exists(&t).unwrap_or(false) }
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
if authed { axum::response::Html(include_str!("../web/bots.html")).into_response() }
|
if authed { axum::response::Html(crate::tmpl::render("bots.html", "bots")).into_response() }
|
||||||
else { Redirect::to("/").into_response() }
|
else { Redirect::to("/").into_response() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ async fn positions_handler(
|
||||||
Some(t) => { let db = state.db.lock().await; db.session_exists(&t).unwrap_or(false) }
|
Some(t) => { let db = state.db.lock().await; db.session_exists(&t).unwrap_or(false) }
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
if authed { axum::response::Html(include_str!("../web/positions.html")).into_response() }
|
if authed { axum::response::Html(crate::tmpl::render("positions.html", "positions")).into_response() }
|
||||||
else { Redirect::to("/").into_response() }
|
else { Redirect::to("/").into_response() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ async fn dashboard_handler(
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
if authed {
|
if authed {
|
||||||
axum::response::Html(include_str!("../web/index.html")).into_response()
|
axum::response::Html(crate::tmpl::render("index.html", "dashboard")).into_response()
|
||||||
} else {
|
} else {
|
||||||
Redirect::to("/").into_response()
|
Redirect::to("/").into_response()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ mod binance;
|
||||||
mod bot;
|
mod bot;
|
||||||
mod config;
|
mod config;
|
||||||
mod storage;
|
mod storage;
|
||||||
|
mod tmpl;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
|
||||||
24
src/tmpl.rs
Normal file
24
src/tmpl.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
use minijinja::{Environment, context};
|
||||||
|
|
||||||
|
static ENV: OnceLock<Environment<'static>> = OnceLock::new();
|
||||||
|
|
||||||
|
fn env() -> &'static Environment<'static> {
|
||||||
|
ENV.get_or_init(|| {
|
||||||
|
let mut e = Environment::new();
|
||||||
|
e.add_template_owned("_header.html", include_str!("web/_header.html").to_string()).unwrap();
|
||||||
|
e.add_template_owned("index.html", include_str!("web/index.html").to_string()).unwrap();
|
||||||
|
e.add_template_owned("bots.html", include_str!("web/bots.html").to_string()).unwrap();
|
||||||
|
e.add_template_owned("bot.html", include_str!("web/bot.html").to_string()).unwrap();
|
||||||
|
e.add_template_owned("positions.html", include_str!("web/positions.html").to_string()).unwrap();
|
||||||
|
e
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(template: &str, active_page: &str) -> String {
|
||||||
|
env()
|
||||||
|
.get_template(template)
|
||||||
|
.unwrap()
|
||||||
|
.render(context! { active_page => active_page })
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
15
src/web/_header.html
Normal file
15
src/web/_header.html
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<header>
|
||||||
|
<div class="logo"><span class="logo-crypto">Crypto</span><span class="logo-fox">Fox</span></div>
|
||||||
|
<div class="h-sep"></div>
|
||||||
|
<nav>
|
||||||
|
<a href="/dashboard" class="nav-link{% if active_page == 'dashboard' %} active{% endif %}">Dashboard</a>
|
||||||
|
<a href="/bots" class="nav-link{% if active_page == 'bots' %} active{% endif %}">Botlar</a>
|
||||||
|
<a href="/positions" class="nav-link{% if active_page == 'positions' %} active{% endif %}">Pozisyonlar</a>
|
||||||
|
</nav>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="mode-toggle">
|
||||||
|
<button class="mode-btn" id="btn-live">Canlı</button>
|
||||||
|
<button class="mode-btn" id="btn-testnet">Testnet</button>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-logout" onclick="logout()">Çıkış</button>
|
||||||
|
</header>
|
||||||
|
|
@ -46,6 +46,8 @@
|
||||||
|
|
||||||
/* ── MAIN ── */
|
/* ── MAIN ── */
|
||||||
main { padding: 24px; max-width: 1400px; margin: 0 auto; }
|
main { padding: 24px; max-width: 1400px; margin: 0 auto; }
|
||||||
|
.page-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; }
|
||||||
|
.page-title { font-size: 16px; font-weight: 600; }
|
||||||
|
|
||||||
/* ── GROUP HEADER ── */
|
/* ── GROUP HEADER ── */
|
||||||
.group-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
|
.group-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
|
||||||
|
|
@ -116,24 +118,14 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<header>
|
{% include "_header.html" %}
|
||||||
<div class="logo"><span class="logo-crypto">Crypto</span><span class="logo-fox">Fox</span></div>
|
|
||||||
<div class="h-sep"></div>
|
|
||||||
<nav>
|
|
||||||
<a href="/dashboard" class="nav-link">Dashboard</a>
|
|
||||||
<a href="/bots" class="nav-link active">Botlar</a>
|
|
||||||
<a href="/positions" class="nav-link">Pozisyonlar</a>
|
|
||||||
</nav>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div class="mode-toggle">
|
|
||||||
<button class="mode-btn" id="btn-live" onclick="setMode('live')">Canlı</button>
|
|
||||||
<button class="mode-btn" id="btn-testnet" onclick="setMode('testnet')">Testnet</button>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary" onclick="openModal()">+ Yeni Bot</button>
|
|
||||||
<button class="btn btn-logout" onclick="logout()">Çıkış</button>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
<div class="page-toolbar">
|
||||||
|
<span class="page-title">Botlar</span>
|
||||||
|
<button class="btn btn-primary" onclick="openModal()">+ Yeni Bot</button>
|
||||||
|
</div>
|
||||||
<div class="group-section group-running">
|
<div class="group-section group-running">
|
||||||
<div class="group-label">Çalışıyor <span class="count" id="count-running">0</span></div>
|
<div class="group-label">Çalışıyor <span class="count" id="count-running">0</span></div>
|
||||||
<div class="cards-grid" id="grid-running"><div class="empty-state">Çalışan bot yok</div></div>
|
<div class="cards-grid" id="grid-running"><div class="empty-state">Çalışan bot yok</div></div>
|
||||||
|
|
|
||||||
|
|
@ -144,21 +144,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<header>
|
{% include "_header.html" %}
|
||||||
<div class="logo"><span class="logo-crypto">Crypto</span><span class="logo-fox">Fox</span></div>
|
|
||||||
<div class="h-sep"></div>
|
|
||||||
<nav>
|
|
||||||
<a href="/dashboard" class="nav-link active">Dashboard</a>
|
|
||||||
<a href="/bots" class="nav-link">Botlar</a>
|
|
||||||
<a href="/positions" class="nav-link">Pozisyonlar</a>
|
|
||||||
</nav>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div class="mode-toggle">
|
|
||||||
<button class="mode-btn" id="btn-testnet" onclick="switchMode('testnet')">Testnet</button>
|
|
||||||
<button class="mode-btn" id="btn-live" onclick="switchMode('live')">Canlı</button>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-logout" onclick="logout()">Çıkış</button>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
||||||
|
|
@ -45,21 +45,8 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<header>
|
{% include "_header.html" %}
|
||||||
<div class="logo"><span class="logo-crypto">Crypto</span><span class="logo-fox">Fox</span></div>
|
|
||||||
<div class="h-sep"></div>
|
|
||||||
<nav>
|
|
||||||
<a href="/dashboard" class="nav-link">Dashboard</a>
|
|
||||||
<a href="/bots" class="nav-link">Botlar</a>
|
|
||||||
<a href="/positions" class="nav-link active">Pozisyonlar</a>
|
|
||||||
</nav>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div class="mode-toggle">
|
|
||||||
<button class="mode-btn" id="btn-testnet">Testnet</button>
|
|
||||||
<button class="mode-btn" id="btn-live">Canlı</button>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-logout" onclick="logout()">Çıkış</button>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue