minor update
This commit is contained in:
Binary file not shown.
@@ -123,4 +123,4 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
# Add these settings
|
||||
LOGIN_REDIRECT_URL = 'citizen_dashboard'
|
||||
LOGIN_URL = 'login'
|
||||
LOGOUT_REDIRECT_URL = 'home'
|
||||
LOGOUT_REDIRECT_URL = 'home'
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -23,7 +23,7 @@ class CitizenRegistrationForm(UserCreationForm):
|
||||
class IssueForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Issue
|
||||
fields = ['title', 'description', 'category', 'location', 'latitude', 'longitude', 'photo']
|
||||
fields = ['title', 'description', 'location', 'latitude', 'longitude', 'photo']
|
||||
widgets = {
|
||||
'latitude': forms.HiddenInput(),
|
||||
'longitude': forms.HiddenInput(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-20 06:30
|
||||
# Generated by Django 5.2.5 on 2025-08-26 06:15
|
||||
|
||||
import django.contrib.auth.models
|
||||
import django.contrib.auth.validators
|
||||
@@ -18,15 +18,6 @@ class Migration(migrations.Migration):
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='IssueCategory',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('description', models.TextField(blank=True)),
|
||||
('icon', models.CharField(default='fas fa-exclamation-circle', max_length=50)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
@@ -57,21 +48,64 @@ class Migration(migrations.Migration):
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Department',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('description', models.TextField(blank=True, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('admin', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='admin_of_department', to=settings.AUTH_USER_MODEL)),
|
||||
('users', models.ManyToManyField(blank=True, related_name='departments', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['name'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Issue',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=200)),
|
||||
('description', models.TextField()),
|
||||
('location', models.CharField(max_length=200)),
|
||||
('latitude', models.FloatField()),
|
||||
('longitude', models.FloatField()),
|
||||
('location', models.CharField(blank=True, max_length=200)),
|
||||
('latitude', models.FloatField(blank=True, null=True)),
|
||||
('longitude', models.FloatField(blank=True, null=True)),
|
||||
('photo', models.ImageField(blank=True, null=True, upload_to='issue_photos/', validators=[django.core.validators.FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])])),
|
||||
('status', models.CharField(choices=[('reported', 'Reported'), ('acknowledged', 'Acknowledged'), ('in_progress', 'In Progress'), ('resolved', 'Resolved')], default='reported', max_length=20)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('department', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='issues', to='core.department')),
|
||||
('reporter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reported_issues', to=settings.AUTH_USER_MODEL)),
|
||||
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.issuecategory')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-created_at'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Comment',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('content', models.TextField()),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='core.comment')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('issue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='core.issue')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['created_at'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Vote',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('issue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='votes', to='core.issue')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('user', 'issue')},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-21 22:31
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Vote',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('issue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='votes', to='core.issue')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('user', 'issue')},
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,29 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-22 00:55
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0002_vote'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Comment',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('content', models.TextField()),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('issue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='core.issue')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='core.comment')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['created_at'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,32 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 06:21
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0003_comment'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Department',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('description', models.TextField(blank=True, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['name'],
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='comment',
|
||||
name='user',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 06:43
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0004_department_alter_comment_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='department',
|
||||
name='users',
|
||||
field=models.ManyToManyField(blank=True, related_name='departments', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 07:20
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0005_department_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='department',
|
||||
name='users',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='department',
|
||||
name='admin',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='admin_of_department', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 07:24
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0006_remove_department_users_department_admin'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='department',
|
||||
name='users',
|
||||
field=models.ManyToManyField(blank=True, related_name='departments', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,38 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 08:23
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0007_department_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='issue',
|
||||
options={'ordering': ['-created_at']},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='issue',
|
||||
name='category',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='issues', to='core.issuecategory'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='issue',
|
||||
name='latitude',
|
||||
field=models.FloatField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='issue',
|
||||
name='location',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='issue',
|
||||
name='longitude',
|
||||
field=models.FloatField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 08:28
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0008_alter_issue_options_alter_issue_category_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='issue',
|
||||
name='department',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='issues', to='core.department'),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
@@ -53,14 +53,6 @@ class Department(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class IssueCategory(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(blank=True)
|
||||
icon = models.CharField(max_length=50, default='fas fa-exclamation-circle')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Issue(models.Model):
|
||||
STATUS_REPORTED = 'reported'
|
||||
STATUS_ACKNOWLEDGED = 'acknowledged'
|
||||
@@ -77,14 +69,6 @@ class Issue(models.Model):
|
||||
title = models.CharField(max_length=200)
|
||||
description = models.TextField()
|
||||
|
||||
category = models.ForeignKey(
|
||||
"IssueCategory",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="issues"
|
||||
)
|
||||
|
||||
reporter = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
|
||||
@@ -89,7 +89,8 @@
|
||||
|
||||
{% if user.is_resolver %}
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'department_dashboard' %}">Department Dashboard</a>
|
||||
<a class="dropdown-item" href="{% url 'department_dashboard' %}">
|
||||
<i class="fas fa-building me-2 text-success"></i>Department Dashboard</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -141,8 +141,18 @@
|
||||
<img src="https://via.placeholder.com/300x200/6c757d/ffffff?text=No+Image" class="card-img-top" alt="No image">
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
<span class="badge bg-{% if issue.category.name == 'Roads' %}warning text-dark{% elif issue.category.name == 'Sanitation' %}success{% else %}info{% endif %} mb-2">
|
||||
{{ issue.category.name|default:"General" }}
|
||||
<span class="badge
|
||||
{% if issue.department.name == 'Roads & Transportation' %} bg-primary
|
||||
{% elif issue.department.name == 'Sanitation & Waste Management' %} bg-success
|
||||
{% elif issue.department.name == 'Public Safety' %} bg-danger
|
||||
{% elif issue.department.name == 'Water & Sewage' %} bg-info text-dark
|
||||
{% elif issue.department.name == 'Parks & Recreation' %} bg-warning text-dark
|
||||
{% elif issue.department.name == 'Electricity & Utilities' %} bg-dark
|
||||
{% elif issue.department.name == 'Environmental Services' %} bg-secondary
|
||||
{% elif issue.department.name == 'Public Works' %} bg-teal text-white
|
||||
{% else %} bg-light text-dark
|
||||
{% endif %} mb-2">
|
||||
{{ issue.department.name|default:"General" }}
|
||||
</span>
|
||||
<h5 class="card-title">{{ issue.title|truncatewords:5 }}</h5>
|
||||
<p class="card-text text-muted">{{ issue.description|truncatewords:15 }}</p>
|
||||
|
||||
@@ -5,8 +5,13 @@
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3>Department Dashboard</h3>
|
||||
<p>Welcome, {{ request.user.username }}. Your Departments:
|
||||
{% for dept in departments %} {{ dept.name }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
||||
<p>
|
||||
Welcome, {{ request.user.username }}. Your Departments:
|
||||
{% for dept in departments %}
|
||||
<span class="badge bg-light text-dark">{{ dept.name }}</span>
|
||||
{% empty %}
|
||||
<span class="text-muted">No department assigned.</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -20,6 +25,7 @@
|
||||
<th>Reported By</th>
|
||||
<th>Status</th>
|
||||
<th>Created At</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -43,6 +49,23 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ issue.created_at|date:"M d, Y H:i" }}</td>
|
||||
<td>
|
||||
{% if issue.status in "reported,acknowledged" %}
|
||||
<form method="post" action="{% url 'update_issue_status' issue.id %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="status" value="in_progress">
|
||||
<button type="submit" class="btn btn-sm btn-warning">In Progress</button>
|
||||
</form>
|
||||
{% elif issue.status == "in_progress" %}
|
||||
<form method="post" action="{% url 'update_issue_status' issue.id %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="status" value="resolved">
|
||||
<button type="submit" class="btn btn-sm btn-success">Resolved</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<span class="text-muted">No actions</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@@ -20,4 +20,5 @@ urlpatterns = [
|
||||
path("issues/<int:pk>/comment/<int:parent_id>/", views.add_comment, name="add_comment"),
|
||||
path('vote/<int:issue_id>/', views.vote_issue, name='vote_issue'),
|
||||
path("department/", views.department_dashboard, name="department_dashboard"),
|
||||
path("update-issue-status/<int:issue_id>/", views.update_issue_status, name="update_issue_status"),
|
||||
]
|
||||
+25
-18
@@ -8,7 +8,7 @@ from django.db.models import Exists, OuterRef
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.views.decorators.http import require_POST
|
||||
from .models import Issue, IssueCategory, User, Vote, Comment, Department
|
||||
from .models import Issue, User, Vote, Comment, Department
|
||||
from .forms import CitizenRegistrationForm, IssueForm, CommentForm, IssueAssignForm
|
||||
|
||||
def home(request):
|
||||
@@ -16,15 +16,12 @@ def home(request):
|
||||
resolved_issues = Issue.objects.filter(status='resolved').count()
|
||||
active_users = User.objects.filter(is_active=True).count()
|
||||
|
||||
# Get recently reported issues (last 3 issues)
|
||||
recent_issues = Issue.objects.all().order_by('-created_at')[:3]
|
||||
|
||||
for issue in recent_issues:
|
||||
issue.user_has_voted = issue.has_user_voted(request.user) if request.user.is_authenticated else False
|
||||
|
||||
# Get municipal departments count (assuming you have a Department model)
|
||||
# If you don't have one yet, you can use a placeholder or create the model
|
||||
municipal_departments = 5 # Placeholder - replace with actual count when you have the model
|
||||
municipal_departments = 5
|
||||
|
||||
context = {
|
||||
'total_issues': total_issues,
|
||||
@@ -46,12 +43,10 @@ def citizen_dashboard(request):
|
||||
all_user_issues = Issue.objects.filter(reporter=request.user)
|
||||
user_issues_display = all_user_issues.order_by('-created_at')[:5]
|
||||
resolved_count = all_user_issues.filter(status='resolved').count()
|
||||
categories = IssueCategory.objects.all()
|
||||
|
||||
context = {
|
||||
'user_issues': user_issues_display,
|
||||
'resolved_count': resolved_count,
|
||||
'categories': categories,
|
||||
'issue_form': IssueForm(),
|
||||
}
|
||||
return render(request, 'dashboard/citizen_dashboard.html', context)
|
||||
@@ -67,6 +62,7 @@ def report_issue(request):
|
||||
if form.is_valid():
|
||||
issue = form.save(commit=False)
|
||||
issue.reporter = request.user
|
||||
issue.status = "reported" # default status
|
||||
issue.save()
|
||||
messages.success(request, 'Issue reported successfully!')
|
||||
return redirect('citizen_dashboard')
|
||||
@@ -87,26 +83,19 @@ def view_all_issues(request):
|
||||
user_vote_subq = Vote.objects.filter(user=request.user, issue_id=OuterRef('pk'))
|
||||
issues = (
|
||||
Issue.objects
|
||||
.select_related('category', 'reporter')
|
||||
.select_related('reporter')
|
||||
.annotate(user_has_voted=Exists(user_vote_subq))
|
||||
.order_by('-created_at')
|
||||
)
|
||||
|
||||
categories = IssueCategory.objects.all()
|
||||
|
||||
# Optional filters (status/category) if you wired the dropdowns
|
||||
# Optional filter (status only now)
|
||||
status = request.GET.get('status') or ''
|
||||
category_id = request.GET.get('category') or ''
|
||||
if status:
|
||||
issues = issues.filter(status=status)
|
||||
if category_id:
|
||||
issues = issues.filter(category_id=category_id)
|
||||
|
||||
return render(request, 'issues/view_all_issues.html', {
|
||||
'issues': issues,
|
||||
'categories': categories,
|
||||
'selected_status': status,
|
||||
'selected_category': category_id,
|
||||
})
|
||||
|
||||
|
||||
@@ -307,6 +296,24 @@ def resolver_check(user):
|
||||
return user.is_resolver
|
||||
|
||||
@login_required
|
||||
@user_passes_test(resolver_check)
|
||||
@user_passes_test(lambda u: u.is_resolver)
|
||||
def department_dashboard(request):
|
||||
return render(request, "dashboard/department_dashboard.html")
|
||||
departments = request.user.departments.all()
|
||||
issues = Issue.objects.filter(department__in=departments).order_by('-created_at')
|
||||
return render(request, "dashboard/department_dashboard.html", {"issues": issues, "departments": departments})
|
||||
|
||||
@login_required
|
||||
@user_passes_test(lambda u: u.is_resolver)
|
||||
def update_issue_status(request, issue_id):
|
||||
issue = get_object_or_404(Issue, id=issue_id)
|
||||
|
||||
# Make sure the user belongs to the department assigned to the issue
|
||||
if issue.department not in request.user.departments.all():
|
||||
return redirect("department_dashboard")
|
||||
|
||||
if request.method == "POST":
|
||||
new_status = request.POST.get("status")
|
||||
if new_status in [Issue.STATUS_IN_PROGRESS, Issue.STATUS_RESOLVED]:
|
||||
issue.status = new_status
|
||||
issue.save()
|
||||
return redirect("department_dashboard")
|
||||
@@ -0,0 +1,5 @@
|
||||
from waitress import serve
|
||||
from civicfix.wsgi import application
|
||||
|
||||
if __name__ == "__main__":
|
||||
serve(application, host="10.1.192.152", port=8000)
|
||||
Reference in New Issue
Block a user