diff --git a/resources/lang/en/menu.php b/resources/lang/en/menu.php index 6dd69af3f..6609ab908 100644 --- a/resources/lang/en/menu.php +++ b/resources/lang/en/menu.php @@ -32,6 +32,7 @@ 'schools' => 'Schools', 'about' => 'About', 'blog' => 'Blog', + 'share_your_stories' => 'Share your stories', 'news' => 'News', 'search' => 'Type & hit Enter...', 'map' => 'Map', diff --git a/resources/views/layout/menu.blade.php b/resources/views/layout/menu.blade.php index 85aea65d1..422fb9553 100644 --- a/resources/views/layout/menu.blade.php +++ b/resources/views/layout/menu.blade.php @@ -288,14 +288,17 @@ class="cookweek-link hover-underline !text-[#1C4DA1] !text-[16px]" {{-- blog --}} - {{-- My account --}} diff --git a/scripts/deploy-blog-share-stories.sh b/scripts/deploy-blog-share-stories.sh new file mode 100755 index 000000000..82f8d24c1 --- /dev/null +++ b/scripts/deploy-blog-share-stories.sh @@ -0,0 +1,220 @@ +#!/usr/bin/env bash +# Production blog deploy — run on server as root: +# WP_ROOT=/var/www/html/blog bash deploy-blog-share-stories-inline.sh + +set -euo pipefail + +WP_ROOT="${WP_ROOT:-/var/www/html/blog}" +THEME="${THEME:-$WP_ROOT/wp-content/themes/eucodewe-1389}" + +if [[ ! -d "$THEME" ]]; then + THEME=$(find /var/www -maxdepth 8 -type d -name 'eucodewe-1389' 2>/dev/null | head -1 || true) + if [[ -n "${THEME:-}" ]]; then + WP_ROOT="$(dirname "$(dirname "$(dirname "$THEME")")")" + fi +fi + +SHARE_URL="https://forms.office.com/Pages/ResponsePage.aspx?id=18F13DIal06vkB3AGRHqbCnyIKB_vXdLsUgagfjd7DRUN1dZTVYxSkJNQ1VWSlVZNlpBOFAyN0g4UC4u&embed=true" +SHARE_TEXT="Share your stories" +HERO_DESCRIPTION="Have a story, activity, or inspiring EU Code Week experience to share? We'd love to hear from you! Submit your experiences, highlights, and initiatives through the form and help us showcase the amazing work happening across the EU Code Week community." + +[[ -d "$THEME" ]] || { echo "Theme eucodewe-1389 not found under /var/www"; find /var/www -maxdepth 6 -name wp-config.php 2>/dev/null; exit 1; } +echo "Using WP_ROOT=$WP_ROOT" +cd "$THEME" +echo "Using THEME=$THEME" + +chmod u+w new.css front-page.php functions.php acf-json/group_5efc9e8719cc2.json 2>/dev/null || true +cp -a new.css "new.css.bak.$(date +%Y%m%d%H%M%S)" +cp -a front-page.php "front-page.php.bak.$(date +%Y%m%d%H%M%S)" + +# --- 1) Enlarge hero so description + CTA fit comfortably --- +python3 <<'PY' +from pathlib import Path +import re + +css = Path("new.css") +text = css.read_text() + +# Desktop hero section +text = re.sub( + r"(\.hero-section\s*\{[^}]*?)min-height:\s*\d+px;", + r"\1min-height: 580px;", + text, + count=1, + flags=re.S, +) +text = re.sub( + r"(\.hero-section\s*\{[^}]*?)height:\s*250px;", + r"\1min-height: 580px;\n height: auto;", + text, + count=1, + flags=re.S, +) +text = re.sub( + r"(\.hero-section\s*\{[^}]*?)padding:\s*[^;]+;", + r"\1padding: 3rem 0;", + text, + count=1, + flags=re.S, +) + +# Hero white card — more room for description + button +text = re.sub( + r"(\.hero-content\s*\{[^}]*?)padding:\s*2rem;", + r"\1padding: 2.5rem 3rem 3rem;", + text, + count=1, + flags=re.S, +) + +if ".hero-description {" in text and "margin-bottom:" not in text.split(".hero-description {", 1)[1].split("}", 1)[0]: + text = text.replace( + ".hero-description {\n color: var(--Slate-500, #333E48);", + ".hero-description {\n margin-bottom: 1.25rem;\n color: var(--Slate-500, #333E48);", + 1, + ) + +# Tablet breakpoint +text = re.sub( + r"(\t\.hero-section\s*\{[^}]*?)min-height:\s*\d+px;", + r"\1min-height: 520px;", + text, + count=1, + flags=re.S, +) +text = re.sub( + r"(\t\.hero-section\s*\{[^}]*?)height:\s*330px;", + r"\1min-height: 520px;\n\t\theight: auto;", + text, + count=1, + flags=re.S, +) + +# Mobile breakpoint — stack layout +text = re.sub( + r"(\t\.hero-section\s*\{\n flex-direction: column-reverse;[^}]*?)padding:\s*[^;]+;", + r"\1padding: 0 0 3rem;\n min-height: 520px;", + text, + count=1, + flags=re.S, +) + +if ".hero-button {" in text and "margin-top:" not in text.split(".hero-button {", 1)[1].split("}", 1)[0]: + text = text.replace( + ".hero-button {\n background-color: #F95C22;", + ".hero-button {\n display: inline-block;\n margin-top: 1.5rem;\n background-color: #F95C22;", + 1, + ) +elif ".hero-button {" in text: + text = re.sub( + r"(\.hero-button\s*\{[^}]*?)margin-top:\s*[^;]+;", + r"\1margin-top: 1.5rem;", + text, + count=1, + flags=re.S, + ) + +css.write_text(text) +print("Updated new.css hero sizing (580px desktop)") +PY + +# --- 2) ACF JSON: add cta_button to hero_section --- +python3 <<'PY' +import json +from pathlib import Path +path = Path("acf-json/group_5efc9e8719cc2.json") +data = json.loads(path.read_text()) +for field in data.get("fields", []): + if field.get("name") != "hero_section": + continue + subs = field.setdefault("sub_fields", []) + if any(s.get("name") == "cta_button" for s in subs): + print("ACF JSON already has cta_button") + break + subs.append({ + "key": "field_codeweek_hero_cta_button", + "label": "Button", + "name": "cta_button", + "type": "link", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": {"width": "", "class": "", "id": ""}, + "return_format": "array", + }) + path.write_text(json.dumps(data, indent=4) + "\n") + print("Added cta_button to ACF JSON") + break +else: + raise SystemExit("hero_section not found in ACF JSON") +PY + +# --- 3) front-page.php: render hero CTA (mirror info section button) --- +python3 <<'PY' +import re +from pathlib import Path +path = Path("front-page.php") +content = path.read_text() +snippet = """ + + + """ + +if "cta_button" in content: + print("front-page.php already references cta_button") +else: + match = re.search(r'(]*class="hero-description"[^>]*>.*?

)', content, re.S) + if not match: + raise SystemExit("Could not find hero-description in front-page.php") + content = content[: match.end()] + snippet + content[match.end() :] + path.write_text(content) + print("Patched front-page.php") +PY + +# --- 4) WP-CLI: defaults + menu --- +if command -v wp >/dev/null 2>&1; then + cd "$WP_ROOT" + wp acf sync --allow-root 2>/dev/null || true + + HERO_DESC_JSON=$(HERO_DESCRIPTION="$HERO_DESCRIPTION" python3 -c 'import json,os; print(json.dumps(os.environ["HERO_DESCRIPTION"]))') + wp eval --allow-root " + \$hero = get_field('hero_section', 2) ?: []; + \$hero['description'] = ${HERO_DESC_JSON}; + \$hero['cta_button'] = ['title' => '$SHARE_TEXT', 'url' => '$SHARE_URL', 'target' => '_blank']; + update_field('hero_section', \$hero, 2); + " 2>/dev/null || true + + ARROW_HTML='arrow right' + SHARE_ID="" + for menu in primary header main "Menu 1" 2; do + SHARE_ID=$(wp menu item list "$menu" --fields=db_id,title --format=csv --allow-root 2>/dev/null \ + | awk -F, -v t="$SHARE_TEXT" '$2 ~ t {print $1; exit}') || true + if [[ -n "${SHARE_ID:-}" ]]; then + echo "Share your stories already in $menu (ID $SHARE_ID)" + break + fi + BLOG_PARENT=$(wp menu item list "$menu" --fields=db_id,title --format=csv --allow-root 2>/dev/null | awk -F, '$2 ~ /Blog/ {print $1; exit}') + if [[ -n "${BLOG_PARENT:-}" ]]; then + SHARE_ID=$(wp menu item add-custom "$menu" "$SHARE_TEXT" "$SHARE_URL" --parent-id="$BLOG_PARENT" --porcelain --allow-root 2>/dev/null || true) + [[ -n "${SHARE_ID:-}" ]] && echo "Added menu item to $menu (ID $SHARE_ID)" && break + fi + done + + if [[ -n "${SHARE_ID:-}" ]]; then + wp eval --allow-root " + \$id = (int) ${SHARE_ID}; + update_post_meta(\$id, '_menu_item_url', '${SHARE_URL}'); + update_post_meta(\$id, 'rt-wp-menu-custom-fields', [ + 'selected-feature' => 'html', + 'html' => ['custom-html' => '${ARROW_HTML}'], + ]); + delete_transient('rt-wp-menu-custom-fields-' . \$id); + echo \"Menu item \$id: URL + arrow icon meta set\n\"; + " 2>/dev/null || true + fi + + wp cache flush --allow-root 2>/dev/null || true + echo "WP-CLI done" +fi + +echo "Done. Verify https://codeweek.eu/blog/" diff --git a/scripts/fix-blog-chevron-and-button.sh b/scripts/fix-blog-chevron-and-button.sh new file mode 100755 index 000000000..78e75a712 --- /dev/null +++ b/scripts/fix-blog-chevron-and-button.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +# Fix Blog chevron (root cause: last-child rule) + hero button typography. +set -euo pipefail + +THEME="${THEME:-/var/www/html/blog/wp-content/themes/eucodewe-1389}" +[[ -d "$THEME" ]] || { echo "Theme not found"; exit 1; } + +cd "$THEME" +chmod u+w new.css 2>/dev/null || true + +python3 <<'PY' +from pathlib import Path +import re + +css = Path("new.css") +text = css.read_text() + +# ROOT FIX: don't hide chevron on last nav item when it has a dropdown +text = text.replace( + ".header__menu nav > ul > li:last-child a:after {\n display: none;\n}", + ".header__menu nav > ul > li:last-child:not(.menu-item-has-children) a:after {\n display: none;\n}", +) + +# Hero button: no top margin, 1.125rem font +text = re.sub( + r"(\.hero-button\s*\{[^}]*?)margin-top:\s*[^;]+;\s*", + r"\1", + text, + count=1, + flags=re.S, +) +if "font-size: 1.125rem" not in text.split(".hero-button {", 1)[1].split("}", 1)[0]: + text = re.sub( + r"(\.hero-button\s*\{[^}]*?font-weight:\s*600;\s*)", + r"\1\n font-size: 1.125rem;\n", + text, + count=1, + flags=re.S, + ) + +# Keep hero content left-aligned +if ".hero-content {\n text-align: left;" not in text: + text = re.sub( + r"(\.hero-content\s*\{[^}]*?)text-align:\s*center;", + r"\1text-align: left;", + text, + count=1, + flags=re.S, + ) + +# Strip redundant blog chevron override blocks (root fix handles it) +for pat in [ + r"\n/\* Blog nav: restore dropdown chevron.*?(?=\n/\* |\Z)", + r"\n/\* Blog nav: chevron on Blog.*?(?=\n/\* |\Z)", +]: + text = re.sub(pat, "\n", text, flags=re.S) + +# Ensure submenu left-align block exists (keep if already there) +submenu_marker = "/* Blog dropdown: Share your stories — left aligned */" +if submenu_marker not in text: + text = text.rstrip() + """ + +/* Blog dropdown: Share your stories — left aligned */ +.menu-item-5643 > .sub-menu > .menu-item-8142, +li#menu-item-5643 > .sub-menu > li#menu-item-8142 { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 8px; +} +.menu-item-5643 > .sub-menu > .menu-item-8142 a, +li#menu-item-5643 > .sub-menu > li#menu-item-8142 a { + text-align: left; +} +""" + +css.write_text(text) +print("Patched new.css") +PY + +echo "--- verify ---" +grep -n "last-child" new.css | head -5 +grep -n -A6 "^\.hero-button {" new.css | head -10 + +cd /var/www/html/blog +wp cache flush --allow-root 2>/dev/null | tail -1 || true +for svc in php8.3-fpm php8.2-fpm php8.1-fpm php8.0-fpm; do + systemctl is-active --quiet "$svc" 2>/dev/null && systemctl reload "$svc" && echo "Reloaded $svc" && break +done +echo "Done. Hard-refresh https://codeweek.eu/blog/" diff --git a/scripts/fix-blog-chevron-and-hero-cta.sh b/scripts/fix-blog-chevron-and-hero-cta.sh new file mode 100755 index 000000000..dcfeb5260 --- /dev/null +++ b/scripts/fix-blog-chevron-and-hero-cta.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# Blog nav chevron (Blog is last item) + hero ACF CTA button. +# Run on server: +# curl -fsSL "https://gist.githubusercontent.com/bernardhanna/REPLACE/raw/fix-blog-chevron-and-hero-cta.sh" | bash + +set -euo pipefail + +WP_ROOT="${WP_ROOT:-/var/www/html/blog}" +THEME="${THEME:-$WP_ROOT/wp-content/themes/eucodewe-1389}" +SHARE_URL="https://forms.office.com/Pages/ResponsePage.aspx?id=18F13DIal06vkB3AGRHqbCnyIKB_vXdLsUgagfjd7DRUN1dZTVYxSkJNQ1VWSlVZNlpBOFAyN0g4UC4u&embed=true" +SHARE_TEXT="Share your stories" + +[[ -d "$THEME" ]] || { echo "Theme not found: $THEME"; exit 1; } +command -v wp >/dev/null 2>&1 || { echo "wp-cli required"; exit 1; } + +cd "$THEME" +chmod u+w new.css front-page.php 2>/dev/null || true + +# --- 1) Blog dropdown chevron (last nav item overrides :last-child { display:none }) --- +python3 <<'PY' +from pathlib import Path + +css = Path("new.css") +text = css.read_text() +marker = "/* Blog nav: restore dropdown chevron (last menu item) */" +block = """ +/* Blog nav: restore dropdown chevron (last menu item) */ +.header__menu nav > ul > li#menu-item-5643.menu-item-has-children > a:after, +#menu-item-5643.menu-item-has-children > a:after { + content: ""; + width: 10px; + height: 10px; + background: url(https://codeweek.eu/blog/wp-content/uploads/2025/01/Vector-6.svg); + display: block; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + transition: 0.3s; +} +.header__menu nav > ul > li#menu-item-5643.menu-item-has-children > a:hover:after, +#menu-item-5643.menu-item-has-children > a:hover:after { + transform: scale(-1); +} +""" +if marker in text: + print("Blog chevron CSS already present") +else: + css.write_text(text.rstrip() + "\n" + block) + print("Added Blog nav chevron CSS") +PY + +# --- 2) front-page.php: render hero ACF cta_button --- +cp -a front-page.php "front-page.php.bak.$(date +%Y%m%d%H%M%S)" 2>/dev/null || true + +python3 <<'PY' +import re +from pathlib import Path + +path = Path("front-page.php") +content = path.read_text() + +snippet = """ + + + """ + +content = re.sub( + r"\s*<\?php if \(! empty\(\$hero\['cta_button'\]\)\).*?<\?php endif; \?>", + "", + content, + flags=re.S, +) +content = re.sub( + r"\s*<\?php\s+\$hero_cta = \$hero\['cta_button'\].*?<\?php endif; \?>", + "", + content, + flags=re.S, +) + +match = re.search(r'(]*class="hero-description"[^>]*>.*?

)', content, re.S) +if not match: + raise SystemExit("Could not find hero-description in front-page.php") + +if 'class="hero-button"' not in content[match.start():match.end() + 800]: + content = content[: match.end()] + snippet + content[match.end() :] + path.write_text(content) + print("Inserted hero CTA block after hero-description") +else: + print("Hero CTA block already present after hero-description") +PY + +echo "--- front-page.php hero lines ---" +grep -n "hero-description\|hero-button\|hero_cta\|cta_button" front-page.php | head -15 + +# --- 3) ACF data for hero button --- +cd "$WP_ROOT" +wp eval --allow-root " + \$hero = get_field('hero_section', 2) ?: []; + \$hero['cta_button'] = [ + 'title' => '${SHARE_TEXT}', + 'url' => '${SHARE_URL}', + 'target' => '_blank', + ]; + update_field('hero_section', \$hero, 2); + echo 'hero_section.cta_button saved on page 2' . PHP_EOL; +" 2>/dev/null | tail -1 + +wp cache flush --allow-root 2>/dev/null || true + +for svc in php8.3-fpm php8.2-fpm php8.1-fpm php8.0-fpm php7.4-fpm; do + if systemctl is-active --quiet "$svc" 2>/dev/null; then + systemctl reload "$svc" 2>/dev/null && echo "Reloaded $svc" && break + fi +done + +echo "Done. Hard-refresh https://codeweek.eu/blog/" diff --git a/scripts/fix-blog-chevron-left-cta.sh b/scripts/fix-blog-chevron-left-cta.sh new file mode 100755 index 000000000..9384518be --- /dev/null +++ b/scripts/fix-blog-chevron-left-cta.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# Fix Blog chevron (desktop uses class not id) + left-align hero CTA + submenu item. +set -euo pipefail + +THEME="${THEME:-/var/www/html/blog/wp-content/themes/eucodewe-1389}" +[[ -d "$THEME" ]] || { echo "Theme not found"; exit 1; } + +cd "$THEME" +chmod u+w new.css 2>/dev/null || true + +python3 <<'PY' +from pathlib import Path +import re + +css = Path("new.css") +text = css.read_text() + +# Strip old blog chevron / submenu patches +for pat in [ + r"\n/\* Blog nav: restore dropdown chevron.*?(?=\n/\* |\Z)", + r"\n/\* Blog nav: chevron on Blog.*?(?=\n/\* |\Z)", + r"\n/\* Blog dropdown: show Share your stories.*?(?=\n/\* |\Z)", + r"\n/\* Blog dropdown: Share your stories.*?(?=\n/\* |\Z)", + r"\n/\* Hero CTA: align left.*?(?=\n/\* |\Z)", +]: + text = re.sub(pat, "\n", text, flags=re.S) + +block = """ +/* Blog nav: chevron on Blog (last item; desktop uses .menu-item-5643 without id) */ +.header__menu nav > ul > li.menu-item-has-children:last-child > a:after, +.header__menu nav > ul > li.menu-item-5643.menu-item-has-children > a:after, +li#menu-item-5643.menu-item-has-children > a:after { + content: "" !important; + width: 10px; + height: 10px; + background: url(https://codeweek.eu/blog/wp-content/uploads/2025/01/Vector-6.svg); + display: block !important; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + transition: 0.3s; +} +.header__menu nav > ul > li.menu-item-has-children:last-child > a:hover:after, +.header__menu nav > ul > li.menu-item-5643.menu-item-has-children > a:hover:after, +li#menu-item-5643.menu-item-has-children > a:hover:after { + transform: scale(-1); +} + +/* Hero CTA: align left (hero-content defaults to text-align: center) */ +.hero-content { + text-align: left; +} + +/* Blog dropdown: Share your stories — left aligned */ +.menu-item-5643 > .sub-menu > .menu-item-8142, +li#menu-item-5643 > .sub-menu > li#menu-item-8142 { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 8px; +} +.menu-item-5643 > .sub-menu > .menu-item-8142 a, +li#menu-item-5643 > .sub-menu > li#menu-item-8142 a { + text-align: left; +} +.menu-item-5643 > .sub-menu > .menu-item-8142 .rt-wp-menu-custom-fields-wrapper, +li#menu-item-5643 > .sub-menu > li#menu-item-8142 .rt-wp-menu-custom-fields-wrapper { + display: flex; + align-items: center; + flex-shrink: 0; +} +.menu-item-5643 > .sub-menu > .menu-item-8142 .rt-wp-menu-custom-fields-custom-html img, +li#menu-item-5643 > .sub-menu > li#menu-item-8142 .rt-wp-menu-custom-fields-custom-html img { + display: block; + width: 20px; + height: auto; +} +""" + +css.write_text(text.rstrip() + "\n" + block) +print("Patched new.css") +PY + +cd /var/www/html/blog +wp cache flush --allow-root 2>/dev/null | tail -1 || true +for svc in php8.3-fpm php8.2-fpm php8.1-fpm php8.0-fpm; do + systemctl is-active --quiet "$svc" 2>/dev/null && systemctl reload "$svc" && echo "Reloaded $svc" && break +done +echo "Done. Hard-refresh https://codeweek.eu/blog/" diff --git a/scripts/fix-blog-hero-cta-render.sh b/scripts/fix-blog-hero-cta-render.sh new file mode 100755 index 000000000..aeca40320 --- /dev/null +++ b/scripts/fix-blog-hero-cta-render.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# Force hero CTA to render on blog homepage. +# Run: bash fix-blog-hero-cta-render.sh + +set -euo pipefail + +WP_ROOT="${WP_ROOT:-/var/www/html/blog}" +THEME="${THEME:-$WP_ROOT/wp-content/themes/eucodewe-1389}" +SHARE_URL="https://forms.office.com/Pages/ResponsePage.aspx?id=18F13DIal06vkB3AGRHqbCnyIKB_vXdLsUgagfjd7DRUN1dZTVYxSkJNQ1VWSlVZNlpBOFAyN0g4UC4u&embed=true" +SHARE_TEXT="Share your stories" + +cd "$THEME" +chmod u+w front-page.php 2>/dev/null || true +cp -a front-page.php "front-page.php.bak.$(date +%Y%m%d%H%M%S)" + +python3 <<'PY' +import re +from pathlib import Path + +path = Path("front-page.php") +content = path.read_text() + +snippet = """ + + + """ + +# Remove any prior cta_button block we may have inserted +content = re.sub( + r"\s*<\?php if \(! empty\(\$hero\['cta_button'\]\)\).*?<\?php endif; \?>", + "", + content, + flags=re.S, +) +content = re.sub( + r"\s*<\?php\s+\$hero_cta = \$hero\['cta_button'\].*?<\?php endif; \?>", + "", + content, + flags=re.S, +) + +match = re.search(r'(]*class="hero-description"[^>]*>.*?

)', content, re.S) +if not match: + raise SystemExit("Could not find hero-description paragraph in front-page.php") + +if 'class="hero-button"' in content[match.start():match.end() + 500]: + print("Hero button markup already follows hero-description") +else: + content = content[: match.end()] + snippet + content[match.end() :] + path.write_text(content) + print("Inserted hero CTA render block after hero-description") +PY + +echo "--- front-page.php (hero area) ---" +grep -n "hero-description\|hero-button\|cta_button\|hero_cta" front-page.php | head -20 + +cd "$WP_ROOT" +wp eval --allow-root " + \$hero = get_field('hero_section', 2) ?: []; + if (empty(\$hero['cta_button']['url'])) { + \$hero['cta_button'] = [ + 'title' => '${SHARE_TEXT}', + 'url' => '${SHARE_URL}', + 'target' => '_blank', + ]; + update_field('hero_section', \$hero, 2); + echo \"Set hero_section.cta_button on page 2\n\"; + } else { + echo \"cta_button already set: \" . \$hero['cta_button']['url'] . \"\n\"; + } +" 2>/dev/null | tail -3 + +wp cache flush --allow-root 2>/dev/null || true + +# Clear PHP opcache if FPM is available +for svc in php8.3-fpm php8.2-fpm php8.1-fpm php8.0-fpm php7.4-fpm; do + if systemctl is-active --quiet "$svc" 2>/dev/null; then + systemctl reload "$svc" 2>/dev/null && echo "Reloaded $svc" && break + fi +done + +echo "Done. Hard-refresh https://codeweek.eu/blog/ and check for class=\"hero-button\"" diff --git a/scripts/patch-blog-hero-cta-and-menu-icon.sh b/scripts/patch-blog-hero-cta-and-menu-icon.sh new file mode 100755 index 000000000..afc4178bc --- /dev/null +++ b/scripts/patch-blog-hero-cta-and-menu-icon.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# Fix blog hero CTA button + Blog dropdown arrow visibility. +# Run on server: bash patch-blog-hero-cta-and-menu-icon.sh + +set -euo pipefail + +WP_ROOT="${WP_ROOT:-/var/www/html/blog}" +THEME="${THEME:-$WP_ROOT/wp-content/themes/eucodewe-1389}" +SHARE_URL="https://forms.office.com/Pages/ResponsePage.aspx?id=18F13DIal06vkB3AGRHqbCnyIKB_vXdLsUgagfjd7DRUN1dZTVYxSkJNQ1VWSlVZNlpBOFAyN0g4UC4u&embed=true" +SHARE_TEXT="Share your stories" +HERO_DESCRIPTION="Have a story, activity, or inspiring EU Code Week experience to share? We'd love to hear from you! Submit your experiences, highlights, and initiatives through the form and help us showcase the amazing work happening across the EU Code Week community." + +[[ -d "$THEME" ]] || { echo "Theme not found: $THEME"; exit 1; } +command -v wp >/dev/null 2>&1 || { echo "wp-cli required"; exit 1; } + +cd "$THEME" +chmod u+w front-page.php new.css acf-json/group_5efc9e8719cc2.json 2>/dev/null || true + +# --- 1) front-page.php: render hero CTA after description --- +python3 <<'PY' +import re +from pathlib import Path + +path = Path("front-page.php") +content = path.read_text() +snippet = """ + + + """ + +if "cta_button" in content: + print("front-page.php already has cta_button") +else: + match = re.search(r'(]*class="hero-description"[^>]*>.*?

)', content, re.S) + if not match: + raise SystemExit("Could not find hero-description in front-page.php") + path.write_text(content[: match.end()] + snippet + content[match.end() :]) + print("Patched front-page.php with hero CTA") +PY + +# --- 2) ACF JSON: ensure cta_button sub-field exists --- +python3 <<'PY' +import json +from pathlib import Path + +path = Path("acf-json/group_5efc9e8719cc2.json") +data = json.loads(path.read_text()) +for field in data.get("fields", []): + if field.get("name") != "hero_section": + continue + subs = field.setdefault("sub_fields", []) + if any(s.get("name") == "cta_button" for s in subs): + print("ACF JSON already has cta_button") + break + subs.append({ + "key": "field_codeweek_hero_cta_button", + "label": "Button", + "name": "cta_button", + "type": "link", + "return_format": "array", + }) + path.write_text(json.dumps(data, indent=4) + "\n") + print("Added cta_button to ACF JSON") + break +PY + +# --- 3) CSS: Blog simple dropdown — flex layout so arrow img is visible --- +python3 <<'PY' +from pathlib import Path + +css = Path("new.css") +text = css.read_text() +block = """ +/* Blog dropdown: show Share your stories arrow icon */ +#menu-item-5643 > .sub-menu > #menu-item-8142 { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; +} +#menu-item-5643 > .sub-menu > #menu-item-8142 .rt-wp-menu-custom-fields-wrapper { + display: flex; + align-items: center; + flex-shrink: 0; +} +#menu-item-5643 > .sub-menu > #menu-item-8142 .rt-wp-menu-custom-fields-custom-html img { + display: block; + width: 20px; + height: auto; +} +""" +marker = "/* Blog dropdown: show Share your stories arrow icon */" +if marker in text: + print("Menu arrow CSS already present") +else: + css.write_text(text.rstrip() + "\n" + block) + print("Added Blog dropdown arrow CSS") +PY + +# --- 4) WP-CLI: hero CTA data + menu arrow meta --- +cd "$WP_ROOT" +wp acf sync --allow-root 2>/dev/null || true + +HERO_DESC_JSON=$(HERO_DESCRIPTION="$HERO_DESCRIPTION" python3 -c 'import json,os; print(json.dumps(os.environ["HERO_DESCRIPTION"]))') +wp eval --allow-root " + \$hero = get_field('hero_section', 2) ?: []; + \$hero['description'] = ${HERO_DESC_JSON}; + \$hero['cta_button'] = [ + 'title' => '${SHARE_TEXT}', + 'url' => '${SHARE_URL}', + 'target' => '_blank', + ]; + update_field('hero_section', \$hero, 2); + echo 'Hero CTA field saved on page 2\n'; +" + +SHARE_ID=$(wp menu item list 2 --fields=db_id,title --format=csv --allow-root \ + | awk -F, -v t="$SHARE_TEXT" '$2 ~ t {print $1; exit}') + +if [[ -n "${SHARE_ID:-}" ]]; then + wp eval --allow-root " + \$ref = 5845; + \$target = (int) ${SHARE_ID}; + \$meta = get_post_meta(\$ref, 'rt-wp-menu-custom-fields', true); + if (empty(\$meta)) { + \$meta = [ + 'selected-feature' => 'html', + 'html' => ['custom-html' => '\"arrow'], + ]; + } + update_post_meta(\$target, '_menu_item_url', '${SHARE_URL}'); + update_post_meta(\$target, 'rt-wp-menu-custom-fields', \$meta); + delete_transient('rt-wp-menu-custom-fields-' . \$target); + echo \"Menu item \$target arrow meta applied\n\"; + " +fi + +wp cache flush --allow-root 2>/dev/null || true +echo "Done. Hard-refresh https://codeweek.eu/blog/" diff --git a/scripts/patch-blog-hero-height.sh b/scripts/patch-blog-hero-height.sh new file mode 100644 index 000000000..9923da093 --- /dev/null +++ b/scripts/patch-blog-hero-height.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# Quick hero height bump — run on the blog server (SSH as root): +# bash patch-blog-hero-height.sh + +set -euo pipefail + +WP_ROOT="${WP_ROOT:-/var/www/html/blog}" +THEME="${THEME:-$WP_ROOT/wp-content/themes/eucodewe-1389}" + +if [[ ! -d "$THEME" ]]; then + THEME=$(find /var/www -maxdepth 8 -type d -name 'eucodewe-1389' 2>/dev/null | head -1 || true) +fi + +[[ -d "$THEME" ]] || { echo "Theme not found"; exit 1; } + +cd "$THEME" +chmod u+w new.css 2>/dev/null || true +cp -a new.css "new.css.bak.$(date +%Y%m%d%H%M%S)" + +python3 <<'PY' +from pathlib import Path +import re + +css = Path("new.css") +text = css.read_text() + +replacements = [ + (r"(\.hero-section\s*\{[^}]*?)min-height:\s*\d+px;", r"\1min-height: 580px;"), + (r"(\.hero-section\s*\{[^}]*?)padding:\s*[^;]+;", r"\1padding: 3rem 0;"), + (r"(\.hero-content\s*\{[^}]*?)padding:\s*2rem;", r"\1padding: 2.5rem 3rem 3rem;"), + (r"(\t\.hero-section\s*\{[^}]*?)min-height:\s*\d+px;", r"\1min-height: 520px;"), + (r"(\t\.hero-section\s*\{\n flex-direction: column-reverse;[^}]*?)padding:\s*[^;]+;", r"\1padding: 0 0 3rem;\n min-height: 520px;"), +] + +for pattern, repl in replacements: + text, n = re.subn(pattern, repl, text, count=1, flags=re.S) + if n: + print(f"Patched: {pattern[:40]}...") + +if ".hero-description {" in text and "margin-bottom:" not in text.split(".hero-description {", 1)[1].split("}", 1)[0]: + text = text.replace( + ".hero-description {\n color: var(--Slate-500, #333E48);", + ".hero-description {\n margin-bottom: 1.25rem;\n color: var(--Slate-500, #333E48);", + 1, + ) + print("Added hero-description margin-bottom") + +css.write_text(text) +print("Done — hero min-height is now 580px (desktop)") +PY + +if command -v wp >/dev/null 2>&1; then + wp cache flush --path="$WP_ROOT" --allow-root 2>/dev/null || true +fi + +echo "Verify: https://codeweek.eu/blog/" diff --git a/scripts/patch-blog-menu-share-stories-icon.sh b/scripts/patch-blog-menu-share-stories-icon.sh new file mode 100755 index 000000000..70d1d75df --- /dev/null +++ b/scripts/patch-blog-menu-share-stories-icon.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Fix "Share your stories" Blog submenu: arrow icon + Office form URL. +# Run on server: WP_ROOT=/var/www/html/blog bash patch-blog-menu-share-stories-icon.sh + +set -euo pipefail + +WP_ROOT="${WP_ROOT:-/var/www/html/blog}" +SHARE_TEXT="Share your stories" +SHARE_URL="https://forms.office.com/Pages/ResponsePage.aspx?id=18F13DIal06vkB3AGRHqbCnyIKB_vXdLsUgagfjd7DRUN1dZTVYxSkJNQ1VWSlVZNlpBOFAyN0g4UC4u&embed=true" +ARROW_HTML='arrow right' + +[[ -d "$WP_ROOT" ]] || { echo "WP_ROOT not found: $WP_ROOT"; exit 1; } +command -v wp >/dev/null 2>&1 || { echo "wp-cli required"; exit 1; } + +cd "$WP_ROOT" + +SHARE_ID="" +for menu in primary header main "Menu 1" 2; do + SHARE_ID=$(wp menu item list "$menu" --fields=db_id,title --format=csv --allow-root 2>/dev/null \ + | awk -F, -v t="$SHARE_TEXT" '$2 ~ t {print $1; exit}') || true + [[ -n "${SHARE_ID:-}" ]] && break +done + +if [[ -z "${SHARE_ID:-}" ]]; then + echo "Menu item '$SHARE_TEXT' not found" + exit 1 +fi + +echo "Patching menu item ID $SHARE_ID" + +# Copy arrow icon meta from an existing submenu item that already shows the arrow +REF_ID=$(wp menu item list 2 --fields=db_id,title --format=csv --allow-root 2>/dev/null \ + | awk -F, '$2 ~ /^Activities$/ {print $1; exit}') || true +REF_ID="${REF_ID:-5845}" + +wp eval --allow-root " +\$ref = (int) ${REF_ID}; +\$target = (int) ${SHARE_ID}; +\$meta = get_post_meta(\$ref, 'rt-wp-menu-custom-fields', true); +if (empty(\$meta) || ! is_array(\$meta)) { + \$meta = [ + 'selected-feature' => 'html', + 'html' => [ + 'custom-html' => '${ARROW_HTML}', + ], + ]; +} +update_post_meta(\$target, '_menu_item_url', '${SHARE_URL}'); +update_post_meta(\$target, 'rt-wp-menu-custom-fields', \$meta); +delete_transient('rt-wp-menu-custom-fields-' . \$target); +echo \"Menu item \$target: URL + arrow icon meta applied (copied from \$ref)\n\"; +" + +wp cache flush --allow-root 2>/dev/null || true +echo "Done. Hard-refresh https://codeweek.eu/blog/ and open Blog dropdown."