implement governance and flow functionality
This commit is contained in:
@@ -6,86 +6,158 @@
|
||||
<title>{% block title %}Actix MVC App{% endblock %}</title>
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/unpoly@3.7.2/unpoly.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<style>
|
||||
/* Minimal custom CSS that can't be achieved with Bootstrap classes */
|
||||
@media (min-width: 768px) {
|
||||
.sidebar {
|
||||
width: 280px;
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
}
|
||||
.main-content {
|
||||
margin-left: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.sidebar {
|
||||
width: 280px;
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
left: -280px;
|
||||
transition: left 0.3s ease;
|
||||
z-index: 1030;
|
||||
}
|
||||
.sidebar.show {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% block extra_css %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">Actix MVC App</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'home' %}active{% endif %}" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'about' %}active{% endif %}" href="/about">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'contact' %}active{% endif %}" href="/contact">Contact</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'tickets' %}active{% endif %}" href="/tickets">Support Tickets</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'editor' %}active{% endif %}" href="/editor">Markdown Editor</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'calendar' %}active{% endif %}" href="/calendar">Calendar</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ms-auto">
|
||||
{% if user and user.id %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ user.name }}
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="/tickets/new">New Ticket</a></li>
|
||||
<li><a class="dropdown-item" href="/tickets/my">My Tickets</a></li>
|
||||
{% if user.role == "Admin" %}
|
||||
<li><a class="dropdown-item" href="/admin">Admin Panel</a></li>
|
||||
{% endif %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="/logout">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'login' %}active{% endif %}" href="/login">Login</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'register' %}active{% endif %}" href="/register">Register</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<body class="d-flex flex-column min-vh-100">
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar bg-light shadow-sm border-end" id="sidebar">
|
||||
<div class="bg-dark text-white p-3">
|
||||
<h3 class="mb-0">Actix MVC App</h3>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="py-3">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'home' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/">
|
||||
<i class="bi bi-house-door me-2"></i> Home
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'tickets' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/tickets">
|
||||
<i class="bi bi-ticket-perforated me-2"></i> Support Tickets
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'governance' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/governance">
|
||||
<i class="bi bi-people me-2"></i> Governance
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'flows' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/flows">
|
||||
<i class="bi bi-diagram-3 me-2"></i> Flows
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'editor' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/editor">
|
||||
<i class="bi bi-markdown me-2"></i> Markdown Editor
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'calendar' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/calendar">
|
||||
<i class="bi bi-calendar3 me-2"></i> Calendar
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'about' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/about">
|
||||
<i class="bi bi-info-circle me-2"></i> About
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link d-flex align-items-center ps-3 py-2 {% if active_page == 'contact' %}active fw-bold border-start border-4 border-primary bg-light{% endif %}" href="/contact">
|
||||
<i class="bi bi-envelope me-2"></i> Contact
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<main class="container py-4">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="bg-dark text-white py-4 mt-5">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5>Actix MVC App</h5>
|
||||
<p>A Rust web application using Actix Web, Tera templates, and Bootstrap.</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-end">
|
||||
<p>© {{ now(year=true) }} Actix MVC App. All rights reserved.</p>
|
||||
<!-- Main Content -->
|
||||
<div class="main-content d-flex flex-column min-vh-100">
|
||||
<!-- Top Navbar -->
|
||||
<nav class="navbar navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler d-md-none" type="button" id="sidebarToggle" aria-label="Toggle navigation">
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
<a class="navbar-brand d-md-none" href="/">Actix MVC App</a>
|
||||
<div class="ms-auto">
|
||||
<ul class="navbar-nav flex-row">
|
||||
{% if user and user.id %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle text-white" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-person-circle"></i> {{ user.name }}
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="/tickets/new">New Ticket</a></li>
|
||||
<li><a class="dropdown-item" href="/my-tickets">My Tickets</a></li>
|
||||
<li><a class="dropdown-item" href="/governance/my-votes">My Votes</a></li>
|
||||
{% if user.role == "Admin" %}
|
||||
<li><a class="dropdown-item" href="/admin">Admin Panel</a></li>
|
||||
{% endif %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="/logout">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item me-2">
|
||||
<a class="nav-link text-white {% if active_page == 'login' %}active{% endif %}" href="/login">Login</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white {% if active_page == 'register' %}active{% endif %}" href="/register">Register</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</nav>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main class="container py-4 flex-grow-1">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-dark text-white py-4 mt-auto">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5>Actix MVC App</h5>
|
||||
<p>A Rust web application using Actix Web, Tera templates, and Bootstrap.</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-end">
|
||||
<p>© {{ now(year=true) }} Actix MVC App. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://unpkg.com/unpoly@3.7.2/unpoly.min.js"></script>
|
||||
<script src="https://unpkg.com/unpoly@3.7.2/unpoly-bootstrap5.min.js"></script>
|
||||
<script>
|
||||
// Toggle sidebar on mobile
|
||||
document.getElementById('sidebarToggle').addEventListener('click', function() {
|
||||
document.getElementById('sidebar').classList.toggle('show');
|
||||
});
|
||||
</script>
|
||||
{% block extra_js %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
102
actix_mvc_app/src/views/flows/create_flow.html
Normal file
102
actix_mvc_app/src/views/flows/create_flow.html
Normal file
@@ -0,0 +1,102 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Create New Flow{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/flows">Flows</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Create New Flow</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h1 class="display-5 mb-3">Create New Flow</h1>
|
||||
<p class="lead">Start a new workflow process by filling out the form below.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="/flows/create" method="post">
|
||||
<!-- Flow Information -->
|
||||
<div class="mb-4">
|
||||
<h5>Flow Information</h5>
|
||||
<hr>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Flow Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
<div class="form-text">A descriptive name for the flow process.</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">Description</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="3" required></textarea>
|
||||
<div class="form-text">Detailed description of the flow's purpose and expected outcome.</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="flow_type" class="form-label">Flow Type</label>
|
||||
<select class="form-select" id="flow_type" name="flow_type" required>
|
||||
<option value="" selected disabled>Select a flow type</option>
|
||||
<option value="CompanyRegistration">Company Registration</option>
|
||||
<option value="UserOnboarding">User Onboarding</option>
|
||||
<option value="ServiceActivation">Service Activation</option>
|
||||
<option value="PaymentProcessing">Payment Processing</option>
|
||||
</select>
|
||||
<div class="form-text">The type of workflow process.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Flow Steps -->
|
||||
<div class="mb-4">
|
||||
<h5>Flow Steps</h5>
|
||||
<hr>
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-info-circle me-2"></i> Steps will be configured after creating the flow.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="/flows" class="btn btn-outline-secondary me-md-2">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Create Flow</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Flow Types</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<h6>Company Registration</h6>
|
||||
<p class="small text-muted">Process for registering a new company, including document submission, verification, and approval.</p>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<h6>User Onboarding</h6>
|
||||
<p class="small text-muted">Process for onboarding new users to the platform, including account setup and verification.</p>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<h6>Service Activation</h6>
|
||||
<p class="small text-muted">Process for activating a service, including subscription selection and payment processing.</p>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<h6>Payment Processing</h6>
|
||||
<p class="small text-muted">Process for handling payments, including verification, processing, and receipt generation.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
247
actix_mvc_app/src/views/flows/flow_detail.html
Normal file
247
actix_mvc_app/src/views/flows/flow_detail.html
Normal file
@@ -0,0 +1,247 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ flow.name }} - Flow Details{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/flows">Flows</a></li>
|
||||
<li class="breadcrumb-item"><a href="/flows/list">All Flows</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ flow.name }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Success message if present -->
|
||||
{% if success %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ success }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Flow Overview -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0">{{ flow.name }}</h4>
|
||||
<span class="badge {% if flow.status == 'In Progress' %}bg-primary{% elif flow.status == 'Completed' %}bg-success{% elif flow.status == 'Stuck' %}bg-danger{% else %}bg-secondary{% endif %} p-2">
|
||||
{{ flow.status }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<h5>Description</h5>
|
||||
<p>{{ flow.description }}</p>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<h5>Details</h5>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<span>Flow Type:</span>
|
||||
<span class="fw-bold">{{ flow.flow_type }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<span>Owner:</span>
|
||||
<span class="fw-bold">{{ flow.owner_name }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<span>Created:</span>
|
||||
<span class="fw-bold">{{ flow.created_at | date(format="%Y-%m-%d %H:%M") }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<span>Last Updated:</span>
|
||||
<span class="fw-bold">{{ flow.updated_at | date(format="%Y-%m-%d %H:%M") }}</span>
|
||||
</li>
|
||||
{% if flow.completed_at %}
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<span>Completed:</span>
|
||||
<span class="fw-bold">{{ flow.completed_at | date(format="%Y-%m-%d %H:%M") }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h5>Progress</h5>
|
||||
<div class="progress mb-3" style="height: 25px;">
|
||||
<div class="progress-bar {% if flow.status == 'Completed' %}bg-success{% elif flow.status == 'Stuck' %}bg-danger{% else %}bg-primary{% endif %}" role="progressbar"
|
||||
style="width: {{ flow.progress_percentage }}%;"
|
||||
aria-valuenow="{{ flow.progress_percentage }}"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100">
|
||||
{{ flow.progress_percentage }}%
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
<strong>Current Step:</strong>
|
||||
{% set current = flow.current_step %}
|
||||
{% if current %}
|
||||
{{ current.name }}
|
||||
{% else %}
|
||||
{% if flow.status == 'Completed' %}
|
||||
All steps completed
|
||||
{% elif flow.status == 'Cancelled' %}
|
||||
Flow cancelled
|
||||
{% else %}
|
||||
No active step
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Actions</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if flow.status == 'In Progress' %}
|
||||
<div class="d-grid gap-2 mb-3">
|
||||
<form action="/flows/{{ flow.id }}/advance" method="post" id="advance">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-arrow-right-circle me-1"></i> Advance to Next Step
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button type="button" class="btn btn-warning w-100" data-bs-toggle="modal" data-bs-target="#markStuckModal">
|
||||
<i class="bi bi-exclamation-triangle me-1"></i> Mark as Stuck
|
||||
</button>
|
||||
</div>
|
||||
{% elif flow.status == 'Stuck' %}
|
||||
<div class="d-grid gap-2">
|
||||
<form action="/flows/{{ flow.id }}/advance" method="post">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-arrow-right-circle me-1"></i> Resume Flow
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-center text-muted">No actions available for {{ flow.status | lower }} flows.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if flow.steps | length > 0 %}
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Add Log to Current Step</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% set current = flow.current_step %}
|
||||
{% if current %}
|
||||
<form action="/flows/{{ flow.id }}/step/{{ current.id }}/log" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="message" class="form-label">Log Message</label>
|
||||
<textarea class="form-control" id="message" name="message" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle me-1"></i> Add Log Entry
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Flow Steps -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Flow Steps</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="flow-steps">
|
||||
{% for step in flow.steps %}
|
||||
<div class="flow-step mb-4">
|
||||
<div class="card {% if step.status == 'In Progress' %}border-primary{% elif step.status == 'Completed' %}border-success{% elif step.status == 'Stuck' %}border-danger{% else %}border-secondary{% endif %}">
|
||||
<div class="card-header d-flex justify-content-between align-items-center {% if step.status == 'In Progress' %}bg-primary text-white{% elif step.status == 'Completed' %}bg-success text-white{% elif step.status == 'Stuck' %}bg-danger text-white{% else %}{% endif %}">
|
||||
<h5 class="mb-0">Step {{ step.order + 1 }}: {{ step.name }}</h5>
|
||||
<span class="badge {% if step.status == 'In Progress' %}bg-light text-primary{% elif step.status == 'Completed' %}bg-light text-success{% elif step.status == 'Stuck' %}bg-light text-danger{% else %}bg-light text-secondary{% endif %}">
|
||||
{{ step.status }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>{{ step.description }}</p>
|
||||
<div class="d-flex justify-content-between small text-muted mb-3">
|
||||
{% if step.started_at %}
|
||||
<span>Started: {{ step.started_at | date(format="%Y-%m-%d %H:%M") }}</span>
|
||||
{% else %}
|
||||
<span>Not started yet</span>
|
||||
{% endif %}
|
||||
|
||||
{% if step.completed_at %}
|
||||
<span>Completed: {{ step.completed_at | date(format="%Y-%m-%d %H:%M") }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if step.logs|length > 0 %}
|
||||
<h6>Logs</h6>
|
||||
<div class="logs-container border rounded p-2 bg-light" style="max-height: 200px; overflow-y: auto;">
|
||||
{% for log in step.logs %}
|
||||
<div class="log-entry mb-2 pb-2 {% if not loop.last %}border-bottom{% endif %}">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="fw-bold">{{ log.timestamp | date(format="%Y-%m-%d %H:%M:%S") }}</span>
|
||||
<span class="text-muted small">ID: {{ log.id }}</span>
|
||||
</div>
|
||||
<p class="mb-0">{{ log.message }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted">No logs for this step.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mark as Stuck Modal -->
|
||||
<div class="modal fade" id="markStuckModal" tabindex="-1" aria-labelledby="markStuckModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form action="/flows/{{ flow.id }}/stuck" method="post">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="markStuckModalLabel">Mark Flow as Stuck</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="reason" class="form-label">Reason</label>
|
||||
<textarea class="form-control" id="reason" name="reason" rows="3" required></textarea>
|
||||
<div class="form-text">Please provide a detailed explanation of why this flow is stuck.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-warning">Mark as Stuck</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
153
actix_mvc_app/src/views/flows/flows.html
Normal file
153
actix_mvc_app/src/views/flows/flows.html
Normal file
@@ -0,0 +1,153 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}All Flows{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/flows">Flows</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">All Flows</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h1 class="display-5 mb-0">All Flows</h1>
|
||||
</div>
|
||||
<div class="col-md-4 text-md-end">
|
||||
<a href="/flows/create" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle me-1"></i> Create New Flow
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Controls -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form class="row g-3" action="/flows/list" method="get">
|
||||
<div class="col-md-4">
|
||||
<label for="status" class="form-label">Status</label>
|
||||
<select class="form-select" id="status" name="status">
|
||||
<option value="all" selected>All</option>
|
||||
<option value="in_progress">In Progress</option>
|
||||
<option value="completed">Completed</option>
|
||||
<option value="stuck">Stuck</option>
|
||||
<option value="cancelled">Cancelled</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="type" class="form-label">Type</label>
|
||||
<select class="form-select" id="type" name="type">
|
||||
<option value="all" selected>All</option>
|
||||
<option value="company_registration">Company Registration</option>
|
||||
<option value="user_onboarding">User Onboarding</option>
|
||||
<option value="service_activation">Service Activation</option>
|
||||
<option value="payment_processing">Payment Processing</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="search" class="form-label">Search</label>
|
||||
<input type="text" class="form-control" id="search" name="search" placeholder="Search flows...">
|
||||
</div>
|
||||
<div class="col-12 text-end">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-filter me-1"></i> Apply Filters
|
||||
</button>
|
||||
<a href="/flows/list" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-x-circle me-1"></i> Clear Filters
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Flows Table -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% if flows|length > 0 %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flow Name</th>
|
||||
<th>Type</th>
|
||||
<th>Status</th>
|
||||
<th>Owner</th>
|
||||
<th>Progress</th>
|
||||
<th>Created</th>
|
||||
<th>Updated</th>
|
||||
<th>Current Step</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for flow in flows %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/flows/{{ flow.id }}">{{ flow.name }}</a>
|
||||
</td>
|
||||
<td>{{ flow.flow_type }}</td>
|
||||
<td>
|
||||
<span class="badge {% if flow.status == 'In Progress' %}bg-primary{% elif flow.status == 'Completed' %}bg-success{% elif flow.status == 'Stuck' %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||
{{ flow.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ flow.owner_name }}</td>
|
||||
<td>
|
||||
<div class="progress mb-2" style="height: 20px;">
|
||||
<div class="progress-bar {% if flow.status == 'Completed' %}bg-success{% elif flow.status == 'Stuck' %}bg-danger{% else %}bg-primary{% endif %}" role="progressbar" style="width: {{ flow.progress_percentage }}%;" aria-valuenow="{{ flow.progress_percentage }}" aria-valuemin="0" aria-valuemax="100">{{ flow.progress_percentage }}%</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ flow.created_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>{{ flow.updated_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>
|
||||
{% set current = flow.current_step %}
|
||||
{% if current %}
|
||||
{{ current.name }}
|
||||
{% else %}
|
||||
{% if flow.status == 'Completed' %}
|
||||
All steps completed
|
||||
{% elif flow.status == 'Cancelled' %}
|
||||
Flow cancelled
|
||||
{% else %}
|
||||
No active step
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a href="/flows/{{ flow.id }}" class="btn btn-sm btn-primary">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if flow.status == 'In Progress' %}
|
||||
<a href="/flows/{{ flow.id }}#advance" class="btn btn-sm btn-success">
|
||||
<i class="bi bi-arrow-right"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-center">No flows found matching your criteria.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
74
actix_mvc_app/src/views/flows/index.html
Normal file
74
actix_mvc_app/src/views/flows/index.html
Normal file
@@ -0,0 +1,74 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Flows Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h1 class="display-5 mb-3">Flows Dashboard</h1>
|
||||
<p class="lead">Track and manage workflow processes across the organization.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics Cards -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-primary h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Flows</h5>
|
||||
<p class="display-4">{{ stats.total_flows }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-success h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">In Progress</h5>
|
||||
<p class="display-4">{{ stats.in_progress_flows }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-danger h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Stuck</h5>
|
||||
<p class="display-4">{{ stats.stuck_flows }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-info h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Completed</h5>
|
||||
<p class="display-4">{{ stats.completed_flows }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Quick Actions</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<a href="/flows/create" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle me-1"></i> Create New Flow
|
||||
</a>
|
||||
<a href="/flows/list" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-list me-1"></i> View All Flows
|
||||
</a>
|
||||
<a href="/flows/my-flows" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-person me-1"></i> My Flows
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
114
actix_mvc_app/src/views/flows/my_flows.html
Normal file
114
actix_mvc_app/src/views/flows/my_flows.html
Normal file
@@ -0,0 +1,114 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}My Flows{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/flows">Flows</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">My Flows</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h1 class="display-5 mb-0">My Flows</h1>
|
||||
</div>
|
||||
<div class="col-md-4 text-md-end">
|
||||
<a href="/flows/create" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle me-1"></i> Create New Flow
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Flows Table -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% if flows|length > 0 %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flow Name</th>
|
||||
<th>Type</th>
|
||||
<th>Status</th>
|
||||
<th>Progress</th>
|
||||
<th>Current Step</th>
|
||||
<th>Created</th>
|
||||
<th>Updated</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for flow in flows %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/flows/{{ flow.id }}">{{ flow.name }}</a>
|
||||
</td>
|
||||
<td>{{ flow.flow_type }}</td>
|
||||
<td>
|
||||
<span class="badge {% if flow.status == 'In Progress' %}bg-primary{% elif flow.status == 'Completed' %}bg-success{% elif flow.status == 'Stuck' %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||
{{ flow.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="progress mb-2" style="height: 20px;">
|
||||
<div class="progress-bar {% if flow.status == 'Completed' %}bg-success{% elif flow.status == 'Stuck' %}bg-danger{% else %}bg-primary{% endif %}" role="progressbar" style="width: {{ flow.progress_percentage }}%;" aria-valuenow="{{ flow.progress_percentage }}" aria-valuemin="0" aria-valuemax="100">{{ flow.progress_percentage }}%</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% set current = flow.current_step %}
|
||||
{% if current %}
|
||||
{{ current.name }}
|
||||
{% else %}
|
||||
{% if flow.status == 'Completed' %}
|
||||
All steps completed
|
||||
{% elif flow.status == 'Cancelled' %}
|
||||
Flow cancelled
|
||||
{% else %}
|
||||
No active step
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ flow.created_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>{{ flow.updated_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a href="/flows/{{ flow.id }}" class="btn btn-sm btn-primary">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if flow.status == 'In Progress' %}
|
||||
<a href="/flows/{{ flow.id }}#advance" class="btn btn-sm btn-success">
|
||||
<i class="bi bi-arrow-right"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-5">
|
||||
<i class="bi bi-diagram-3 display-1 text-muted"></i>
|
||||
<h4 class="mt-3">You don't have any flows yet</h4>
|
||||
<p class="text-muted">Create a new flow to get started with tracking your processes.</p>
|
||||
<a href="/flows/create" class="btn btn-primary mt-2">
|
||||
<i class="bi bi-plus-circle me-1"></i> Create New Flow
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
119
actix_mvc_app/src/views/governance/create_proposal.html
Normal file
119
actix_mvc_app/src/views/governance/create_proposal.html
Normal file
@@ -0,0 +1,119 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Create Proposal - Governance Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h1 class="display-5 mb-4">Create Governance Proposal</h1>
|
||||
<p class="lead">Submit a new proposal for the community to vote on.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/proposals">All Proposals</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/my-votes">My Votes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/governance/create">Create Proposal</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Proposal Form -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8 mx-auto">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">New Proposal</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="/governance/create" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="title" class="form-label">Title</label>
|
||||
<input type="text" class="form-control" id="title" name="title" required
|
||||
placeholder="Enter a clear, concise title for your proposal">
|
||||
<div class="form-text">Make it descriptive and specific</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">Description</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6" required
|
||||
placeholder="Provide a detailed description of your proposal..."></textarea>
|
||||
<div class="form-text">Explain the purpose, benefits, and implementation details</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="voting_start_date" class="form-label">Voting Start Date</label>
|
||||
<input type="date" class="form-control" id="voting_start_date" name="voting_start_date">
|
||||
<div class="form-text">When should voting begin?</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="voting_end_date" class="form-label">Voting End Date</label>
|
||||
<input type="date" class="form-control" id="voting_end_date" name="voting_end_date">
|
||||
<div class="form-text">When should voting end?</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="draft" name="draft" value="true">
|
||||
<label class="form-check-label" for="draft">
|
||||
Save as draft (not ready for voting yet)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary">Submit Proposal</button>
|
||||
<a href="/governance" class="btn btn-outline-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Guidelines Card -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8 mx-auto">
|
||||
<div class="card bg-light">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Proposal Guidelines</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item bg-transparent">
|
||||
<strong>Be specific:</strong> Clearly state what you're proposing and why.
|
||||
</li>
|
||||
<li class="list-group-item bg-transparent">
|
||||
<strong>Provide context:</strong> Explain the current situation and why change is needed.
|
||||
</li>
|
||||
<li class="list-group-item bg-transparent">
|
||||
<strong>Consider implementation:</strong> Outline how your proposal could be implemented.
|
||||
</li>
|
||||
<li class="list-group-item bg-transparent">
|
||||
<strong>Address concerns:</strong> Anticipate potential objections and address them.
|
||||
</li>
|
||||
<li class="list-group-item bg-transparent">
|
||||
<strong>Be respectful:</strong> Focus on ideas, not individuals or groups.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
164
actix_mvc_app/src/views/governance/index.html
Normal file
164
actix_mvc_app/src/views/governance/index.html
Normal file
@@ -0,0 +1,164 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Governance Dashboard - Actix MVC App{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h1 class="display-5 mb-4">Governance Dashboard</h1>
|
||||
<p class="lead">Participate in the decision-making process by voting on proposals and creating new ones.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics Cards -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-primary h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Proposals</h5>
|
||||
<p class="card-text display-6">{{ stats.total_proposals }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-success h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Active Proposals</h5>
|
||||
<p class="card-text display-6">{{ stats.active_proposals }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-info h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Votes</h5>
|
||||
<p class="card-text display-6">{{ stats.total_votes }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="card text-white bg-secondary h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Participation Rate</h5>
|
||||
<p class="card-text display-6">{{ stats.participation_rate }}%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/governance">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/proposals">All Proposals</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/my-votes">My Votes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/create">Create Proposal</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Active Proposals Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Active Proposals</h5>
|
||||
<a href="/governance/proposals" class="btn btn-sm btn-outline-primary">View All</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Creator</th>
|
||||
<th>Status</th>
|
||||
<th>Voting Ends</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for proposal in proposals %}
|
||||
{% if proposal.status == "Active" %}
|
||||
<tr>
|
||||
<td>{{ proposal.title }}</td>
|
||||
<td>{{ proposal.creator_name }}</td>
|
||||
<td><span class="badge bg-success">{{ proposal.status }}</span></td>
|
||||
<td>{{ proposal.voting_ends_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>
|
||||
<a href="/governance/proposals/{{ proposal.id }}" class="btn btn-sm btn-primary">View</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Proposals Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Recent Proposals</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
{% set count = 0 %}
|
||||
{% for proposal in proposals %}
|
||||
{% if count < 3 %}
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ proposal.title }}</h5>
|
||||
<h6 class="card-subtitle mb-2 text-muted">By {{ proposal.creator_name }}</h6>
|
||||
<p class="card-text">{{ proposal.description | truncate(length=100) }}</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="badge {% if proposal.status == 'Active' %}bg-success{% elif proposal.status == 'Approved' %}bg-primary{% elif proposal.status == 'Rejected' %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||
{{ proposal.status }}
|
||||
</span>
|
||||
<a href="/governance/proposals/{{ proposal.id }}" class="btn btn-sm btn-outline-primary">View Details</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer text-muted">
|
||||
Created: {{ proposal.created_at | date(format="%Y-%m-%d") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% set count = count + 1 %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Call to Action -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card bg-light">
|
||||
<div class="card-body text-center">
|
||||
<h4 class="mb-3">Have an idea to improve our platform?</h4>
|
||||
<p class="mb-4">Create a proposal and let the community vote on it.</p>
|
||||
<a href="/governance/create" class="btn btn-primary">Create Proposal</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
144
actix_mvc_app/src/views/governance/my_votes.html
Normal file
144
actix_mvc_app/src/views/governance/my_votes.html
Normal file
@@ -0,0 +1,144 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}My Votes - Governance Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h1 class="display-5 mb-4">My Votes</h1>
|
||||
<p class="lead">View all proposals you have voted on.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/proposals">All Proposals</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/governance/my-votes">My Votes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/create">Create Proposal</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- My Votes List -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">My Voting History</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if votes | length > 0 %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Proposal</th>
|
||||
<th>My Vote</th>
|
||||
<th>Status</th>
|
||||
<th>Voted On</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for vote, proposal in votes %}
|
||||
<tr>
|
||||
<td>{{ proposal.title }}</td>
|
||||
<td>
|
||||
<span class="badge {% if vote.vote_type == 'Yes' %}bg-success{% elif vote.vote_type == 'No' %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||
{{ vote.vote_type }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge {% if proposal.status == 'Active' %}bg-success{% elif proposal.status == 'Approved' %}bg-primary{% elif proposal.status == 'Rejected' %}bg-danger{% elif proposal.status == 'Draft' %}bg-secondary{% else %}bg-warning{% endif %}">
|
||||
{{ proposal.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ vote.created_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>
|
||||
<a href="/governance/proposals/{{ proposal.id }}" class="btn btn-sm btn-primary">View Proposal</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-5">
|
||||
<i class="bi bi-clipboard-check fs-1 text-muted mb-3"></i>
|
||||
<h5>You haven't voted on any proposals yet</h5>
|
||||
<p class="text-muted">When you vote on proposals, they will appear here.</p>
|
||||
<a href="/governance/proposals" class="btn btn-primary mt-3">Browse Proposals</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Voting Stats -->
|
||||
{% if votes | length > 0 %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card text-white bg-success h-100">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">Yes Votes</h5>
|
||||
<p class="display-4">
|
||||
{% set yes_count = 0 %}
|
||||
{% for vote, proposal in votes %}
|
||||
{% if vote.vote_type == 'Yes' %}
|
||||
{% set yes_count = yes_count + 1 %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ yes_count }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card text-white bg-danger h-100">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">No Votes</h5>
|
||||
<p class="display-4">
|
||||
{% set no_count = 0 %}
|
||||
{% for vote, proposal in votes %}
|
||||
{% if vote.vote_type == 'No' %}
|
||||
{% set no_count = no_count + 1 %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ no_count }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card text-white bg-secondary h-100">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">Abstain Votes</h5>
|
||||
<p class="display-4">
|
||||
{% set abstain_count = 0 %}
|
||||
{% for vote, proposal in votes %}
|
||||
{% if vote.vote_type == 'Abstain' %}
|
||||
{% set abstain_count = abstain_count + 1 %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ abstain_count }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
189
actix_mvc_app/src/views/governance/proposal_detail.html
Normal file
189
actix_mvc_app/src/views/governance/proposal_detail.html
Normal file
@@ -0,0 +1,189 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ proposal.title }} - Governance Proposal{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/governance">Governance</a></li>
|
||||
<li class="breadcrumb-item"><a href="/governance/proposals">Proposals</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ proposal.title }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Success message if present -->
|
||||
{% if success %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ success }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Proposal Details -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">{{ proposal.title }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between mb-3">
|
||||
<span class="badge {% if proposal.status == 'Active' %}bg-success{% elif proposal.status == 'Approved' %}bg-primary{% elif proposal.status == 'Rejected' %}bg-danger{% elif proposal.status == 'Draft' %}bg-secondary{% else %}bg-warning{% endif %} p-2">
|
||||
{{ proposal.status }}
|
||||
</span>
|
||||
<small class="text-muted">Created by {{ proposal.creator_name }} on {{ proposal.created_at | date(format="%Y-%m-%d") }}</small>
|
||||
</div>
|
||||
|
||||
<h5>Description</h5>
|
||||
<p class="mb-4">{{ proposal.description }}</p>
|
||||
|
||||
<h5>Voting Period</h5>
|
||||
<p>
|
||||
{% if proposal.voting_starts_at and proposal.voting_ends_at %}
|
||||
<strong>Start:</strong> {{ proposal.voting_starts_at | date(format="%Y-%m-%d") }} <br>
|
||||
<strong>End:</strong> {{ proposal.voting_ends_at | date(format="%Y-%m-%d") }}
|
||||
{% else %}
|
||||
Not set
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Voting Results</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
{% set yes_percent = 0 %}
|
||||
{% set no_percent = 0 %}
|
||||
{% set abstain_percent = 0 %}
|
||||
|
||||
{% if results.total_votes > 0 %}
|
||||
{% set yes_percent = (results.yes_count * 100 / results.total_votes) | int %}
|
||||
{% set no_percent = (results.no_count * 100 / results.total_votes) | int %}
|
||||
{% set abstain_percent = (results.abstain_count * 100 / results.total_votes) | int %}
|
||||
{% endif %}
|
||||
|
||||
<p class="mb-1">Yes: {{ results.yes_count }} ({{ yes_percent }}%)</p>
|
||||
<div class="progress mb-3">
|
||||
<div class="progress-bar bg-success" role="progressbar" style="width: {{ yes_percent }}%"></div>
|
||||
</div>
|
||||
|
||||
<p class="mb-1">No: {{ results.no_count }} ({{ no_percent }}%)</p>
|
||||
<div class="progress mb-3">
|
||||
<div class="progress-bar bg-danger" role="progressbar" style="width: {{ no_percent }}%"></div>
|
||||
</div>
|
||||
|
||||
<p class="mb-1">Abstain: {{ results.abstain_count }} ({{ abstain_percent }}%)</p>
|
||||
<div class="progress mb-3">
|
||||
<div class="progress-bar bg-secondary" role="progressbar" style="width: {{ abstain_percent }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center"><strong>Total Votes:</strong> {{ results.total_votes }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Vote Form -->
|
||||
{% if proposal.status == "Active" and user and user.id %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Cast Your Vote</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="/governance/proposals/{{ proposal.id }}/vote" method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Vote Type</label>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="vote_type" id="voteYes" value="Yes" checked>
|
||||
<label class="form-check-label" for="voteYes">
|
||||
Yes - I support this proposal
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="vote_type" id="voteNo" value="No">
|
||||
<label class="form-check-label" for="voteNo">
|
||||
No - I oppose this proposal
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="vote_type" id="voteAbstain" value="Abstain">
|
||||
<label class="form-check-label" for="voteAbstain">
|
||||
Abstain - I choose not to vote
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="comment" class="form-label">Comment (Optional)</label>
|
||||
<textarea class="form-control" id="comment" name="comment" rows="3" placeholder="Explain your vote..."></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Submit Vote</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% elif not user or not user.id %}
|
||||
<div class="card">
|
||||
<div class="card-body text-center">
|
||||
<p>You must be logged in to vote.</p>
|
||||
<a href="/login" class="btn btn-primary">Login to Vote</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Votes List -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Votes ({{ votes | length }})</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if votes | length > 0 %}
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Voter</th>
|
||||
<th>Vote</th>
|
||||
<th>Comment</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for vote in votes %}
|
||||
<tr>
|
||||
<td>{{ vote.voter_name }}</td>
|
||||
<td>
|
||||
<span class="badge {% if vote.vote_type == 'Yes' %}bg-success{% elif vote.vote_type == 'No' %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||
{{ vote.vote_type }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{% if vote.comment %}{{ vote.comment }}{% else %}No comment{% endif %}</td>
|
||||
<td>{{ vote.created_at | date(format="%Y-%m-%d %H:%M") }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-center">No votes have been cast yet.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
128
actix_mvc_app/src/views/governance/proposals.html
Normal file
128
actix_mvc_app/src/views/governance/proposals.html
Normal file
@@ -0,0 +1,128 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Proposals - Governance Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h1 class="display-5 mb-4">Governance Proposals</h1>
|
||||
<p class="lead">View and vote on all proposals in the system.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Success message if present -->
|
||||
{% if success %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ success }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/governance/proposals">All Proposals</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/my-votes">My Votes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/governance/create">Create Proposal</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Controls -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="/governance/proposals" method="get" class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label for="status" class="form-label">Status</label>
|
||||
<select class="form-select" id="status" name="status">
|
||||
<option value="">All Statuses</option>
|
||||
<option value="Draft">Draft</option>
|
||||
<option value="Active">Active</option>
|
||||
<option value="Approved">Approved</option>
|
||||
<option value="Rejected">Rejected</option>
|
||||
<option value="Cancelled">Cancelled</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="search" class="form-label">Search</label>
|
||||
<input type="text" class="form-control" id="search" name="search" placeholder="Search by title or description">
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary w-100">Filter</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Proposals List -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">All Proposals</h5>
|
||||
<a href="/governance/create" class="btn btn-sm btn-primary">Create New Proposal</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Creator</th>
|
||||
<th>Status</th>
|
||||
<th>Created</th>
|
||||
<th>Voting Period</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for proposal in proposals %}
|
||||
<tr>
|
||||
<td>{{ proposal.title }}</td>
|
||||
<td>{{ proposal.creator_name }}</td>
|
||||
<td>
|
||||
<span class="badge {% if proposal.status == 'Active' %}bg-success{% elif proposal.status == 'Approved' %}bg-primary{% elif proposal.status == 'Rejected' %}bg-danger{% elif proposal.status == 'Draft' %}bg-secondary{% else %}bg-warning{% endif %}">
|
||||
{{ proposal.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ proposal.created_at | date(format="%Y-%m-%d") }}</td>
|
||||
<td>
|
||||
{% if proposal.voting_starts_at and proposal.voting_ends_at %}
|
||||
{{ proposal.voting_starts_at | date(format="%Y-%m-%d") }} to {{ proposal.voting_ends_at | date(format="%Y-%m-%d") }}
|
||||
{% else %}
|
||||
Not set
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="/governance/proposals/{{ proposal.id }}" class="btn btn-sm btn-primary">View</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user