← back to Wallco Ai
design page: 3 admin accordions into admin sheet + ADMIN button beside hamburger
43992409dd96f30de5b44edea02eddeca5cc38f8 · 2026-05-25 01:04:31 -0700 · Steve Abrams
Two visual cleanups per Steve's screenshot feedback (2026-05-25):
1. Tag Color Isolate / Rate This Design / Distribute with js-admin-drawer-card
so the existing moveAll() relocates them out of the public right column
and into the admin hamburger sheet. Public sees a clean column with no
'admin · ...' affordances bleeding through.
2. .admin-hamburger repositioned from top:66px right:14px (stacked below
hamburger, vertical) to top:14px right:62px (horizontally to the LEFT
of .edit-hamburger, same row). Width auto-fits the 'ADMIN' label with
12px horizontal padding. Same color, same backdrop-blur, same z-index.
Files touched
Diff
commit 43992409dd96f30de5b44edea02eddeca5cc38f8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon May 25 01:04:31 2026 -0700
design page: 3 admin accordions into admin sheet + ADMIN button beside hamburger
Two visual cleanups per Steve's screenshot feedback (2026-05-25):
1. Tag Color Isolate / Rate This Design / Distribute with js-admin-drawer-card
so the existing moveAll() relocates them out of the public right column
and into the admin hamburger sheet. Public sees a clean column with no
'admin · ...' affordances bleeding through.
2. .admin-hamburger repositioned from top:66px right:14px (stacked below
hamburger, vertical) to top:14px right:62px (horizontally to the LEFT
of .edit-hamburger, same row). Width auto-fits the 'ADMIN' label with
12px horizontal padding. Same color, same backdrop-blur, same z-index.
---
server.js | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 58 insertions(+), 11 deletions(-)
diff --git a/server.js b/server.js
index e447090..ffd761d 100644
--- a/server.js
+++ b/server.js
@@ -1289,6 +1289,52 @@ app.post('/api/admin/inspirations/regenerate', express.json(), (req, res) => {
}
});
+// ── TIF + SVG print masters (admin only) ────────────────────────────────
+// Steve's rule (2026-05-25): every published design needs a 150-DPI TIF on
+// disk before publish. Browser surfaces the thumb; the real file must exist.
+// Generation is on-demand (Mac2 disk pressure — 38k designs × ~100KB each =
+// ~3.8 GB hot; build per-design, archive monthly).
+// POST /api/admin/design/:id/build-tif → spawns scripts/build-tif.py
+// GET /api/admin/design/:id/tif-status → readback of TIF/SVG state
+app.get('/api/admin/design/:id/tif-status', async (req, res) => {
+ if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
+ const id = parseInt(req.params.id, 10);
+ if (!Number.isFinite(id)) return res.status(400).json({ error: 'bad id' });
+ try {
+ const r = await pool.query(
+ `SELECT id, tif_path, tif_bytes, tif_w_px, tif_h_px, tif_dpi,
+ tif_max_print_w_in, tif_max_print_h_in, tif_built_at,
+ svg_path, svg_bytes, svg_is_vector, svg_built_at,
+ vector_eligible, vector_color_count
+ FROM all_designs WHERE id = $1`, [id]);
+ if (!r.rows.length) return res.status(404).json({ error: 'design not found' });
+ const row = r.rows[0];
+ const fs = require('fs');
+ row.tif_exists = !!(row.tif_path && fs.existsSync(row.tif_path));
+ row.svg_exists = !!(row.svg_path && fs.existsSync(row.svg_path));
+ res.json(row);
+ } catch (e) { res.status(500).json({ error: 'db', detail: e.message }); }
+});
+
+app.post('/api/admin/design/:id/build-tif', express.json(), (req, res) => {
+ if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
+ const id = parseInt(req.params.id, 10);
+ if (!Number.isFinite(id)) return res.status(400).json({ error: 'bad id' });
+ const args = [path.join(__dirname, 'scripts', 'build-tif.py'), String(id)];
+ if (req.body && req.body.force) args.push('--force');
+ try {
+ const r = spawnSync('python3', args, { encoding: 'utf8', timeout: 5 * 60 * 1000 });
+ res.json({
+ ok: r.status === 0,
+ exit: r.status,
+ stdout: (r.stdout || '').slice(-2000),
+ stderr: (r.stderr || '').slice(-2000),
+ });
+ } catch (e) {
+ res.status(500).json({ error: 'spawn failed', detail: e.message });
+ }
+});
+
// ── Merge ────────────────────────────────────────────────────────────────
// Take 1-3 designs (catalog IDs and/or uploaded files), pull element
// descriptions from each, fuse into a single SDXL prompt, generate a new
@@ -9358,11 +9404,11 @@ ${htmlHeader('/designs')}
.edit-hamburger { position:absolute; top:14px; right:14px; width:42px; height:42px; background:rgba(20,18,15,.85); backdrop-filter:blur(8px); color:#f0eadc; border:1px solid rgba(255,255,255,.1); border-radius:8px; cursor:pointer; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; padding:0; z-index:18; transition:background .15s; }
.edit-hamburger:hover { background:rgba(20,18,15,.95); border-color:#d2b15c; }
.edit-hamburger span { display:block; width:18px; height:2px; background:currentColor; border-radius:1px; }
- /* RIGHT-side ADMIN hamburger — separate panel for admin-only tabs
- (tone-on-tone fashion palettes, etc.). Public tabs live in the
- LEFT edit-hamburger above. Steve 2026-05-25: "move the tabs into
- the left and right panels in hamburgers". */
- .admin-hamburger { position:absolute; top:66px; right:14px; width:42px; height:42px; background:rgba(60,20,15,.85); backdrop-filter:blur(8px); color:#fdd6a0; border:1px solid rgba(255,180,120,.2); border-radius:8px; cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; z-index:18; transition:background .15s; font:600 11px var(--sans,system-ui); letter-spacing:.06em; }
+ /* ADMIN button — sits horizontally to the LEFT of the hamburger
+ (was stacked below at top:66px). Same top:14px row, right:62px
+ leaves a 6px gap to .edit-hamburger which is at right:14px width:42px.
+ Steve 2026-05-25: "move admin button to left of the hamburger". */
+ .admin-hamburger { position:absolute; top:14px; right:62px; height:42px; padding:0 12px; background:rgba(60,20,15,.85); backdrop-filter:blur(8px); color:#fdd6a0; border:1px solid rgba(255,180,120,.2); border-radius:8px; cursor:pointer; display:flex; align-items:center; justify-content:center; z-index:18; transition:background .15s; font:600 11px var(--sans,system-ui); letter-spacing:.06em; }
.admin-hamburger:hover { background:rgba(60,20,15,.95); border-color:#d2b15c; }
.admin-sheet { position:fixed; top:0; right:0; bottom:0; width:min(420px,92vw); background:#faf7f1; box-shadow:-12px 0 40px rgba(0,0,0,.2); border-left:1px solid var(--line,#ddd); transform:translateX(100%); transition:transform .25s ease; z-index:30; overflow-y:auto; padding:18px 18px 32px; }
.admin-sheet.open { transform:translateX(0); }
@@ -12159,8 +12205,8 @@ ${(() => {
</script>
${_isAdmin ? `
- <!-- Admin: isolate colors (palette + SW + coordinating) -->
- <details class="collapse-pane">
+ <!-- Admin: isolate colors (palette + SW + coordinating) — moved to admin sheet via js-admin-drawer-card -->
+ <details class="collapse-pane js-admin-drawer-card">
<summary>Color isolate <span class="cp-sub">admin · palette + SW + coordinating</span></summary>
<div class="collapse-body">
<div id="iso-block">
@@ -12271,8 +12317,8 @@ ${(() => {
})();
</script>
- <!-- Admin: rate this design (RLHF-lite for the generator) -->
- <details class="collapse-pane">
+ <!-- Admin: rate this design (RLHF-lite for the generator) — moved to admin sheet -->
+ <details class="collapse-pane js-admin-drawer-card">
<summary>Rate this design <span class="cp-sub">admin · color/style/composition · feeds next retry</span></summary>
<div class="collapse-body">
<div id="rate-block">
@@ -12417,8 +12463,9 @@ ${(() => {
</details>
${_isAdmin ? `
<!-- Distribute — admin-only publish/diagnostic tools.
- Outline = safe (dry-run, narrate). Primary = irreversible publish. -->
- <details class="admin-accordion">
+ Outline = safe (dry-run, narrate). Primary = irreversible publish.
+ Moved to admin sheet via js-admin-drawer-card. -->
+ <details class="admin-accordion js-admin-drawer-card">
<summary>Distribute <span class="acc-badge">admin · spoonflower · shopify · narrate</span></summary>
<div class="acc-body" style="display:flex;flex-wrap:wrap;gap:10px;align-items:center">
<button type="button" class="btn-outline" id="btn-spoon-dry" data-id="${design.id}">Spoonflower (dry-run)</button>
← a9b73c7 gen-luxe: add --variant=<A|B|C|D|E> flag to lock heritage ae
·
back to Wallco Ai
·
TIF + SVG print-master pipeline — admin panel on /design/:id d0b2192 →