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]
|
[workspace]
|
||||||
exclude = ["utils/db-migrations"] #, "utils/cache-bust"]
|
exclude = ["utils/db-migrations"] #, "utils/cache-bust"]
|
||||||
members = [".", "mailpit_client", "twilio_client"]
|
members = [".", "mailpit_client", "twilio_client", "web_ui"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-identity = "0.8.0"
|
actix-identity = "0.8.0"
|
||||||
|
@ -38,6 +38,7 @@ url = { version = "2.5.0", features = ["serde"] }
|
||||||
uuid = { version = "1.10.0", features = ["v4", "serde"] }
|
uuid = { version = "1.10.0", features = ["v4", "serde"] }
|
||||||
validator = { version = "0.19.0", features = ["derive"] }
|
validator = { version = "0.19.0", features = ["derive"] }
|
||||||
twilio_client = { path = "./twilio_client" }
|
twilio_client = { path = "./twilio_client" }
|
||||||
|
web_ui = { path = "./web_ui" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
#reqwest = { version = "0.12.4", features = ["json"] }
|
#reqwest = { version = "0.12.4", features = ["json"] }
|
||||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -16,6 +16,7 @@ mod inventory;
|
||||||
mod ordering;
|
mod ordering;
|
||||||
mod settings;
|
mod settings;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[macro_use]
|
||||||
mod tests;
|
mod tests;
|
||||||
mod types;
|
mod types;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
@ -33,6 +34,7 @@ async fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
web_ui::init();
|
||||||
|
|
||||||
let db = db::sqlx_postgres::Postgres::init(&settings.database.url).await;
|
let db = db::sqlx_postgres::Postgres::init(&settings.database.url).await;
|
||||||
db.migrate().await;
|
db.migrate().await;
|
||||||
|
@ -58,21 +60,10 @@ async fn main() {
|
||||||
.wrap(
|
.wrap(
|
||||||
middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")),
|
middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")),
|
||||||
)
|
)
|
||||||
.configure(billing::adapters::load_adapters(
|
.configure(utils::load_adapters::load_adapters(
|
||||||
db.pool.clone(),
|
db.pool.clone(),
|
||||||
settings.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)
|
.bind(&socket_addr)
|
||||||
.unwrap()
|
.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