[object Object]

← back to Designer Wallcoverings

Add push script for collection grid slider + descriptions deployment

f74571edaf9bebc1db12ad3a5c4c586a4e33dd60 · 2026-06-22 17:42:10 -0700 · Steve Abrams

Files touched

Diff

commit f74571edaf9bebc1db12ad3a5c4c586a4e33dd60
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jun 22 17:42:10 2026 -0700

    Add push script for collection grid slider + descriptions deployment
---
 shopify/push-collection-fixes.sh | 135 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/shopify/push-collection-fixes.sh b/shopify/push-collection-fixes.sh
new file mode 100755
index 00000000..e92284be
--- /dev/null
+++ b/shopify/push-collection-fixes.sh
@@ -0,0 +1,135 @@
+#!/usr/bin/env bash
+# Push collection page fixes to live theme
+#
+# Deploys to both dev and main theme:
+#   sections/collection.liquid      — grid density slider + description restoration
+#   assets/collection-grid-density.js — localStorage grid density control
+#   assets/custom.css              — grid density CSS + description visible
+#   snippets/product-list-item.liquid — description field visible
+#
+# DEFAULT TARGET = dev theme. Pass TARGET_THEME_ID=143739584563 ALLOW_LIVE=1 for live.
+#
+#   bash push-collection-fixes.sh            # dev
+#   TARGET_THEME_ID=143739584563 ALLOW_LIVE=1 bash push-collection-fixes.sh    # LIVE
+set -euo pipefail
+cd "$(dirname "$0")"
+
+STORE="designer-laboratory-sandbox.myshopify.com"
+API="2024-10"
+SECRETS="$HOME/Projects/secrets-manager/.env"
+DEV_NAME="Updated copy of NewWall Template [Dev]"
+LIVE_ID="143739584563"
+
+TOK="${THEME_TOKEN:-$(grep -hE '^SHOPIFY_THEME_TOKEN=' "$SECRETS" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"'"'"' ')}"
+[ -z "$TOK" ] && { echo "No theme token. Run:  THEME_TOKEN=shpat_xxx bash $0"; exit 1; }
+echo "token …${TOK: -4}"
+
+mkdir -p theme-backups
+
+python3 - "$STORE" "$API" "$TOK" "$DEV_NAME" "$LIVE_ID" "theme-backups" "${TARGET_THEME_ID:-}" "${ALLOW_LIVE:-0}" <<'PY'
+import sys, json, re, urllib.request, urllib.parse, datetime, os
+
+store, api, tok, dev_name, live_id, bkdir, target_id, allow_live = sys.argv[1:9]
+script_dir = os.path.dirname(os.path.abspath(__file__))
+
+H = {"X-Shopify-Access-Token": tok, "Content-Type": "application/json"}
+
+def gget(url):
+    return json.load(urllib.request.urlopen(urllib.request.Request(url, headers=H)))
+
+def asset_url(tid, key):
+    return f"https://{store}/admin/api/{api}/themes/{tid}/assets.json?" + \
+           urllib.parse.urlencode({"asset[key]": key})
+
+# Resolve target theme
+themes = gget(f"https://{store}/admin/api/{api}/themes.json")["themes"]
+print("Available themes:")
+for t in themes:
+    print(f"  {t['id']} {t['role']:10} | {t['name']}")
+
+if target_id:
+    match = [t for t in themes if str(t["id"]) == str(target_id)]
+    if not match:
+        print(f"target theme id {target_id} not found")
+        sys.exit(1)
+    theme = match[0]
+    if str(theme["id"]) == live_id and allow_live != "1":
+        print("REFUSING live PUT: set ALLOW_LIVE=1 to target the main/live theme.")
+        sys.exit(2)
+else:
+    match = [t for t in themes if t["name"] == dev_name and t["role"] != "main"]
+    if not match:
+        print(f'dev theme "{dev_name}" not found')
+        sys.exit(1)
+    theme = match[0]
+
+tid = theme["id"]
+is_live = (str(tid) == live_id)
+print(f'\n=== target: {tid} "{theme["name"]}" (role={theme["role"]}, LIVE={is_live}) ===\n')
+
+stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
+
+# Files to push
+files_to_push = [
+    "sections/collection.liquid",
+    "assets/collection-grid-density.js",
+    "assets/custom.css",
+    "snippets/product-list-item.liquid",
+]
+
+def to_theme_key(local_path):
+    # e.g. "_cwGRID/sections/collection.liquid" -> "sections/collection.liquid"
+    parts = local_path.split("/", 1)
+    return parts[1] if len(parts) > 1 else local_path
+
+for rel_path in files_to_push:
+    local_path = os.path.join(script_dir, "_cwGRID", rel_path)
+    theme_key = to_theme_key(f"_cwGRID/{rel_path}")
+
+    print(f"--- {theme_key} ---")
+
+    # Read local source
+    with open(local_path, "r", encoding="utf-8") as f:
+        new_content = f.read()
+
+    # Pull current version for backup
+    try:
+        cur = gget(asset_url(tid, theme_key))["asset"]["value"]
+        bk = os.path.join(bkdir, f"{theme_key.replace('/', '__')}.{tid}.{stamp}.bak")
+        os.makedirs(os.path.dirname(bk) if os.path.dirname(bk) else ".", exist_ok=True)
+        with open(bk, "w", encoding="utf-8") as f:
+            f.write(cur)
+        print(f"  backup: {bk} ({len(cur)} bytes)")
+    except Exception as e:
+        print(f"  backup SKIP (asset may not exist yet): {e}")
+
+    # Push
+    body = json.dumps({"asset": {"key": theme_key, "value": new_content}}).encode()
+    try:
+        r = urllib.request.urlopen(urllib.request.Request(
+            f"https://{store}/admin/api/{api}/themes/{tid}/assets.json",
+            data=body, method="PUT", headers=H))
+        print(f"  PUT HTTP {r.status} OK ({len(new_content)} bytes)")
+    except urllib.error.HTTPError as e:
+        print(f"  PUT FAILED HTTP {e.code}: {e.read().decode()[:300]}")
+        sys.exit(1)
+
+    # Spot-verify
+    check = gget(asset_url(tid, theme_key))["asset"]["value"]
+    if theme_key == "sections/collection.liquid":
+        ok = "data-collection-grid-slider" in check
+        print(f"  verify: grid slider present = {ok}")
+    elif theme_key == "assets/collection-grid-density.js":
+        ok = "STORAGE_KEY" in check and "updateGridDensity" in check
+        print(f"  verify: JS logic present = {ok}")
+    elif theme_key == "assets/custom.css":
+        ok = "collection-grid-controls" in check
+        print(f"  verify: slider CSS present = {ok}")
+    elif theme_key == "snippets/product-list-item.liquid":
+        ok = "product-list-item-description" in check
+        print(f"  verify: description field = {ok}")
+    print()
+
+print(f"\nPREVIEW: https://www.designerwallcoverings.com/collections/animal-skin" + ("" if is_live else f"?preview_theme_id={tid}"))
+print(f"REVERT:  restore from theme-backups/ files above")
+PY

← 659024e5 Restore collection page: show descriptions + add grid densit  ·  back to Designer Wallcoverings  ·  Collection cards: image-only with hover overlay (pattern nam 1b6044ab →