From 17f309dcdab80f11e89317e933f34171e00ef493 Mon Sep 17 00:00:00 2001 From: Gokuldevx Date: Mon, 25 Aug 2025 13:52:30 +0530 Subject: [PATCH] minor update --- .../core/__pycache__/models.cpython-313.pyc | Bin 7376 -> 8036 bytes .../core/__pycache__/urls.cpython-313.pyc | Bin 1587 -> 1680 bytes .../core/__pycache__/views.cpython-313.pyc | Bin 13811 -> 14218 bytes civicfix/core/models.py | 73 +++++++++++++----- .../dashboard/superadmin_dashboard.html | 3 + .../core/templates/issues/manage_issues.html | 53 +++++++++++++ civicfix/core/urls.py | 2 + civicfix/core/views.py | 8 +- 8 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 civicfix/core/templates/issues/manage_issues.html diff --git a/civicfix/core/__pycache__/models.cpython-313.pyc b/civicfix/core/__pycache__/models.cpython-313.pyc index 10f13c8df0c1a9292e4286a8f8bae9faa19cb7fb..7f5d826ba841edb754e9c730018c3e721c738b9f 100644 GIT binary patch delta 2299 zcmah~TWlN072TouSU#4!e2Fj7BK4{%*;Zm(ktL-`Ws9;EE0V$?W2aKeu+l9MlEqq#~e;x=-5r?M$3==fnKNP{iw@-XX%gV8?hM z6y_VE+aZC~hEazPW{3FiLLphA67^Gg$iWmV8VE(=fqWMh_1^=cJ-EWF(7;d&3xjQC zl02|OaLC3Y;5mZ3OSoqUJkhUsV&FNBoX#+Cq`5?g&@a%)3uJ)oW$P!jb;!<=&E4hb zoCtbjkg*MX!6p;8%j%;Z;F%&*S8GgH7ffGy{!+E}-DP!Q5iD<|T3ThbMW$*RlC;|LYv301 z2lUbTOVm!-?y<`Gnln8Uz44+x%QXx)1DXjy5~4A#h*%fEOp18SM~Cvi@;s;9-U`u86=j< zI{$rmn180YItmcMsOAQEQ!v7rThG2NvTm>#`sWEJzA!n>A9|9aU!bHYnm*@w> zcEa8zWLu`zZ0W-$$!2Y)L$Bz|su^5V^^&HS^~+jmp`xuWm#=WIx9h|#X6gi}3r4W@ z-QL^1x7yb8_w3v0!OisGgY;0NefU?IhWvCxeA=pEFMZD(EV(1h?ze~_6rqsj72|>8 zC@1)c?+Cx?^>k93RhH>^t){CQ!(Pa?n69O=R@QaKN?`M!dI$P(qT%(|g}-(m`M9t# zxZORn**$VYzq$6-+P2)jDYrk6GY#?dZvz1Q-`=G7L!jRgiiAHI2p>PleM%5!TOeYM z|5@GFu>kNQGMSCjepyGW>Qh~(XHw5g*lS^Jb#WtN!s%bLo@vkp_KXr=OHeMznA zm3h2I_6jU#CH@OvlBoQTzJc_&!J&-+!0~$JZEqSrA65rTo*@3AS3}y znHEM1MOw<|W~TFn+?W~KcZ{AnKQ(<}GBoWXtP#8hb}KYcczqx4HF>Gb4_xiS8d zlpMp0W=|mu;_jaD8dEEa)${5VQ>3{zNuQ^6i&ClF8^tMGC#HZ_b>1iU-#WoQfN+}3n`+DII3*rP_gr(tik96L_I6JPIb zh~0*}ZN1tMj~ede`pXTm&v3^q|Bjnq@^@c*C`Y#C^p>19#HbOBz1x4g-;e@^KWIc! zyI!Z_te@La1f{h}QntnPrkFIaME@c<2jm`%+uJlo8BeS}E}7aPL;%xd-8iM(DX+c)OkT z+>T%HhqtBFmXtC=5kom-DD9Bg@2rpS_=I4L_sOZqzwE@(xhnvC?j(+{e=ZWo8N&1O zXR#$XuKQ%~6~W$TX8{UqhR??1{8gn_TtR}3sr)C(`Hc1ZXWs`Gx;1QCIOas(+w%VN zz?Hzwhzf2~#3rqlS5$TbOg77JN8}rnL|Em80J3@`_HeTX>AvU z*%W&bZJh2^jV-gMjKd7c2Tx!6)-zvy`uIqsNPYlzpS&R=T%#*8J&>O)JC zCEHSHiNnq}UGuf74#l!{O!+01Xkts7BK)(gs!YGa-ow83yn_)0jeDba$vdC^EILle z8+&URbGA_iyMf#u47&?&JsLF2A3=>b0)TQgD|)*_I+3e7bEo7<`sQ WZj9fYd~5Ox0j6J!+4zsz2L1!N@;{jX delta 1632 zcmZ8gOKcNY6rE>#lCfvTFf#6bV(RQtz_~i8`{5&bjx# z`_6su`S;#(xBG8dc5(R4H-3G(uHl~h zCRMa+j&4HhQG1}G`XDAac_%6#DwP+J1>pTAugq(_R@d#I^2?kXS%l@pdQIrIQxEED zPiL)XLyCuz;Dd-D+P$ls_hH>8ws*S|d-AEKHV$36hDaB>WnY45BJSj0>8D63hbC)o z+#`UoZMfF&RM2&BMP2lu3TX{Nj<#rxh+)l(7}0z*I-$m!EdGFDOzDr-VfVNrZnFfc zpD9vP&sxIp3x-iCGyYDY_-2n_5OG^4YiJbn zXKM{>?9oHqjc!I5iQ6q_v5?N{dEL~ho5f|g;PTh)W7G%VxQ1+W=bYFDvn@NEabodi z&dlqOmparQEHNa661S{)XU<(YR~DL~6bO;+b5aOer4~;IN4H=BdgRX*P2GT_a#v&* zTc@sFx1>ZXN_0_aEeoyiog5NO%--Zi2|V`tTpLlaFS7yum0l4>iAK7~a6JsU!|k@X z{Rp~pOc^>&#vPU?XQVSz=4riP=EgI4jPxkna)-zm%)7gMyRnOrKtRW$vLwdv2a>Xt z#9&rb;kFWtYM7Oa{w~6xLNI7+?qGU?@S989*P4kg^k@AsrMLG2% z5nWKCcRDLdVol+q(uT^@wB%`B@U$*^+DiwPrN$*GydZ_|C=bks9Y1dDU3eq4xbZ}J z!^y{X(juQCrM{nK?~)u|ki&Nx@1A^kydobfC6^og@JmD3^~6E=;FCJSw}H3u&p;oV z|B}$^?H^@>B@ssG06Y&h!#3|G;UFup(J{z+54Bm2e%;K_vlwG>qaNWBw;bGjRiW%G z=y@o6XVfvImcXv4keSr!G|Oo4YM>de`()A&w|vL8yv2g-V5!c4Eurjz)v61O6&ajo z(21uVa8X7X^ub>BB%${|S2dyzV!#r{i<6W128^nIYJ$t(QG3#Ck{&4d-Oe}Ja@G?r zi#_eN#vh<$al?s#llWq@y;p^mS-zK=;V1tnc@MqE$#ED9+$JaBpTO?Hs{5+ls{87M z)nTf0u;*mej~5FjTB6rb(f<#`Dg^uwpV6r~O|MtyE3rZbgYZ@JC!}=$U@%EY25yAb zkpY+wy+-!IAEDz(cKmcJ13$tM`r!(#`CiXt_1Hc_#)@A~7o6R(I^DIFx5+d-YuVes zYOal~0WUA&@9b3ZA$zpaYulLd~;I~LmqbEYt%gLF;R}MerkUrf_ IAQA2Q4;9RI PxfKQZnHsr^cnD7~qa-({ zC=@8K$yy`~q>3~_gbs+%1rdBeLX)Y;2*d^{D`o-`3JOIacirLznH32)tY|(^kRRxY zVlyD4f#C}q1D|kzY-j9sUb&0Ba+i4(uJdYMy%@f)%iwE$%`4L4_-%x9d;Zzj&Q8pvk^;$q#+24>ofTpw9<7}<-= Gfg%8IK^F%A diff --git a/civicfix/core/models.py b/civicfix/core/models.py index de722af..2e9f04a 100644 --- a/civicfix/core/models.py +++ b/civicfix/core/models.py @@ -34,37 +34,72 @@ class IssueCategory(models.Model): def __str__(self): return self.name +# issues/models.py class Issue(models.Model): + STATUS_REPORTED = 'reported' + STATUS_ACKNOWLEDGED = 'acknowledged' + STATUS_IN_PROGRESS = 'in_progress' + STATUS_RESOLVED = 'resolved' + STATUS_CHOICES = [ - ('reported', 'Reported'), - ('acknowledged', 'Acknowledged'), - ('in_progress', 'In Progress'), - ('resolved', 'Resolved'), + (STATUS_REPORTED, 'Reported'), + (STATUS_ACKNOWLEDGED, 'Acknowledged'), + (STATUS_IN_PROGRESS, 'In Progress'), + (STATUS_RESOLVED, 'Resolved'), ] - + title = models.CharField(max_length=200) description = models.TextField() - category = models.ForeignKey(IssueCategory, on_delete=models.SET_NULL, null=True, blank=True) - reporter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reported_issues') - location = models.CharField(max_length=200) - latitude = models.FloatField() - longitude = models.FloatField() - photo = models.ImageField(upload_to='issue_photos/', blank=True, null=True, - validators=[FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])]) - status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='reported') + + 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, + related_name="reported_issues" + ) + + location = models.CharField(max_length=200, blank=True) + latitude = models.FloatField(null=True, blank=True) + longitude = models.FloatField(null=True, blank=True) + + photo = models.ImageField( + upload_to="issue_photos/", + blank=True, + null=True, + validators=[FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])] + ) + + status = models.CharField( + max_length=20, + choices=STATUS_CHOICES, + default=STATUS_REPORTED + ) + created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - + + class Meta: + ordering = ["-created_at"] # 🔹 latest issues first by default + def __str__(self): - return self.title - + return f"{self.title} ({self.get_status_display()})" + + # 🔹 Helpers def vote_count(self): - return self.votes.count() - + return self.votes.count() if hasattr(self, "votes") else 0 + def has_user_voted(self, user): - if user.is_authenticated: + if user.is_authenticated and hasattr(self, "votes"): return self.votes.filter(user=user).exists() return False + class Vote(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) diff --git a/civicfix/core/templates/dashboard/superadmin_dashboard.html b/civicfix/core/templates/dashboard/superadmin_dashboard.html index ef052f1..0ab3c71 100644 --- a/civicfix/core/templates/dashboard/superadmin_dashboard.html +++ b/civicfix/core/templates/dashboard/superadmin_dashboard.html @@ -19,6 +19,9 @@ Manage Departments +
  • + Manage Issues +
  • Manage Roles & Permissions
  • diff --git a/civicfix/core/templates/issues/manage_issues.html b/civicfix/core/templates/issues/manage_issues.html new file mode 100644 index 0000000..7597f0e --- /dev/null +++ b/civicfix/core/templates/issues/manage_issues.html @@ -0,0 +1,53 @@ +{% extends "core/base.html" %} + +{% block content %} +
    +
    +
    +

    Manage Issues

    +
    +
    + {% if issues %} + + + + + + + + + + + + + {% for issue in issues %} + + + + + + + + + {% endfor %} + +
    #TitleCategoryReported ByStatusCreated At
    {{ forloop.counter }}{{ issue.title }}{{ issue.category.name|default:"—" }}{{ issue.reporter.username }} + {% if issue.status == "reported" %} + Reported + {% elif issue.status == "acknowledged" %} + Acknowledged + {% elif issue.status == "in_progress" %} + In Progress + {% elif issue.status == "resolved" %} + Resolved + {% else %} + Unknown + {% endif %} + {{ issue.created_at|date:"M d, Y H:i" }}
    + {% else %} +

    No issues reported yet.

    + {% endif %} +
    +
    +
    +{% endblock %} diff --git a/civicfix/core/urls.py b/civicfix/core/urls.py index af20d7b..5ecf5f9 100644 --- a/civicfix/core/urls.py +++ b/civicfix/core/urls.py @@ -7,6 +7,8 @@ urlpatterns = [ path("superadmin/", views.superadmin_dashboard, name="superadmin_dashboard"), path("superadmin/departments/", views.manage_departments, name="manage_departments"), path("superadmin/departments//", views.department_detail, name="department_detail"), + path("superadmin/manage/", views.manage_issues, name="manage_issues"), + path('register/', views.register, name='register'), path('login/', views.custom_login, name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), diff --git a/civicfix/core/views.py b/civicfix/core/views.py index 6a8ecac..934ab4d 100644 --- a/civicfix/core/views.py +++ b/civicfix/core/views.py @@ -266,4 +266,10 @@ def department_detail(request, pk): return render(request, "department/department_detail.html", { "department": department, "users": users, - }) \ No newline at end of file + }) + +@login_required +@user_passes_test(superadmin_check) +def manage_issues(request): + issues = Issue.objects.all().order_by("-created_at") + return render(request, "issues/manage_issues.html", {"issues": issues}) \ No newline at end of file