From 34594b95fa551018a39a9b9ba1bc3a08b6de09b6 Mon Sep 17 00:00:00 2001 From: despiegk Date: Tue, 22 Apr 2025 10:39:29 +0400 Subject: [PATCH] ... --- actix_mvc_app/src/controllers/auth.rs | 17 +--- actix_mvc_app/src/controllers/calendar.rs | 26 ++---- actix_mvc_app/src/controllers/contract.rs | 57 ++----------- actix_mvc_app/src/controllers/flow.rs | 71 ++++------------ actix_mvc_app/src/controllers/governance.rs | 91 ++++++--------------- actix_mvc_app/src/controllers/home.rs | 44 ++-------- actix_mvc_app/src/controllers/ticket.rs | 33 ++------ actix_mvc_app/src/utils/mod.rs | 67 ++++++++++++++- actix_mvc_app/src/views/error.html | 34 +++++++- actix_mvc_app/src/views/flows/flows.html | 67 +++++++++------ 10 files changed, 208 insertions(+), 299 deletions(-) diff --git a/actix_mvc_app/src/controllers/auth.rs b/actix_mvc_app/src/controllers/auth.rs index eb072f4..681a1c8 100644 --- a/actix_mvc_app/src/controllers/auth.rs +++ b/actix_mvc_app/src/controllers/auth.rs @@ -2,6 +2,7 @@ use actix_web::{web, HttpResponse, Responder, Result, http::header, cookie::Cook use actix_session::Session; use tera::Tera; use crate::models::user::{User, LoginCredentials, RegistrationData, UserRole}; +use crate::utils::render_template; use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey, DecodingKey}; use serde::{Deserialize, Serialize}; use chrono::{Utc, Duration}; @@ -91,13 +92,7 @@ impl AuthController { let mut ctx = tera::Context::new(); ctx.insert("active_page", "login"); - let rendered = tmpl.render("auth/login.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "auth/login.html", &ctx) } /// Handles user login @@ -146,13 +141,7 @@ impl AuthController { let mut ctx = tera::Context::new(); ctx.insert("active_page", "register"); - let rendered = tmpl.render("auth/register.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "auth/register.html", &ctx) } /// Handles user registration diff --git a/actix_mvc_app/src/controllers/calendar.rs b/actix_mvc_app/src/controllers/calendar.rs index 646644a..e4bfbc6 100644 --- a/actix_mvc_app/src/controllers/calendar.rs +++ b/actix_mvc_app/src/controllers/calendar.rs @@ -6,7 +6,7 @@ use tera::Tera; use serde_json::Value; use crate::models::{CalendarEvent, CalendarViewMode}; -use crate::utils::RedisCalendarService; +use crate::utils::{RedisCalendarService, render_template}; /// Controller for handling calendar-related routes pub struct CalendarController; @@ -215,13 +215,7 @@ impl CalendarController { }, } - let rendered = tmpl.render("calendar/index.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "calendar/index.html", &ctx) } /// Handles the new event page route @@ -234,13 +228,7 @@ impl CalendarController { ctx.insert("user", &user); } - let rendered = tmpl.render("calendar/new_event.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "calendar/new_event.html", &ctx) } /// Handles the create event route @@ -298,13 +286,9 @@ impl CalendarController { ctx.insert("user", &user); } - let rendered = tmpl.render("calendar/new_event.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; + let result = render_template(&tmpl, "calendar/new_event.html", &ctx)?; - Ok(HttpResponse::InternalServerError().content_type("text/html").body(rendered)) + Ok(HttpResponse::InternalServerError().content_type("text/html").body(result.into_body())) } } } diff --git a/actix_mvc_app/src/controllers/contract.rs b/actix_mvc_app/src/controllers/contract.rs index d8578b6..d53bbfd 100644 --- a/actix_mvc_app/src/controllers/contract.rs +++ b/actix_mvc_app/src/controllers/contract.rs @@ -4,6 +4,7 @@ use chrono::{Utc, Duration}; use serde::Deserialize; use crate::models::contract::{Contract, ContractStatus, ContractType, ContractStatistics, SignerStatus}; +use crate::utils::render_template; #[derive(Debug, Deserialize)] pub struct ContractForm { @@ -62,15 +63,7 @@ impl ContractController { context.insert("draft_contracts", &draft_contracts); - let rendered = tmpl.render("contracts/index.html", &context) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", context); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contracts/index.html", &context) } // Display the list of all contracts @@ -89,15 +82,7 @@ impl ContractController { context.insert("contracts", &contracts_data); context.insert("filter", &"all"); - let rendered = tmpl.render("contracts/contracts.html", &context) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", context); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contracts/contracts.html", &context) } // Display the list of user's contracts @@ -115,15 +100,7 @@ impl ContractController { context.insert("contracts", &contracts_data); - let rendered = tmpl.render("contracts/my_contracts.html", &context) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", context); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contracts/my_contracts.html", &context) } // Display a specific contract @@ -146,15 +123,7 @@ impl ContractController { context.insert("contract", &contract_json); context.insert("user_has_signed", &false); // Mock data - let rendered = tmpl.render("contracts/contract_detail.html", &context) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", context); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contracts/contract_detail.html", &context) }, None => { Ok(HttpResponse::NotFound().finish()) @@ -180,26 +149,18 @@ impl ContractController { context.insert("contract_types", &contract_types); - let rendered = tmpl.render("contracts/create_contract.html", &context) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", context); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contracts/create_contract.html", &context) } // Process the create contract form pub async fn create( - tmpl: web::Data, - form: web::Form, + _tmpl: web::Data, + _form: web::Form, ) -> Result { // In a real application, we would save the contract to the database // For now, we'll just redirect to the contracts list - Ok(HttpResponse::Found().header("Location", "/contracts").finish()) + Ok(HttpResponse::Found().append_header(("Location", "/contracts")).finish()) } // Helper method to convert Contract to a JSON object for templates diff --git a/actix_mvc_app/src/controllers/flow.rs b/actix_mvc_app/src/controllers/flow.rs index 7649242..9816296 100644 --- a/actix_mvc_app/src/controllers/flow.rs +++ b/actix_mvc_app/src/controllers/flow.rs @@ -3,10 +3,10 @@ use actix_session::Session; use chrono::{Utc, Duration}; use serde::Deserialize; use tera::Tera; -use std::error::Error; // Add this line use crate::models::flow::{Flow, FlowStatus, FlowType, FlowStatistics, FlowStep, StepStatus, FlowLog}; use crate::controllers::auth::Claims; +use crate::utils::render_template; pub struct FlowController; @@ -25,15 +25,7 @@ impl FlowController { ctx.insert("active_flows", &flows.iter().filter(|f| f.status == FlowStatus::InProgress).collect::>()); ctx.insert("stuck_flows", &flows.iter().filter(|f| f.status == FlowStatus::Stuck).collect::>()); - let rendered = tmpl.render("flows/index.html", &ctx) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", ctx); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "flows/index.html", &ctx) } /// Renders the flows list page @@ -46,15 +38,7 @@ impl FlowController { ctx.insert("user", &user); ctx.insert("flows", &flows); - let rendered = tmpl.render("flows/flows.html", &ctx) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", ctx); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "flows/flows.html", &ctx) } /// Renders the flow detail page @@ -76,29 +60,20 @@ impl FlowController { ctx.insert("user", &user); ctx.insert("flow", flow); - let rendered = tmpl.render("flows/flow_detail.html", &ctx) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", ctx); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "flows/flow_detail.html", &ctx) } else { let mut ctx = tera::Context::new(); ctx.insert("active_page", "flows"); ctx.insert("error", "Flow not found"); - let rendered = tmpl.render("error.html", &ctx) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", ctx); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::NotFound().content_type("text/html").body(rendered)) + // For the error page, we'll use a special case to set the status code to 404 + match tmpl.render("error.html", &ctx) { + Ok(content) => Ok(HttpResponse::NotFound().content_type("text/html").body(content)), + Err(e) => { + log::error!("Error rendering error template: {}", e); + Err(actix_web::error::ErrorInternalServerError(format!("Error: {}", e))) + } + } } } @@ -110,21 +85,13 @@ impl FlowController { ctx.insert("active_page", "flows"); ctx.insert("user", &user); - let rendered = tmpl.render("flows/create_flow.html", &ctx) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", ctx); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "flows/create_flow.html", &ctx) } /// Handles the create flow form submission pub async fn create_flow( _form: web::Form, - session: Session + _session: Session ) -> impl Responder { // In a real application, we would create a new flow here // For now, just redirect to the flows list @@ -149,15 +116,7 @@ impl FlowController { ctx.insert("user", &user); ctx.insert("flows", &my_flows); - let rendered = tmpl.render("flows/my_flows.html", &ctx) - .map_err(|e| { - log::error!("Template rendering error: {}", e); - log::error!("Error details: {:?}", e); - log::error!("Context: {:?}", ctx); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "flows/my_flows.html", &ctx) } else { Ok(HttpResponse::Found() .append_header(("Location", "/login")) diff --git a/actix_mvc_app/src/controllers/governance.rs b/actix_mvc_app/src/controllers/governance.rs index a570821..c77004f 100644 --- a/actix_mvc_app/src/controllers/governance.rs +++ b/actix_mvc_app/src/controllers/governance.rs @@ -5,6 +5,7 @@ use serde_json::Value; use serde::{Deserialize, Serialize}; use chrono::{Utc, Duration}; use crate::models::governance::{Proposal, Vote, ProposalStatus, VoteType, VotingResults}; +use crate::utils::render_template; /// Controller for handling governance-related routes pub struct GovernanceController; @@ -35,13 +36,7 @@ impl GovernanceController { let stats = Self::get_mock_statistics(); ctx.insert("stats", &stats); - let rendered = tmpl.render("governance/index.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/index.html", &ctx) } /// Handles the proposal list page route @@ -59,13 +54,7 @@ impl GovernanceController { let proposals = Self::get_mock_proposals(); ctx.insert("proposals", &proposals); - let rendered = tmpl.render("governance/proposals.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/proposals.html", &ctx) } /// Handles the proposal detail page route @@ -96,23 +85,18 @@ impl GovernanceController { let results = Self::get_mock_voting_results(&proposal_id); ctx.insert("results", &results); - let rendered = tmpl.render("governance/proposal_detail.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/proposal_detail.html", &ctx) } else { // Proposal not found ctx.insert("error", "Proposal not found"); - let rendered = tmpl.render("error.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::NotFound().content_type("text/html").body(rendered)) + // For the error page, we'll use a special case to set the status code to 404 + match tmpl.render("error.html", &ctx) { + Ok(content) => Ok(HttpResponse::NotFound().content_type("text/html").body(content)), + Err(e) => { + eprintln!("Error rendering error template: {}", e); + Err(actix_web::error::ErrorInternalServerError(format!("Error: {}", e))) + } + } } } @@ -130,18 +114,12 @@ impl GovernanceController { return Ok(HttpResponse::Found().append_header(("Location", "/login")).finish()); } - let rendered = tmpl.render("governance/create_proposal.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/create_proposal.html", &ctx) } /// Handles the submission of a new proposal pub async fn submit_proposal( - form: web::Form, + _form: web::Form, tmpl: web::Data, session: Session ) -> Result { @@ -166,19 +144,13 @@ impl GovernanceController { let proposals = Self::get_mock_proposals(); ctx.insert("proposals", &proposals); - let rendered = tmpl.render("governance/proposals.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/proposals.html", &ctx) } /// Handles the submission of a vote on a proposal pub async fn submit_vote( path: web::Path, - form: web::Form, + _form: web::Form, tmpl: web::Data, session: Session ) -> Result { @@ -211,23 +183,18 @@ impl GovernanceController { let results = Self::get_mock_voting_results(&proposal_id); ctx.insert("results", &results); - let rendered = tmpl.render("governance/proposal_detail.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/proposal_detail.html", &ctx) } else { // Proposal not found ctx.insert("error", "Proposal not found"); - let rendered = tmpl.render("error.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::NotFound().content_type("text/html").body(rendered)) + // For the error page, we'll use a special case to set the status code to 404 + match tmpl.render("error.html", &ctx) { + Ok(content) => Ok(HttpResponse::NotFound().content_type("text/html").body(content)), + Err(e) => { + eprintln!("Error rendering error template: {}", e); + Err(actix_web::error::ErrorInternalServerError(format!("Error: {}", e))) + } + } } } @@ -245,13 +212,7 @@ impl GovernanceController { let votes = Self::get_mock_votes_for_user(1); // Assuming user ID 1 for mock data ctx.insert("votes", &votes); - let rendered = tmpl.render("governance/my_votes.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "governance/my_votes.html", &ctx) } else { // Redirect to login if not logged in Ok(HttpResponse::Found().append_header(("Location", "/login")).finish()) diff --git a/actix_mvc_app/src/controllers/home.rs b/actix_mvc_app/src/controllers/home.rs index 114be0d..166f2e5 100644 --- a/actix_mvc_app/src/controllers/home.rs +++ b/actix_mvc_app/src/controllers/home.rs @@ -1,8 +1,10 @@ -use actix_web::{web, HttpResponse, Responder, Result}; +use actix_web::{web, Responder, Result}; use actix_session::Session; use tera::Tera; use serde_json::Value; +use crate::utils::render_template; + /// Controller for handling home-related routes pub struct HomeController; @@ -24,13 +26,7 @@ impl HomeController { ctx.insert("user", &user); } - let rendered = tmpl.render("editor.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "editor.html", &ctx) } /// Handles the home page route @@ -43,13 +39,7 @@ impl HomeController { ctx.insert("user", &user); } - let rendered = tmpl.render("index.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "index.html", &ctx) } /// Handles the about page route @@ -62,13 +52,7 @@ impl HomeController { ctx.insert("user", &user); } - let rendered = tmpl.render("about.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "about.html", &ctx) } /// Handles the contact page route @@ -81,13 +65,7 @@ impl HomeController { ctx.insert("user", &user); } - let rendered = tmpl.render("contact.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contact.html", &ctx) } /// Handles form submissions from the contact page @@ -112,13 +90,7 @@ impl HomeController { ctx.insert("user", &user); } - let rendered = tmpl.render("contact.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "contact.html", &ctx) } } diff --git a/actix_mvc_app/src/controllers/ticket.rs b/actix_mvc_app/src/controllers/ticket.rs index ef95769..1cf290e 100644 --- a/actix_mvc_app/src/controllers/ticket.rs +++ b/actix_mvc_app/src/controllers/ticket.rs @@ -4,6 +4,7 @@ use tera::Tera; use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::models::{User, Ticket, TicketComment, TicketStatus, TicketPriority}; +use crate::utils::render_template; use std::collections::HashMap; use std::sync::{Arc, Mutex}; @@ -131,13 +132,7 @@ impl TicketController { ]); // Render the template - let rendered = tmpl.render("tickets/list.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "tickets/list.html", &ctx) } /// Shows the form for creating a new ticket @@ -172,13 +167,7 @@ impl TicketController { ]); // Render the template - let rendered = tmpl.render("tickets/new.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "tickets/new.html", &ctx) } /// Creates a new ticket @@ -285,13 +274,7 @@ impl TicketController { ]); // Render the template - let rendered = tmpl.render("tickets/show.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "tickets/show.html", &ctx) } /// Adds a comment to a ticket @@ -443,12 +426,6 @@ impl TicketController { ctx.insert("my_tickets", &true); // Render the template - let rendered = tmpl.render("tickets/list.html", &ctx) - .map_err(|e| { - eprintln!("Template rendering error: {}", e); - actix_web::error::ErrorInternalServerError("Template rendering error") - })?; - - Ok(HttpResponse::Ok().content_type("text/html").body(rendered)) + render_template(&tmpl, "tickets/list.html", &ctx) } } \ No newline at end of file diff --git a/actix_mvc_app/src/utils/mod.rs b/actix_mvc_app/src/utils/mod.rs index 7661b1b..bb1e553 100644 --- a/actix_mvc_app/src/utils/mod.rs +++ b/actix_mvc_app/src/utils/mod.rs @@ -1,5 +1,6 @@ +use actix_web::{error, Error, HttpResponse}; use chrono::{DateTime, Utc}; -use tera::{self, Function, Result, Value}; +use tera::{self, Context, Function, Tera, Value}; // Export modules pub mod redis_service; @@ -7,6 +8,22 @@ pub mod redis_service; // Re-export for easier imports pub use redis_service::RedisCalendarService; +/// Error type for template rendering +#[derive(Debug)] +pub struct TemplateError { + pub message: String, + pub details: String, + pub location: String, +} + +impl std::fmt::Display for TemplateError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Template error in {}: {}", self.location, self.message) + } +} + +impl std::error::Error for TemplateError {} + /// Registers custom Tera functions pub fn register_tera_functions(tera: &mut tera::Tera) { tera.register_function("now", NowFunction); @@ -18,7 +35,7 @@ pub fn register_tera_functions(tera: &mut tera::Tera) { pub struct NowFunction; impl Function for NowFunction { - fn call(&self, args: &std::collections::HashMap) -> Result { + fn call(&self, args: &std::collections::HashMap) -> tera::Result { let format = match args.get("format") { Some(val) => match val.as_str() { Some(s) => s, @@ -43,7 +60,7 @@ impl Function for NowFunction { pub struct FormatDateFunction; impl Function for FormatDateFunction { - fn call(&self, args: &std::collections::HashMap) -> Result { + fn call(&self, args: &std::collections::HashMap) -> tera::Result { let timestamp = match args.get("timestamp") { Some(val) => match val.as_i64() { Some(ts) => ts, @@ -96,6 +113,50 @@ pub fn truncate_string(s: &str, max_length: usize) -> String { } } +/// Renders a template with error handling +/// +/// This function attempts to render a template and handles any errors by rendering +/// the error template with detailed error information. +pub fn render_template( + tmpl: &Tera, + template_name: &str, + ctx: &Context, +) -> Result { + match tmpl.render(template_name, ctx) { + Ok(content) => Ok(HttpResponse::Ok().content_type("text/html").body(content)), + Err(e) => { + // Log the error + log::error!("Template rendering error: {}", e); + log::error!("Error details: {:?}", e); + log::error!("Context: {:?}", ctx); + + // Create a context for the error template + let mut error_ctx = Context::new(); + error_ctx.insert("error", &format!("Template rendering error: {}", e)); + error_ctx.insert("error_details", &format!("{:?}", e)); + error_ctx.insert("error_location", &template_name); + + // Try to render the error template + match tmpl.render("error.html", &error_ctx) { + Ok(error_page) => { + // Return the error page with a 500 status code + Ok(HttpResponse::InternalServerError() + .content_type("text/html") + .body(error_page)) + } + Err(render_err) => { + // If we can't render the error template, log it and return a basic error + log::error!("Error rendering error template: {}", render_err); + Err(error::ErrorInternalServerError(format!( + "Template rendering error: {}. Failed to render error page: {}", + e, render_err + ))) + } + } + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/actix_mvc_app/src/views/error.html b/actix_mvc_app/src/views/error.html index e583b93..dd010ee 100644 --- a/actix_mvc_app/src/views/error.html +++ b/actix_mvc_app/src/views/error.html @@ -7,18 +7,44 @@
-

