diff --git a/froide/foirequest/templates/foirequest/foiproject_detail.html b/froide/foirequest/templates/foirequest/foiproject_detail.html index 471a22315..dac13a4ab 100644 --- a/froide/foirequest/templates/foirequest/foiproject_detail.html +++ b/froide/foirequest/templates/foirequest/foiproject_detail.html @@ -3,6 +3,7 @@ {% load static %} {% load markup %} {% load foirequest_tags %} +{% load permission_helper %} {% load form_helper %} {% block title %} {{ object.title }} @@ -114,6 +115,7 @@

{{ object.title }}

{% trans "public body" %} {% if object|can_read_foiproject_authenticated:request %} {% trans "is public?" %} + {% trans "has problems?" %} {% endif %} @@ -153,6 +155,14 @@

{{ object.title }}

{% translate "No" %} {% endif %} + + {% if req.has_problems %} + + {% translate "Yes" %} + {% else %} + {% translate "No" %} + {% endif %} + {% endif %} {% endfor %} @@ -160,7 +170,54 @@

{{ object.title }}

{% if object|can_write_foiproject:request %}{% endif %} + {% if problems %} +
+

{% translate "Unresolved problem reports" %}

+
+ + + + + + + + + + + {% for report in problems %} + + + + + + + {% endfor %} + +
{% translate "Request" %}{% trans "Problem" %}{% trans "Date" %}{% trans "State" %}
+ {% include "foirequest/snippets/request_item_mini_pb.html" with object=report.message.request url=report.get_absolute_url %} + + + {{ report.get_kind_display }} + {% if report.auto_submitted %} +
+ {% trans "auto detected" %} + {% endif %} +
+
{{ report.timestamp|date:"SHORT_DATETIME_FORMAT" }} + {% if request.user.is_staff and request.user|has_perm:"problem.view_problemreport" %} + + {% endif %} + {% if report.resolved %} + {% trans "Resolved" %} + {% else %} + {% trans "Pending" %} + {% endif %} + {% if request.user.is_staff and request.user|has_perm:"problem.view_problemreport" %}{% endif %} +
+
+ {% endif %} {% if team_form %} +
{% trans "Assign team to project" as legend %} {% trans "Set team for project" as submit_button %} {% url 'foirequest-project_set_team' slug=object.slug as submit_url %} diff --git a/froide/foirequest/templates/foirequest/snippets/request_item_mini_pb.html b/froide/foirequest/templates/foirequest/snippets/request_item_mini_pb.html new file mode 100644 index 000000000..5a6e92f78 --- /dev/null +++ b/froide/foirequest/templates/foirequest/snippets/request_item_mini_pb.html @@ -0,0 +1,23 @@ +{% load i18n %} +{% load humanize %} +
+ {% if object.status_representation %} + + {% endif %} +
+ + + + {{ object.title }} + +
+ + {{ object.public_body.name }} + – {{ object.jurisdiction.name }} + +
+
+
diff --git a/froide/foirequest/views/project.py b/froide/foirequest/views/project.py index f9cd97ed0..b4e8d5c92 100644 --- a/froide/foirequest/views/project.py +++ b/froide/foirequest/views/project.py @@ -2,6 +2,7 @@ from typing import Any, Dict from django.contrib import messages +from django.db.models import Exists, OuterRef, Q from django.forms import Form from django.http import Http404 from django.shortcuts import get_object_or_404, redirect @@ -11,6 +12,7 @@ from django.views.generic import DetailView, UpdateView from froide.helper.utils import render_400, render_403 +from froide.problem.models import ProblemReport from froide.team.forms import AssignTeamForm from froide.team.views import AssignTeamView @@ -61,9 +63,19 @@ class ProjectView(AuthRequiredMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) public_requests = self.object.foirequest_set.filter(public=True).count() - context["foirequests"] = get_read_foirequest_queryset( - self.request, queryset=self.object.foirequest_set.all() - ).prefetch_related("public_body") + context["foirequests"] = ( + get_read_foirequest_queryset( + self.request, queryset=self.object.foirequest_set.all() + ) + .annotate( + has_problems=Exists( + ProblemReport.objects.filter( + message__request=OuterRef("pk"), resolved=False + ) + ) + ) + .prefetch_related("public_body") + ) context["public_requests"] = public_requests context["all_public"] = public_requests == self.object.request_count context["all_non_public"] = public_requests == 0 @@ -73,6 +85,18 @@ def get_context_data(self, **kwargs): context["team_form"] = AssignTeamForm( instance=self.object, user=self.request.user ) + user_filter = Q(user=None) + if self.object.team: + user_filter |= Q(user__in=self.object.team.get_active_users()) + context["problems"] = ( + ProblemReport.objects.filter( + message__request__in=context["foirequests"], + resolved=False, + ) + .filter(user_filter) + .select_related("message") + .prefetch_related("message__request", "message__request__public_body") + ) return context diff --git a/froide/team/models.py b/froide/team/models.py index 24f010a1a..d829c52c3 100644 --- a/froide/team/models.py +++ b/froide/team/models.py @@ -1,9 +1,13 @@ from django.conf import settings +from django.contrib.auth import get_user_model from django.db import models +from django.db.models import Exists, OuterRef from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ +User = get_user_model() + class TeamRole(models.TextChoices): OWNER = "owner", _("owner") @@ -104,6 +108,14 @@ def get_role_display(self): return TeamMembership.ROLES_DICT[self.role] return "" + def get_active_users(self): + active_members = TeamMembership.objects.filter( + user=OuterRef("pk"), + status=TeamMembership.MEMBERSHIP_STATUS.ACTIVE, + team=self, + ) + return User.objects.filter(Exists(active_members)) + @property def member_count(self): return self.members.count()