• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

liqd / adhocracy-plus / 18908688697

29 Oct 2025 12:59PM UTC coverage: 44.622% (-44.5%) from 89.135%
18908688697

Pull #2986

github

web-flow
Merge 1dfde8ee7 into 445e1d498
Pull Request #2986: Draft: Speed up Github Ci Tests

3012 of 6750 relevant lines covered (44.62%)

0.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/apps/userdashboard/views.py
1
from django.contrib.auth.mixins import LoginRequiredMixin
×
2
from django.contrib.contenttypes.models import ContentType
×
3
from django.shortcuts import get_object_or_404
×
4
from django.urls import reverse
×
5
from django.views import generic
×
6

7
from adhocracy4.actions.models import Action
×
8
from adhocracy4.comments.models import Comment
×
9
from adhocracy4.polls.models import Poll
×
10
from adhocracy4.projects.models import Project
×
11
from adhocracy4.rules import mixins as rules_mixins
×
12
from apps.documents.models import Chapter
×
13
from apps.documents.models import Paragraph
×
14
from apps.moderatorfeedback.models import ModeratorCommentFeedback
×
15
from apps.organisations.models import Organisation
×
16
from apps.users.models import User
×
17

18

19
class UserDashboardBaseMixin(
×
20
    LoginRequiredMixin,
21
    generic.base.ContextMixin,
22
    generic.base.TemplateResponseMixin,
23
    generic.base.View,
24
):
25
    """
26
    Adds followed projects and organisations as properties.
27

28
    To be used in the user dashboard views, as they all need this info.
29
    """
30

31
    model = User
×
32

33
    def get(self, request):
×
34
        response = self.render_to_response(self.get_context_data())
×
35
        return response
×
36

37
    @property
×
38
    def organisations(self):
×
39
        return Organisation.objects.filter(
×
40
            project__follow__creator=self.request.user, project__follow__enabled=True
41
        ).distinct()
42

43
    @property
×
44
    def projects(self):
×
45
        projects = Project.objects.filter(
×
46
            follow__creator=self.request.user, follow__enabled=True
47
        )
48
        return projects
×
49

50

51
# user views
52
class UserDashboardOverviewView(UserDashboardBaseMixin):
×
53
    template_name = "a4_candy_userdashboard/userdashboard_overview.html"
×
54
    menu_item = "overview"
×
55

56
    @property
×
57
    def actions(self):
×
58
        """Return comment/feedback actions that are  on content the user created.
59

60
        Do not return actions on comments for polls and documents to not spam
61
        initiators.
62
        """
63
        user = self.request.user
×
64
        comment_actions = (
×
65
            Action.objects.filter(
66
                obj_content_type=ContentType.objects.get_for_model(Comment),
67
                verb="add",
68
                target_creator=user,
69
            )
70
            .exclude(
71
                target_content_type__in=[
72
                    ContentType.objects.get_for_model(Poll),
73
                    ContentType.objects.get_for_model(Chapter),
74
                    ContentType.objects.get_for_model(Paragraph),
75
                ]
76
            )
77
            .exclude(actor=user)
78
            .select_related("actor", "project")
79
            .prefetch_related("obj", "target__creator")
80
        )
81
        filtered_comment_actions = [
×
82
            action for action in comment_actions if not action.obj.is_blocked
83
        ]
84
        feedback_actions = (
×
85
            Action.objects.filter(
86
                obj_content_type=ContentType.objects.get_for_model(
87
                    ModeratorCommentFeedback
88
                ),
89
                obj_comment_creator=user,
90
            )
91
            .exclude(actor=user)
92
            .select_related("project", "project__organisation")
93
            .prefetch_related("obj__comment__creator", "obj__comment__content_object")
94
        )
95

96
        return sorted(
×
97
            filtered_comment_actions + list(feedback_actions),
98
            key=lambda action: action.timestamp,
99
            reverse=True,
100
        )
101

102
    @property
×
103
    def projects_carousel(self):
