update governance ui

This commit is contained in:
timurgordon
2025-05-16 14:07:20 +03:00
parent 9468595395
commit 2fd74defab
5 changed files with 238 additions and 154 deletions

View File

@@ -12,9 +12,24 @@ pub struct GovernanceController;
impl GovernanceController {
/// Helper function to get user from session
/// For testing purposes, this will always return a mock user
fn get_user_from_session(session: &Session) -> Option<Value> {
session.get::<String>("user").ok().flatten().and_then(|user_json| {
// Try to get user from session first
let session_user = session.get::<String>("user").ok().flatten().and_then(|user_json| {
serde_json::from_str(&user_json).ok()
});
// If user is not in session, return a mock user for testing
session_user.or_else(|| {
// Create a mock user
let mock_user = serde_json::json!({
"id": 1,
"username": "test_user",
"email": "test@example.com",
"name": "Test User",
"role": "member"
});
Some(mock_user)
})
}
@@ -23,14 +38,32 @@ impl GovernanceController {
let mut ctx = tera::Context::new();
ctx.insert("active_page", "governance");
// Add user to context if available
if let Some(user) = Self::get_user_from_session(&session) {
ctx.insert("user", &user);
}
// Add user to context (will always be available with our mock user)
let user = Self::get_user_from_session(&session).unwrap();
ctx.insert("user", &user);
// Get mock proposals for the dashboard
let proposals = Self::get_mock_proposals();
ctx.insert("proposals", &proposals);
let mut proposals = Self::get_mock_proposals();
// Filter for active proposals only
let active_proposals: Vec<Proposal> = proposals.into_iter()
.filter(|p| p.status == ProposalStatus::Active)
.collect();
// Sort active proposals by voting end date (ascending)
let mut sorted_active_proposals = active_proposals.clone();
sorted_active_proposals.sort_by(|a, b| a.voting_ends_at.cmp(&b.voting_ends_at));
ctx.insert("proposals", &sorted_active_proposals);
// Get the nearest deadline proposal for the voting pane
if let Some(nearest_proposal) = sorted_active_proposals.first() {
ctx.insert("nearest_proposal", nearest_proposal);
}
// Get recent activity for the timeline
let recent_activity = Self::get_mock_recent_activity();
ctx.insert("recent_activity", &recent_activity);
// Get some statistics
let stats = Self::get_mock_statistics();
@@ -106,13 +139,9 @@ impl GovernanceController {
ctx.insert("active_page", "governance");
ctx.insert("active_tab", "create");
// Add user to context if available
if let Some(user) = Self::get_user_from_session(&session) {
ctx.insert("user", &user);
} else {
// Redirect to login if not logged in
return Ok(HttpResponse::Found().append_header(("Location", "/login")).finish());
}
// Add user to context (will always be available with our mock user)
let user = Self::get_user_from_session(&session).unwrap();
ctx.insert("user", &user);
render_template(&tmpl, "governance/create_proposal.html", &ctx)
}
@@ -123,18 +152,12 @@ impl GovernanceController {
tmpl: web::Data<Tera>,
session: Session
) -> Result<impl Responder> {
// Check if user is logged in
if Self::get_user_from_session(&session).is_none() {
return Ok(HttpResponse::Found().append_header(("Location", "/login")).finish());
}
let mut ctx = tera::Context::new();
ctx.insert("active_page", "governance");
// Add user to context if available
if let Some(user) = Self::get_user_from_session(&session) {
ctx.insert("user", &user);
}
// Add user to context (will always be available with our mock user)
let user = Self::get_user_from_session(&session).unwrap();
ctx.insert("user", &user);
// In a real application, we would save the proposal to a database
// For now, we'll just redirect to the proposals page with a success message
@@ -204,19 +227,77 @@ impl GovernanceController {
ctx.insert("active_page", "governance");
ctx.insert("active_tab", "my_votes");
// Add user to context if available
if let Some(user) = Self::get_user_from_session(&session) {
ctx.insert("user", &user);
// Get mock votes for this user
let votes = Self::get_mock_votes_for_user(1); // Assuming user ID 1 for mock data
ctx.insert("votes", &votes);
render_template(&tmpl, "governance/my_votes.html", &ctx)
} else {
// Redirect to login if not logged in
Ok(HttpResponse::Found().append_header(("Location", "/login")).finish())
}
// Add user to context (will always be available with our mock user)
let user = Self::get_user_from_session(&session).unwrap();
ctx.insert("user", &user);
// Get mock votes for this user
let votes = Self::get_mock_votes_for_user(1); // Assuming user ID 1 for mock data
ctx.insert("votes", &votes);
render_template(&tmpl, "governance/my_votes.html", &ctx)
}
/// Generate mock recent activity data for the dashboard
fn get_mock_recent_activity() -> Vec<serde_json::Value> {
vec![
serde_json::json!({
"type": "vote",
"user": "Sarah Johnson",
"proposal_id": "prop-001",
"proposal_title": "Community Garden Initiative",
"action": "voted Yes",
"timestamp": (Utc::now() - Duration::hours(2)).to_rfc3339(),
"icon": "bi-check-circle-fill text-success"
}),
serde_json::json!({
"type": "comment",
"user": "Michael Chen",
"proposal_id": "prop-003",
"proposal_title": "Weekly Community Calls",
"action": "commented",
"comment": "I think this would greatly improve communication.",
"timestamp": (Utc::now() - Duration::hours(5)).to_rfc3339(),
"icon": "bi-chat-left-text-fill text-primary"
}),
serde_json::json!({
"type": "vote",
"user": "Robert Callingham",
"proposal_id": "prop-005",
"proposal_title": "Security Audit Implementation",
"action": "voted Yes",
"timestamp": (Utc::now() - Duration::hours(8)).to_rfc3339(),
"icon": "bi-check-circle-fill text-success"
}),
serde_json::json!({
"type": "proposal",
"user": "Emma Rodriguez",
"proposal_id": "prop-004",
"proposal_title": "Sustainability Roadmap",
"action": "created proposal",
"timestamp": (Utc::now() - Duration::hours(12)).to_rfc3339(),
"icon": "bi-file-earmark-text-fill text-info"
}),
serde_json::json!({
"type": "vote",
"user": "David Kim",
"proposal_id": "prop-002",
"proposal_title": "Governance Framework Update",
"action": "voted No",
"timestamp": (Utc::now() - Duration::hours(16)).to_rfc3339(),
"icon": "bi-x-circle-fill text-danger"
}),
serde_json::json!({
"type": "comment",
"user": "Lisa Wang",
"proposal_id": "prop-001",
"proposal_title": "Community Garden Initiative",
"action": "commented",
"comment": "I'd like to volunteer to help coordinate this effort.",
"timestamp": (Utc::now() - Duration::hours(24)).to_rfc3339(),
"icon": "bi-chat-left-text-fill text-primary"
}),
]
}
// Mock data generation methods