use rustlavel::prelude::*;
use crate::models::user::User;
pub async fn shell(req: &Request, nav: &str) -> ViewContext {
let config = req.config();
let name = config.string("app.name", "Rustlavel");
let mut context = ViewContext::new()
.with("app_name", Json::from(name.as_str()))
.with("app_initial", Json::from(name.chars().next().unwrap_or('R').to_string()))
.with("nav", Json::from(nav))
.with("csrf_field", Json::from(rustlavel::auth::csrf::field(req)));
let theme = req.cookie("theme").filter(|t| t == "dark" || t == "light").unwrap_or_else(|| "light".into());
context = context
.with("theme", Json::from(theme.as_str()))
.with("theme_class", Json::from(if theme == "dark" { "dark" } else { "" }))
.with("theme_next", Json::from(if theme == "dark" { "light" } else { "dark" }));
let errors = req.errors();
let old = req.old();
let mut summary: Option<String> = None;
if let Some(fields) = errors.as_object() {
for (field, messages) in fields {
if let Some(message) = messages.as_array().and_then(|m| m.first()).and_then(Json::as_str) {
if summary.is_none() {
summary = Some(message.to_string());
}
context = context.with(format!("error_{field}"), Json::from(message));
}
}
}
if let Some(fields) = old.as_object() {
for (field, value) in fields {
context = context.with(format!("old_{field}"), value.clone());
}
}
context = context
.with("errors", errors)
.with("old", old)
.with("error_summary", summary.map_or(Json::Null, Json::from));
let session = req.session();
let message = session.forget("flash_message").and_then(|v| v.as_str().map(str::to_string));
let kind = session.forget("flash_kind").and_then(|v| v.as_str().map(str::to_string));
context = context
.with("flash_message", message.map_or(Json::Null, Json::from))
.with("flash_kind", Json::from(kind.unwrap_or_else(|| "success".into())));
context
}
pub async fn with_user(mut context: ViewContext, req: &Request, user: &User) -> Result<ViewContext> {
context = context
.with("user_name", Json::from(user.name.as_str()))
.with("user_email", Json::from(user.email.as_str()))
.with("user_initials", Json::from(user.initials()))
.with("first_name", Json::from(user.first_name()));
let impersonating = rustlavel::auth::Impersonation::is_impersonating(req.session());
context = context.with("impersonating", Json::from(impersonating));
for (flag, permission) in [
("can_view_users", "users.view"),
("can_view_roles", "roles.view"),
("can_view_permissions", "permissions.view"),
("can_manage_settings", "settings.manage"),
("can_view_menus", "menus.view"),
("can_view_audit", "audit.view"),
] {
context = context.with(flag, Json::from(req.can(permission).await?));
}
Ok(context)
}
pub fn flash(req: &Request, kind: &str, message: impl Into<String>) {
let session = req.session();
session.put("flash_message", Json::from(message.into()));
session.put("flash_kind", Json::from(kind));
}
pub fn old(context: ViewContext, fields: &[(&str, Option<String>)]) -> ViewContext {
let mut context = context;
for (name, value) in fields {
context = context.with(
format!("old_{name}"),
Json::from(value.clone().unwrap_or_default()),
);
}
context
}
pub fn check(values: &[(&str, &str)], rules: &[(&str, &str)]) -> rustlavel::validation::Errors {
let input = Json::object(values.iter().map(|(name, value)| (*name, Json::from(*value))));
rustlavel::validation::Validator::new(&input).rules(rules).errors()
}
pub fn errors(context: ViewContext, errors: &rustlavel::validation::Errors) -> ViewContext {
let mut context = context;
let mut first: Option<String> = None;
for (field, messages) in errors.all() {
if let Some(message) = messages.first() {
if first.is_none() {
first = Some(message.clone());
}
context = context.with(format!("error_{field}"), Json::from(message.as_str()));
}
}
context.with("error_summary", first.map_or(Json::Null, Json::from))
}