Error

+

Template Rendering Error

-
Something went wrong
-

{{ error }}

+
Something went wrong while rendering the template
+ +
+

Error Message:

+
{{ error | default(value="Unknown error") }}
+
+ + {% if error_details is defined and error_details %} +
+

Error Details:

+
{{ error_details }}
+
+ {% endif %} + + {% if error_location is defined and error_location %} +
+

Error Location:

+

{{ error_location }}

+
+ {% endif %} + +
+

This error is visible only in development mode. In production, a generic error page will be shown.

+
+
Go to Home - + Go Back +
diff --git a/actix_mvc_app/src/views/flows/flows.html b/actix_mvc_app/src/views/flows/flows.html index f8e1309..bf31a76 100644 --- a/actix_mvc_app/src/views/flows/flows.html +++ b/actix_mvc_app/src/views/flows/flows.html @@ -1,14 +1,14 @@ {% extends "base.html" %} -{% block title %}All Flows{% endblock %} +{% block title %}Freezone Workflows{% endblock %} {% block content %}
@@ -16,11 +16,11 @@
-

All Flows

+

Freezone Workflow Management

@@ -31,7 +31,7 @@
-
+
-
- + +
+ + +
Coming soon
+
+
+
-
+
- +
{% else %} -

No flows found matching your criteria.

+
+ +

No workflows found matching your criteria.

+

Try adjusting your filters or create a new workflow.

+
{% endif %}