feat: bootstrap templating engine
This commit is contained in:
parent
104fc1525c
commit
1c327aaffb
25 changed files with 1051 additions and 158 deletions
499
Cargo.lock
generated
499
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[workspace]
|
||||
exclude = ["utils/db-migrations"] #, "utils/cache-bust"]
|
||||
members = [".", "mailpit_client", "twilio_client"]
|
||||
members = [".", "mailpit_client", "twilio_client", "web_ui"]
|
||||
|
||||
[dependencies]
|
||||
actix-identity = "0.8.0"
|
||||
|
@ -38,6 +38,7 @@ url = { version = "2.5.0", features = ["serde"] }
|
|||
uuid = { version = "1.10.0", features = ["v4", "serde"] }
|
||||
validator = { version = "0.19.0", features = ["derive"] }
|
||||
twilio_client = { path = "./twilio_client" }
|
||||
web_ui = { path = "./web_ui" }
|
||||
|
||||
[dev-dependencies]
|
||||
#reqwest = { version = "0.12.4", features = ["json"] }
|
||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -16,6 +16,7 @@ mod inventory;
|
|||
mod ordering;
|
||||
mod settings;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod tests;
|
||||
mod types;
|
||||
mod utils;
|
||||
|
@ -33,6 +34,7 @@ async fn main() {
|
|||
}
|
||||
|
||||
pretty_env_logger::init();
|
||||
web_ui::init();
|
||||
|
||||
let db = db::sqlx_postgres::Postgres::init(&settings.database.url).await;
|
||||
db.migrate().await;
|
||||
|
@ -58,21 +60,10 @@ async fn main() {
|
|||
.wrap(
|
||||
middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")),
|
||||
)
|
||||
.configure(billing::adapters::load_adapters(
|
||||
.configure(utils::load_adapters::load_adapters(
|
||||
db.pool.clone(),
|
||||
settings.clone(),
|
||||
))
|
||||
.configure(identity::adapters::load_adapters(
|
||||
db.pool.clone(),
|
||||
settings.clone(),
|
||||
))
|
||||
.configure(billing::adapters::load_adapters(
|
||||
db.pool.clone(),
|
||||
settings.clone(),
|
||||
))
|
||||
// .configure(auth::adapter::load_adapters(db.pool.clone(), &settings))
|
||||
.configure(utils::random_string::GenerateRandomString::inject())
|
||||
.configure(utils::uuid::GenerateUUID::inject())
|
||||
})
|
||||
.bind(&socket_addr)
|
||||
.unwrap()
|
||||
|
|
1
web_ui/.gitignore
vendored
Normal file
1
web_ui/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
tmp/
|
15
web_ui/Cargo.toml
Normal file
15
web_ui/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "web_ui"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
derive_builder = "0.20.0"
|
||||
derive_more = { version = "0.99.17", features = ["error"]}
|
||||
lazy_static = "1.5.0"
|
||||
rust-embed = { version = "8.4.0", features = ["debug-embed"]}
|
||||
serde = { version = "1.0.201", features = ["derive"] }
|
||||
serde_json = "1.0.117"
|
||||
tera = "1.19.0"
|
||||
tracing = { version = "0.1.40", features = ["log"] }
|
||||
url = { version = "2.5.0", features = ["serde"] }
|
2
web_ui/Makefile
Normal file
2
web_ui/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
check: ## Check for syntax errors on all workspaces
|
||||
cargo check --tests --all-features
|
17
web_ui/src/identity/mod.rs
Normal file
17
web_ui/src/identity/mod.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pub mod owner_update_email;
|
||||
pub mod owner_verify_email;
|
||||
|
||||
pub fn register_templates(t: &mut tera::Tera) {
|
||||
for template in [
|
||||
owner_update_email::ONWER_UPDATE_EMAIL_PAGE,
|
||||
owner_verify_email::ONWER_VERIFY_EMAIL_PAGE,
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
template.register(t).expect(template.name);
|
||||
}
|
||||
}
|
67
web_ui/src/identity/owner_update_email.rs
Normal file
67
web_ui/src/identity/owner_update_email.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
use std::cell::RefCell;
|
||||
|
||||
use derive_builder::*;
|
||||
use derive_more::*;
|
||||
use serde::*;
|
||||
use tera::Context;
|
||||
use url::Url;
|
||||
|
||||
pub use super::*;
|
||||
use crate::utils::*;
|
||||
|
||||
pub const ONWER_UPDATE_EMAIL_PAGE: TemplateFile = TemplateFile::new(
|
||||
"identity.owner_update_email",
|
||||
"identity/owner_update_email.html",
|
||||
);
|
||||
|
||||
pub fn register_templates(t: &mut tera::Tera) {
|
||||
ONWER_UPDATE_EMAIL_PAGE
|
||||
.register(t)
|
||||
.expect(ONWER_UPDATE_EMAIL_PAGE.name);
|
||||
}
|
||||
|
||||
pub struct OwnerUpdateEmailPage {
|
||||
ctx: RefCell<Context>,
|
||||
}
|
||||
|
||||
impl OwnerUpdateEmailPage {
|
||||
pub fn new() -> Self {
|
||||
let mut ctx = context();
|
||||
|
||||
//ctx.insert(PAYLOAD_KEY, p);
|
||||
|
||||
let ctx = RefCell::new(ctx);
|
||||
Self { ctx }
|
||||
}
|
||||
|
||||
pub fn render(&self) -> String {
|
||||
TEMPLATES
|
||||
.render(ONWER_UPDATE_EMAIL_PAGE.name, &self.ctx.borrow())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn page() -> String {
|
||||
let p = Self::new();
|
||||
p.render()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn render_page_and_write() {
|
||||
const FILE: &str = "./tmp/identity-owner_update_email.html";
|
||||
|
||||
let tw = TestWriterBuilder::default()
|
||||
.file(FILE.into())
|
||||
.contents(OwnerUpdateEmailPage::page())
|
||||
.build()
|
||||
.unwrap();
|
||||
tw.write();
|
||||
}
|
||||
}
|
67
web_ui/src/identity/owner_verify_email.rs
Normal file
67
web_ui/src/identity/owner_verify_email.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
use std::cell::RefCell;
|
||||
|
||||
use derive_builder::*;
|
||||
use derive_more::*;
|
||||
use serde::*;
|
||||
use tera::Context;
|
||||
use url::Url;
|
||||
|
||||
pub use super::*;
|
||||
use crate::utils::*;
|
||||
|
||||
pub const ONWER_VERIFY_EMAIL_PAGE: TemplateFile = TemplateFile::new(
|
||||
"identity.owner_verify_email",
|
||||
"identity/owner_verify_email.html",
|
||||
);
|
||||
|
||||
pub fn register_templates(t: &mut tera::Tera) {
|
||||
ONWER_VERIFY_EMAIL_PAGE
|
||||
.register(t)
|
||||
.expect(ONWER_VERIFY_EMAIL_PAGE.name);
|
||||
}
|
||||
|
||||
pub struct OwnerVerifyEmailPage {
|
||||
ctx: RefCell<Context>,
|
||||
}
|
||||
|
||||
impl OwnerVerifyEmailPage {
|
||||
pub fn new() -> Self {
|
||||
let mut ctx = context();
|
||||
|
||||
//ctx.insert(PAYLOAD_KEY, p);
|
||||
|
||||
let ctx = RefCell::new(ctx);
|
||||
Self { ctx }
|
||||
}
|
||||
|
||||
pub fn render(&self) -> String {
|
||||
TEMPLATES
|
||||
.render(ONWER_VERIFY_EMAIL_PAGE.name, &self.ctx.borrow())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn page() -> String {
|
||||
let p = Self::new();
|
||||
p.render()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn render_page_and_write() {
|
||||
const FILE: &str = "./tmp/identity-owner_verify_email.html";
|
||||
|
||||
let tw = TestWriterBuilder::default()
|
||||
.file(FILE.into())
|
||||
.contents(OwnerVerifyEmailPage::page())
|
||||
.build()
|
||||
.unwrap();
|
||||
tw.write();
|
||||
}
|
||||
}
|
11
web_ui/src/lib.rs
Normal file
11
web_ui/src/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pub mod identity;
|
||||
mod log;
|
||||
mod utils;
|
||||
|
||||
pub fn init() {
|
||||
lazy_static::initialize(&utils::TEMPLATES);
|
||||
}
|
25
web_ui/src/log.rs
Normal file
25
web_ui/src/log.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
pub(crate) use println as info;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
pub(crate) use println as error;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
pub(crate) use println as trace;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
pub(crate) use println as debug;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
pub(crate) use println as warn;
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub use tracing::{debug, error, info, trace, warn};
|
149
web_ui/src/utils.rs
Normal file
149
web_ui/src/utils.rs
Normal file
|
@ -0,0 +1,149 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use rust_embed::RustEmbed;
|
||||
use serde::*;
|
||||
use tera::*;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
pub use tests::*;
|
||||
|
||||
pub struct TemplateFile {
|
||||
pub name: &'static str,
|
||||
pub path: &'static str,
|
||||
}
|
||||
|
||||
impl TemplateFile {
|
||||
pub const fn new(name: &'static str, path: &'static str) -> Self {
|
||||
Self { name, path }
|
||||
}
|
||||
|
||||
pub fn register(&self, t: &mut Tera) -> std::result::Result<(), tera::Error> {
|
||||
t.add_raw_template(self.name, &Templates::get_template(self).expect(self.name))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
pub fn register_from_file(&self, t: &mut Tera) -> std::result::Result<(), tera::Error> {
|
||||
use std::path::Path;
|
||||
t.add_template_file(Path::new("templates/").join(self.path), Some(self.name))
|
||||
}
|
||||
}
|
||||
|
||||
pub const PAYLOAD_KEY: &str = "payload";
|
||||
|
||||
pub const NAV_SEGMENT: TemplateFile = TemplateFile::new("nav_segment.html", "nav_segment.html");
|
||||
|
||||
pub const TAILWIND_CONFIG: TemplateFile =
|
||||
TemplateFile::new("tailwind_config.html", "tailwind_config.html");
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TEMPLATES: Tera = {
|
||||
let mut tera = Tera::default();
|
||||
for t in [NAV_SEGMENT, TAILWIND_CONFIG].iter() {
|
||||
t.register(&mut tera).unwrap();
|
||||
}
|
||||
tera.autoescape_on(vec![".html", ".sql"]);
|
||||
crate::identity::register_templates(&mut tera);
|
||||
tera
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "templates/"]
|
||||
pub struct Templates;
|
||||
|
||||
impl Templates {
|
||||
pub fn get_template(t: &TemplateFile) -> Option<String> {
|
||||
match Self::get(t.path) {
|
||||
Some(file) => Some(String::from_utf8_lossy(&file.data).into_owned()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context() -> Context {
|
||||
let ctx = Context::new();
|
||||
// let footer = Footer::new(s);
|
||||
// ctx.insert("footer", &footer);
|
||||
// ctx.insert("page", &PAGES);
|
||||
// ctx.insert("assets", &*ASSETS);
|
||||
ctx
|
||||
}
|
||||
|
||||
//pub fn auth_ctx(username: Option<&str>, s: &Settings) -> Context {
|
||||
// use routes::GistProfilePathComponent;
|
||||
// let mut profile_link = None;
|
||||
// if let Some(name) = username {
|
||||
// profile_link = Some(
|
||||
// PAGES
|
||||
// .gist
|
||||
// .get_profile_route(GistProfilePathComponent { username: name }),
|
||||
// );
|
||||
// }
|
||||
// let mut ctx = Context::new();
|
||||
// let footer = Footer::new(s);
|
||||
// ctx.insert("footer", &footer);
|
||||
// ctx.insert("page", &PAGES);
|
||||
// ctx.insert("assets", &*ASSETS);
|
||||
// ctx.insert("loggedin_user", &profile_link);
|
||||
// ctx
|
||||
//}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Footer<'a> {
|
||||
// version: &'a str,
|
||||
admin_email: &'a str,
|
||||
source_code: &'a str,
|
||||
// git_hash: &'a str,
|
||||
// settings: &'a Settings,
|
||||
// demo_user: &'a str,
|
||||
// demo_password: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Footer<'a> {
|
||||
pub fn new(admin_email: &'a str, source_code: &'a str) -> Self {
|
||||
Self {
|
||||
// version: VERSION,
|
||||
source_code,
|
||||
admin_email,
|
||||
// git_hash: &GIT_COMMIT_HASH[..8],
|
||||
// demo_user: crate::demo::DEMO_USER,
|
||||
// demo_password: crate::demo::DEMO_PASSWORD,
|
||||
// settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use derive_builder::*;
|
||||
use derive_more::*;
|
||||
use tracing::info;
|
||||
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Builder)]
|
||||
pub struct TestWriter {
|
||||
file: String,
|
||||
contents: String,
|
||||
}
|
||||
|
||||
impl TestWriter {
|
||||
pub fn write(&self) {
|
||||
let p = Path::new(&self.file);
|
||||
if p.exists() {
|
||||
info!("{:?} exists; removing", p.canonicalize().unwrap());
|
||||
fs::remove_file(&self.file).unwrap();
|
||||
}
|
||||
|
||||
let _ = fs::write(&self.file, self.contents.as_bytes());
|
||||
info!("contents written to file: {:?}", p.canonicalize().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
14
web_ui/templates/identity/employee_exit_organization.html
Normal file
14
web_ui/templates/identity/employee_exit_organization.html
Normal 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.0">
|
||||
<title>Exit organization | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/delete/user" method="post">
|
||||
<button type="submit">Exit organization</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
27
web_ui/templates/identity/employee_login.html
Normal file
27
web_ui/templates/identity/employee_login.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/employee/login" method="post">
|
||||
<label for="country_code">
|
||||
Country Code
|
||||
<input type="number" name="country_code" id="country_code" value="91">
|
||||
</label>
|
||||
|
||||
<label for="number">
|
||||
Phone number
|
||||
<input type="number" name="number" id="number">
|
||||
</label>
|
||||
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
|
||||
<p>New here? Click <a href="/employee/register">here to register!</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
37
web_ui/templates/identity/employee_register.html
Normal file
37
web_ui/templates/identity/employee_register.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Register | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/employee/register" method="post">
|
||||
<label for="first_name">
|
||||
First Name
|
||||
<input type="text" name="first_name" id="first_name">
|
||||
</label>
|
||||
<label for="last_name">
|
||||
Last Name
|
||||
<input type="text" name="last_name" id="last_name">
|
||||
</label>
|
||||
|
||||
<label for="country_code">
|
||||
Country Code
|
||||
<input type="number" name="country_code" id="country_code" value="91">
|
||||
</label>
|
||||
|
||||
<label for="number">
|
||||
Phone number
|
||||
<input type="number" name="number" id="number">
|
||||
</label>
|
||||
|
||||
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
|
||||
<p>Already have an account? Click <a href="/employee/login">here to log in!</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
25
web_ui/templates/identity/owner_add_store.html
Normal file
25
web_ui/templates/identity/owner_add_store.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Create Store | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/store" method="post">
|
||||
<label for="name">
|
||||
Store name
|
||||
<input type="text" name="name" id="name" required>
|
||||
</label>
|
||||
|
||||
<label for="address">
|
||||
Address
|
||||
<input type="text" name="address" id="address">
|
||||
</label>
|
||||
|
||||
<button type="submit">Create Store</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
31
web_ui/templates/identity/owner_change_password.html
Normal file
31
web_ui/templates/identity/owner_change_password.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Change Password | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/user/password/change" method="post">
|
||||
<label for="current_password">
|
||||
Current password
|
||||
<input type="password" name="current_password" id="current_password">
|
||||
</label>
|
||||
|
||||
<label for="new_password">
|
||||
New password
|
||||
<input type="password" name="new_password" id="new_password">
|
||||
</label>
|
||||
|
||||
<label for="confirm_new_password">
|
||||
Confirm new password
|
||||
<input type="password" name="confirm_new_password" id="confirm_new_password">
|
||||
</label>
|
||||
|
||||
|
||||
<button type="submit">Change password</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
20
web_ui/templates/identity/owner_delete_user.html
Normal file
20
web_ui/templates/identity/owner_delete_user.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Delete account | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/delete/user" method="post">
|
||||
|
||||
<label for="password">
|
||||
Password
|
||||
<input type="password" name="password" id="password">
|
||||
</label>
|
||||
|
||||
<button type="submit">Delete account</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
27
web_ui/templates/identity/owner_login.html
Normal file
27
web_ui/templates/identity/owner_login.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/login" method="post">
|
||||
<label for="email">
|
||||
Email
|
||||
<input type="email" name="email" id="email">
|
||||
</label>
|
||||
|
||||
<label for="password">
|
||||
Password
|
||||
<input type="password" name="password" id="password">
|
||||
</label>
|
||||
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
|
||||
<p>New here? Click <a href="/owner/register">here to register!</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
43
web_ui/templates/identity/owner_register.html
Normal file
43
web_ui/templates/identity/owner_register.html
Normal file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Register | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/register" method="post">
|
||||
<label for="first_name">
|
||||
First Name
|
||||
<input type="text" name="first_name" id="first_name">
|
||||
</label>
|
||||
<label for="last_name">
|
||||
Last Name
|
||||
<input type="text" name="last_name" id="last_name">
|
||||
</label>
|
||||
|
||||
<label for="email">
|
||||
Email
|
||||
<input type="email" name="email" id="email">
|
||||
</label>
|
||||
|
||||
<label for="password">
|
||||
Password
|
||||
<input type="password" name="password" id="password">
|
||||
</label>
|
||||
|
||||
|
||||
<label for="confirm_password">
|
||||
Confirm Password
|
||||
<input type="confirm_password" name="confirm_password" id="confirm_password">
|
||||
</label>
|
||||
|
||||
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
|
||||
<p>Already have an account? Click <a href="/owner/login">here to log in!</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
25
web_ui/templates/identity/owner_update_email.html
Normal file
25
web_ui/templates/identity/owner_update_email.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Update Email | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/user/email/update" method="post">
|
||||
<label for="email">
|
||||
Email
|
||||
<input type="email" name="email" id="email">
|
||||
</label>
|
||||
|
||||
<label for="password">
|
||||
Password
|
||||
<input type="password" name="password" id="password">
|
||||
</label>
|
||||
|
||||
<button type="submit">Update</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
25
web_ui/templates/identity/owner_update_store.html
Normal file
25
web_ui/templates/identity/owner_update_store.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Update Store | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/store/update" method="post">
|
||||
<label for="name">
|
||||
Store name
|
||||
<input type="text" name="name" id="name" required>
|
||||
</label>
|
||||
|
||||
<label for="address">
|
||||
Address
|
||||
<input type="text" name="address" id="address">
|
||||
</label>
|
||||
|
||||
<button type="submit">Update Store</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
14
web_ui/templates/identity/owner_verify_email.html
Normal file
14
web_ui/templates/identity/owner_verify_email.html
Normal 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.0">
|
||||
<title>Verify email | Vanikam</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form action="/owner/delete/user" method="post">
|
||||
<button type="submit">Verify email</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
25
web_ui/templates/nav_segment.html
Normal file
25
web_ui/templates/nav_segment.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<nav class="flex bg-darkest w-full flex-row items-center mb-9">
|
||||
<span class="m-4 flex flex-column items-center">
|
||||
<a href="/">
|
||||
<img
|
||||
class="size-16 rounded-md"
|
||||
src="https://forgeflux.org/logo-thumbnail.png"
|
||||
alt="Go to home"
|
||||
/>
|
||||
</a>
|
||||
<p class="text-lightest text-3xl ml-3">ForgeFlux</p>
|
||||
</span>
|
||||
<form
|
||||
class="grow m-4 bg-green-300 flex flex-row rounded-md"
|
||||
action="/search"
|
||||
method="get"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="w-full rounded-md size-8 text-start p-4"
|
||||
name="q"
|
||||
id="q"
|
||||
placeholder="Search for persons, repositories, etc."
|
||||
/>
|
||||
</form>
|
||||
</nav>
|
25
web_ui/templates/tailwind_config.html
Normal file
25
web_ui/templates/tailwind_config.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 9;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
darkest: "#171717",
|
||||
dark: "#414141",
|
||||
medium: "#808080",
|
||||
light: "#e0e0e0",
|
||||
lightest: "#f5f5f5",
|
||||
white: "#fff",
|
||||
primary: "#cc3229",
|
||||
backdrop: "#e8e9ea",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
Loading…
Reference in a new issue