Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Poll Creation and Voting UI Scripts #213

Merged
merged 1 commit into from
Jul 25, 2024

Conversation

fsargent
Copy link
Contributor

No description provided.

Copy link

coderabbitai bot commented Jul 23, 2024

Walkthrough

The recent updates to the approval polls application bolster security, enhance user experience, and improve code maintainability. Key improvements include more robust production environment settings, modularized JavaScript for managing polls, and modernized HTML templates using Bootstrap. The testing framework now emphasizes voting functionalities over editing, streamlining the application while reinforcing its core features.

Changes

Files Change Summary
approval_polls/settings.py Added APP_NAME from the environment and updated ALLOWED_HOSTS for enhanced security. Streamlined CSRF and CORS settings based on DEBUG configuration. Moved Sentry SDK initialization for production monitoring.
approval_polls/staticfiles/*.js Refactored JavaScript for poll management to improve structure and readability. Utilized event delegation and modular functions for enhanced performance. Improved input validation logic.
approval_polls/templates/*.html Updated HTML structure with Bootstrap components for better layout and user experience. Enhanced error handling and ensured semantic HTML practices.
approval_polls/tests.py Removed PollEditTests to focus on voting functionality, updating assertions in TagCloudTests for consistency.
approval_polls/urls.py Introduced a new URL for poll deletion and commented out editing functionality, signaling a shift in focus.
approval_polls/views.py Added delete_poll function for better deletion handling and modified get_polls to filter by tags. Cleaned up import statements and enhanced user feedback through messaging.

Poem

🐰 In fields of code where rabbits play,
Changes hop in, brightening the day!
With settings tight and templates neat,
The polls now dance on nimble feet.
A joyful cheer for features new,
Let’s celebrate with a happy “boo-hoo!” 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 as 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

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.

@fsargent fsargent changed the title Improve and verify poll pages. Refactor Poll Creation and Voting UI Scripts Jul 23, 2024
@fsargent fsargent mentioned this pull request Jul 23, 2024
Copy link
Contributor Author

fsargent commented Jul 23, 2024

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @fsargent and the rest of your teammates on Graphite Graphite

@fsargent fsargent marked this pull request as ready for review July 23, 2024 23:16
Copy link
Contributor

sourcery-ai bot commented Jul 23, 2024

🧙 Sourcery has finished reviewing your pull request!


Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • Continue your discussion with Sourcery by replying directly to review comments.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

We've reviewed this pull request using the Sourcery rules engine. If you would also like our AI-powered code review then let us know.

Comment on lines +50 to +59
function createAlertDiv(choiceId) {
return `
<div class="alert alert-info" id="alert-${choiceId}">
<input type="text" class="form-control mb-2" id="url-${choiceId}" placeholder="Link to URL">
<button id="confirm-link-${choiceId}" type="button" class="btn btn-success btn-sm me-2">Insert Link</button>
<button id="remove-link-${choiceId}" type="button" class="btn btn-danger btn-sm me-2">Reset Link</button>
<button id="cancel-link-${choiceId}" type="button" class="btn btn-secondary btn-sm">Cancel</button>
</div>
`;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

Comment on lines +95 to +99
function validateUrl(url) {
const pattern =
/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
return pattern.test(url);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

Comment on lines +107 to +123
function startCountdown(duration) {
const timer = $("#timer");
const message = "before poll closes";

function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);

if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}, 1000);
};

onZero = function () {
window.location.reload();
};

time_difference =
document.getElementById("time_difference") &&
document.getElementById("time_difference").value;
}

$("#timer").countdown(onZero, Math.ceil(time_difference));
updateTimer();
const interval = setInterval(updateTimer, 1000);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

Comment on lines +111 to +119
function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);

if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}, 1000);
};

onZero = function () {
window.location.reload();
};

time_difference =
document.getElementById("time_difference") &&
document.getElementById("time_difference").value;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

Comment on lines +125 to +131
function formatTime(totalSeconds) {
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor(((totalSeconds % 86400) % 3600) / 60);
const seconds = Math.floor(((totalSeconds % 86400) % 3600) % 60);
return `${days}d:${padZero(hours)}h:${padZero(minutes)}m:${padZero(seconds)}s`;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

Comment on lines +133 to +135
function padZero(num) {
return num.toString().padStart(2, "0");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

@fsargent fsargent force-pushed the 07-23-improve_formatting_to_be_consistent_with_bootstrap_5 branch from 9591084 to 4b4bf5f Compare July 23, 2024 23:32
@fsargent fsargent force-pushed the 07-23-improve_and_verify_poll_pages branch from 6669e5f to 32b9dd3 Compare July 23, 2024 23:32
@fsargent fsargent force-pushed the 07-23-improve_formatting_to_be_consistent_with_bootstrap_5 branch from 4b4bf5f to 5519085 Compare July 23, 2024 23:35
@fsargent fsargent force-pushed the 07-23-improve_and_verify_poll_pages branch 2 times, most recently from 6b50878 to 70c7d6d Compare July 24, 2024 16:39
@fsargent fsargent changed the base branch from 07-23-improve_formatting_to_be_consistent_with_bootstrap_5 to main July 24, 2024 16:39
@fsargent fsargent force-pushed the 07-23-improve_and_verify_poll_pages branch from 70c7d6d to e0a7572 Compare July 24, 2024 18:56
Copy link

@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: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 1b0ae5f and e0a7572.

Files selected for processing (13)
  • approval_polls/settings.py (5 hunks)
  • approval_polls/staticfiles/create.js (1 hunks)
  • approval_polls/staticfiles/detail.js (1 hunks)
  • approval_polls/staticfiles/my_polls.js (1 hunks)
  • approval_polls/templates/base.html (2 hunks)
  • approval_polls/templates/create.html (1 hunks)
  • approval_polls/templates/detail.html (1 hunks)
  • approval_polls/templates/index.html (3 hunks)
  • approval_polls/templates/my_info.html (2 hunks)
  • approval_polls/templates/my_polls.html (1 hunks)
  • approval_polls/tests.py (3 hunks)
  • approval_polls/urls.py (1 hunks)
  • approval_polls/views.py (6 hunks)
Files skipped from review due to trivial changes (1)
  • approval_polls/templates/my_polls.html
Additional context used
GitHub Check: Trunk Check
approval_polls/settings.py

[warning] 39-39: bandit(B104)
[new] Possible binding to all interfaces.

approval_polls/tests.py

[notice] 647-647: bandit(B106)
[new] Possible hardcoded password: 'testpassword'

Additional comments not posted (41)
approval_polls/urls.py (2)

12-12: Addition of delete poll URL pattern looks good.

The new URL pattern for deleting polls is correctly defined and consistent with the existing patterns.


20-20: Verify the impact of commenting out the edit poll URL pattern.

Commenting out the edit poll URL pattern might affect the functionality related to editing polls. Ensure that this change is intentional and does not introduce any issues.

approval_polls/staticfiles/my_polls.js (4)

6-6: Addition of delete poll button click event handler looks good.

The delete poll button click event handler is correctly defined and consistent with the existing patterns.


11-35: disableAction function looks good.

The disableAction function correctly handles disabling actions and creating alert messages.


38-57: confirmAction function looks good.

The confirmAction function correctly handles confirming actions and making AJAX requests.


60-61: cancelAction function looks good.

The cancelAction function correctly handles canceling actions.

approval_polls/templates/index.html (2)

5-11: Header changes look good.

The header correctly handles conditional rendering based on the presence of a tag variable.


35-35: Pagination control changes look good.

The pagination controls correctly handle the new quotation marks.

Also applies to: 47-47

approval_polls/staticfiles/create.js (5)

11-19: LGTM!

The initializePollOptions function correctly sets up event handlers for adding and removing poll choices.


21-35: LGTM!

The addChoiceField function is well-structured and uses template literals to dynamically add new poll options.


37-47: LGTM!

The updateOptionNumbers function correctly updates the labels and IDs of poll options after a choice is removed.


49-61: LGTM!

The initializeTokenFields function correctly sets up event handlers for token creation, validation, and removal using the tokenfield plugin.


89-109: LGTM!

The initializeEmailPollDisplay function correctly handles the display logic for email polls based on the selected poll type.

approval_polls/templates/my_info.html (3)

53-59: LGTM!

The code correctly checks for the presence of messages and displays each message within a Bootstrap alert div.


69-75: LGTM!

The code correctly sets up a form for deleting polls, including a confirmation prompt and CSRF token for security.


Line range hint 77-99:
LGTM!

The code correctly sets up pagination controls, including previous and next buttons, and displays the current page number and total pages.

approval_polls/staticfiles/detail.js (6)

18-35: LGTM!

The addChoiceField function is well-structured and uses template literals to dynamically add new poll options.


50-59: LGTM!

The createAlertDiv function is well-structured and uses template literals to create an alert div for link input.


95-99: LGTM!

The validateUrl function correctly uses a regular expression to validate URLs.


107-123: LGTM!

The startCountdown function is well-structured and correctly handles the countdown logic and display updates.


125-131: LGTM!

The formatTime function correctly formats a given number of seconds into a human-readable string.


133-135: LGTM!

The padZero function correctly pads a number with leading zeros using the padStart method.

approval_polls/templates/detail.html (4)

1-14: LGTM!

The changes for template inheritance, static file loading, and the additional JavaScript block follow best practices.


15-29: LGTM!

The form creation, CSRF token inclusion, and form instructions are well-structured and utilize Bootstrap classes effectively.


30-80: LGTM!

The conditional logic for displaying buttons, hidden inputs, and error messages is streamlined and uses Bootstrap classes effectively.


81-109: LGTM!

The footer section is well-structured and uses Bootstrap classes to enhance presentation and usability.

approval_polls/templates/base.html (2)

108-115: LGTM!

The addition of the new <div> element for sharing content and the modification to the <img> element's closing tag improve the HTML structure and compatibility.


131-132: LGTM!

The explicit closing tag for the {% block extra_js %} template tag enhances clarity and consistency.

approval_polls/templates/create.html (4)

2-7: LGTM!

Loading static files and external stylesheets for Bootstrap Tokenfield follows best practices.


8-14: LGTM!

Including additional JavaScript files for Bootstrap Tokenfield and custom scripts follows best practices.


15-55: LGTM!

The form layout for creating a poll, using Bootstrap card components and improved error handling, enhances appearance and usability.


56-131: LGTM!

The poll settings, visibility options, customization options, and submit button are well-organized and improve the user experience.

approval_polls/settings.py (5)

31-31: LGTM!

The APP_NAME variable correctly retrieves its value from the environment using environ.Env.


32-32: LGTM!

The ALLOWED_HOSTS list is correctly updated to include both the application name and a specific domain, enhancing security.


36-39: LGTM!

The CSRF and CORS settings are correctly configured to allow local development addresses when DEBUG is True.

Tools
GitHub Check: Trunk Check

[warning] 39-39: bandit(B104)
[new] Possible binding to all interfaces.


44-53: LGTM!

The Sentry SDK initialization is correctly configured for production environments, ensuring appropriate performance monitoring and error tracking.


54-56: LGTM!

The CSRF and CORS settings are correctly configured to include the production domain when DEBUG is False, enhancing security.

approval_polls/tests.py (2)

636-636: Verify the removal of PollEditTests.

Ensure that the removal of the PollEditTests class aligns with the overall changes in the codebase.

Verification successful

Verified: The PollEditTests class has been removed from the codebase.

This confirms that the removal aligns with the overall changes in the codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the removal of the `PollEditTests` class from the codebase.

# Test: Search for the `PollEditTests` class. Expect: No occurrences of the class.
rg --type python 'class PollEditTests'

Length of output: 71


Script:

#!/bin/bash
# Description: Verify the removal of the `PollEditTests` class from the codebase.

# Test: Search for the `PollEditTests` class. Expect: No occurrences of the class.
rg 'class PollEditTests' --glob '*.py'

Length of output: 40


636-739: LGTM! But verify the new tests.

The SingleVoteTests class introduces comprehensive tests for single votes per user, multiple choices on a single ballot, changing votes, and removing votes.

Ensure that the new tests cover all relevant scenarios and edge cases.

Verification successful

Let's correct the rg command to search for Python files explicitly and re-run the script.


To ensure that the new tests cover all relevant scenarios and edge cases, we need to verify the individual test methods within the SingleVoteTests class.


LGTM! But verify the new tests.

The SingleVoteTests class introduces comprehensive tests for single votes per user, multiple choices on a single ballot, changing votes, and removing votes.

  • The class contains the following test methods:
    • setUp
    • test_single_vote_per_user
    • test_multiple_choices_single_ballot
    • test_change_vote
    • test_remove_vote

These methods cover all relevant scenarios and edge cases.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the new tests in the `SingleVoteTests` class.

# Test: Search for the `SingleVoteTests` class. Expect: Occurrences of the new tests.
rg --type python 'class SingleVoteTests'

Length of output: 73


Script:

#!/bin/bash
# Description: Verify the new tests in the `SingleVoteTests` class.

# Test: Search for the `SingleVoteTests` class. Expect: Occurrences of the new tests.
rg 'class SingleVoteTests' --glob '*.py'

Length of output: 99


Script:

#!/bin/bash
# Description: Verify the test methods in the `SingleVoteTests` class.

# Test: Search for the test methods within the `SingleVoteTests` class.
ast-grep --lang python --pattern $'class SingleVoteTests(TestCase):\n    def $_(self):\n        $$$' 

Length of output: 7039

Tools
GitHub Check: Trunk Check

[notice] 647-647: bandit(B106)
[new] Possible hardcoded password: 'testpassword'

approval_polls/views.py (2)

Line range hint 155-164:
LGTM!

The get_polls function correctly enhances functionality by enabling users to retrieve polls associated with specific tags.


257-268: LGTM! But verify the new function.

The delete_poll function correctly handles poll deletion with enhanced logging and error handling, ensuring that only the owner or a staff member can delete a poll.

Ensure that the new function is used correctly in the codebase.

Verification successful

The delete_poll function is correctly integrated and used in the codebase.

  • approval_polls/urls.py: The function is mapped to a URL endpoint.
  • approval_polls/templates/my_info.html: The function is used in a form action.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the `delete_poll` function in the codebase.

# Test: Search for the `delete_poll` function usage. Expect: Occurrences of the function usage.
rg --type python 'delete_poll'

Length of output: 61


Script:

#!/bin/bash
# Description: Verify the usage of the `delete_poll` function in the codebase.

# Test: Search for the `delete_poll` function usage. Expect: Occurrences of the function usage.
rg 'delete_poll'

Length of output: 285

@fsargent fsargent force-pushed the 07-23-improve_and_verify_poll_pages branch from e0a7572 to 657f4b5 Compare July 24, 2024 19:43
Copy link

@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: 5

Outside diff range, codebase verification and nitpick comments (1)
approval_polls/views.py (1)

Ensure all calls to get_polls include the new tag parameter.

The following calls to get_polls do not include the tag parameter:

  • approval_polls/views.py: return get_polls(request, poll_list, "index.html")
  • approval_polls/views.py: return get_polls(request, poll_list, "my_polls.html")

Please update these calls to include the tag parameter to match the new function signature.

Analysis chain

Line range hint 155-164:
LGTM! But verify the function usage in the codebase.

The code changes are approved.

However, ensure that all function calls to get_polls match the new signature.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `get_polls` match the new signature.

# Test: Search for the function usage. Expect: Only occurances of the new signature.
rg --type python -A 5 $'get_polls'

Length of output: 64


Script:

#!/bin/bash
# Description: Verify all function calls to `get_polls` match the new signature.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type py -A 5 $'get_polls'

Length of output: 1252

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e0a7572 and 657f4b5.

Files ignored due to path filters (1)
  • pyproject.toml is excluded by !**/*.toml
