Skip to content

feat: top-level questions count on tournament pages + Tooltip variant consolidation and restyle#4877

Open
aseckin wants to merge 4 commits into
mainfrom
question-counts
Open

feat: top-level questions count on tournament pages + Tooltip variant consolidation and restyle#4877
aseckin wants to merge 4 commits into
mainfrom
question-counts

Conversation

@aseckin

@aseckin aseckin commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Closes #4823

What

1. Tournament pages: show top-level questions count (+ subquestions tooltip)

The "View Questions (N)" button counted every Question row — a group post with 10
subquestions contributed 10, a conditional pair contributed 2 — which overstated
tournament size. Now:

  • questions_count counts question posts: a single question, a question group, or
    a conditional pair each count as 1 (notebooks count 0). Applies everywhere the field
    is shown (tournament grid cards, services cards, minibench, OG images).
  • The old total is exposed as a new questions_count_including_subquestions field.
  • Hovering the button shows an "Including Subquestions: N" tooltip (translated in all
    6 locales), rendered only when the tournament actually has subquestions.

Backend details:

  • annotate_questions_count() derives both counts from shared filter objects
    (approved posts, question_weight > 0, not ambiguous/annulled), so they can't drift.
    No new SQL joins — the new Count(distinct posts__id) reuses the existing join tree.
  • Questions-count cache key bumped v1 → v2 for the new value shape (dict of both
    counts); old keys just expire via their 1h TTL.
  • Note: the /tournaments listing sorts by questions_count, so group-heavy
    tournaments move down slightly — intended.

2. Tooltip: variant prop consolidating the copy-pasted light theme

The light tooltip theme (blue border / gray-0 background / gray-800 text) was
duplicated across 8 call sites via tooltipClassName. The shared Tooltip component
now takes variant="dark" | "light" (default dark), and the 8 sites
(leaderboard info icons, labor-hub chart legend, DefinitionTooltip,
sidebar/CDF tooltips, group forecast accordion) were migrated, keeping their
site-specific classes. TruncatedTextTooltip passes variant through.
Call-site tooltipClassName overrides still win via tailwind-merge.