×
104
        (
×
105
            sorted_active_projects,
106
            sorted_future_projects,
107
            sorted_past_projects,
108
        ) = self.request.user.get_projects_follow_list()
109
        projects = (
×
110
            list(sorted_active_projects)
111
            + list(sorted_future_projects)
112
            + list(sorted_past_projects)
113
        )[:8]
114

115
        return projects
×
116

117

118
class UserDashboardActivitiesView(UserDashboardBaseMixin):
×
119
    template_name = "a4_candy_userdashboard/userdashboard_activities.html"
×
120
    menu_item = "overview"
×
121

122
    @property
×
123
    def actions(self):
×
124
        """Return comment/feedback actions that are  on content the user created.
125

126
        Do not return actions on comments for polls and documents to not spam
127
        initiators.
128
        """
129
        user = self.request.user
×
130
        comment_actions = (
×
131
            Action.objects.filter(
132
                obj_content_type=ContentType.objects.get_for_model(Comment),
133
                verb="add",
134
                target_creator=user,
135
            )
136
            .exclude(
137
                target_content_type__in=[
138
                    ContentType.objects.get_for_model(Poll),
139
                    ContentType.objects.get_for_model(Chapter),
140
                    ContentType.objects.get_for_model(Paragraph),
141
                ]
142
            )
143
            .exclude(
144
                actor=user,
145
            )
146
            .select_related("actor", "project")
147
            .prefetch_related("obj", "target__creator")
148
        )
149

150
        filtered_comment_actions = [
×
151
            action for action in comment_actions if not action.obj.is_blocked
152
        ]
153
        feedback_actions = (
×
154
            Action.objects.filter(
155
                obj_content_type=ContentType.objects.get_for_model(
156
                    ModeratorCommentFeedback
157
                ),
158
                obj_comment_creator=user,
159
            )
160
            .exclude(actor=user)
161
            .select_related("project")
162
            .prefetch_related("obj__comment__creator")
163
        )
164

165
        return sorted(
×
166
            filtered_comment_actions + list(feedback_actions),
167
            key=lambda action: action.timestamp,
168
            reverse=True,
169
        )
170

171

172
class UserDashboardFollowingView(UserDashboardBaseMixin):
×
173
    template_name = "a4_candy_userdashboard/userdashboard_following.html"
×
174
    menu_item = "overview"
×
175

176

177
# moderation views
178
class UserDashboardModerationView(
×
179
    UserDashboardBaseMixin, rules_mixins.PermissionRequiredMixin
180
):
181
    template_name = "a4_candy_userdashboard/userdashboard_moderation.html"
×
182
    permission_required = "a4_candy_userdashboard.view_moderation_dashboard"
×
183
    menu_item = "moderation"
×
184

185
    def get_context_data(self, **kwargs):
×
186
        context = super().get_context_data(**kwargs)
×
187
        context["project_api_url"] = reverse("moderationprojects-list")
×
188
        return context
×
189

190

191
class UserDashboardModerationDetailView(
×
192
    UserDashboardBaseMixin, rules_mixins.PermissionRequiredMixin
193
):
194
    template_name = "a4_candy_userdashboard/userdashboard_moderation_detail.html"
×
195
    permission_required = "a4_candy_userdashboard.change_moderation_comment"
×
196

197
    def get_context_data(self, **kwargs):
×
198
        context = super().get_context_data(**kwargs)
×
199
        context["moderation_comments_api_url"] = reverse(
×
200
            "moderationcomments-list", kwargs={"project_pk": self.project.pk}
201
        )
202
        return context
×
203

204
    def dispatch(self, request, *args, **kwargs):
×
205
        self.slug = kwargs.pop("slug")
×
206
        return super().dispatch(request, *args, **kwargs)
×
207

208
    @property
×
209
    def project(self):
×
210
        return get_object_or_404(Project, slug=self.slug)
×
211

212
    @property
×
213
    def project_url(self):
×
214
        return self.project.get_absolute_url()
×
215

216
    def get_permission_object(self):
×
217
        return self.project
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc