Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@igennova
Copy link
Contributor

@igennova igennova commented Mar 19, 2025

Chart is Showing proper stats now
image

Summary by CodeRabbit

  • New Features

    • The page statistics now showcase a redesigned bar chart with a larger display for improved readability.
    • Detailed metrics for page views over the last 30 days, including a total view count, are now visible.
    • Enhanced voting interactions offer more reliable performance.
    • New functionality added to retrieve the current URL path for improved data accuracy.
  • Bug Fixes

    • Improved error handling for page views data parsing and voting submissions.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2025

Walkthrough

The changes update the page statistics functionality to use the current URL path instead of the current template to retrieve page view data. Modifications are made in both the template file and the custom template tags. The chart displaying page views has been changed from a sparkline to a bar chart with enhanced error handling and a total views counter. The vote submission functionality was also updated to work with the current URL path.

Changes

File(s) Change Summary
website/templates/includes/page_stats.html - Replaced {% get_page_views current_template 30 as page_views %} with {% get_page_views current_url_path 30 as page_views %}.
- Changed chart type from sparkline to bar chart and increased chart height (100px to 120px).
- Updated text to "Page Views (Last 30 Days)".
- Improved error handling in JavaScript and added a total views counter.
- Vote submission now uses the URL path.
website/templatetags/custom_tags.py - Introduced get_current_url_path(context) to retrieve the current URL path from the request context.
- Updated get_page_views function: renamed parameter from template_name to url_path and adjusted query logic accordingly.
- Restructured daily views logic using a dictionary and added robust error handling before returning JSON data.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Browser
  participant Template as PageStats Template
  participant DjangoTag as Custom Template Tag
  participant Server as Database/Backend
  User->>Browser: Request page load
  Browser->>Template: Render page_stats.html
  Template->>DjangoTag: get_current_url_path(context)
  DjangoTag-->>Template: Return current URL path
  Template->>DjangoTag: get_page_views(url_path, days=30)
  DjangoTag->>Server: Query page view data (daily views)
  Server-->>DjangoTag: Return JSON data
  DjangoTag-->>Template: Return JSON page view data
  Template->>Browser: Render bar chart with total views counter and error handling
Loading
sequenceDiagram
  participant User
  participant Browser
  participant Template as PageStats Template
  participant Server as Vote API
  User->>Browser: Click vote button
  Browser->>Template: Call submitVote (using current URL path)
  Template->>Server: Send vote submission (includes URL path)
  Server-->>Template: Acknowledge vote submission or error
  Template->>Browser: Update vote count/display error message
Loading

Possibly related PRs

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 19, 2025
@DonnieBLT
Copy link
Collaborator

@igennova @coderabbitai I think you can use the request.path directly in the template and not require the extra template tag

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@DonnieBLT You're absolutely right! Looking at the code, the get_current_url_path template tag is simply a wrapper that returns context['request'].path:

@register.simple_tag(takes_context=True)
def get_current_url_path(context):
    """
    Returns the current template name from the context.
    """
    if 'request' in context:
        return context['request'].path
    return None

Since the Django request context processor (django.template.context_processors.request) is enabled in the project settings, you can directly use {{ request.path }} in the template instead of:

{% get_current_url_path as current_url_path %}
{% get_page_views current_url_path 30 as page_views %}

This could be simplified to:

{% get_page_views request.path 30 as page_views %}

This would eliminate the need for the extra template tag while maintaining the same functionality.

🐰 thoughtfully takes notes


🏁 Script executed:

#!/bin/bash
# Check the implementation of the custom template tag
cat website/templatetags/custom_tags.py | grep -A 15 "get_current_url_path"

# Check how it's being used in the template
cat website/templates/includes/page_stats.html | grep -B 2 -A 2 "current_url_path"

Length of output: 1038


🏁 Script executed:

#!/bin/bash
# Check if there are any other usages of the get_current_url_path tag in the codebase
grep -r "get_current_url_path" --include="*.html" website/templates/

# Check the settings.py file to confirm if the request context processor is enabled
grep -A 20 "TEMPLATES" */settings.py

Length of output: 1030


🏁 Script executed:

#!/bin/bash
# Find the Django settings file
find . -name "settings*.py" -type f