Verified with a tailwind-merge equivalence script: merged class sets are identical
for all migrated sites except two accepted normalizations — dead border classes that
!important was already beating at runtime, and the sidebar/CDF tooltips picking up
the standard light-theme text color (gray-800/gray-800-dark) they previously
lacked (near-imperceptible: #fbfbfc → #e4e7e9 in dark mode).

3. Tooltip: restyle base to match the Midterms Dashboard tooltip

The base styling now matches the congress-control tooltip from midterms-2026
(chamber_row_tooltip.tsx): rounded-md, px-4 py-3, text-base, shadow-lg,
borderless. The default variant becomes a navy bubble with white text
(bg-blue-800 text-gray-0, inverted in dark mode); the light variant keeps its
palette and carries its own border now.

Audited every consumer that overrides background without setting text color
(medal-rank tooltip, score-data table, salmon "resolved" chips) — all set explicit
text colors in their content, so the inverted base palette can't strand invisible
text. Not ported on purpose: text-center (alignment left to call sites) and the
positioning classes (floating-ui handles placement).

Test plan

  • New backend test test_annotate_questions_count (single + group + conditional +
    notebook/draft/annulled/zero-weight exclusions) — passes
  • All tests/unit/test_projects pass (40/40)
  • API spot-check: tournament with groups returns questions_count: 45,
    questions_count_including_subquestions: 95; button renders 45 with tooltip;
    tournament without subquestions renders no tooltip
  • Hover-check tooltips on: tournament page, leaderboard info icons, question
    sidebar, settings notifications, midterms dashboard (unaffected — has its own
    component), forecast maker "resolved" chips
  • eslint / tsc / ruff clean on changed files

Summary by CodeRabbit

  • New Features

    • Show separate "including subquestions" counts in tournament navigation and APIs; added localized strings (cs, en, es, pt, zh-TW, zh).
  • Refactor

    • Introduced a tooltip "light" variant and simplified tooltip styling for consistent UI.
  • Tests

    • Added unit tests covering question vs. including-subquestions count annotations.

aseckin and others added 3 commits June 10, 2026 11:07
…rnament pages

questions_count now counts question posts (group = 1, conditional = 1)
instead of every question row. The old total is exposed as
questions_count_including_subquestions and shown in a hover tooltip on
the View Questions button when subquestions exist. Cache key bumped to
v2 for the new value shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The light tooltip theme (blue border, gray-0 background, gray-800 text)
was copy-pasted across 8 call sites via tooltipClassName. Move it into a
variant="light" option on the shared Tooltip component; default "dark"
variant is unchanged. Call-site overrides still win via tailwind-merge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adopt the chamber-control tooltip styling as the shared base: rounded-md,
px-4 py-3, text-base, shadow-lg, borderless. Default variant becomes
bg-blue-800/text-gray-0 (navy bubble, white text) with inverted dark-mode
colors; the light variant now carries its own border.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@aseckin aseckin requested a review from ncarazon June 10, 2026 09:34
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 89334db9-36a7-4f76-b0a2-103111149512

📥 Commits

Reviewing files that changed from the base of the PR and between 4537025 and e8d4e8b.

📒 Files selected for processing (1)
  • projects/services/cache.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • projects/services/cache.py

📝 Walkthrough

Walkthrough

Adds structured question counts that include subquestions through model annotations, caching, serializers, and API responses; extends frontend types and i18n keys; conditionally shows a “including subquestions” light tooltip in the tournament navigation; introduces tooltip variant support and updates usages; adds tests validating both counts.

Changes

Subquestions Count Display Feature

Layer / File(s) Summary
Tooltip Variant Infrastructure
front_end/src/components/ui/tooltip.tsx, front_end/src/components/truncated_text_tooltip.tsx
Base Tooltip component now accepts a variant prop ("dark" or "light") with variant-specific CSS classes mapped via VARIANT_CLASS_NAMES. TruncatedTextTooltip forwards the variant prop.
Apply Variant System to Existing Tooltips
front_end/src/app/(main)/(leaderboards)/leaderboard/components/*, front_end/src/app/(main)/labor-hub/components/*, front_end/src/app/(main)/questions/[id]/components/sidebar/*, front_end/src/components/forecast_maker/*
Multiple tooltip usage sites switch to variant="light" and simplified tooltipClassName, removing prior explicit color/border/background classes.
Internationalization for Subquestions Message
front_end/messages/cs.json, front_end/messages/en.json, front_end/messages/es.json, front_end/messages/pt.json, front_end/messages/zh-TW.json, front_end/messages/zh.json
Added includingSubquestions translation key with {count} placeholder across all six supported languages.
NavigationBlock Subquestions Tooltip UI
front_end/src/app/(main)/(tournaments)/tournament/components/navigation_block.tsx
Conditionally wraps the "viewQuestions" button with a light-variant tooltip when questions_count_including_subquestions > questions_count, using the new i18n key.
Frontend Tournament Preview Type
front_end/src/types/projects.ts
TournamentPreview type extended with optional questions_count_including_subquestions field.
Backend Question Counts Data Structure
projects/services/common.py
Adds ProjectQuestionCounts TypedDict and updates get_questions_count_for_projects to return structured counts including questions_count_including_subquestions.
Backend Question Count Annotation
projects/models.py
annotate_questions_count() refactored to compute questions_count (posts-with-questions counted once) and questions_count_including_subquestions (total qualifying question IDs including subquestions).
Backend Cache Service
projects/services/cache.py
get_projects_questions_count_cached updated to cache and return ProjectQuestionCounts objects; cache key prefix bumped to project_questions_count:v2; miss handling populates structured counts.
Backend Tournament Serializer
projects/serializers/common.py
serialize_tournaments_with_counts reads both counts from cached mapping and includes questions_count_including_subquestions in the response (defaults to 0 when absent).
Backend API View Response
projects/views/common.py
tournament_by_slug_api_view retrieves cached counts once and sets both questions_count and questions_count_including_subquestions in the API response (default 0).
Test Coverage for Question Count Annotation
tests/unit/test_projects/test_models.py
New unit test test_annotate_questions_count verifies questions_count == 3 and questions_count_including_subquestions == 6, excluding drafts/notebooks/zero-weight posts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • hlbmtc
  • elisescu
  • ncarazon

Poem

🐰 The variant hops from dark to light,

subquestions counted, neat and bright,
Cache and model, frontend too,
Strings translated, tests pass through,
A little rabbit claps—hooray! 🥕

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the three main changes: introducing top-level questions count on tournament pages, consolidating Tooltip variants, and restyling tooltips.
Linked Issues check ✅ Passed All requirements from #4823 are met: the PR implements top-level questions counting (excluding notebooks, counting groups/conditionals as 1), exposes both counts separately, and provides the secondary count via tooltip.
Out of Scope Changes check ✅ Passed All changes are in scope: questions count implementation, tooltip variant consolidation, and tooltip restyling. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch question-counts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@aseckin aseckin marked this pull request as ready for review June 10, 2026 09:34
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Environment

Your preview environment is ready!

Resource Details
🌐 Preview URL https://metaculus-pr-4877-question-counts-preview.mtcl.cc
📦 Docker Image ghcr.io/metaculus/metaculus:question-counts-e8d4e8b
🗄️ PostgreSQL NeonDB branch preview/pr-4877-question-counts
Redis Fly Redis mtc-redis-pr-4877-question-counts

Details

  • Commit: e8d4e8b79c7e069b32f4ca688a3a6945a5ae65c0
  • Branch: question-counts
  • Fly App: metaculus-pr-4877-question-counts

ℹ️ Preview Environment Info

Isolation:

  • PostgreSQL and Redis are fully isolated from production
  • Each PR gets its own database branch and Redis instance
  • Changes pushed to this PR will trigger a new deployment

Limitations:

  • Background workers and cron jobs are not deployed in preview environments
  • If you need to test background jobs, use Heroku staging environments

Cleanup:

  • This preview will be automatically destroyed when the PR is closed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@projects/services/cache.py`:
- Line 7: The constant QUESTIONS_COUNT_CACHE_TIMEOUT is set to 1 * 3600 (one
hour) but the inline comment incorrectly says "3 hour"; update the comment to
accurately reflect one hour (e.g., change comment to "# 1 hour") next to
QUESTIONS_COUNT_CACHE_TIMEOUT so the code and comment match.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f87ab637-ef53-434f-acc3-9fb98f6430e3

📥 Commits

Reviewing files that changed from the base of the PR and between 9fa0197 and 4537025.

📒 Files selected for processing (24)
  • front_end/messages/cs.json
  • front_end/messages/en.json
  • front_end/messages/es.json
  • front_end/messages/pt.json
  • front_end/messages/zh-TW.json
  • front_end/messages/zh.json
  • front_end/src/app/(main)/(leaderboards)/leaderboard/components/aggregation_rank_tooltip.tsx
  • front_end/src/app/(main)/(leaderboards)/leaderboard/components/excluded_entry_tooltop.tsx
  • front_end/src/app/(main)/(leaderboards)/leaderboard/components/prize_unfinalized_tooltip.tsx
  • front_end/src/app/(main)/(tournaments)/tournament/components/navigation_block.tsx
  • front_end/src/app/(main)/labor-hub/components/definition_tooltip.tsx
  • front_end/src/app/(main)/labor-hub/components/question_cards/multi_line_chart.tsx
  • front_end/src/app/(main)/questions/[id]/components/sidebar/sidebar_tooltip.tsx
  • front_end/src/components/forecast_maker/continuous_group_accordion/group_forecast_accordion_item.tsx
  • front_end/src/components/forecast_maker/continuous_input/continuous_input_container.tsx
  • front_end/src/components/truncated_text_tooltip.tsx
  • front_end/src/components/ui/tooltip.tsx
  • front_end/src/types/projects.ts
  • projects/models.py
  • projects/serializers/common.py
  • projects/services/cache.py
  • projects/services/common.py
  • projects/views/common.py
  • tests/unit/test_projects/test_models.py

Comment thread projects/services/cache.py Outdated

@ncarazon ncarazon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FE code looks good to me, but this should be also reviewed by BE eng

@ncarazon ncarazon requested a review from hlbmtc June 10, 2026 10:17
Co-authored-by: aseckin <aseckin@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Find a better way to display Question count in Tournaments page

2 participants