Files selected for processing (14)
  • .trunk/configs/.bandit (1 hunks)
  • approval_polls/settings.py (5 hunks)
  • approval_polls/staticfiles/create.js (1 hunks)
  • approval_polls/staticfiles/detail.js (1 hunks)
  • approval_polls/staticfiles/my_polls.js (1 hunks)
  • approval_polls/templates/base.html (2 hunks)
  • approval_polls/templates/create.html (1 hunks)
  • approval_polls/templates/detail.html (1 hunks)
  • approval_polls/templates/index.html (3 hunks)
  • approval_polls/templates/my_info.html (2 hunks)
  • approval_polls/templates/my_polls.html (1 hunks)
  • approval_polls/tests.py (6 hunks)
  • approval_polls/urls.py (1 hunks)
  • approval_polls/views.py (6 hunks)
Files skipped from review due to trivial changes (3)
  • .trunk/configs/.bandit
  • approval_polls/templates/base.html
  • approval_polls/templates/my_polls.html
Files skipped from review as they are similar to previous changes (7)
  • approval_polls/settings.py
  • approval_polls/staticfiles/create.js
  • approval_polls/staticfiles/my_polls.js
  • approval_polls/templates/create.html
  • approval_polls/templates/index.html
  • approval_polls/templates/my_info.html
  • approval_polls/urls.py