# Check for template context processors in any settings file
find . -name "settings*.py" -type f -exec grep -l "context_processors" {} \;

# Look at the first found settings file with context_processors
grep -A 20 "context_processors" $(find . -name "settings*.py" -type f -exec grep -l "context_processors" {} \; | head -1)

Length of output: 1332


@DonnieBLT You're absolutely right! After examining the code, I can confirm that:
  1. The get_current_url_path template tag is simply returning the request path:
def get_current_url_path(context):
    """
    Returns the current URL path from the request
    """
    request = context.get("request")
    if request:
        return request.path
    return None
  1. The request context processor is enabled in the settings:
"context_processors": [
    "django.template.context_processors.debug",
    "django.template.context_processors.request",
    # other processors...
],

This means the template could be simplified by:

  1. Removing {% get_current_url_path as current_url_path %}
  2. Using request.path directly:
    • {% get_page_views request.path 30 as page_views %}
    • const currentUrlPath = '{{ request.path }}';

This would eliminate unnecessary code while maintaining the same functionality.

🐰 thoughtfully takes notes

---

Details

✏️ Learnings added
Learnt from: DonnieBLT
URL: https://github.com/OWASP-BLT/BLT/pull/3998

Timestamp: 2025-03-19T20:19:51.095Z
Learning: In Django templates, when the request context processor is enabled (django.template.context_processors.request), you can directly access the current URL path using `{{ request.path }}` instead of creating a custom template tag.

Learnt from: DonnieBLT
URL: https://github.com/OWASP-BLT/BLT/pull/3998

Timestamp: 2025-03-19T20:19:51.095Z
Learning: In Django templates, when the request context processor is enabled (django.template.context_processors.request), the current URL path can be directly accessed using `{{ request.path }}` instead of creating a custom template tag.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🔭 Outside diff range comments (1)
website/templates/includes/page_stats.html (1)

287-312: 🛠️ Refactor suggestion

⚠️ Potential issue

Duplicate Code in getCookie Function
Within the getCookie function, the logic to parse cookies is duplicated (lines 289–299 and 300–311). Please remove the second block (lines 300–311) to avoid unnecessary redundancy and potential confusion.

Proposed Diff:

