← back to Wallco Ai
generator: replace dead DW-orders palette with style-guide palettes + fix the page-killing onclick escaping
dafdb2d58376ec84f6c1d4c7e4b67b78a4ad1139 · 2026-06-01 16:48:03 -0700 · Steve Abrams
- Swap the 'DW orders palette' card + 'Refresh from Shopify (last 50)' button + 'DW Orders palette (last 40)' grid for a Style Guides palette section sourced from /api/styleguides/brands (30 houses / 111 swatches). Swatch click appends a hex to batch Colors; house-name click loads the whole palette. Event-delegated, density slider persisted to localStorage.
- Fix pre-existing fatal bug: the batch-picker onclick builders (toggleBatchTexture/Style/Element + suggest-palette + pickBatchPattern) emitted single-backslash \' escapes that the server template literal collapsed to bare quotes, throwing 'Unexpected string' / 'missing )' and aborting the ENTIRE inline script. The whole generator UI (cron, recipes, runs, all pickers) was dead client-side on prod. Corrected escaping; refactored pickBatchPattern to data-idx event delegation instead of inlining JSON.stringify into an attribute.
- Verified headless (Playwright): 0 console errors, all sections render + interact.
Files touched
Diff
commit dafdb2d58376ec84f6c1d4c7e4b67b78a4ad1139
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jun 1 16:48:03 2026 -0700
generator: replace dead DW-orders palette with style-guide palettes + fix the page-killing onclick escaping
- Swap the 'DW orders palette' card + 'Refresh from Shopify (last 50)' button + 'DW Orders palette (last 40)' grid for a Style Guides palette section sourced from /api/styleguides/brands (30 houses / 111 swatches). Swatch click appends a hex to batch Colors; house-name click loads the whole palette. Event-delegated, density slider persisted to localStorage.
- Fix pre-existing fatal bug: the batch-picker onclick builders (toggleBatchTexture/Style/Element + suggest-palette + pickBatchPattern) emitted single-backslash \' escapes that the server template literal collapsed to bare quotes, throwing 'Unexpected string' / 'missing )' and aborting the ENTIRE inline script. The whole generator UI (cron, recipes, runs, all pickers) was dead client-side on prod. Corrected escaping; refactored pickBatchPattern to data-idx event delegation instead of inlining JSON.stringify into an attribute.
- Verified headless (Playwright): 0 console errors, all sections render + interact.
---
server.js | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/server.js b/server.js
index 3b32b6e..5295823 100644
--- a/server.js
+++ b/server.js
@@ -22200,14 +22200,14 @@ var TEXTURE_OPTIONS = ['grasscloth','cork','raffia','mica','linen','silk','sisal
async function loadBatchPickers(){
document.getElementById('batch-texture-picker').innerHTML = TEXTURE_OPTIONS.map(function(t){
- return '<button onclick="toggleBatchTexture(\''+t+'\')" data-tex="'+t+'" style="padding:3px 9px;font-size:11px;border-radius:11px;border:1px solid #555;background:#0f0e0c;color:#aaa;cursor:pointer;text-transform:capitalize">'+t+'</button>';
+ return '<button onclick="toggleBatchTexture(\\''+t+'\\')" data-tex="'+t+'" style="padding:3px 9px;font-size:11px;border-radius:11px;border:1px solid #555;background:#0f0e0c;color:#aaa;cursor:pointer;text-transform:capitalize">'+t+'</button>';
}).join('');
var [styles, elements] = await Promise.all([
fetch('/api/studio/styles').then(r=>r.json()),
fetch('/api/studio/elements').then(r=>r.json())
]);
document.getElementById('batch-styles-picker').innerHTML = styles.map(function(s){
- return '<button onclick="toggleBatchStyle(\''+(s.name.replace(/[\\\\\']/g,''))+'\')" data-style="'+s.name+'" style="padding:3px 9px;font-size:11px;border-radius:11px;border:1px solid #555;background:#0f0e0c;color:#aaa;cursor:pointer">'+s.name+'</button>';
+ return '<button onclick="toggleBatchStyle(\\''+(s.name.replace(/[\\\\\']/g,''))+'\\')" data-style="'+s.name+'" style="padding:3px 9px;font-size:11px;border-radius:11px;border:1px solid #555;background:#0f0e0c;color:#aaa;cursor:pointer">'+s.name+'</button>';
}).join('');
// Group elements by category for tighter display
var byCat = {};
@@ -22215,14 +22215,14 @@ async function loadBatchPickers(){
document.getElementById('batch-elements-picker').innerHTML = Object.keys(byCat).sort().map(function(c){
return '<div style="width:100%;font-size:9px;text-transform:uppercase;color:#666;letter-spacing:.08em;margin-top:4px">'+c+'</div>' +
byCat[c].map(function(e){
- return '<button onclick="toggleBatchElement(\''+e.name+'\')" data-el="'+e.name+'" style="padding:2px 8px;font-size:11px;border-radius:9px;border:1px solid #555;background:#0f0e0c;color:#aaa;cursor:pointer;margin:1px">'+e.name+'</button>';
+ return '<button onclick="toggleBatchElement(\\''+e.name+'\\')" data-el="'+e.name+'" style="padding:2px 8px;font-size:11px;border-radius:9px;border:1px solid #555;background:#0f0e0c;color:#aaa;cursor:pointer;margin:1px">'+e.name+'</button>';
}).join('');
}).join('');
// Suggest 3 starter palettes for color hint
var pj = await fetch('/api/studio/suggest-palettes',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'}).then(r=>r.json());
document.getElementById('batch-color-suggest').innerHTML =
'Suggested: ' + (pj.palettes||[]).slice(0,3).map(function(p){
- return '<span style="cursor:pointer;text-decoration:underline" onclick="document.getElementById(\'batch-colors\').value=\''+(p.colors||[]).join(', ')+'\'">'+p.name+'</span>';
+ return '<span style="cursor:pointer;text-decoration:underline" onclick="document.getElementById(\\'batch-colors\\').value=\\''+(p.colors||[]).join(', ')+'\\'">'+p.name+'</span>';
}).join(' · ');
}
@@ -22257,16 +22257,26 @@ window.toggleBatchTexture = function(name){
}
};
+// Pattern search results — kept in a module array + clicked via event delegation
+// (data-idx), instead of inlining JSON.stringify(x) into an onclick attribute.
+// The inline form mangled quote-escaping inside the server template literal.
+var BATCH_SEARCH = [];
document.getElementById('batch-patterns').addEventListener('input', async function(e){
var q = e.target.value.trim();
- if (q.length < 2) { document.getElementById('batch-patterns-results').innerHTML=''; return; }
+ if (q.length < 2) { document.getElementById('batch-patterns-results').innerHTML=''; BATCH_SEARCH=[]; return; }
var r = await fetch('/api/studio/search?q='+encodeURIComponent(q)+'&limit=24').then(x=>x.json());
- document.getElementById('batch-patterns-results').innerHTML = r.map(function(x){
- return '<div onclick="pickBatchPattern('+JSON.stringify(x).replace(/"/g,'"').replace(/'/g,'\\\\\'')+')" style="cursor:pointer;border:1px solid #444;border-radius:4px;padding:2px;background:#0f0e0c" title="'+((x.title||'').slice(0,60))+'">'+
+ BATCH_SEARCH = Array.isArray(r) ? r : [];
+ document.getElementById('batch-patterns-results').innerHTML = BATCH_SEARCH.map(function(x, i){
+ return '<div class="bp-result" data-idx="'+i+'" style="cursor:pointer;border:1px solid #444;border-radius:4px;padding:2px;background:#0f0e0c" title="'+((x.title||'').slice(0,60).replace(/"/g,'"'))+'">'+
(x.thumb_url?'<img src="'+x.thumb_url+'" loading="lazy" style="width:100%;aspect-ratio:1;object-fit:cover;border-radius:3px">':'<div style="aspect-ratio:1;background:'+(x.dominant_hex||'#222')+'"></div>')+
'</div>';
}).join('');
});
+document.getElementById('batch-patterns-results').addEventListener('click', function(e){
+ var card = e.target.closest('.bp-result'); if (!card) return;
+ var x = BATCH_SEARCH[parseInt(card.dataset.idx, 10)];
+ if (x) pickBatchPattern(x);
+});
window.pickBatchPattern = function(p){
if (BATCH.patterns.find(function(x){return x.id===p.id && x.source===p.source;})) return;
BATCH.patterns.push(p);
← 46878b0 add Path B surgical color-name backfill (re-derive title col
·
back to Wallco Ai
·
add PDP theme smoke test — verifies every theme renders + v1 8919030 →