From 7e95391a9cabf5bdf548ca9f894b6cbf52712ed6 Mon Sep 17 00:00:00 2001 From: Mahmoud-Emad Date: Tue, 3 Jun 2025 15:31:50 +0300 Subject: [PATCH] feat: Refactor governance models and views - Moved governance models (`Vote`, `VoteType`, `VotingResults`) from `models/governance.rs` to `controllers/governance.rs` for better organization and to avoid circular dependencies. This improves maintainability and reduces complexity. - Updated governance views to use the new model locations. - Added a limit to the number of recent activities displayed on the dashboard for performance optimization. --- actix_mvc_app/src/controllers/governance.rs | 71 +++++- actix_mvc_app/src/models/governance.rs | 222 ------------------ actix_mvc_app/src/models/mod.rs | 2 +- actix_mvc_app/src/views/governance/index.html | 13 +- 4 files changed, 76 insertions(+), 232 deletions(-) delete mode 100644 actix_mvc_app/src/models/governance.rs diff --git a/actix_mvc_app/src/controllers/governance.rs b/actix_mvc_app/src/controllers/governance.rs index f76954d..16cfbbd 100644 --- a/actix_mvc_app/src/controllers/governance.rs +++ b/actix_mvc_app/src/controllers/governance.rs @@ -2,7 +2,7 @@ use crate::db::governance::{ self, create_activity, get_all_activities, get_proposal_by_id, get_proposals, get_recent_activities, }; -use crate::models::governance::{Vote, VoteType, VotingResults}; +// Note: Now using heromodels directly instead of local governance models use crate::utils::render_template; use actix_session::Session; use actix_web::{HttpResponse, Responder, Result, web}; @@ -15,6 +15,71 @@ use tera::Tera; use chrono::prelude::*; +/// Simple vote type for UI display +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum VoteType { + Yes, + No, + Abstain, +} + +/// Simple vote structure for UI display +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Vote { + pub id: String, + pub proposal_id: String, + pub voter_id: i32, + pub voter_name: String, + pub vote_type: VoteType, + pub comment: Option, + pub created_at: DateTime, + pub updated_at: DateTime, +} + +impl Vote { + pub fn new( + proposal_id: String, + voter_id: i32, + voter_name: String, + vote_type: VoteType, + comment: Option, + ) -> Self { + let now = Utc::now(); + Self { + id: uuid::Uuid::new_v4().to_string(), + proposal_id, + voter_id, + voter_name, + vote_type, + comment, + created_at: now, + updated_at: now, + } + } +} + +/// Simple voting results structure for UI display +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VotingResults { + pub proposal_id: String, + pub yes_count: usize, + pub no_count: usize, + pub abstain_count: usize, + pub total_votes: usize, +} + +impl VotingResults { + pub fn new(proposal_id: String) -> Self { + Self { + proposal_id, + yes_count: 0, + no_count: 0, + abstain_count: 0, + total_votes: 0, + } + } +} + /// Controller for handling governance-related routes pub struct GovernanceController; @@ -153,9 +218,9 @@ impl GovernanceController { let stats = Self::calculate_statistics_from_database(&proposals_for_stats); ctx.insert("stats", &stats); - // Get recent governance activities from our tracker + // Get recent governance activities from our tracker (limit to 4 for dashboard) let recent_activity = match Self::get_recent_governance_activities() { - Ok(activities) => activities, + Ok(activities) => activities.into_iter().take(4).collect::>(), Err(e) => { eprintln!("Failed to load recent activities: {}", e); Vec::new() diff --git a/actix_mvc_app/src/models/governance.rs b/actix_mvc_app/src/models/governance.rs deleted file mode 100644 index b2e2eef..0000000 --- a/actix_mvc_app/src/models/governance.rs +++ /dev/null @@ -1,222 +0,0 @@ -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -/// Represents the status of a governance proposal -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub enum ProposalStatus { - /// Proposal is in draft status, not yet open for voting - Draft, - /// Proposal is active and open for voting - Active, - /// Proposal has been approved by the community - Approved, - /// Proposal has been rejected by the community - Rejected, - /// Proposal has been cancelled by the creator - Cancelled, -} - -impl std::fmt::Display for ProposalStatus { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ProposalStatus::Draft => write!(f, "Draft"), - ProposalStatus::Active => write!(f, "Active"), - ProposalStatus::Approved => write!(f, "Approved"), - ProposalStatus::Rejected => write!(f, "Rejected"), - ProposalStatus::Cancelled => write!(f, "Cancelled"), - } - } -} - -/// Represents a vote on a governance proposal -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub enum VoteType { - /// Vote in favor of the proposal - Yes, - /// Vote against the proposal - No, - /// Abstain from voting on the proposal - Abstain, -} - -impl std::fmt::Display for VoteType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - VoteType::Yes => write!(f, "Yes"), - VoteType::No => write!(f, "No"), - VoteType::Abstain => write!(f, "Abstain"), - } - } -} - -/// Represents a governance proposal in the system -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Proposal { - /// Unique identifier for the proposal - pub id: String, - /// User ID of the proposal creator - pub creator_id: i32, - /// Name of the proposal creator - pub creator_name: String, - /// Title of the proposal - pub title: String, - /// Detailed description of the proposal - pub description: String, - /// Current status of the proposal - pub status: ProposalStatus, - /// Date and time when the proposal was created - pub created_at: DateTime, - /// Date and time when the proposal was last updated - pub updated_at: DateTime, - /// Date and time when voting starts - pub voting_starts_at: Option>, - /// Date and time when voting ends - pub voting_ends_at: Option>, -} - -#[allow(dead_code)] -impl Proposal { - /// Creates a new proposal - pub fn new(creator_id: i32, creator_name: String, title: String, description: String) -> Self { - let now = Utc::now(); - Self { - id: Uuid::new_v4().to_string(), - creator_id, - creator_name, - title, - description, - status: ProposalStatus::Draft, - created_at: now, - updated_at: now, - voting_starts_at: None, - voting_ends_at: None, - } - } - - /// Updates the proposal status - pub fn update_status(&mut self, status: ProposalStatus) { - self.status = status; - self.updated_at = Utc::now(); - } - - /// Sets the voting period for the proposal - pub fn set_voting_period(&mut self, starts_at: DateTime, ends_at: DateTime) { - self.voting_starts_at = Some(starts_at); - self.voting_ends_at = Some(ends_at); - self.updated_at = Utc::now(); - } - - /// Activates the proposal for voting - pub fn activate(&mut self) { - self.status = ProposalStatus::Active; - self.updated_at = Utc::now(); - } - - /// Cancels the proposal - pub fn cancel(&mut self) { - self.status = ProposalStatus::Cancelled; - self.updated_at = Utc::now(); - } -} - -/// Represents a vote cast on a proposal -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Vote { - /// Unique identifier for the vote - pub id: String, - /// ID of the proposal being voted on - pub proposal_id: String, - /// User ID of the voter - pub voter_id: i32, - /// Name of the voter - pub voter_name: String, - /// Type of vote cast - pub vote_type: VoteType, - /// Optional comment explaining the vote - pub comment: Option, - /// Date and time when the vote was cast - pub created_at: DateTime, - /// Date and time when the vote was last updated - pub updated_at: DateTime, -} - -#[allow(dead_code)] -impl Vote { - /// Creates a new vote - pub fn new( - proposal_id: String, - voter_id: i32, - voter_name: String, - vote_type: VoteType, - comment: Option, - ) -> Self { - let now = Utc::now(); - Self { - id: Uuid::new_v4().to_string(), - proposal_id, - voter_id, - voter_name, - vote_type, - comment, - created_at: now, - updated_at: now, - } - } - - /// Updates the vote type - pub fn update_vote(&mut self, vote_type: VoteType, comment: Option) { - self.vote_type = vote_type; - self.comment = comment; - self.updated_at = Utc::now(); - } -} - -/// Represents a filter for searching proposals -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ProposalFilter { - /// Filter by proposal status - pub status: Option, - /// Filter by creator ID - pub creator_id: Option, - /// Search term for title and description - pub search: Option, -} - -impl Default for ProposalFilter { - fn default() -> Self { - Self { - status: None, - creator_id: None, - search: None, - } - } -} - -/// Represents the voting results for a proposal -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct VotingResults { - /// Proposal ID - pub proposal_id: String, - /// Number of yes votes - pub yes_count: usize, - /// Number of no votes - pub no_count: usize, - /// Number of abstain votes - pub abstain_count: usize, - /// Total number of votes - pub total_votes: usize, -} - -impl VotingResults { - /// Creates a new VotingResults instance - pub fn new(proposal_id: String) -> Self { - Self { - proposal_id, - yes_count: 0, - no_count: 0, - abstain_count: 0, - total_votes: 0, - } - } -} diff --git a/actix_mvc_app/src/models/mod.rs b/actix_mvc_app/src/models/mod.rs index cc9f331..de69970 100644 --- a/actix_mvc_app/src/models/mod.rs +++ b/actix_mvc_app/src/models/mod.rs @@ -4,7 +4,7 @@ pub mod calendar; pub mod contract; pub mod defi; pub mod flow; -pub mod governance; + pub mod marketplace; pub mod ticket; pub mod user; diff --git a/actix_mvc_app/src/views/governance/index.html b/actix_mvc_app/src/views/governance/index.html index 6d329a9..0a8a3c9 100644 --- a/actix_mvc_app/src/views/governance/index.html +++ b/actix_mvc_app/src/views/governance/index.html @@ -87,15 +87,16 @@
Cast Your Vote
-
+
- +
- - - + + +