8000 add banner cmpt in new pages by mrfinch · Pull Request #8024 · codecombat/codecombat · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

add banner cmpt in new pages #8024

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

Merged
merged 2 commits into from
Jun 27, 2025
Merged

add banner cmpt in new pages #8024

merged 2 commits into from
Jun 27, 2025

Conversation

mrfinch
Copy link
Contributor
@mrfinch mrfinch commented Jun 26, 2025

fixes eng-1881

Screenshot 2025-06-26 at 3 00 33 PM

Summary by CodeRabbit

  • New Features
    • Introduced a site-wide banner that displays dynamic, localized content at the top of the Home and Schools pages.
    • Banner supports Markdown formatting and safe HTML rendering for enhanced content presentation.

Copy link
Contributor
coderabbitai bot commented Jun 26, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

A new BannerComponent Vue component was created to fetch and display banner content from a backend endpoint, processing and rendering it securely. This component was then integrated at the top of both the home and schools page views, with necessary imports and registrations added to those files. Additionally, the PageSchools component name was corrected.

Changes

File(s) Change Summary
app/components/common/elements/BannerComponent.vue Added new Vue component that fetches, processes, and displays banner content with safe HTML rendering.
app/views/home/PageHome.vue, app/views/schools/PageSchools.vue Imported, registered, and rendered the new BannerComponent at the top of each page's main container.
app/views/schools/PageSchools.vue Fixed component name from 'PageHome' to 'PageSchools'.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant BannerComponent
    participant Backend

    User->>BannerComponent: Loads page (Home/Schools)
    BannerComponent->>Backend: GET /db/banner
    Backend-->>BannerComponent: Returns banner content (Markdown)
    BannerComponent->>BannerComponent: Localize and process content (Markdown→HTML, sanitize)
    BannerComponent-->>User: Renders banner HTML at top of page
Loading

Possibly related PRs

Suggested reviewers

  • smallst

Poem

A banner now graces the top of the view,
With messages fresh, and styling brand new.
Markdown or HTML, all safely displayed,
On Home and on Schools, this feature has stayed.
Hopping with joy, the code rabbits cheer—
A purple surprise for all to revere!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE package: 'treema@0.0.0',
npm warn EBADENGINE required: { node: '0.8.x' },
npm warn EBADENGINE current: { node: 'v24.3.0', npm: '11.4.2' }
npm warn EBADENGINE }
npm warn skipping integrity check for git dependency ssh://git@github.com/codecombat/treema.git
npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-27T07_33_25_516Z-debug-0.log


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b6bf61e and fb44f93.

📒 Files selected for processing (1)
  • app/views/schools/PageSchools.vue (3 hunks)

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
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in 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.

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 (2)
app/views/home/PageHome.vue (2)

84-88: Fix invalid nested h2 elements

Nested h2 elements create invalid HTML structure and can cause accessibility and SEO issues.

-      <h2 class="text-h2">
-        <h2 class="text-h2">
-          {{ $t('home_v3.programming_languages') }}
-        </h2>
-      </h2>
+      <h2 class="text-h2">
+        {{ $t('home_v3.programming_languages') }}
+      </h2>

193-201: Fix another instance of invalid nested h2 elements

Another occurrence of nested h2 elements that needs to be corrected.

-          <h2 class="text-h2">
-            <h2 class="text-h2">
-              <mixed-color-label
-                :text="$t('home_v3.faq_visit_help_center')"
-                link="https://codecombat.zendesk.com/hc/en-us"
-                target="_blank"
-              />
-            </h2>
-          </h2>
+          <h2 class="text-h2">
+            <mixed-color-label
+              :text="$t('home_v3.faq_visit_help_center')"
+              link="https://codecombat.zendesk.com/hc/en-us"
+              target="_blank"
+            />
+          </h2>
🧹 Nitpick comments (3)
app/components/common/elements/BannerComponent.vue (3)

31-31: Consider adding request timeout and better error context

The API request lacks timeout configuration and error handling doesn't provide context about what failed.

-        const data = await fetchJson('/db/banner', { data: { cacheEdge: true } })
+        const data = await fetchJson('/db/banner', { 
+          data: { cacheEdge: true },
+          timeout: 5000 
+        })

42-44: Improve error handling with logging

Silent failure makes debugging difficult. Consider logging errors while still providing graceful degradation.

       } catch (e) {
+        console.warn('Failed to fetch banner content:', e)
         this.bannerHtml = ''
       }

50-51: Document CSS scoping decision and potential conflicts

