From 8c1ad49518cf5904b86c9b5ade6964902f753bc1 Mon Sep 17 00:00:00 2001 From: DPN MW Date: Sun, 8 Mar 2026 00:56:01 -0400 Subject: [PATCH] Compatibility with discourse admin Fixes towards admin settings. --- .../community-landing-admin-tabs.js | 70 +++++++- .../stylesheets/community_landing/admin.css | 161 +++++++++++++++++- .../stylesheets/community_landing/landing.css | 4 + config/locales/en.yml | 11 ++ config/settings.yml | 38 +++++ lib/community_landing/page_builder.rb | 46 +++-- 6 files changed, 311 insertions(+), 19 deletions(-) diff --git a/assets/javascripts/discourse/initializers/community-landing-admin-tabs.js b/assets/javascripts/discourse/initializers/community-landing-admin-tabs.js index 3970a17..2d528db 100644 --- a/assets/javascripts/discourse/initializers/community-landing-admin-tabs.js +++ b/assets/javascripts/discourse/initializers/community-landing-admin-tabs.js @@ -16,7 +16,9 @@ const TABS = [ id: "navbar", label: "Navbar", settings: new Set([ - "navbar_signin_label", "navbar_join_label", "navbar_bg_color", "navbar_border_style" + "navbar_signin_label", "navbar_signin_enabled", "navbar_signin_color", + "navbar_join_label", "navbar_join_enabled", "navbar_join_color", + "navbar_bg_color", "navbar_border_style" ]) }, { @@ -25,13 +27,14 @@ const TABS = [ settings: new Set([ "hero_title", "hero_subtitle", "hero_card_enabled", "hero_background_image_url", "hero_image_urls", "hero_image_max_height", - "hero_primary_button_label", "hero_primary_button_url", - "hero_secondary_button_label", "hero_secondary_button_url", + "hero_primary_button_enabled", "hero_primary_button_label", "hero_primary_button_url", + "hero_secondary_button_enabled", "hero_secondary_button_label", "hero_secondary_button_url", "hero_video_url", "hero_video_button_color", "hero_video_blur_on_hover", "hero_bg_dark", "hero_bg_light", "hero_min_height", "hero_border_style", "hero_card_bg_dark", "hero_card_bg_light", "hero_card_opacity", "contributors_enabled", "contributors_title", "contributors_title_enabled", "contributors_count_label", "contributors_count_label_enabled", + "contributors_alignment", "contributors_pill_max_width", "contributors_pill_bg_color", "contributors_days", "contributors_count" ]) }, @@ -62,7 +65,8 @@ const TABS = [ id: "topics", label: "Trending", settings: new Set([ - "topics_enabled", "topics_title", "topics_count", "topics_card_bg_color", + "topics_enabled", "topics_title_enabled", "topics_title", "topics_count", + "topics_card_bg_color", "topics_bg_dark", "topics_bg_light", "topics_min_height", "topics_border_style" ]) }, @@ -70,7 +74,8 @@ const TABS = [ id: "groups", label: "Spaces", settings: new Set([ - "groups_enabled", "groups_title", "groups_count", "groups_selected", "groups_card_bg_color", + "groups_enabled", "groups_title_enabled", "groups_title", "groups_count", + "groups_selected", "groups_card_bg_color", "groups_bg_dark", "groups_bg_light", "groups_min_height", "groups_border_style" ]) }, @@ -218,6 +223,55 @@ function wrapBgPairs() { }); } +/** + * Remove all injected tabs and restore clean state. + * Called when navigating away from the community-landing settings page. + */ +function cleanupTabs() { + // Remove injected
  • tabs from native nav + document.querySelectorAll("li.cl-admin-tab").forEach((li) => li.remove()); + + // Restore native Settings
  • — remove our hook class + const nativeItem = document.querySelector(".cl-native-settings-item"); + if (nativeItem) { + nativeItem.classList.remove("cl-native-settings-item", "active"); + } + + // Remove filter-active class from native nav + const nativeNav = document.querySelector(".d-nav-submenu__tabs"); + if (nativeNav) { + nativeNav.classList.remove("cl-filter-active"); + } + + // Remove standalone tab bar if present + const standaloneBar = document.querySelector(".cl-admin-tabs"); + if (standaloneBar) { + standaloneBar.remove(); + } + + // Unwrap bg-pair wrappers + document.querySelectorAll(".cl-bg-pair").forEach((wrapper) => { + const parent = wrapper.parentNode; + while (wrapper.firstChild) { + parent.insertBefore(wrapper.firstChild, wrapper); + } + wrapper.remove(); + }); + + // Remove cl-tabs-active from container and un-hide all settings + const container = getContainer(); + if (container) { + container.classList.remove("cl-tabs-active"); + container.querySelectorAll(".cl-tab-hidden").forEach((el) => { + el.classList.remove("cl-tab-hidden"); + }); + } + + // Reset state + currentTab = "settings"; + filterActive = false; +} + function buildTabsUI() { const container = getContainer(); if (!container) return false; @@ -366,6 +420,7 @@ export default { // Initial injection with retries let attempts = 0; const tryInject = () => { + if (!isActive) return; // Guard: user navigated away during retries if (buildTabsUI() || attempts > 15) return; attempts++; setTimeout(tryInject, 200); @@ -387,7 +442,10 @@ export default { }, 500); } } else { - // Left plugin settings page — clean up + // Left plugin settings page — clean up injected tabs + if (isActive) { + cleanupTabs(); + } isActive = false; if (recheckTimer) { clearInterval(recheckTimer); diff --git a/assets/stylesheets/community_landing/admin.css b/assets/stylesheets/community_landing/admin.css index c32f977..d3028c7 100644 --- a/assets/stylesheets/community_landing/admin.css +++ b/assets/stylesheets/community_landing/admin.css @@ -102,6 +102,20 @@ html.dark-scheme .cl-admin-tabs .cl-admin-tab:hover { flex: 1; min-width: 0; margin-bottom: 0 !important; + padding-bottom: 10px !important; +} + +/* Inside bg-pairs, let the label and value stack vertically to fit the narrower space */ +.cl-bg-pair > .row.setting .setting-label { + float: none; + width: 100%; + margin-right: 0; +} + +.cl-bg-pair > .row.setting .setting-value { + float: none; + width: 100%; + padding-right: 0; } .cl-bg-pair.cl-tab-hidden { @@ -173,8 +187,149 @@ html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="c border-top-color: rgba(255, 255, 255, 0.12); } -/* ── Tab content spacing ── */ +/* ── Settings row distribution (match Discourse native layout) ── */ -.cl-tabs-active .row.setting[data-setting] { - margin-bottom: 16px; +.cl-tabs-active .row.setting { + padding-bottom: 20px; +} + +/* Clearfix without overflow:hidden (avoids clipping dropdowns/color pickers) */ +.cl-tabs-active .row.setting::after { + content: ""; + display: table; + clear: both; +} + +.cl-tabs-active .row.setting .setting-label { + float: left; + width: 17.6576%; + margin-right: 12px; +} + +.cl-tabs-active .row.setting .setting-label h3 { + font-size: var(--font-0); + font-weight: normal; +} + +.cl-tabs-active .row.setting .setting-label .history-icon { + opacity: 0; + transition: opacity 0.3s; + color: var(--primary-medium); +} + +.cl-tabs-active .row.setting .setting-label:hover .history-icon { + opacity: 1; +} + +.cl-tabs-active .row.setting .setting-value { + float: left; + width: 53%; + padding-right: 20px; +} + +.cl-tabs-active .row.setting .setting-value input[type="checkbox"], +.cl-tabs-active .row.setting .setting-value input[type="radio"] { + flex: 0 0 auto; +} + +.cl-tabs-active .row.setting .setting-value .select-kit { + width: 100% !important; +} + +.cl-tabs-active .row.setting .setting-value .category-selector { + width: 95%; +} + +.cl-tabs-active .row.setting .setting-value .input-setting-string, +.cl-tabs-active .row.setting .setting-value .input-setting-integer, +.cl-tabs-active .row.setting .setting-value .input-setting-textarea { + width: 100%; +} + +.cl-tabs-active .row.setting .setting-value .input-setting-textarea { + height: 150px; +} + +.cl-tabs-active .row.setting .setting-value .input-setting-list { + padding: 1px; + background-color: var(--secondary); + border: 1px solid var(--input-border-color); + border-radius: 3px; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +.cl-tabs-active .row.setting .setting-controls { + float: left; +} + +.cl-tabs-active .row.setting .desc, +.cl-tabs-active .row.setting .validation-error { + padding-top: 3px; + font-size: var(--font-down-1); + line-height: var(--line-height-large); +} + +.cl-tabs-active .row.setting .desc { + color: var(--primary-medium); +} + +.cl-tabs-active .row.setting .validation-error { + color: var(--danger); +} + +.cl-tabs-active .row.setting .setting-theme-warning { + font-size: var(--font-down-1); + color: var(--primary-medium); +} + +/* Overridden settings indicator (yellow dot) */ +.cl-tabs-active .row.setting.overridden .values input { + background-color: var(--highlight-bg); +} + +.cl-tabs-active .row.setting.overridden h3 { + position: relative; +} + +.cl-tabs-active .row.setting.overridden h3::before { + content: ""; + position: absolute; + top: 0.5rem; + left: -1rem; + width: 0.5rem; + height: 0.5rem; + border-radius: 100%; + background-color: var(--highlight-high); +} + +.cl-tabs-active .row.setting.overridden.string input[type="text"], +.cl-tabs-active .row.setting.overridden.string input[type="password"], +.cl-tabs-active .row.setting.overridden.string textarea { + background-color: var(--highlight-bg); +} + +@media (max-width: 767px) { + .cl-tabs-active .row.setting .setting-label { + float: none; + width: 100%; + margin-right: 0; + margin-left: 0; + } + + .cl-tabs-active .row.setting .setting-label h3 { + margin-bottom: 6px; + } + + .cl-tabs-active .row.setting .setting-value { + width: 100%; + padding-right: 0; + } + + .cl-tabs-active .row.setting .setting-value .input-setting-list { + width: 100%; + } + + .cl-tabs-active .row.setting .setting-value .select-kit { + width: 100% !important; + } } diff --git a/assets/stylesheets/community_landing/landing.css b/assets/stylesheets/community_landing/landing.css index 85f77a7..15d753d 100644 --- a/assets/stylesheets/community_landing/landing.css +++ b/assets/stylesheets/community_landing/landing.css @@ -884,6 +884,10 @@ margin-top: 2rem; } +.cl-hero__creators--left { + align-items: flex-start; +} + .cl-hero__creators-title { font-size: 0.85rem; font-weight: 700; diff --git a/config/locales/en.yml b/config/locales/en.yml index 3ad5f9d..44a4080 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -20,7 +20,11 @@ en: # ── 1. Navbar ── navbar_signin_label: "━━ ROW 1: NAVBAR ━━ — Fixed navigation bar at the top with logo, theme toggle, sign-in link, and join button. This setting controls the sign-in link text." + navbar_signin_enabled: "Show the sign-in link in the navbar." + navbar_signin_color: "Custom color for the sign-in link text and border. Leave blank for default." navbar_join_label: "Text for the join/register CTA button in the navbar." + navbar_join_enabled: "Show the join/register button in the navbar." + navbar_join_color: "Custom background color for the join button. Leave blank to use the accent color." navbar_bg_color: "Custom background color for the navbar when scrolled. Leave blank for the default frosted glass effect." navbar_border_style: "Border style at the bottom of the navbar when scrolled." @@ -31,8 +35,10 @@ en: hero_background_image_url: "Full-bleed background image behind the hero section. In card mode, fills the card with a dark overlay. In flat mode, covers the entire section." hero_image_urls: "Images displayed on the right side of the hero. Add up to 5 URLs — a random one is shown on each page load." hero_image_max_height: "Maximum height in pixels for the hero image (100–1200)." + hero_primary_button_enabled: "Show the primary CTA button in the hero section." hero_primary_button_label: "Text on the primary (filled, accent-colored) CTA button." hero_primary_button_url: "URL the primary button links to. Use a relative path like /latest or an absolute URL." + hero_secondary_button_enabled: "Show the secondary CTA button in the hero section." hero_secondary_button_label: "Text on the secondary (outlined) CTA button." hero_secondary_button_url: "URL the secondary button links to." hero_video_url: "URL for a hero video. Supports MP4 and YouTube links. A play button appears in the hero area; clicking opens a lightbox modal with the video." @@ -86,6 +92,7 @@ en: # ── 5. Trending Discussions ── topics_enabled: "━━ ROW 5: TRENDING ━━ — Show the Trending Discussions section: a horizontally scrollable row of topic cards showing the most active discussions. Each card displays category badge, title, reply count, and like count — all live data. Supports drag-to-scroll and native swipe." + topics_title_enabled: "Show the section heading above the trending topic cards." topics_title: "Heading text above the scrollable topic cards." topics_count: "Number of trending topic cards to display." topics_card_bg_color: "Background color for each trending topic card. Leave blank for default card styling." @@ -100,11 +107,15 @@ en: contributors_title_enabled: "Show the heading above the creators list." contributors_count_label: "Label shown before each creator's count (e.g. 'Cheers', 'Points'). Leave blank for no prefix." contributors_count_label_enabled: "Show the count label prefix before each creator's activity count." + contributors_alignment: "Horizontal alignment of the creators list: center or left." + contributors_pill_max_width: "Maximum width in pixels for each creator pill card (200–600)." + contributors_pill_bg_color: "Custom background color for creator pill cards. Leave blank for default glass card styling." contributors_days: "Lookback period in days for calculating top contributors." contributors_count: "Number of top contributors to fetch (top 3 are shown in the hero)." # ── 7. Community Spaces ── groups_enabled: "━━ ROW 7: SPACES ━━ — Show the Community Spaces section: a grid of colorful cards representing your public groups. Each card shows a colored icon (with group's first letter or flair), group name, and member count. Only public, non-automatic groups are shown." + groups_title_enabled: "Show the section heading above the group cards." groups_title: "Heading text above the group cards." groups_count: "Number of group cards to display." groups_selected: "Show only specific groups. Enter group names separated by pipes (e.g. designers|developers|artists). Leave blank to auto-select public groups." diff --git a/config/settings.yml b/config/settings.yml index dc577e1..20c4a08 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -77,9 +77,21 @@ plugins: navbar_signin_label: default: "Sign In" type: string + navbar_signin_enabled: + default: true + type: bool + navbar_signin_color: + default: "" + type: color navbar_join_label: default: "Get Started" type: string + navbar_join_enabled: + default: true + type: bool + navbar_join_color: + default: "" + type: color navbar_bg_color: default: "" type: color @@ -115,12 +127,18 @@ plugins: type: integer min: 100 max: 1200 + hero_primary_button_enabled: + default: true + type: bool hero_primary_button_label: default: "View Latest Topics" type: string hero_primary_button_url: default: "/latest" type: string + hero_secondary_button_enabled: + default: true + type: bool hero_secondary_button_label: default: "Explore Our Spaces" type: string @@ -303,6 +321,9 @@ plugins: topics_enabled: default: true type: bool + topics_title_enabled: + default: true + type: bool topics_title: default: "Trending Discussions" type: string @@ -350,6 +371,20 @@ plugins: contributors_count_label_enabled: default: true type: bool + contributors_alignment: + default: "center" + type: enum + choices: + - center + - left + contributors_pill_max_width: + default: 340 + type: integer + min: 200 + max: 600 + contributors_pill_bg_color: + default: "" + type: color contributors_days: default: 90 type: integer @@ -363,6 +398,9 @@ plugins: groups_enabled: default: true type: bool + groups_title_enabled: + default: true + type: bool groups_title: default: "Community Spaces" type: string diff --git a/lib/community_landing/page_builder.rb b/lib/community_landing/page_builder.rb index 1bdb685..1768934 100644 --- a/lib/community_landing/page_builder.rb +++ b/lib/community_landing/page_builder.rb @@ -100,10 +100,21 @@ module CommunityLanding end html << "\n" + signin_enabled = @s.navbar_signin_enabled rescue true + join_enabled = @s.navbar_join_enabled rescue true + signin_color = hex(@s.navbar_signin_color) rescue nil + join_color = hex(@s.navbar_join_color) rescue nil + html << "
    " html << theme_toggle - html << "#{e(signin_label)}\n" - html << "#{e(join_label)}\n" + if signin_enabled + signin_style = signin_color ? " style=\"color: #{signin_color}; border-color: #{signin_color}\"" : "" + html << "#{e(signin_label)}\n" + end + if join_enabled + join_style = join_color ? " style=\"background: #{join_color}; border-color: #{join_color}\"" : "" + html << "#{e(join_label)}\n" + end html << "
    " html << "\n" @@ -145,15 +156,19 @@ module CommunityLanding html << "

    #{e(@s.hero_subtitle)}

    \n" + primary_on = @s.hero_primary_button_enabled rescue true + secondary_on = @s.hero_secondary_button_enabled rescue true primary_label = @s.hero_primary_button_label.presence || "View Latest Topics" primary_url = @s.hero_primary_button_url.presence || "/latest" secondary_label = @s.hero_secondary_button_label.presence || "Explore Our Spaces" secondary_url = @s.hero_secondary_button_url.presence || login_url - html << "
    \n" - html << "#{e(primary_label)}\n" - html << "#{e(secondary_label)}\n" - html << "
    \n" + if primary_on || secondary_on + html << "
    \n" + html << "#{e(primary_label)}\n" if primary_on + html << "#{e(secondary_label)}\n" if secondary_on + html << "
    \n" + end # Hero creators (top 3 with gold/silver/bronze ranks) contributors = @data[:contributors] @@ -164,15 +179,22 @@ module CommunityLanding show_title = @s.contributors_title_enabled rescue true count_label = @s.contributors_count_label.presence || "" show_count_label = @s.contributors_count_label_enabled rescue true + alignment = @s.contributors_alignment rescue "center" + pill_max_w = @s.contributors_pill_max_width rescue 340 + pill_bg = hex(@s.contributors_pill_bg_color) rescue nil - html << "