Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions froide/foirequest/templates/foirequest/foiproject_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{% load static %}
{% load markup %}
{% load foirequest_tags %}
{% load permission_helper %}
{% load form_helper %}
{% block title %}
{{ object.title }}
Expand Down Expand Up @@ -114,6 +115,7 @@ <h1>{{ object.title }}</h1>
<th scope="col">{% trans "public body" %}</th>
{% if object|can_read_foiproject_authenticated:request %}
<th scope="col">{% trans "is public?" %}</th>
<th scope="col">{% trans "has problems?" %}</th>
{% endif %}
</tr>
</thead>
Expand Down Expand Up @@ -153,14 +155,69 @@ <h1>{{ object.title }}</h1>
<span class="visually-hidden">{% translate "No" %}</span>
{% endif %}
</td>
<td class="text-center">
{% if req.has_problems %}
<span class="fa fa-exclamation-triangle"></span>
<span class="visually-hidden">{% translate "Yes" %}</span>
{% else %}
<span class="visually-hidden">{% translate "No" %}</span>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if object|can_write_foiproject:request %}</form>{% endif %}
{% if problems %}
<hr />
<h3>{% translate "Unresolved problem reports" %}</h3>
<div class="table-responsive">
<table class="table table-hover table-sm">
<thead>
<tr>
<th>{% translate "Request" %}</th>
<th>{% trans "Problem" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "State" %}</th>
</tr>
</thead>
<tbody>
{% for report in problems %}
<tr>
<td>
{% include "foirequest/snippets/request_item_mini_pb.html" with object=report.message.request url=report.get_absolute_url %}
</td>
<td>
<a href="{{ report.get_absolute_url }}">
<span class="badge text-bg-body-secondary">{{ report.get_kind_display }}</span>
{% if report.auto_submitted %}
<br />
<span class="badge text-bg-dark">{% trans "auto detected" %}</span>
{% endif %}
</a>
</td>
<td>{{ report.timestamp|date:"SHORT_DATETIME_FORMAT" }}</td>
<td>
{% if request.user.is_staff and request.user|has_perm:"problem.view_problemreport" %}
<a href="{% url 'admin:problem_problemreport_change' object_id=report.id %}">
{% endif %}
{% if report.resolved %}
<span class="badge text-bg-success">{% trans "Resolved" %}</span>
{% else %}
<span class="badge text-bg-secondary">{% trans "Pending" %}</span>
{% endif %}
{% if request.user.is_staff and request.user|has_perm:"problem.view_problemreport" %}</a>{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% if team_form %}
<hr />
{% 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 %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% load i18n %}
{% load humanize %}
<div class="mb-0 d-flex flex-column">
{% if object.status_representation %}
<a class="flex-shrink-0 "
href="{{ url|default:object.url }}"
title="{{ object.readable_status }}"></a>
{% endif %}
<div class="flex-grow-1">
<span class="mt-0 mb-1">
<a href="{{ url|default:object.url }}">
<span class="small-icon status-{{ object.status_representation }} {% if object.has_fee %}--has-fee{% endif %}"></span>
{{ object.title }}
</a>
<br>
<small>
<a href="{{ object.public_body.get_absolute_urll }}"
class="link-secondary">{{ object.public_body.name }}</a>
– <span class="muted">{{ object.jurisdiction.name }}</span>
</small>
</span>
</div>
</div>
30 changes: 27 additions & 3 deletions froide/foirequest/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
12 changes: 12 additions & 0 deletions froide/team/models.py
Original file line number Diff line number Diff line change
@@ -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")
Expand Down Expand Up @@ -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()
Expand Down