Add a placeholder Evaluations nav entry so the design doesn't get forgotten
Under Settings, next to Referee levels/Forms -- but deliberately not behind a waffle Flag like the shop/forms stubs, since a flag-gated link disappears from the nav entirely until someone remembers to turn it on, which defeats the point of a standing reminder. Visible to MEMBER_ADMIN/ADMIN unconditionally, links to a bare "coming soon" page (reuses _generic_list.html with an empty object_list -- there's no model yet). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
@@ -126,6 +126,7 @@ _NAV_SECTIONS = {
|
||||
"invoice_list": "invoice_list",
|
||||
"form_list": "form_list",
|
||||
"submission_list": "form_list",
|
||||
"evaluations": "evaluations",
|
||||
"club_settings": "club_settings",
|
||||
"onboarding_requirement_list": "onboarding_requirement_list",
|
||||
"onboarding_requirement_create": "onboarding_requirement_list",
|
||||
@@ -171,6 +172,7 @@ _TOP_SECTION = {
|
||||
"discount_list": "finance",
|
||||
"invoice_list": "finance",
|
||||
"form_list": "settings",
|
||||
"evaluations": "settings",
|
||||
"club_settings": "settings",
|
||||
"onboarding_requirement_list": "settings",
|
||||
"role_list": "settings",
|
||||
|
||||
@@ -100,6 +100,12 @@
|
||||
<a class="nav-subitem {% if nav == 'position_list' %}active{% endif %}" href="{% url 'management:position_list' %}">{% trans "Positions" %}</a>
|
||||
{% endif %}
|
||||
<a class="nav-subitem {% if nav == 'referee_level_list' %}active{% endif %}" href="{% url 'management:referee_level_list' %}">{% trans "Referee levels" %}</a>
|
||||
{% comment %}
|
||||
Deliberately not behind a waffle flag like Forms above -- this is a standing
|
||||
"not built yet" reminder, so it stays visible rather than disappearing until
|
||||
someone remembers to flip a flag on. See management.views.EvaluationsComingSoonView.
|
||||
{% endcomment %}
|
||||
<a class="nav-subitem flex items-center gap-1.5 {% if nav == 'evaluations' %}active{% endif %}" href="{% url 'management:evaluations' %}">{% trans "Evaluations" %} <span class="badge badge-neutral badge-xs">{% trans "Soon" %}</span></a>
|
||||
{% if is_club_admin %}
|
||||
{% if forms_enabled %}
|
||||
<a class="nav-subitem {% if nav == 'form_list' %}active{% endif %}" href="{% url 'management:form_list' %}">{% trans "Forms" %}</a>
|
||||
|
||||
@@ -6716,6 +6716,42 @@ class FeatureGatedSectionsTests(ManagementTestBase):
|
||||
self.assertNotContains(response, "Forms")
|
||||
|
||||
|
||||
class EvaluationsComingSoonViewTests(ManagementTestBase):
|
||||
"""Placeholder nav entry/page for player evaluations (design: ARCHITECTURE.md
|
||||
§5.8) -- see management.views.EvaluationsComingSoonView."""
|
||||
|
||||
def make_plain_staff(self, email="physio-eval@example.com"):
|
||||
staff_user = User.objects.create_user(email=email, password="pw-secret-123")
|
||||
staff_member = Member.objects.create(user=staff_user, first_name="Pat", last_name="Physio")
|
||||
ClubMembership.objects.create(club=self.club, member=staff_member, season=self.season, status=ClubMembership.StatusChoices.ACTIVE)
|
||||
team = Team.objects.create(club=self.club, name="Physio Team", short_name="PHY")
|
||||
position = Position.objects.create(club=self.club, name="Physio", short_name="PH", staff_position=True, management_position=False)
|
||||
StaffAssignment.objects.create(team=team, member=staff_member, season=self.season, position=position)
|
||||
return staff_user
|
||||
|
||||
def test_member_admin_can_reach_it(self):
|
||||
self.client.force_login(self.admin_user)
|
||||
|
||||
response = self.club_get("evaluations")
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Player evaluations")
|
||||
|
||||
def test_plain_staff_gets_403(self):
|
||||
self.client.force_login(self.make_plain_staff())
|
||||
|
||||
response = self.club_get("evaluations")
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_nav_shows_the_placeholder_unconditionally_no_flag_needed(self):
|
||||
self.client.force_login(self.admin_user)
|
||||
|
||||
response = self.club_get("club_settings")
|
||||
|
||||
self.assertContains(response, "Evaluations")
|
||||
|
||||
|
||||
RBIHF_SAMPLE_HTML = """<html><body>
|
||||
<div class="block"><div class="block-header"><h2>Sportoase Antwerp Phantoms</h2></div></div>
|
||||
<div class="block"><div class="block-header"><h2 id="games-upcoming">Upcoming games</h2></div>
|
||||
|
||||
@@ -135,6 +135,8 @@ urlpatterns = [
|
||||
# Forms
|
||||
path("forms/", views.FormListView.as_view(), name="form_list"),
|
||||
path("forms/<uuid:pk>/submissions/", views.SubmissionListView.as_view(), name="submission_list"),
|
||||
# Evaluations (placeholder -- see ARCHITECTURE.md §5.8, nothing built yet)
|
||||
path("evaluations/", views.EvaluationsComingSoonView.as_view(), name="evaluations"),
|
||||
# Settings (admin only)
|
||||
path("settings/", views.ClubSettingsView.as_view(), name="club_settings"),
|
||||
path("settings/email-previews/<str:key>/render/", views.EmailPreviewRenderView.as_view(), name="email_preview_render"),
|
||||
|
||||
@@ -3405,6 +3405,22 @@ class SubmissionListView(FeatureRequiredMixin, StubListMixin, ListView):
|
||||
return Submission.objects.filter(form__club=self.request.club, form_id=self.kwargs["pk"])
|
||||
|
||||
|
||||
class EvaluationsComingSoonView(MemberAdminRequiredMixin, TemplateView):
|
||||
"""Placeholder nav entry for player evaluations (design: ARCHITECTURE.md
|
||||
§5.8) -- nothing else is built yet. Deliberately *not* a FeatureRequiredMixin/
|
||||
waffle-flagged stub like the shop/forms sections above: those hide their nav
|
||||
item until a platform operator turns the flag on for a club, which is exactly
|
||||
wrong for a standing "don't forget to build this" reminder -- this stays
|
||||
visible to every MEMBER_ADMIN/ADMIN on every club unconditionally. Reuses
|
||||
_generic_list.html (StubListMixin's own template) with an empty object_list
|
||||
rather than a real queryset, since there's no model behind this yet at all."""
|
||||
|
||||
template_name = "management/_generic_list.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
return super().get_context_data(page_title=_("Player evaluations"), object_list=[], **kwargs)
|
||||
|
||||
|
||||
class ClubSettingsView(ClubAdminRequiredMixin, UpdateView):
|
||||
"""A club's own self-service identity/branding editor -- the "Club identity"
|
||||
settings sub-item. Singleton by construction: always edits request.club, never
|
||||
|
||||
Reference in New Issue
Block a user