From 4c2913e1310ee69b589915aa3f3dfd8680d2584d Mon Sep 17 00:00:00 2001 From: Do Siki Date: Thu, 20 Aug 2026 11:53:23 +0200 Subject: [PATCH] feat(cms): add interactive canvas logo editor modal Closes MITHOME-76: - Interactive Canvas-based modal for logo editing in CMS - Crop with presets (1:1, 3:1, 4:1, 16:9, free) - Drag-to-pan positioning and wheel/slider zoom - 90 deg rotation and horizontal/vertical flip - Configurable padding/margins around logo - Brightness, contrast, and color invert filters - Direct high-DPI (2x retina) PNG export and atomic save --- TODO.md | 2 +- scripts/cms-logo-page.js | 399 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 378 insertions(+), 23 deletions(-) diff --git a/TODO.md b/TODO.md index 66c5cff..89cd70a 100755 --- a/TODO.md +++ b/TODO.md @@ -54,7 +54,7 @@ Next.js 15 alapú weboldal a mozdIT Bt. számára, Docker Compose-szal deployolv | MITHOME-73 | Lábléc/Kapcsolat cím CMS-szerkeszthetővé tétele (common.json footer.address) | ✅ | | MITHOME-74 | CMS publish deploy: hiányzó cwd — a deploy a gyökérben landolt | ✅ | | MITHOME-75 | CMS: gyorsbillentyűk (Ctrl+S Mentés, Ctrl+P Publikálás, Ctrl+Shift+V Verziók, ? súgó) | ✅ | -| MITHOME-76 | CMS: publish public path javítása, brute-force & timing attack védelem, Docker localhost bind | ✅ | +| MITHOME-76 | CMS: Interaktív logó szerkesztő (vágás, méretezés, forgatás, margó, korrekció) | ✅ | --- diff --git a/scripts/cms-logo-page.js b/scripts/cms-logo-page.js index 487b0e4..bba78f8 100644 --- a/scripts/cms-logo-page.js +++ b/scripts/cms-logo-page.js @@ -1,5 +1,5 @@ -// Branding page for the Content Editor: upload/replace the two logos with -// client-side preview. Kept separate from cms-pages.js (file-size limits). +// Branding page for the Content Editor: upload/replace and edit logos with +// interactive Canvas editor (crop, zoom/pan, rotate/flip, padding, filters). const { LOGO_TARGETS } = require('./cms-logo'); const LOGO_PAGE = (csrfToken) => ` @@ -24,11 +24,38 @@ const LOGO_PAGE = (csrfToken) => ` .preview img { max-width: 100%; max-height: 72px; } input[type=file] { color: #94a3b8; font-size: 14px; margin-bottom: 12px; width: 100%; } .meta { font-size: 13px; color: #94a3b8; min-height: 20px; margin-bottom: 12px; } - button { background: linear-gradient(135deg,#3b82f6,#8b5cf6); color: #fff; border: none; border-radius: 8px; padding: 10px 22px; font-size: 14px; font-weight: 700; cursor: pointer; } + .actions-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; } + .btn-save { background: linear-gradient(135deg,#059669,#10b981); color: #fff; border: none; border-radius: 8px; padding: 9px 18px; font-size: 14px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; } + .btn-edit { background: linear-gradient(135deg,#3b82f6,#6366f1); color: #fff; border: none; border-radius: 8px; padding: 9px 16px; font-size: 14px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; } + .btn-secondary { background: #334155; color: #e2e8f0; border: 1px solid #475569; border-radius: 8px; padding: 9px 16px; font-size: 14px; font-weight: 600; cursor: pointer; } button:hover { filter: brightness(1.1); } button:disabled { opacity: .5; cursor: wait; } .msg { font-size: 14px; margin-top: 12px; min-height: 20px; } .ok { color: #6ee7b7; } .err { color: #fca5a5; } + + /* Modal Styles */ + .modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.85); backdrop-filter: blur(4px); z-index: 1000; display: none; align-items: center; justify-content: center; padding: 14px; } + .modal-backdrop.open { display: flex; } + .modal-box { background: #1a2035; border: 1px solid #334155; border-radius: 14px; width: 100%; max-width: 860px; max-height: 92vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 20px 40px rgba(0,0,0,0.6); } + .modal-header { padding: 12px 20px; border-bottom: 1px solid #2d3748; display: flex; align-items: center; justify-content: space-between; background: #141824; } + .modal-header h3 { font-size: 16px; color: #93c5fd; } + .btn-close { background: transparent; border: none; color: #94a3b8; font-size: 18px; cursor: pointer; padding: 4px 8px; } + .modal-body { display: grid; grid-template-columns: 1fr 280px; gap: 16px; padding: 16px; overflow-y: auto; max-height: calc(92vh - 120px); } + @media (max-width: 720px) { .modal-body { grid-template-columns: 1fr; } } + .canvas-container { background: repeating-conic-gradient(#1e293b 0% 25%, #0f1420 0% 50%) 50% / 20px 20px; border: 1px solid #334155; border-radius: 10px; display: flex; align-items: center; justify-content: center; min-height: 320px; position: relative; overflow: hidden; cursor: grab; user-select: none; } + .canvas-container.grabbing { cursor: grabbing; } + canvas { max-width: 100%; max-height: 100%; display: block; } + .editor-controls { display: flex; flex-direction: column; gap: 14px; font-size: 13px; color: #cbd5e1; } + .ctrl-group { background: #141824; border: 1px solid #2d3748; border-radius: 8px; padding: 10px 12px; } + .ctrl-group h4 { font-size: 12px; text-transform: uppercase; color: #94a3b8; margin-bottom: 8px; letter-spacing: 0.5px; } + .btn-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; } + .btn-tool { background: #1e293b; border: 1px solid #475569; color: #cbd5e1; border-radius: 6px; padding: 5px 9px; font-size: 12px; cursor: pointer; } + .btn-tool.active { background: #2563eb; color: #fff; border-color: #3b82f6; } + .slider-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; } + .slider-row label { width: 68px; font-size: 12px; color: #94a3b8; } + .slider-row input[type=range] { flex: 1; accent-color: #3b82f6; } + .slider-row span { width: 38px; font-size: 11px; text-align: right; color: #cbd5e1; } + .modal-footer { padding: 12px 20px; border-top: 1px solid #2d3748; background: #141824; display: flex; justify-content: flex-end; gap: 10px; align-items: center; } @@ -39,7 +66,7 @@ const LOGO_PAGE = (csrfToken) => `
-

Csak PNG fájl, max. 1 MB. A régi logó mentésre kerül (a 🕘 Verziókhoz hasonlóan visszavonható). A CMS-belei változás azonnal, a weboldalon a Publikálás (deploy) után jelenik meg. Ajánlott átlátszó háttérű PNG a sötét fejléchez.

+

Csak PNG fájl tölthető fel (max. 1 MB). A régi logóról automatikus biztonsági mentés készül. A szerkesztővel közvetlenül vágatod, méretezheted, forgathatod és korrigálhatod a logókat a mentés előtt. A változás a weboldalon a Publikálás (deploy) után jelenik meg.

Weboldal fejléc logója (szöveges)

@@ -47,7 +74,10 @@ const LOGO_PAGE = (csrfToken) => `
fejléc logó előnézet
- +
+ + +

@@ -57,11 +87,91 @@ const LOGO_PAGE = (csrfToken) => `
ikon logó előnézet
- +
+ + +

+ + + `;