weclome-banner/javascripts/discourse/components/welcome-banner.gjs
gabeszm c683bc82a9 Modernize to .gjs Glimmer component with renderInOutlet pattern
- Replace plugin outlet connectors with modern .gjs Glimmer component
- Use api.renderInOutlet() instead of connector templates (official pattern)
- Add service injection (@service router, @service site)
- Implement lifecycle hooks with didInsert/willDestroy modifiers
- Use native SearchMenu component integration
- Remove old connector directory structure
- Update CSS to target outlet wrapper classes
- Simplify API initializer to 10 lines (from 112 lines)
- Add route-based display logic with router service
- Direct settings access without this.theme wrapper

This follows the official discourse-search-banner implementation pattern.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:16:53 +02:00

162 lines
6.3 KiB
Text

import Component from "@glimmer/component";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import { on } from "@ember/modifier";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
import SearchMenu from "discourse/components/search-menu";
export default class WelcomeBanner extends Component {
@service router;
@service site;
get displayForRoute() {
const showOnPages = settings.show_on_pages || "homepage_only";
const currentRoute = this.router.currentRouteName;
if (showOnPages === "all_pages") {
return true;
}
// Show only on homepage
return currentRoute === "discovery.latest" || currentRoute === "discovery.categories";
}
get shouldDisplay() {
return settings.enable_welcome_banner && this.displayForRoute;
}
get isMobile() {
return this.site.mobileView;
}
didInsert() {
document.documentElement.classList.add("display-welcome-banner");
}
willDestroy() {
document.documentElement.classList.remove("display-welcome-banner");
}
openSearchMenu(event) {
event.preventDefault();
// Search menu will be handled by Discourse's native component
}
<template>
{{#if this.shouldDisplay}}
<section class={{concat settings.banner_position "-outlet"}} {{didInsert this.didInsert}} {{willDestroy this.willDestroy}}>
<div class="welcome-card">
<div class="hero-section">
<div class="hero-deco"></div>
<div class="hero-content">
<h2 class="hero-title">
{{htmlSafe settings.hero_title_html}}
</h2>
<div class="hero-description">
{{htmlSafe settings.hero_content_html}}
</div>
{{#if (and settings.enable_hero_search (not this.isMobile))}}
<div class="search-container" role="search">
<SearchMenu @searchInputId="welcome-banner-search" />
</div>
{{/if}}
</div>
</div>
<div class="cta-section">
<ul class="cta-list">
{{#if settings.cta_card_1_enabled}}
<li>
<a href={{settings.cta_card_1_url}} class="cta-card" aria-label={{settings.cta_card_1_title}}>
<div class="cta-icon">
{{#if (eq settings.cta_card_1_icon_type "font_awesome")}}
<i class="fas fa-{{settings.cta_card_1_icon_font_awesome}}"></i>
{{else}}
{{settings.cta_card_1_icon_emoji}}
{{/if}}
</div>
<div class="cta-content">
<span class="cta-title">{{settings.cta_card_1_title}}</span>
<span class="cta-desc">{{settings.cta_card_1_description}}</span>
<span class="cta-cta">
<i class="fas fa-angle-double-right"></i>
{{settings.cta_card_1_cta_text}}
</span>
</div>
</a>
</li>
{{/if}}
{{#if settings.cta_card_2_enabled}}
<li>
<a href={{settings.cta_card_2_url}} class="cta-card" aria-label={{settings.cta_card_2_title}}>
<div class="cta-icon">
{{#if (eq settings.cta_card_2_icon_type "font_awesome")}}
<i class="fas fa-{{settings.cta_card_2_icon_font_awesome}}"></i>
{{else}}
{{settings.cta_card_2_icon_emoji}}
{{/if}}
</div>
<div class="cta-content">
<span class="cta-title">{{settings.cta_card_2_title}}</span>
<span class="cta-desc">{{settings.cta_card_2_description}}</span>
<span class="cta-cta">
<i class="fas fa-angle-double-right"></i>
{{settings.cta_card_2_cta_text}}
</span>
</div>
</a>
</li>
{{/if}}
{{#if settings.cta_card_3_enabled}}
<li>
<a href={{settings.cta_card_3_url}} class="cta-card" aria-label={{settings.cta_card_3_title}}>
<div class="cta-icon">
{{#if (eq settings.cta_card_3_icon_type "font_awesome")}}
<i class="fas fa-{{settings.cta_card_3_icon_font_awesome}}"></i>
{{else}}
{{settings.cta_card_3_icon_emoji}}
{{/if}}
</div>
<div class="cta-content">
<span class="cta-title">{{settings.cta_card_3_title}}</span>
<span class="cta-desc">{{settings.cta_card_3_description}}</span>
<span class="cta-cta">
<i class="fas fa-angle-double-right"></i>
{{settings.cta_card_3_cta_text}}
</span>
</div>
</a>
</li>
{{/if}}
{{#if settings.cta_card_4_enabled}}
<li>
<a href={{settings.cta_card_4_url}} class="cta-card" aria-label={{settings.cta_card_4_title}}>
<div class="cta-icon">
{{#if (eq settings.cta_card_4_icon_type "font_awesome")}}
<i class="fas fa-{{settings.cta_card_4_icon_font_awesome}}"></i>
{{else}}
{{settings.cta_card_4_icon_emoji}}
{{/if}}
</div>
<div class="cta-content">
<span class="cta-title">{{settings.cta_card_4_title}}</span>
<span class="cta-desc">{{settings.cta_card_4_description}}</span>
<span class="cta-cta">
<i class="fas fa-angle-double-right"></i>
{{settings.cta_card_4_cta_text}}
</span>
</div>
</a>
</li>
{{/if}}
</ul>
</div>
</div>
</section>
{{/if}}
</template>
}