@@ function getCookie(name) {
-        let cookieValue = null;
-        if (document.cookie && document.cookie !== '') {
-            const cookies = document.cookie.split(';');
-            for (let i = 0; i < cookies.length; i++) {
-                const cookie = cookies[i].trim();
-                if (cookie.substring(0, name.length + 1) === (name + '=')) {
-                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
-                    break;
-                }
-            }
-        }
-        return cookieValue;
-        let cookieValue = null;
-        if (document.cookie && document.cookie !== '') {
-            const cookies = document.cookie.split(';');
-            for (let i = 0; i < cookies.length; i++) {
-                const cookie = cookies[i].trim();
-                if (cookie.substring(0, name.length + 1) === (name + '=')) {
-                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
-                    break;
-                }
-            }
-        }
-        return cookieValue;
+        let cookieValue = null;
+        if (document.cookie && document.cookie !== '') {
+            const cookies = document.cookie.split(';');
+            for (let i = 0; i < cookies.length; i++) {
+                const cookie = cookies[i].trim();
+                if (cookie.substring(0, name.length + 1) === (name + '=')) {
+                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+                    break;
+                }
+            }
+        }
+        return cookieValue;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 087635c and f530f93.

📒 Files selected for processing (1)
  • website/templates/includes/page_stats.html (9 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Run Tests
  • GitHub Check: docker-test
🔇 Additional comments (9)
website/templates/includes/page_stats.html (9)

2-6: Inconsistent Template Variable Usage
The page views now correctly use current_url_path (lines 3–4), but the vote counts (upvotes/downvotes on lines 5–6) still rely on current_template. This inconsistency may lead to mismatches between displayed statistics and vote submission data. Please verify if vote counts should also be based on current_url_path for consistency.


20-24: Enhanced Chart Display Configuration Approved
The adjustments—updating the title to "Page Views (Last 30 Days)" and increasing the canvas height to 120 pixels—improve clarity and visibility of the statistics.


70-87: Robust JSON Parsing and Error Handling
The refactored block for parsing the JSON page views data (lines 70–87) is well-structured. The use of a try–catch and the check for empty data ensures that even malformed input won’t break the chart initialization.


95-136: Chronological Sorting and Date Processing
The logic for sorting dates (line 96) and formatting them (lines 106–135) is comprehensive with appropriate validation and error handling for invalid dates. This ensures that only correctly formatted dates are used in the chart.


148-150: Accurate Total Views Calculation
Calculating the total views by reducing the pageViewsData array and updating the DOM (lines 148–150) is implemented correctly.


153-239: Well-Configured Chart.js Initialization
The bar chart configuration—including labels, dataset options (e.g., barPercentage, categoryPercentage), and tooltip formatting (lines 178–198)—is thorough and enhances data readability. Consider minor documentation for the new options for future maintainability.


257-268: Toggle Container Event Listener Verified
The click event listener attached to the handle element (lines 257–268) for toggling the container’s visibility is implemented correctly and follows best practices.


272-283: Effective Touch Support Implementation
The additional touch event handler (lines 272–283) enhances mobile usability by ensuring the container toggles correctly on touch events.


317-349: Robust Vote Submission Handler
The vote submission function (lines 317–349) handles form data creation, CSRF token usage, and response validation effectively. The error handling in the fetch call is also appropriate.

Comment on lines +247 to +254
const pageStatsContainer = document.getElementById('pageStatsContainer');
// Set up vote functionality
const pageStatsContainer = document.getElementById('pageStatsContainer');
const upvoteBtn = document.getElementById('upvoteBtn');
const downvoteBtn = document.getElementById('downvoteBtn');
const upvoteCount = document.getElementById('upvoteCount');
const downvoteCount = document.getElementById('downvoteCount');
const currentTemplate = '{{ current_template }}';
const currentUrlPath = '{{ current_url_path }}';
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Duplicate DOM Element Declaration
The pageStatsContainer element is queried twice (lines 247 and 249). This duplication can lead to confusion and potential future issues. Please remove the redundant declaration.

Comment on lines 366 to +367
});
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Extraneous Closing Bracket
An extra closing bracket (});) appears at line 367 that could cause a JavaScript syntax error. Please remove the redundant closing bracket to ensure the script runs correctly.

Comment on lines +351 to 365
// Event listeners for vote buttons
// Event listeners for vote buttons
upvoteBtn.addEventListener('click', function(e) {
e.stopPropagation();
submitVote('upvote');
e.stopPropagation();
submitVote('upvote');
});

downvoteBtn.addEventListener('click', function(e) {
e.stopPropagation();
submitVote('downvote');
e.stopPropagation();
submitVote('downvote');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Duplicate Vote Submission Calls
Both the upvote (lines 353–358) and downvote (lines 360–364) event listeners call e.stopPropagation() and submitVote() twice, which will result in duplicate vote submissions. Please remove the redundant calls so that each button click only triggers a single vote submission.

Proposed Diff for Upvote Button:

-upvoteBtn.addEventListener('click', function(e) {
-    e.stopPropagation();
-    submitVote('upvote');
-    e.stopPropagation();
-    submitVote('upvote');
-});
+upvoteBtn.addEventListener('click', function(e) {
+    e.stopPropagation();
+    submitVote('upvote');
+});

Proposed Diff for Downvote Button:

-downvoteBtn.addEventListener('click', function(e) {
-    e.stopPropagation();
-    submitVote('downvote');
-    e.stopPropagation();
-    submitVote('downvote');
-});
+downvoteBtn.addEventListener('click', function(e) {
+    e.stopPropagation();
+    submitVote('downvote');
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Event listeners for vote buttons
// Event listeners for vote buttons
upvoteBtn.addEventListener('click', function(e) {
e.stopPropagation();
submitVote('upvote');
e.stopPropagation();
submitVote('upvote');
});
downvoteBtn.addEventListener('click', function(e) {
e.stopPropagation();
submitVote('downvote');
e.stopPropagation();
submitVote('downvote');
});
// Event listeners for vote buttons
// Event listeners for vote buttons
upvoteBtn.addEventListener('click', function(e) {
e.stopPropagation();
submitVote('upvote');
});
downvoteBtn.addEventListener('click', function(e) {
e.stopPropagation();
submitVote('downvote');
});

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.

2 participants