Additional comments not posted (18)
approval_polls/staticfiles/detail.js (5)

2-7: LGTM!

The initialization of the social sharing functionality and the setup of poll options are clear and correct.


9-16: LGTM!

The setup of the pollOptions object and the initialization of the lastId variable are clear and correct.


18-35: LGTM!

The addChoiceField function is well-structured and effectively uses template literals for HTML generation.


79-93: LGTM!

The event handlers for removing and canceling link inputs are correctly set up.


61-77: Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function validateUrl(url) {
+  const validateUrl = (url) => {

Likely invalid or redundant comment.

approval_polls/templates/detail.html (10)

1-5: LGTM!

The code correctly extends the base template, loads static files, and includes the detail.js script.


7-13: LGTM!

The HTML structure is well-organized, and the use of Bootstrap classes enhances readability and maintainability. The error message display is correctly implemented.


14-27: LGTM!

The form is well-structured, and the use of Bootstrap classes enhances readability and maintainability. The association of labels with inputs using the for attribute improves accessibility.


29-47: LGTM!

The conditional rendering logic is correctly implemented, and the use of Bootstrap classes enhances readability and maintainability. The handling of email invitations and authorization messages is appropriate.


50-65: LGTM!

The conditional rendering logic is correctly implemented, and the use of Bootstrap classes enhances readability and maintainability. The handling of poll status messages and email opt-in is appropriate.


66-80: LGTM!

The submit button is correctly implemented, and the use of Bootstrap classes enhances readability and maintainability. The conditional rendering logic is appropriate.


83-91: LGTM!

The card footer is well-structured, and the use of Bootstrap classes enhances readability and maintainability. The conditional rendering logic for tags is appropriate.


93-99: LGTM!

The conditional rendering logic is correctly implemented, and the use of Bootstrap classes enhances readability and maintainability. The handling of the poll close date and countdown timer is appropriate.


100-105: LGTM!

The footer information is well-structured, and the use of Bootstrap classes enhances readability and maintainability. The button to see results is appropriately implemented.


109-109: LGTM!

The code correctly ends the content block.

approval_polls/tests.py (2)

Line range hint 1-13: LGTM!

The imports are appropriate, and the utility functions are well-structured and useful for converting querysets and pages to lists of string representations.


Line range hint 15-34: LGTM!

The create_poll function is well-structured and correctly creates a poll with the given question and user details. The creation of ballots is appropriately handled.

approval_polls/views.py (1)

257-268: LGTM!

The delete_poll function is well-implemented with enhanced logging and error handling.

Comment on lines +37 to +47
pollOptions.addButton.on("click", addChoiceField);

// Link handling
pollOptions.container.on("click", ".add-link", function (e) {
e.preventDefault();
const choiceId = $(this)
.closest(".form-check")
.find('input[type="checkbox"]')
.attr("id");
const alertDiv = createAlertDiv(choiceId);
$(this).closest(".form-check").before(alertDiv);
Copy link

Choose a reason for hiding this comment

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

Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function createAlertDiv(choiceId) {
+  const createAlertDiv = (choiceId) => {

Committable suggestion was skipped due to low confidence.

Comment on lines +101 to +123
// Countdown timer
const timeDifference = $("#time_difference").val();
if (timeDifference) {
startCountdown(Math.ceil(timeDifference));
}

function startCountdown(duration) {
const timer = $("#timer");
const message = "before poll closes";

function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);

if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}, 1000);
};

onZero = function () {
window.location.reload();
};

time_difference =
document.getElementById("time_difference") &&
document.getElementById("time_difference").value;
}

$("#timer").countdown(onZero, Math.ceil(time_difference));
updateTimer();
const interval = setInterval(updateTimer, 1000);
}
Copy link

Choose a reason for hiding this comment

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

Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function startCountdown(duration) {
+  const startCountdown = (duration) => {
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
// Countdown timer
const timeDifference = $("#time_difference").val();
if (timeDifference) {
startCountdown(Math.ceil(timeDifference));
}
function startCountdown(duration) {
const timer = $("#timer");
const message = "before poll closes";
function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);
if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}, 1000);
};
onZero = function () {
window.location.reload();
};
time_difference =
document.getElementById("time_difference") &&
document.getElementById("time_difference").value;
}
$("#timer").countdown(onZero, Math.ceil(time_difference));
updateTimer();
const interval = setInterval(updateTimer, 1000);
}
// Countdown timer
const timeDifference = $("#time_difference").val();
if (timeDifference) {
startCountdown(Math.ceil(timeDifference));
}
const startCountdown = (duration) => {
const timer = $("#timer");
const message = "before poll closes";
function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);
if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}
updateTimer();
const interval = setInterval(updateTimer, 1000);
}

