mirror of
https://github.com/dpnmw/community-landing.git
synced 2026-03-18 09:27:16 +00:00
Bug Fixes and UI Tweaks
This commit is contained in:
@@ -28,13 +28,16 @@ const TABS = [
|
|||||||
"hero_primary_button_label", "hero_primary_button_url",
|
"hero_primary_button_label", "hero_primary_button_url",
|
||||||
"hero_secondary_button_label", "hero_secondary_button_url",
|
"hero_secondary_button_label", "hero_secondary_button_url",
|
||||||
"hero_video_url", "hero_video_button_color", "hero_video_blur_on_hover",
|
"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_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_days", "contributors_count"
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "stats",
|
id: "stats",
|
||||||
label: "Stats",
|
label: "Stats",
|
||||||
settings: new Set([
|
settings: new Set([
|
||||||
|
"stats_enabled", "stat_labels_enabled",
|
||||||
"stats_title", "stat_icon_color", "stat_icon_bg_color", "stat_icon_shape", "stat_counter_color",
|
"stats_title", "stat_icon_color", "stat_icon_bg_color", "stat_icon_shape", "stat_counter_color",
|
||||||
"stat_members_label", "stat_topics_label", "stat_posts_label",
|
"stat_members_label", "stat_topics_label", "stat_posts_label",
|
||||||
"stat_likes_label", "stat_chats_label", "stat_round_numbers",
|
"stat_likes_label", "stat_chats_label", "stat_round_numbers",
|
||||||
@@ -60,14 +63,6 @@ const TABS = [
|
|||||||
"topics_bg_dark", "topics_bg_light", "topics_min_height", "topics_border_style"
|
"topics_bg_dark", "topics_bg_light", "topics_min_height", "topics_border_style"
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "contributors",
|
|
||||||
label: "Creators",
|
|
||||||
settings: new Set([
|
|
||||||
"contributors_enabled", "contributors_title", "contributors_days", "contributors_count",
|
|
||||||
"contributors_bg_dark", "contributors_bg_light", "contributors_min_height", "contributors_border_style"
|
|
||||||
])
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: "groups",
|
id: "groups",
|
||||||
label: "Spaces",
|
label: "Spaces",
|
||||||
@@ -99,6 +94,18 @@ const TABS = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Pairs of dark/light background settings to display side-by-side
|
||||||
|
const BG_PAIRS = [
|
||||||
|
["hero_bg_dark", "hero_bg_light"],
|
||||||
|
["hero_card_bg_dark", "hero_card_bg_light"],
|
||||||
|
["stats_bg_dark", "stats_bg_light"],
|
||||||
|
["about_bg_dark", "about_bg_light"],
|
||||||
|
["topics_bg_dark", "topics_bg_light"],
|
||||||
|
["groups_bg_dark", "groups_bg_light"],
|
||||||
|
["app_cta_bg_dark", "app_cta_bg_light"],
|
||||||
|
["footer_bg_dark", "footer_bg_light"],
|
||||||
|
];
|
||||||
|
|
||||||
let currentTab = "settings";
|
let currentTab = "settings";
|
||||||
let filterActive = false;
|
let filterActive = false;
|
||||||
let isActive = false;
|
let isActive = false;
|
||||||
@@ -126,6 +133,14 @@ function applyTabFilter() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Toggle visibility on bg-pair wrappers
|
||||||
|
container.querySelectorAll(".cl-bg-pair").forEach((pair) => {
|
||||||
|
const firstRow = pair.querySelector(".row.setting[data-setting]");
|
||||||
|
if (firstRow) {
|
||||||
|
pair.classList.toggle("cl-tab-hidden", firstRow.classList.contains("cl-tab-hidden"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Update filter-active dimming on whichever tab container exists
|
// Update filter-active dimming on whichever tab container exists
|
||||||
const nativeTabs = container.querySelector(".admin-plugin-config-area__tabs");
|
const nativeTabs = container.querySelector(".admin-plugin-config-area__tabs");
|
||||||
if (nativeTabs) {
|
if (nativeTabs) {
|
||||||
@@ -179,6 +194,25 @@ function handleTabClick(container, tabId) {
|
|||||||
applyTabFilter();
|
applyTabFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wrapBgPairs() {
|
||||||
|
const container = getContainer();
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
BG_PAIRS.forEach(([darkName, lightName]) => {
|
||||||
|
const darkRow = container.querySelector(`.row.setting[data-setting="${darkName}"]`);
|
||||||
|
const lightRow = container.querySelector(`.row.setting[data-setting="${lightName}"]`);
|
||||||
|
if (!darkRow || !lightRow) return;
|
||||||
|
// Skip if already wrapped
|
||||||
|
if (darkRow.parentElement && darkRow.parentElement.classList.contains("cl-bg-pair")) return;
|
||||||
|
|
||||||
|
const wrapper = document.createElement("div");
|
||||||
|
wrapper.className = "cl-bg-pair";
|
||||||
|
darkRow.parentNode.insertBefore(wrapper, darkRow);
|
||||||
|
wrapper.appendChild(darkRow);
|
||||||
|
wrapper.appendChild(lightRow);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function buildTabsUI() {
|
function buildTabsUI() {
|
||||||
const container = getContainer();
|
const container = getContainer();
|
||||||
if (!container) return false;
|
if (!container) return false;
|
||||||
@@ -229,6 +263,7 @@ function buildTabsUI() {
|
|||||||
|
|
||||||
nativeTabsEl.classList.add("cl-tabs-injected");
|
nativeTabsEl.classList.add("cl-tabs-injected");
|
||||||
container.classList.add("cl-tabs-active");
|
container.classList.add("cl-tabs-active");
|
||||||
|
wrapBgPairs();
|
||||||
applyTabFilter();
|
applyTabFilter();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -273,6 +308,7 @@ function buildTabsUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
container.classList.add("cl-tabs-active");
|
container.classList.add("cl-tabs-active");
|
||||||
|
wrapBgPairs();
|
||||||
applyTabFilter();
|
applyTabFilter();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* ═══════════════════════════════════════════════════════════════════
|
/* ═══════════════════════════════════════════════════════════════════
|
||||||
Community Landing — Admin Settings Panel Styles
|
Community Landing — Admin Settings Panel Styles
|
||||||
Tab navigation + fallback separators
|
Tab navigation + fallback separators + bg-pair layout
|
||||||
═══════════════════════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
/* ── Tab-hidden class (used instead of inline display:none) ── */
|
/* ── Tab-hidden class (used instead of inline display:none) ── */
|
||||||
@@ -123,6 +123,30 @@ html.dark-scheme .cl-admin-tabs .cl-admin-tab:hover {
|
|||||||
padding-top: 0 !important;
|
padding-top: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Dual-color background pairs (side-by-side dark/light) ── */
|
||||||
|
|
||||||
|
.cl-bg-pair {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cl-bg-pair > .row.setting {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cl-bg-pair.cl-tab-hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.cl-bg-pair {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Fallback: Separator borders when tabs are NOT active ──
|
/* ── Fallback: Separator borders when tabs are NOT active ──
|
||||||
(e.g. if JS fails to load or on older Discourse) */
|
(e.g. if JS fails to load or on older Discourse) */
|
||||||
|
|
||||||
@@ -155,10 +179,9 @@ html.dark-scheme .cl-admin-tabs .cl-admin-tab:hover {
|
|||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="scroll_animation"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="scroll_animation"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="navbar_signin_label"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="navbar_signin_label"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="hero_title"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="hero_title"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="stats_title"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="stats_enabled"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="about_enabled"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="about_enabled"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="topics_enabled"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="topics_enabled"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="contributors_enabled"],
|
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="groups_enabled"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="groups_enabled"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="show_app_ctas"],
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="show_app_ctas"],
|
||||||
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="footer_description"] {
|
.admin-detail:not(.cl-tabs-active) .row.setting[data-setting="footer_description"] {
|
||||||
@@ -173,10 +196,9 @@ html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="a
|
|||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="scroll_animation"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="scroll_animation"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="navbar_signin_label"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="navbar_signin_label"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="hero_title"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="hero_title"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="stats_title"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="stats_enabled"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="about_enabled"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="about_enabled"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="topics_enabled"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="topics_enabled"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="contributors_enabled"],
|
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="groups_enabled"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="groups_enabled"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="show_app_ctas"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="show_app_ctas"],
|
||||||
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="footer_description"],
|
html.dark-scheme .admin-detail:not(.cl-tabs-active) .row.setting[data-setting="footer_description"],
|
||||||
|
|||||||
@@ -602,6 +602,8 @@
|
|||||||
min-height: 80vh;
|
min-height: 80vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
@@ -692,34 +694,15 @@
|
|||||||
transition: opacity 0.6s ease;
|
transition: opacity 0.6s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Hero Background Image (flat mode) ── */
|
|
||||||
.cl-hero__bg {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
z-index: 0;
|
|
||||||
opacity: 0.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cl-hero__bg::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background: linear-gradient(to bottom, transparent 60%, var(--cl-bg));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Hero Card Mode ── */
|
/* ── Hero Card Mode ── */
|
||||||
.cl-hero--card .cl-hero__inner {
|
.cl-hero--card .cl-hero__inner {
|
||||||
background: var(--cl-card);
|
background: var(--cl-hero-card-bg, var(--cl-card));
|
||||||
border: 1px solid var(--cl-border);
|
border: 1px solid var(--cl-border);
|
||||||
border-radius: var(--cl-radius);
|
border-radius: var(--cl-radius);
|
||||||
padding: 3rem 2.5rem;
|
padding: 3rem 2.5rem;
|
||||||
backdrop-filter: var(--cl-blur);
|
backdrop-filter: var(--cl-blur);
|
||||||
-webkit-backdrop-filter: var(--cl-blur);
|
-webkit-backdrop-filter: var(--cl-blur);
|
||||||
box-shadow: 0 8px 32px var(--cl-shadow);
|
box-shadow: 0 8px 32px var(--cl-shadow);
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
@@ -892,10 +875,11 @@
|
|||||||
transition: filter 0.4s ease;
|
transition: filter 0.4s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Hero Creators (top 3 pills in hero) ── */
|
/* ── Hero Creators (top 3 ranked pills in hero) ── */
|
||||||
.cl-hero__creators {
|
.cl-hero__creators {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: nowrap;
|
||||||
|
justify-content: center;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
@@ -1224,18 +1208,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ═══════════════════════════════════════════════════════════════════
|
/* ═══════════════════════════════════════════════════════════════════
|
||||||
6. TOP CREATORS — pill badges
|
6. CREATOR PILLS — used in hero section
|
||||||
═══════════════════════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════════════════════ */
|
||||||
.cl-creators {
|
|
||||||
padding: 2.5rem 0 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cl-creators__list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cl-creator-pill {
|
.cl-creator-pill {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1245,29 +1219,48 @@
|
|||||||
border: 1px solid var(--cl-border);
|
border: 1px solid var(--cl-border);
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
position: relative;
|
||||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
backdrop-filter: var(--cl-blur);
|
backdrop-filter: var(--cl-blur);
|
||||||
-webkit-backdrop-filter: var(--cl-blur);
|
-webkit-backdrop-filter: var(--cl-blur);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cl-creator-pill:hover {
|
.cl-creator-pill:hover {
|
||||||
border-color: var(--cl-border-hover);
|
border-color: var(--rank-color, var(--cl-border-hover));
|
||||||
background: var(--cl-accent-subtle);
|
background: var(--cl-accent-subtle);
|
||||||
transform: translateY(-3px);
|
transform: translateY(-3px);
|
||||||
box-shadow: 0 8px 24px var(--cl-shadow);
|
box-shadow: 0 8px 24px var(--cl-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cl-creator-pill__rank {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
left: -6px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--rank-color);
|
||||||
|
color: #000;
|
||||||
|
font-size: 0.65rem;
|
||||||
|
font-weight: 900;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 2;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.cl-creator-pill__avatar {
|
.cl-creator-pill__avatar {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid var(--cl-border);
|
border: 2px solid var(--rank-color, var(--cl-border));
|
||||||
transition: border-color 0.3s ease;
|
transition: border-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cl-creator-pill:hover .cl-creator-pill__avatar {
|
.cl-creator-pill:hover .cl-creator-pill__avatar {
|
||||||
border-color: var(--cl-accent);
|
border-color: var(--rank-color, var(--cl-accent));
|
||||||
}
|
}
|
||||||
|
|
||||||
.cl-creator-pill__name {
|
.cl-creator-pill__name {
|
||||||
|
|||||||
@@ -42,9 +42,14 @@ en:
|
|||||||
hero_bg_light: "Background color for the hero section in light mode. Hex value. Leave blank for default."
|
hero_bg_light: "Background color for the hero section in light mode. Hex value. Leave blank for default."
|
||||||
hero_min_height: "Minimum height for the hero section in pixels. Set to 0 for auto height."
|
hero_min_height: "Minimum height for the hero section in pixels. Set to 0 for auto height."
|
||||||
hero_border_style: "Border style at the bottom of the hero section."
|
hero_border_style: "Border style at the bottom of the hero section."
|
||||||
|
hero_card_bg_dark: "Background color for the hero card overlay in dark mode. Only applies when hero card mode is enabled. Leave blank for default glass effect."
|
||||||
|
hero_card_bg_light: "Background color for the hero card overlay in light mode. Only applies when hero card mode is enabled. Leave blank for default glass effect."
|
||||||
|
hero_card_opacity: "Opacity of the hero card background (0 to 1, default 0.85). Lower values make the card more transparent, showing the background image through."
|
||||||
|
|
||||||
# ── 3. Stats Section ──
|
# ── 3. Stats Section ──
|
||||||
stats_title: "━━ ROW 3: PREMIUM STATS ━━ — Full-width row of live community statistics (members, topics, posts, likes, chats) with animated counters and icons. Each card shows icon + label on one line with the counter below. This is the section heading."
|
stats_enabled: "━━ ROW 3: PREMIUM STATS ━━ — Show or hide the entire stats section."
|
||||||
|
stat_labels_enabled: "Show text labels below stat counters (e.g. 'Members', 'Topics'). When off, only numbers and icons are displayed."
|
||||||
|
stats_title: "Section heading text above the stats row."
|
||||||
stat_icon_color: "Color for all stat counter icons. Hex value (e.g. #d4a24e)."
|
stat_icon_color: "Color for all stat counter icons. Hex value (e.g. #d4a24e)."
|
||||||
stat_icon_bg_color: "Background color behind each stat icon. Leave blank for a subtle accent tint."
|
stat_icon_bg_color: "Background color behind each stat icon. Leave blank for a subtle accent tint."
|
||||||
stat_icon_shape: "Shape of the icon background: circle or rounded square."
|
stat_icon_shape: "Shape of the icon background: circle or rounded square."
|
||||||
@@ -87,15 +92,10 @@ en:
|
|||||||
topics_min_height: "Minimum height for the trending section in pixels. Set to 0 for auto height."
|
topics_min_height: "Minimum height for the trending section in pixels. Set to 0 for auto height."
|
||||||
topics_border_style: "Border style at the bottom of the trending section."
|
topics_border_style: "Border style at the bottom of the trending section."
|
||||||
|
|
||||||
# ── 6. Top Creators ──
|
# ── 6. Hero Creators ──
|
||||||
contributors_enabled: "━━ ROW 6: CREATORS ━━ — Show the Top Creators section: pill-shaped badges showing your most active community members. Each pill displays avatar, @username, and post count from the lookback period."
|
contributors_enabled: "Show top 3 creators in the hero section with gold, silver, and bronze rank badges. Each pill displays avatar, @username, and post count."
|
||||||
contributors_title: "Heading text above the creator pills."
|
|
||||||
contributors_days: "Lookback period in days for calculating top contributors."
|
contributors_days: "Lookback period in days for calculating top contributors."
|
||||||
contributors_count: "Number of top contributor pills to display. Recommended: 6–12."
|
contributors_count: "Number of top contributors to fetch (top 3 are shown in the hero)."
|
||||||
contributors_bg_dark: "Background color for the creators section in dark mode. Leave blank for default."
|
|
||||||
contributors_bg_light: "Background color for the creators section in light mode. Leave blank for default."
|
|
||||||
contributors_min_height: "Minimum height for the creators section in pixels. Set to 0 for auto height."
|
|
||||||
contributors_border_style: "Border style at the bottom of the creators section."
|
|
||||||
|
|
||||||
# ── 7. Community Spaces ──
|
# ── 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_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."
|
||||||
|
|||||||
@@ -155,10 +155,25 @@ plugins:
|
|||||||
- solid
|
- solid
|
||||||
- dashed
|
- dashed
|
||||||
- dotted
|
- dotted
|
||||||
|
hero_card_bg_dark:
|
||||||
|
default: ""
|
||||||
|
type: color
|
||||||
|
hero_card_bg_light:
|
||||||
|
default: ""
|
||||||
|
type: color
|
||||||
|
hero_card_opacity:
|
||||||
|
default: "0.85"
|
||||||
|
type: string
|
||||||
|
|
||||||
# ══════════════════════════════════════════
|
# ══════════════════════════════════════════
|
||||||
# 3. Premium Stats Section
|
# 3. Premium Stats Section
|
||||||
# ══════════════════════════════════════════
|
# ══════════════════════════════════════════
|
||||||
|
stats_enabled:
|
||||||
|
default: true
|
||||||
|
type: bool
|
||||||
|
stat_labels_enabled:
|
||||||
|
default: true
|
||||||
|
type: bool
|
||||||
stats_title:
|
stats_title:
|
||||||
default: "Premium Stats"
|
default: "Premium Stats"
|
||||||
type: string
|
type: string
|
||||||
@@ -307,39 +322,17 @@ plugins:
|
|||||||
- dotted
|
- dotted
|
||||||
|
|
||||||
# ══════════════════════════════════════════
|
# ══════════════════════════════════════════
|
||||||
# 6. Top Creators Section
|
# 6. Hero Creators (Top 3 in Hero)
|
||||||
# ══════════════════════════════════════════
|
# ══════════════════════════════════════════
|
||||||
contributors_enabled:
|
contributors_enabled:
|
||||||
default: true
|
default: true
|
||||||
type: bool
|
type: bool
|
||||||
contributors_title:
|
|
||||||
default: "Top Creators"
|
|
||||||
type: string
|
|
||||||
contributors_days:
|
contributors_days:
|
||||||
default: 90
|
default: 90
|
||||||
type: integer
|
type: integer
|
||||||
contributors_count:
|
contributors_count:
|
||||||
default: 10
|
default: 10
|
||||||
type: integer
|
type: integer
|
||||||
contributors_bg_dark:
|
|
||||||
default: ""
|
|
||||||
type: color
|
|
||||||
contributors_bg_light:
|
|
||||||
default: ""
|
|
||||||
type: color
|
|
||||||
contributors_min_height:
|
|
||||||
default: 0
|
|
||||||
type: integer
|
|
||||||
min: 0
|
|
||||||
max: 2000
|
|
||||||
contributors_border_style:
|
|
||||||
default: "none"
|
|
||||||
type: enum
|
|
||||||
choices:
|
|
||||||
- none
|
|
||||||
- solid
|
|
||||||
- dashed
|
|
||||||
- dotted
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════
|
# ══════════════════════════════════════════
|
||||||
# 7. Community Spaces Section
|
# 7. Community Spaces Section
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ module CommunityLanding
|
|||||||
html << render_stats
|
html << render_stats
|
||||||
html << render_about
|
html << render_about
|
||||||
html << render_topics
|
html << render_topics
|
||||||
html << render_contributors
|
|
||||||
html << render_groups
|
html << render_groups
|
||||||
html << render_app_cta
|
html << render_app_cta
|
||||||
html << render_footer_desc
|
html << render_footer_desc
|
||||||
@@ -127,18 +126,15 @@ module CommunityLanding
|
|||||||
site_name = @s.title
|
site_name = @s.title
|
||||||
|
|
||||||
html = +""
|
html = +""
|
||||||
html << "<section class=\"cl-hero#{hero_card ? ' cl-hero--card' : ''}\" id=\"cl-hero\"#{section_style(hero_border, hero_min_h)}>\n"
|
# Build hero section style: bg image on the section itself + border/min-height
|
||||||
|
hero_style_parts = []
|
||||||
|
hero_style_parts << "background-image: url('#{hero_bg_img}');" if hero_bg_img
|
||||||
|
hero_style_parts << "border-bottom: 1px #{hero_border} var(--cl-border);" if hero_border.present? && hero_border != "none"
|
||||||
|
hero_style_parts << "min-height: #{hero_min_h}px;" if hero_min_h.to_i > 0
|
||||||
|
hero_attr = hero_style_parts.any? ? " style=\"#{hero_style_parts.join(' ')}\"" : ""
|
||||||
|
html << "<section class=\"cl-hero#{hero_card ? ' cl-hero--card' : ''}\" id=\"cl-hero\"#{hero_attr}>\n"
|
||||||
|
|
||||||
if hero_bg_img && !hero_card
|
html << "<div class=\"cl-hero__inner\">\n<div class=\"cl-hero__content\">\n"
|
||||||
html << "<div class=\"cl-hero__bg\" style=\"background-image: url('#{hero_bg_img}');\"></div>\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
inner_style = ""
|
|
||||||
if hero_card && hero_bg_img
|
|
||||||
inner_style = " style=\"background-image: linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url('#{hero_bg_img}'); background-size: cover; background-position: center;\""
|
|
||||||
end
|
|
||||||
|
|
||||||
html << "<div class=\"cl-hero__inner\"#{inner_style}>\n<div class=\"cl-hero__content\">\n"
|
|
||||||
|
|
||||||
title_words = @s.hero_title.to_s.split(" ")
|
title_words = @s.hero_title.to_s.split(" ")
|
||||||
if title_words.length > 1
|
if title_words.length > 1
|
||||||
@@ -159,15 +155,18 @@ module CommunityLanding
|
|||||||
html << "<a href=\"#{secondary_url}\" class=\"cl-btn cl-btn--ghost cl-btn--lg\">#{e(secondary_label)}</a>\n"
|
html << "<a href=\"#{secondary_url}\" class=\"cl-btn cl-btn--ghost cl-btn--lg\">#{e(secondary_label)}</a>\n"
|
||||||
html << "</div>\n"
|
html << "</div>\n"
|
||||||
|
|
||||||
# Hero creators (top 3)
|
# Hero creators (top 3 with gold/silver/bronze ranks)
|
||||||
contributors = @data[:contributors]
|
contributors = @data[:contributors]
|
||||||
if (@s.contributors_enabled rescue false) && contributors&.any?
|
if (@s.contributors_enabled rescue false) && contributors&.any?
|
||||||
top3 = contributors.first(3)
|
top3 = contributors.first(3)
|
||||||
|
rank_colors = ["#FFD700", "#C0C0C0", "#CD7F32"]
|
||||||
html << "<div class=\"cl-hero__creators\">\n"
|
html << "<div class=\"cl-hero__creators\">\n"
|
||||||
top3.each do |user|
|
top3.each_with_index do |user, idx|
|
||||||
avatar_url = user.avatar_template.gsub("{size}", "120")
|
avatar_url = user.avatar_template.gsub("{size}", "120")
|
||||||
activity_count = user.attributes["post_count"].to_i rescue 0
|
activity_count = user.attributes["post_count"].to_i rescue 0
|
||||||
html << "<a href=\"#{login_url}\" class=\"cl-creator-pill\">\n"
|
rank_color = rank_colors[idx]
|
||||||
|
html << "<a href=\"#{login_url}\" class=\"cl-creator-pill cl-creator-pill--rank-#{idx + 1}\" style=\"--rank-color: #{rank_color}\">\n"
|
||||||
|
html << "<span class=\"cl-creator-pill__rank\">#{idx + 1}</span>\n"
|
||||||
html << "<img src=\"#{avatar_url}\" alt=\"#{e(user.username)}\" class=\"cl-creator-pill__avatar\" loading=\"lazy\">\n"
|
html << "<img src=\"#{avatar_url}\" alt=\"#{e(user.username)}\" class=\"cl-creator-pill__avatar\" loading=\"lazy\">\n"
|
||||||
html << "<span class=\"cl-creator-pill__name\">@#{e(user.username)}</span>\n"
|
html << "<span class=\"cl-creator-pill__name\">@#{e(user.username)}</span>\n"
|
||||||
html << "<span class=\"cl-creator-pill__count\">#{activity_count}</span>\n"
|
html << "<span class=\"cl-creator-pill__count\">#{activity_count}</span>\n"
|
||||||
@@ -214,22 +213,25 @@ module CommunityLanding
|
|||||||
# ── 3. STATS ──
|
# ── 3. STATS ──
|
||||||
|
|
||||||
def render_stats
|
def render_stats
|
||||||
|
return "" unless (@s.stats_enabled rescue true)
|
||||||
|
|
||||||
stats = @data[:stats]
|
stats = @data[:stats]
|
||||||
stats_title = @s.stats_title.presence || "Premium Stats"
|
stats_title = @s.stats_title.presence || "Premium Stats"
|
||||||
border = @s.stats_border_style rescue "none"
|
border = @s.stats_border_style rescue "none"
|
||||||
min_h = @s.stats_min_height rescue 0
|
min_h = @s.stats_min_height rescue 0
|
||||||
icon_shape = @s.stat_icon_shape rescue "circle"
|
icon_shape = @s.stat_icon_shape rescue "circle"
|
||||||
round_nums = @s.stat_round_numbers rescue false
|
round_nums = @s.stat_round_numbers rescue false
|
||||||
|
show_labels = @s.stat_labels_enabled rescue true
|
||||||
|
|
||||||
html = +""
|
html = +""
|
||||||
html << "<section class=\"cl-stats cl-anim\" id=\"cl-stats-row\"#{section_style(border, min_h)}><div class=\"cl-container\">\n"
|
html << "<section class=\"cl-stats cl-anim\" id=\"cl-stats-row\"#{section_style(border, min_h)}><div class=\"cl-container\">\n"
|
||||||
html << "<h2 class=\"cl-section-title\">#{e(stats_title)}</h2>\n"
|
html << "<h2 class=\"cl-section-title\">#{e(stats_title)}</h2>\n"
|
||||||
html << "<div class=\"cl-stats__grid\">\n"
|
html << "<div class=\"cl-stats__grid\">\n"
|
||||||
html << stat_card(Icons::STAT_MEMBERS_SVG, stats[:members], @s.stat_members_label, icon_shape, round_nums)
|
html << stat_card(Icons::STAT_MEMBERS_SVG, stats[:members], @s.stat_members_label, icon_shape, round_nums, show_labels)
|
||||||
html << stat_card(Icons::STAT_TOPICS_SVG, stats[:topics], @s.stat_topics_label, icon_shape, round_nums)
|
html << stat_card(Icons::STAT_TOPICS_SVG, stats[:topics], @s.stat_topics_label, icon_shape, round_nums, show_labels)
|
||||||
html << stat_card(Icons::STAT_POSTS_SVG, stats[:posts], @s.stat_posts_label, icon_shape, round_nums)
|
html << stat_card(Icons::STAT_POSTS_SVG, stats[:posts], @s.stat_posts_label, icon_shape, round_nums, show_labels)
|
||||||
html << stat_card(Icons::STAT_LIKES_SVG, stats[:likes], @s.stat_likes_label, icon_shape, round_nums)
|
html << stat_card(Icons::STAT_LIKES_SVG, stats[:likes], @s.stat_likes_label, icon_shape, round_nums, show_labels)
|
||||||
html << stat_card(Icons::STAT_CHATS_SVG, stats[:chats], @s.stat_chats_label, icon_shape, round_nums)
|
html << stat_card(Icons::STAT_CHATS_SVG, stats[:chats], @s.stat_chats_label, icon_shape, round_nums, show_labels)
|
||||||
html << "</div>\n</div></section>\n"
|
html << "</div>\n</div></section>\n"
|
||||||
html
|
html
|
||||||
end
|
end
|
||||||
@@ -309,35 +311,6 @@ module CommunityLanding
|
|||||||
html
|
html
|
||||||
end
|
end
|
||||||
|
|
||||||
# ── 6. TOP CREATORS ──
|
|
||||||
|
|
||||||
def render_contributors
|
|
||||||
contributors = @data[:contributors]
|
|
||||||
return "" unless @s.contributors_enabled && contributors&.any?
|
|
||||||
|
|
||||||
border = @s.contributors_border_style rescue "none"
|
|
||||||
min_h = @s.contributors_min_height rescue 0
|
|
||||||
|
|
||||||
html = +""
|
|
||||||
html << "<section class=\"cl-creators cl-anim\" id=\"cl-contributors\"#{section_style(border, min_h)}><div class=\"cl-container\">\n"
|
|
||||||
html << "<h2 class=\"cl-section-title\">#{e(@s.contributors_title)}</h2>\n"
|
|
||||||
html << "<div class=\"cl-creators__list\">\n"
|
|
||||||
|
|
||||||
contributors.each do |user|
|
|
||||||
avatar_url = user.avatar_template.gsub("{size}", "120")
|
|
||||||
activity_count = user.attributes["post_count"].to_i rescue 0
|
|
||||||
|
|
||||||
html << "<a href=\"#{login_url}\" class=\"cl-creator-pill\">\n"
|
|
||||||
html << "<img src=\"#{avatar_url}\" alt=\"#{e(user.username)}\" class=\"cl-creator-pill__avatar\" loading=\"lazy\">\n"
|
|
||||||
html << "<span class=\"cl-creator-pill__name\">@#{e(user.username)}</span>\n"
|
|
||||||
html << "<span class=\"cl-creator-pill__count\">#{activity_count}</span>\n"
|
|
||||||
html << "</a>\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
html << "</div>\n</div></section>\n"
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
# ── 7. COMMUNITY SPACES ──
|
# ── 7. COMMUNITY SPACES ──
|
||||||
|
|
||||||
def render_groups
|
def render_groups
|
||||||
@@ -466,14 +439,15 @@ module CommunityLanding
|
|||||||
|
|
||||||
# ── Shared helpers ──
|
# ── Shared helpers ──
|
||||||
|
|
||||||
def stat_card(icon_svg, count, label, icon_shape = "circle", round_numbers = false)
|
def stat_card(icon_svg, count, label, icon_shape = "circle", round_numbers = false, show_label = true)
|
||||||
shape_class = icon_shape == "rounded" ? "cl-stat-icon--rounded" : "cl-stat-icon--circle"
|
shape_class = icon_shape == "rounded" ? "cl-stat-icon--rounded" : "cl-stat-icon--circle"
|
||||||
round_attr = round_numbers ? ' data-round="true"' : ''
|
round_attr = round_numbers ? ' data-round="true"' : ''
|
||||||
|
label_html = show_label ? "<span class=\"cl-stat-card__label\">#{e(label)}</span>\n" : ""
|
||||||
"<div class=\"cl-stat-card\">\n" \
|
"<div class=\"cl-stat-card\">\n" \
|
||||||
"<div class=\"cl-stat-card__icon-wrap #{shape_class}\">#{icon_svg}</div>\n" \
|
"<div class=\"cl-stat-card__icon-wrap #{shape_class}\">#{icon_svg}</div>\n" \
|
||||||
"<div class=\"cl-stat-card__text\">\n" \
|
"<div class=\"cl-stat-card__text\">\n" \
|
||||||
"<span class=\"cl-stat-card__value\" data-count=\"#{count}\"#{round_attr}>0</span>\n" \
|
"<span class=\"cl-stat-card__value\" data-count=\"#{count}\"#{round_attr}>0</span>\n" \
|
||||||
"<span class=\"cl-stat-card__label\">#{e(label)}</span>\n" \
|
"#{label_html}" \
|
||||||
"</div>\n" \
|
"</div>\n" \
|
||||||
"</div>\n"
|
"</div>\n"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ module CommunityLanding
|
|||||||
space_card_bg = hex(@s.groups_card_bg_color.presence) rescue nil
|
space_card_bg = hex(@s.groups_card_bg_color.presence) rescue nil
|
||||||
topic_card_bg = hex(@s.topics_card_bg_color.presence) rescue nil
|
topic_card_bg = hex(@s.topics_card_bg_color.presence) rescue nil
|
||||||
video_btn_bg = hex(@s.hero_video_button_color.presence) rescue nil
|
video_btn_bg = hex(@s.hero_video_button_color.presence) rescue nil
|
||||||
|
hero_card_dark = hex(@s.hero_card_bg_dark.presence) rescue nil
|
||||||
|
hero_card_light = hex(@s.hero_card_bg_light.presence) rescue nil
|
||||||
|
hero_card_opacity = [[@s.hero_card_opacity.to_s.to_f, 0].max, 1].min rescue 0.85
|
||||||
|
hero_card_opacity = 0.85 if hero_card_opacity == 0.0 && (@s.hero_card_opacity.to_s.strip.empty? rescue true)
|
||||||
accent_rgb = hex_to_rgb(accent)
|
accent_rgb = hex_to_rgb(accent)
|
||||||
stat_icon_rgb = hex_to_rgb(stat_icon)
|
stat_icon_rgb = hex_to_rgb(stat_icon)
|
||||||
|
|
||||||
@@ -35,6 +39,12 @@ module CommunityLanding
|
|||||||
space_card_bg_val = space_card_bg || "var(--cl-card)"
|
space_card_bg_val = space_card_bg || "var(--cl-card)"
|
||||||
topic_card_bg_val = topic_card_bg || "var(--cl-card)"
|
topic_card_bg_val = topic_card_bg || "var(--cl-card)"
|
||||||
|
|
||||||
|
# Hero card bg: convert hex + opacity to rgba
|
||||||
|
hero_card_dark_rgb = hero_card_dark ? hex_to_rgb(hero_card_dark) : "12, 12, 25"
|
||||||
|
hero_card_light_rgb = hero_card_light ? hex_to_rgb(hero_card_light) : "255, 255, 255"
|
||||||
|
hero_card_dark_val = "rgba(#{hero_card_dark_rgb}, #{hero_card_opacity})"
|
||||||
|
hero_card_light_val = "rgba(#{hero_card_light_rgb}, #{hero_card_opacity})"
|
||||||
|
|
||||||
about_bg_extra = about_bg_img ? ", url('#{about_bg_img}') center/cover no-repeat" : ""
|
about_bg_extra = about_bg_img ? ", url('#{about_bg_img}') center/cover no-repeat" : ""
|
||||||
video_btn_line = video_btn_bg ? "\n --cl-video-btn-bg: #{video_btn_bg};" : ""
|
video_btn_line = video_btn_bg ? "\n --cl-video-btn-bg: #{video_btn_bg};" : ""
|
||||||
|
|
||||||
@@ -54,6 +64,7 @@ module CommunityLanding
|
|||||||
--cl-stat-counter-color: #{stat_counter_val};
|
--cl-stat-counter-color: #{stat_counter_val};
|
||||||
--cl-space-card-bg: #{space_card_bg_val};
|
--cl-space-card-bg: #{space_card_bg_val};
|
||||||
--cl-topic-card-bg: #{topic_card_bg_val};#{video_btn_line}
|
--cl-topic-card-bg: #{topic_card_bg_val};#{video_btn_line}
|
||||||
|
--cl-hero-card-bg: #{hero_card_dark_val};
|
||||||
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
||||||
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
||||||
}
|
}
|
||||||
@@ -72,6 +83,7 @@ module CommunityLanding
|
|||||||
--cl-stat-counter-color: #{stat_counter_val};
|
--cl-stat-counter-color: #{stat_counter_val};
|
||||||
--cl-space-card-bg: #{space_card_bg_val};
|
--cl-space-card-bg: #{space_card_bg_val};
|
||||||
--cl-topic-card-bg: #{topic_card_bg_val};#{video_btn_line}
|
--cl-topic-card-bg: #{topic_card_bg_val};#{video_btn_line}
|
||||||
|
--cl-hero-card-bg: #{hero_card_light_val};
|
||||||
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
||||||
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
||||||
}
|
}
|
||||||
@@ -102,7 +114,6 @@ module CommunityLanding
|
|||||||
["#cl-stats-row", safe_hex(:stats_bg_dark), safe_hex(:stats_bg_light)],
|
["#cl-stats-row", safe_hex(:stats_bg_dark), safe_hex(:stats_bg_light)],
|
||||||
["#cl-about", safe_hex(:about_bg_dark), safe_hex(:about_bg_light)],
|
["#cl-about", safe_hex(:about_bg_dark), safe_hex(:about_bg_light)],
|
||||||
["#cl-topics", safe_hex(:topics_bg_dark), safe_hex(:topics_bg_light)],
|
["#cl-topics", safe_hex(:topics_bg_dark), safe_hex(:topics_bg_light)],
|
||||||
["#cl-contributors", safe_hex(:contributors_bg_dark), safe_hex(:contributors_bg_light)],
|
|
||||||
["#cl-groups", safe_hex(:groups_bg_dark), safe_hex(:groups_bg_light)],
|
["#cl-groups", safe_hex(:groups_bg_dark), safe_hex(:groups_bg_light)],
|
||||||
["#cl-app-cta", safe_hex(:app_cta_bg_dark), safe_hex(:app_cta_bg_light)],
|
["#cl-app-cta", safe_hex(:app_cta_bg_dark), safe_hex(:app_cta_bg_light)],
|
||||||
["#cl-footer", safe_hex(:footer_bg_dark), safe_hex(:footer_bg_light)],
|
["#cl-footer", safe_hex(:footer_bg_dark), safe_hex(:footer_bg_light)],
|
||||||
|
|||||||
@@ -42,10 +42,12 @@ after_initialize do
|
|||||||
base_url = Discourse.base_url
|
base_url = Discourse.base_url
|
||||||
csp = "default-src 'self' #{base_url}; " \
|
csp = "default-src 'self' #{base_url}; " \
|
||||||
"script-src 'self' 'unsafe-inline'; " \
|
"script-src 'self' 'unsafe-inline'; " \
|
||||||
"style-src 'self' 'unsafe-inline'; " \
|
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " \
|
||||||
|
"style-src-elem 'self' 'unsafe-inline' https://fonts.googleapis.com; " \
|
||||||
"img-src 'self' #{base_url} data: https:; " \
|
"img-src 'self' #{base_url} data: https:; " \
|
||||||
"font-src 'self' #{base_url} https://fonts.gstatic.com; " \
|
"font-src 'self' #{base_url} https://fonts.gstatic.com; " \
|
||||||
"media-src 'self' https:; " \
|
"media-src 'self' https:; " \
|
||||||
|
"connect-src 'self' #{base_url}; " \
|
||||||
"frame-src https://www.youtube.com https://www.youtube-nocookie.com; " \
|
"frame-src https://www.youtube.com https://www.youtube-nocookie.com; " \
|
||||||
"frame-ancestors 'self'"
|
"frame-ancestors 'self'"
|
||||||
response.headers["Content-Security-Policy"] = csp
|
response.headers["Content-Security-Policy"] = csp
|
||||||
|
|||||||
Reference in New Issue
Block a user