The unscoped styles could lead to conflicts with existing application styles, especially with generic class names like .content.

Consider using more specific class names or CSS modules to avoid conflicts:

   .content {
+  &.banner-content {
     display: inline-block;
     max-width: 900px;
     // ... rest of styles
+  }
   }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 984c2c9 and b6bf61e.

📒 Files selected for processing (3)
  • app/components/common/elements/BannerComponent.vue (1 hunks)
  • app/views/home/PageHome.vue (3 hunks)
  • app/views/schools/PageSchools.vue (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Node.js CI (20.19.2)
🔇 Additional comments (2)
app/views/schools/PageSchools.vue (1)

3-3: Clean integration of BannerComponent

The banner component is properly imported, registered, and placed at the top of the page layout. The implementation follows Vue best practices.

Also applies to: 519-519, 542-542

app/views/home/PageHome.vue (1)

3-3: Proper integration of BannerComponent

The banner component is correctly imported, registered, and positioned at the top of the page layout, following consistent patterns with the schools page.

Also applies to: 241-241, 269-269

Comment on lines +89 to +91
.no-gap-banner {
margin-bottom: -80px !important;
}
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

Questionable CSS with magic number and layout impact

The negative margin of -80px with !important suggests a layout hack that could cause issues across different screen sizes and layouts.

Consider a more robust approach to spacing:

-.no-gap-banner {
-  margin-bottom: -80px !important;
-}
+.no-gap-banner {
+  margin-bottom: 0;
+}
+
+.no-gap-banner + * {
+  margin-top: 0;
+}
📝 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
.no-gap-banner {
margin-bottom: -80px !important;
}
.no-gap-banner {
margin-bottom: 0;
}
.no-gap-banner + * {
margin-top: 0;
}
🤖 Prompt for AI Agents
In app/components/common/elements/BannerComponent.vue around lines 89 to 91, the
CSS uses a negative margin of -80px with !important, which is a fragile layout
hack that may break on different screen sizes. Replace this magic number with a
more flexible spacing method such as using relative units (em, rem, %) or CSS
grid/flexbox gap properties to control spacing without relying on negative
margins or !important overrides.

Comment on lines +35 to +41
if (window.marked && window.DOMPurify) {
this.bannerHtml = window.DOMPurify.sanitize(window.marked(content || ''))
} else if (window.marked) {
this.bannerHtml = window.marked(content || '')
} else {
this.bannerHtml = content || ''
}
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

Critical security vulnerability: Unsanitized HTML rendering

When only window.marked is available without window.DOMPurify, the markdown is converted to HTML but not sanitized before rendering via v-html. This creates an XSS vulnerability where malicious content from the /db/banner endpoint could execute arbitrary JavaScript.

Apply this fix to ensure content is always sanitized or falls back to plain text:

-        if (window.marked && window.DOMPurify) {
-          this.bannerHtml = window.DOMPurify.sanitize(window.marked(content || ''))
-        } else if (window.marked) {
-          this.bannerHtml = window.marked(content || '')
-        } else {
-          this.bannerHtml = content || ''
-        }
+        if (window.marked && window.DOMPurify) {
+          this.bannerHtml = window.DOMPurify.sanitize(window.marked(content || ''))
+        } else {
+          // Only use plain text if sanitization is not available
+          this.bannerHtml = content || ''
+        }
📝 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
if (window.marked && window.DOMPurify) {
this.bannerHtml = window.DOMPurify.sanitize(window.marked(content || ''))
} else if (window.marked) {
this.bannerHtml = window.marked(content || '')
} else {
this.bannerHtml = content || ''
}
if (window.marked && window.DOMPurify) {
this.bannerHtml = window.DOMPurify.sanitize(window.marked(content || ''))
} else {
// Only use plain text if sanitization is not available
this.bannerHtml = content || ''
}
🤖 Prompt for AI Agents
In app/components/common/elements/BannerComponent.vue lines 35 to 41, the code
converts markdown to HTML using window.marked but only sanitizes it if
window.DOMPurify is available, leaving a security risk when DOMPurify is
missing. To fix this, ensure that the HTML output is always sanitized before
assigning to bannerHtml by either using DOMPurify if available or falling back
to rendering plain text without HTML. This prevents any unsanitized HTML from
being rendered and eliminates the XSS vulnerability.

@mrfinch mrfinch merged commit b338db8 into master Jun 27, 2025
1 of 2 checks passed
@mrfinch mrfinch deleted the saurabh/banner branch June 27, 2025 07:29
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
0