- 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>
162 lines
6.3 KiB
Text
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>
|
|
}
|