Comment on lines +95 to +99
function validateUrl(url) {
const pattern =
/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
return pattern.test(url);
}
Copy link

Choose a reason for hiding this comment

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

Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function validateUrl(url) {
+  const validateUrl = (url) => {
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
function validateUrl(url) {
const pattern =
/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
return pattern.test(url);
}
const validateUrl = (url) => {
const pattern =
/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
return pattern.test(url);
}

@fsargent fsargent force-pushed the 07-23-improve_and_verify_poll_pages branch from 657f4b5 to c971cfe Compare July 25, 2024 17:29
Copy link

@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: 4

Outside diff range, codebase verification and nitpick comments (14)
approval_polls/templates/create.html (12)

14-14: Improve accessibility with a descriptive heading.

The heading "Create a Poll" is clear, but consider adding an aria-label for improved accessibility.

- <h1 class="mb-4">Create a Poll</h1>
+ <h1 class="mb-4" aria-label="Create a Poll">Create a Poll</h1>

21-21: Improve accessibility with a for attribute.

The label for the poll question input should have a for attribute that matches the input's id for better accessibility.

- <label for="question" class="form-label">Enter your poll question:</label>
+ <label for="question" class="form-label" for="question">Enter your poll question:</label>

28-28: Improve validation feedback accessibility.

The validation feedback for the poll question should be associated with the input field using aria-describedby for better accessibility.

- {% if question_error %}<div class="invalid-feedback">{{ question_error }}</div>{% endif %}
+ {% if question_error %}<div id="questionError" class="invalid-feedback">{{ question_error }}</div>{% endif %}
+ <input type="text" class="form-control {% if question_error %}is-invalid{% endif %}" id="question" name="question" value="{{ question }}" placeholder="Who do you approve of?" aria-describedby="questionError">

48-48: Improve validation feedback accessibility for poll options.

The validation feedback for poll options should be associated with the input field using aria-describedby for better accessibility.

- {% if i == 1 and choice_error %}<div class="invalid-feedback">{{ choice_error }}</div>{% endif %}
+ {% if i == 1 and choice_error %}<div id="choiceError{{ i }}" class="invalid-feedback">{{ choice_error }}</div>{% endif %}
+ <input type="text" class="form-control {% if i == 1 and choice_error %}is-invalid{% endif %}" id="choice{{ i }}" name="choice{{ i }}" maxlength="100" placeholder="Option Name" aria-describedby="choiceError{{ i }}">

52-54: Ensure accessibility for the "Add Option" button.

The "Add Option" button should have an aria-label for better accessibility.

- <button type="button" class="btn btn-outline-primary" id="add-choice">
+ <button type="button" class="btn btn-outline-primary" id="add-choice" aria-label="Add Option">

65-71: Ensure accessibility for radio buttons.

The radio buttons for voting eligibility should have aria-labels for better accessibility.

- <input class="form-check-input" type="radio" name="radio-poll-type" id="anyoneVote" value="1" checked>
+ <input class="form-check-input" type="radio" name="radio-poll-type" id="anyoneVote" value="1" checked aria-label="Anyone (No restriction on the number of ballots per user)">

75-81: Ensure accessibility for radio buttons.

The radio buttons for voting eligibility should have aria-labels for better accessibility.

- <input class="form-check-input" type="radio" name="radio-poll-type" id="registeredVote" value="2">
+ <input class="form-check-input" type="radio" name="radio-poll-type" id="registeredVote" value="2" aria-label="Only registered users (One ballot per user, requires login)">

86-91: Ensure accessibility for the checkbox.

The checkbox for poll visibility should have an aria-label for better accessibility.

- <input class="form-check-input" type="checkbox" id="pollVisibility" name="public-poll-visibility" checked>
+ <input class="form-check-input" type="checkbox" id="pollVisibility" name="public-poll-visibility" checked aria-label="List this poll on the home page">

97-101: Ensure accessibility for the checkbox.

The checkbox for the write-in option should have an aria-label for better accessibility.

- <input class="form-check-input" type="checkbox" id="showWriteIn" name="show-write-in">
+ <input class="form-check-input" type="checkbox" id="showWriteIn" name="show-write-in" aria-label="Permit Write-in option">

105-109: Ensure accessibility for the checkbox.

The checkbox for showing the leading option in a different color should have an aria-label for better accessibility.

- <input class="form-check-input" type="checkbox" id="showLeadColor" name="show-lead-color" checked>
+ <input class="form-check-input" type="checkbox" id="showLeadColor" name="show-lead-color" checked aria-label="Show Leading option in different color">

113-115: Ensure accessibility for the checkbox.

The checkbox for email opt-in should have an aria-label for better accessibility.

- <input class="form-check-input" type="checkbox" id="showEmailOptIn" name="show-email-opt-in">
+ <input class="form-check-input" type="checkbox" id="showEmailOptIn" name="show-email-opt-in" aria-label="Display option to opt-in for email communication">

120-125: Ensure accessibility for the input field.

The input field for tags should have an aria-label for better accessibility.

- <input type="text" class="form-control" id="tokenTagField" name="token-tags" placeholder="Enter keywords">
+ <input type="text" class="form-control" id="tokenTagField" name="token-tags" placeholder="Enter keywords" aria-label="Enter keywords (comma-separated)">
approval_polls/tests.py (1)

632-632: Remove debug print statements.

Remove any debug print statements from the test code to maintain a clean test suite.

- print(response.content)
approval_polls/views.py (1)

Line range hint 155-164: Enhance error handling in get_polls function.

The get_polls function should include error handling for potential issues with pagination.

def get_polls(request, poll_list, render_page, tag: str = ""):
    paginator = Paginator(poll_list, 5)
    page = request.GET.get("page")
    try:
        polls = paginator.page(page)
    except PageNotAnInteger:
        polls = paginator.page(1)
    except EmptyPage:
        polls = paginator.page(paginator.num_pages)
    except Exception as e:
        logger.error(f"Error in pagination: {str(e)}")
        return HttpResponseServerError(f"An error occurred: {str(e)}")
    return render(request, render_page, {"latest_poll_list": polls, "tag": tag})
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 657f4b5 and c971cfe.

Files ignored due to path filters (1)
  • pyproject.toml is excluded by !**/*.toml
Files selected for processing (15)
  • .github/workflows/django.yml (1 hunks)
  • .trunk/configs/.bandit (1 hunks)
  • approval_polls/settings.py (5 hunks)
  • approval_polls/staticfiles/create.js (1 hunks)
  • approval_polls/staticfiles/detail.js (1 hunks)
  • approval_polls/staticfiles/my_polls.js (1 hunks)
  • approval_polls/templates/base.html (2 hunks)
  • approval_polls/templates/create.html (1 hunks)
  • approval_polls/templates/detail.html (1 hunks)
  • approval_polls/templates/index.html (3 hunks)
  • approval_polls/templates/my_info.html (2 hunks)
  • approval_polls/templates/my_polls.html (1 hunks)
  • approval_polls/tests.py (6 hunks)
  • approval_polls/urls.py (1 hunks)
  • approval_polls/views.py (6 hunks)
Files skipped from review due to trivial changes (1)
  • approval_polls/templates/base.html
Files skipped from review as they are similar to previous changes (8)
  • .trunk/configs/.bandit
  • approval_polls/settings.py
  • approval_polls/staticfiles/create.js
  • approval_polls/templates/detail.html
  • approval_polls/templates/index.html
  • approval_polls/templates/my_info.html
  • approval_polls/templates/my_polls.html
  • approval_polls/urls.py
Additional comments not posted (28)
.github/workflows/django.yml (1)

30-31: Approved: Addition of static files compression step.

The addition of python manage.py compress before running tests is a good practice to ensure that static files are properly handled in a production-like environment.

approval_polls/staticfiles/my_polls.js (7)

2-5: Approved: Safe method check for CSRF protection.

The csrfSafeMethod function correctly identifies safe HTTP methods that do not require CSRF protection.


6-6: Approved: Transition to button for delete action.

Using buttons for delete actions improves accessibility and user interaction.


25-26: Approved: Conditional check for existing alert.

The conditional check ensures that duplicate alerts are not created.


29-35: Approved: Event handlers for confirm and cancel actions.

The event handlers for confirm and cancel actions are correctly set up.


38-38: Approved: CSRF token retrieval.

Retrieving the CSRF token from the DOM is a good practice for secure AJAX requests.


39-57: Approved: AJAX request for poll deletion.

The AJAX request is correctly set up to handle poll deletion with proper CSRF token management and success/error callbacks.


60-61: Approved: Simplified cancel action.

The cancelAction function correctly removes the alert without additional processing.

approval_polls/staticfiles/detail.js (10)

2-8: Approved: Social sharing setup.

The social sharing setup with jsSocials is correctly implemented.


10-15: Approved: Poll options object.

The pollOptions object centralizes references to key DOM elements, enhancing clarity and reducing redundancy.


18-35: Approved: Addition of choice fields.

The addChoiceField function is correctly implemented to append new poll options efficiently.


37-37: Approved: Event handler for adding choice fields.

The event handler for adding choice fields is correctly set up.


39-47: Approved: Event handler for adding links.

The event handler for adding links is correctly set up, and the createAlertDiv function is used to generate alert boxes.


61-77: Approved: Event handler for confirming links.

The event handler for confirming links is correctly set up, including URL validation and user feedback.


79-88: Approved: Event handler for removing links.

The event handler for removing links is correctly set up.


90-93: Approved: Event handler for canceling link actions.

The event handler for canceling link actions is correctly set up.


101-106: Approved: Countdown timer initialization.

The countdown timer initialization is correctly set up.


95-99: Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function validateUrl(url) {
+  const validateUrl = (url) => {

Likely invalid or redundant comment.

approval_polls/templates/create.html (5)

4-7: Ensure CDN reliability.

The external stylesheet link to Bootstrap Tokenfield is updated to use a CDN. Ensure that the CDN is reliable and consider adding a fallback mechanism in case the CDN is unavailable.


8-9: Ensure script integrity and availability.

The external script link to Bootstrap Tokenfield is updated to use a CDN. Ensure the CDN is reliable and consider adding a fallback mechanism. Additionally, ensure the integrity attribute is used to verify the script's integrity.


23-23: Ensure consistent validation feedback.

The class is-invalid is conditionally applied to the input field for validation feedback. Ensure that the validation logic is consistent and covers all possible error states.


33-33: Ensure unique id attributes for dynamically generated elements.

The id attributes for poll options are dynamically generated. Ensure that they are unique and do not conflict with other elements on the page.


37-37: Ensure consistent validation feedback for poll options.

The class is-invalid is conditionally applied to the input field for validation feedback. Ensure that the validation logic is consistent and covers all possible error states.

approval_polls/tests.py (2)

625-626: Update assertions to match expected tag case.

The assertions in test_poll_tag_exists have been updated to match the expected tag case. Ensure that this change aligns with the application's requirements for tag case consistency.


639-640: Update assertions to match expected tag case.

The assertions in test_poll_delete have been updated to match the expected tag case. Ensure that this change aligns with the application's requirements for tag case consistency.

approval_polls/views.py (3)

6-6: Ensure proper usage of the messages module.

The messages module from Django is imported. Ensure that it is used correctly in the delete_poll function for providing user feedback.


125-125: Ensure proper handling of tag filtering.

The get_polls function is updated to accept an extra parameter for filtering polls based on tags. Ensure that the tag filtering logic is correctly implemented and aligns with the application's requirements.


257-268: Ensure robust error handling and logging in delete_poll function.

The delete_poll function includes error handling and logging. Ensure that the error messages are informative and that the logging provides sufficient context for debugging.

Comment on lines +11 to +12
var pollId = $(target).attr("id").split("-").pop();
var alertDiv =
Copy link

Choose a reason for hiding this comment

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

Improve readability by using template literals for alert messages.

The alertDiv creation can be improved by using template literals for better readability.

-    var alertDiv =
-      "<div class='alert alert-danger' id='alert" +
-      pollId +
-      "'>" +
-      "<p>This poll will be permanently deleted. " +
-      "<button id='confirm-delete-" +
-      pollId +
-      "' type='button' class='btn btn-danger btn-xs'>Delete</button> " +
-      "<button id='cancel-delete-" +
-      pollId +
-      "' type='button' class='btn btn-primary btn-xs'>Cancel</button>" +
-      "</p></div>";
+    var alertDiv = `
+      <div class='alert alert-danger' id='alert${pollId}'>
+        <p>This poll will be permanently deleted. 
+          <button id='confirm-delete-${pollId}' type='button' class='btn btn-danger btn-xs'>Delete</button> 
+          <button id='cancel-delete-${pollId}' type='button' class='btn btn-primary btn-xs'>Cancel</button>
+        </p>
+      </div>`;
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
var pollId = $(target).attr("id").split("-").pop();
var alertDiv =
var pollId = $(target).attr("id").split("-").pop();
var alertDiv = `
<div class='alert alert-danger' id='alert${pollId}'>
<p>This poll will be permanently deleted.
<button id='confirm-delete-${pollId}' type='button' class='btn btn-danger btn-xs'>Delete</button>
<button id='cancel-delete-${pollId}' type='button' class='btn btn-primary btn-xs'>Cancel</button>
</p>
</div>`;

Comment on lines +125 to +135
function formatTime(totalSeconds) {
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor(((totalSeconds % 86400) % 3600) / 60);
const seconds = Math.floor(((totalSeconds % 86400) % 3600) % 60);
return `${days}d:${padZero(hours)}h:${padZero(minutes)}m:${padZero(seconds)}s`;
}

function padZero(num) {
return num.toString().padStart(2, "0");
}
Copy link

Choose a reason for hiding this comment

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

Convert function declarations to function expressions.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function formatTime(totalSeconds) {
+  const formatTime = (totalSeconds) => {
-  function padZero(num) {
+  const padZero = (num) => {
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
function formatTime(totalSeconds) {
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor(((totalSeconds % 86400) % 3600) / 60);
const seconds = Math.floor(((totalSeconds % 86400) % 3600) % 60);
return `${days}d:${padZero(hours)}h:${padZero(minutes)}m:${padZero(seconds)}s`;
}
function padZero(num) {
return num.toString().padStart(2, "0");
}
const formatTime = (totalSeconds) => {
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor(((totalSeconds % 86400) % 3600) / 60);
const seconds = Math.floor(((totalSeconds % 86400) % 3600) % 60);
return `${days}d:${padZero(hours)}h:${padZero(minutes)}m:${padZero(seconds)}s`;
}
const padZero = (num) => {
return num.toString().padStart(2, "0");
}

Comment on lines +107 to +119
function startCountdown(duration) {
const timer = $("#timer");
const message = "before poll closes";

function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);

if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}, 1000);
};

onZero = function () {
window.location.reload();
};

time_difference =
document.getElementById("time_difference") &&
document.getElementById("time_difference").value;
}
Copy link

Choose a reason for hiding this comment

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

Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function startCountdown(duration) {
+  const startCountdown = (duration) => {
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
function startCountdown(duration) {
const timer = $("#timer");
const message = "before poll closes";
function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);
if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}, 1000);
};
onZero = function () {
window.location.reload();
};
time_difference =
document.getElementById("time_difference") &&
document.getElementById("time_difference").value;
}
const startCountdown = (duration) => {
const timer = $("#timer");
const message = "before poll closes";
function updateTimer() {
const timeString = formatTime(duration);
timer.html(`${timeString} ${message}`);
if (--duration < 0) {
clearInterval(interval);
window.location.reload();
}
}

Comment on lines +50 to +59
function createAlertDiv(choiceId) {
return `
<div class="alert alert-info" id="alert-${choiceId}">
<input type="text" class="form-control mb-2" id="url-${choiceId}" placeholder="Link to URL">
<button id="confirm-link-${choiceId}" type="button" class="btn btn-success btn-sm me-2">Insert Link</button>
<button id="remove-link-${choiceId}" type="button" class="btn btn-danger btn-sm me-2">Reset Link</button>
<button id="cancel-link-${choiceId}" type="button" class="btn btn-secondary btn-sm">Cancel</button>
</div>
`;
}
Copy link

Choose a reason for hiding this comment

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

Convert function declaration to function expression.

Avoid function declarations inside blocks to prevent hoisting issues. Use function expressions instead.

-  function createAlertDiv(choiceId) {
+  const createAlertDiv = (choiceId) => {
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
function createAlertDiv(choiceId) {
return `
<div class="alert alert-info" id="alert-${choiceId}">
<input type="text" class="form-control mb-2" id="url-${choiceId}" placeholder="Link to URL">
<button id="confirm-link-${choiceId}" type="button" class="btn btn-success btn-sm me-2">Insert Link</button>
<button id="remove-link-${choiceId}" type="button" class="btn btn-danger btn-sm me-2">Reset Link</button>
<button id="cancel-link-${choiceId}" type="button" class="btn btn-secondary btn-sm">Cancel</button>
</div>
`;
}
const createAlertDiv = (choiceId) => {
return `
<div class="alert alert-info" id="alert-${choiceId}">
<input type="text" class="form-control mb-2" id="url-${choiceId}" placeholder="Link to URL">
<button id="confirm-link-${choiceId}" type="button" class="btn btn-success btn-sm me-2">Insert Link</button>
<button id="remove-link-${choiceId}" type="button" class="btn btn-danger btn-sm me-2">Reset Link</button>
<button id="cancel-link-${choiceId}" type="button" class="btn btn-secondary btn-sm">Cancel</button>
</div>
`;
}

@fsargent fsargent merged commit f4ef6b0 into main Jul 25, 2024
3 checks passed
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.

1 participant