From 9435507bc7c525092c8500af64828847147d08dc Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Mon, 8 Jun 2026 00:24:21 +0000 Subject: [PATCH] =?UTF-8?q?Ajuste=20dblclick=20para=20edi=C3=A7=C3=A3o=20d?= =?UTF-8?q?e=20texto=20e=20cards=20quadrados=20na=20barra=20lateral=20de?= =?UTF-8?q?=20assets=20do=20canvas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/app.js | 66 +++++++++++++++++++++++++++++++++++++-- server.js | 86 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/public/app.js b/public/app.js index 87e9412..7e3519c 100644 --- a/public/app.js +++ b/public/app.js @@ -7741,12 +7741,31 @@ document.addEventListener('DOMContentLoaded', () => { updateToolbarForSelected(); }); + + // Clique duplo para focar e editar texto + item.addEventListener('dblclick', (e) => { + if (!canvasModeActive) return; + if (item.querySelector('img')) return; // Evita editar imagens + + e.stopPropagation(); + item.setAttribute('contenteditable', 'true'); + item.focus(); + + // Coloca o cursor de digitação no texto + const range = document.createRange(); + range.selectNodeContents(item); + range.collapse(false); + const sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + }); item.addEventListener('mousedown', (e) => { if (!canvasModeActive) return; if (e.target.classList.contains('canvas-resize-handle')) return; - if (document.activeElement === item && e.target !== item && !e.target.classList.contains('canvas-item')) { + // Se o item já estiver focado/editando, permite seleção de texto livre sem arrastar + if (item.getAttribute('contenteditable') === 'true' && document.activeElement === item) { return; } @@ -7774,7 +7793,9 @@ document.addEventListener('DOMContentLoaded', () => { if (!canvasModeActive) return; if (e.target.classList.contains('canvas-resize-handle')) return; - if (document.activeElement === item && e.target !== item) return; + if (item.getAttribute('contenteditable') === 'true' && document.activeElement === item) { + return; + } selectedCanvasItem = item; document.querySelectorAll('.canvas-item').forEach(el => el.classList.remove('active-item')); @@ -8186,6 +8207,7 @@ document.addEventListener('DOMContentLoaded', () => { item.style.justifyContent = 'center'; item.style.gap = '6px'; item.style.transition = 'all 0.2s'; + item.style.aspectRatio = '1'; item.title = asset.nome; item.addEventListener('mouseenter', () => { @@ -8204,13 +8226,21 @@ document.addEventListener('DOMContentLoaded', () => { previewHtml = ``; } else if (asset.tipo === 'forma') { if (asset.url === 'rect') { - previewHtml = `
`; + previewHtml = `
`; + } else if (asset.url === 'square') { + previewHtml = `
`; } else if (asset.url === 'circle') { previewHtml = `
`; } else if (asset.url === 'ellipse') { previewHtml = `
`; } else if (asset.url === 'line') { previewHtml = `
`; + } else if (asset.url === 'triangle') { + previewHtml = `
`; + } else if (asset.url === 'star') { + previewHtml = `
`; + } else if (asset.url === 'arrow') { + previewHtml = `
➡️
`; } } @@ -8263,6 +8293,10 @@ document.addEventListener('DOMContentLoaded', () => { item.style.border = '3px solid ' + (cartazTextColor.value || '#2d3748'); if (asset.url === 'rect') { item.style.borderRadius = '4px'; + } else if (asset.url === 'square') { + item.style.borderRadius = '4px'; + item.style.width = '20%'; + item.style.height = '20%'; } else if (asset.url === 'circle' || asset.url === 'ellipse') { item.style.borderRadius = '50%'; item.style.width = '20%'; @@ -8272,6 +8306,32 @@ document.addEventListener('DOMContentLoaded', () => { item.style.borderTop = '4px solid ' + (cartazTextColor.value || '#2d3748'); item.style.height = '10px'; item.style.width = '40%'; + } else if (asset.url === 'triangle') { + item.style.border = 'none'; + item.style.background = cartazTextColor.value || '#2d3748'; + item.style.clipPath = 'polygon(50% 0%, 0% 100%, 100% 100%)'; + item.style.width = '20%'; + item.style.height = '20%'; + } else if (asset.url === 'star') { + item.style.border = 'none'; + item.style.color = cartazTextColor.value || '#2d3748'; + item.style.fontSize = '48px'; + item.style.display = 'flex'; + item.style.alignItems = 'center'; + item.style.justifyContent = 'center'; + item.innerHTML = '⭐'; + item.style.width = '20%'; + item.style.height = '20%'; + } else if (asset.url === 'arrow') { + item.style.border = 'none'; + item.style.color = cartazTextColor.value || '#2d3748'; + item.style.fontSize = '48px'; + item.style.display = 'flex'; + item.style.alignItems = 'center'; + item.style.justifyContent = 'center'; + item.innerHTML = '➡️'; + item.style.width = '20%'; + item.style.height = '20%'; } } diff --git a/server.js b/server.js index ed18e07..72410d0 100644 --- a/server.js +++ b/server.js @@ -2241,39 +2241,59 @@ async function initDatabase() { ); `); - const checkAssets = await dbPool.query("SELECT COUNT(*) FROM escola.biblioteca_assets;"); - if (parseInt(checkAssets.rows[0].count) === 0) { - console.log('[Database Init] Inserindo assets padrão na biblioteca (Design Canvas 2.0)...'); - await dbPool.query(` - INSERT INTO escola.biblioteca_assets (tipo, nome, url, tags) VALUES - ('postit', 'Post-it Amarelo', '#feff9c', ARRAY['post-it', 'amarelo', 'anotacao']), - ('postit', 'Post-it Azul', '#7afcff', ARRAY['post-it', 'azul', 'anotacao']), - ('postit', 'Post-it Rosa', '#ff7eb9', ARRAY['post-it', 'rosa', 'anotacao']), - ('postit', 'Post-it Verde', '#98ff98', ARRAY['post-it', 'verde', 'anotacao']), - ('postit', 'Post-it Laranja', '#ffb7b2', ARRAY['post-it', 'laranja', 'anotacao']), - - ('sticker', 'Escola', 'https://openmoji.org/data/color/svg/1F3EB.svg', ARRAY['escola', 'colegio', 'aula']), - ('sticker', 'Lápis', 'https://openmoji.org/data/color/svg/270F.svg', ARRAY['lapis', 'escrever', 'desenhar']), - ('sticker', 'Caderno', 'https://openmoji.org/data/color/svg/1F4DD.svg', ARRAY['caderno', 'anotacao', 'estudo']), - ('sticker', 'Paleta de Arte', 'https://openmoji.org/data/color/svg/1F3A8.svg', ARRAY['arte', 'paleta', 'pintura', 'desenho']), - ('sticker', 'Quebra-cabeça', 'https://openmoji.org/data/color/svg/1F9E9.svg', ARRAY['jogo', 'quebra-cabeca', 'brinquedo']), - ('sticker', 'Ursinho', 'https://openmoji.org/data/color/svg/1F9F8.svg', ARRAY['brinquedo', 'ursinho', 'fofo']), - ('sticker', 'Foguete', 'https://openmoji.org/data/color/svg/1F680.svg', ARRAY['foguete', 'espaco', 'voar']), - ('sticker', 'Notas Musicais', 'https://openmoji.org/data/color/svg/1F3B6.svg', ARRAY['musica', 'som', 'notas']), - ('sticker', 'Gatinho', 'https://openmoji.org/data/color/svg/1F431.svg', ARRAY['animal', 'gato', 'gatinho', 'fofo']), - ('sticker', 'Cachorrinho', 'https://openmoji.org/data/color/svg/1F436.svg', ARRAY['animal', 'cao', 'cachorro', 'fofo']), - ('sticker', 'Maçã', 'https://openmoji.org/data/color/svg/1F34E.svg', ARRAY['fruta', 'maca', 'comida']), - ('sticker', 'Balão', 'https://openmoji.org/data/color/svg/1F388.svg', ARRAY['festa', 'balao', 'bexiga']), - ('sticker', 'Estrela Brilhante', 'https://openmoji.org/data/color/svg/1F31F.svg', ARRAY['estrela', 'brilho', 'premio']), - ('sticker', 'Coração', 'https://openmoji.org/data/color/svg/1F496.svg', ARRAY['amor', 'coracao', 'carinho']), - ('sticker', 'Balão de Fala', 'https://openmoji.org/data/color/svg/1F4AC.svg', ARRAY['fala', 'dialogo', 'comunicacao']), - - ('forma', 'Retângulo', 'rect', ARRAY['forma', 'retangulo', 'quadrado', 'fundo']), - ('forma', 'Círculo', 'circle', ARRAY['forma', 'circulo', 'bola', 'redondo']), - ('forma', 'Elipse', 'ellipse', ARRAY['forma', 'elipse', 'oval']), - ('forma', 'Linha Horizontal', 'line', ARRAY['forma', 'linha', 'divisoria']); - `); - } + console.log('[Database Init] Atualizando assets padrão na biblioteca (Design Canvas 2.0)...'); + await dbPool.query(`TRUNCATE escola.biblioteca_assets;`); + await dbPool.query(` + INSERT INTO escola.biblioteca_assets (tipo, nome, url, tags) VALUES + ('postit', 'Post-it Amarelo', '#feff9c', ARRAY['post-it', 'amarelo', 'anotacao']), + ('postit', 'Post-it Azul', '#7afcff', ARRAY['post-it', 'azul', 'anotacao']), + ('postit', 'Post-it Rosa', '#ff7eb9', ARRAY['post-it', 'rosa', 'anotacao']), + ('postit', 'Post-it Verde', '#98ff98', ARRAY['post-it', 'verde', 'anotacao']), + ('postit', 'Post-it Laranja', '#ffb7b2', ARRAY['post-it', 'laranja', 'anotacao']), + ('postit', 'Post-it Roxo', '#e2bbff', ARRAY['post-it', 'roxo', 'anotacao']), + ('postit', 'Post-it Ciano', '#bae1ff', ARRAY['post-it', 'ciano', 'anotacao']), + ('postit', 'Post-it Branco', '#ffffff', ARRAY['post-it', 'branco', 'clean']), + + ('sticker', 'Escola', 'https://openmoji.org/data/color/svg/1F3EB.svg', ARRAY['escola', 'colegio', 'aula']), + ('sticker', 'Lápis', 'https://openmoji.org/data/color/svg/270F.svg', ARRAY['lapis', 'escrever', 'desenhar']), + ('sticker', 'Caderno', 'https://openmoji.org/data/color/svg/1F4DD.svg', ARRAY['caderno', 'anotacao', 'estudo']), + ('sticker', 'Paleta de Arte', 'https://openmoji.org/data/color/svg/1F3A8.svg', ARRAY['arte', 'paleta', 'pintura', 'desenho']), + ('sticker', 'Quebra-cabeça', 'https://openmoji.org/data/color/svg/1F9E9.svg', ARRAY['jogo', 'quebra-cabeca', 'brinquedo']), + ('sticker', 'Ursinho', 'https://openmoji.org/data/color/svg/1F9F8.svg', ARRAY['brinquedo', 'ursinho', 'fofo']), + ('sticker', 'Foguete', 'https://openmoji.org/data/color/svg/1F680.svg', ARRAY['foguete', 'espaco', 'voar']), + ('sticker', 'Notas Musicais', 'https://openmoji.org/data/color/svg/1F3B6.svg', ARRAY['musica', 'som', 'notas']), + ('sticker', 'Gatinho', 'https://openmoji.org/data/color/svg/1F431.svg', ARRAY['animal', 'gato', 'gatinho', 'fofo']), + ('sticker', 'Cachorrinho', 'https://openmoji.org/data/color/svg/1F436.svg', ARRAY['animal', 'cao', 'cachorro', 'fofo']), + ('sticker', 'Maçã', 'https://openmoji.org/data/color/svg/1F34E.svg', ARRAY['fruta', 'maca', 'comida']), + ('sticker', 'Balão', 'https://openmoji.org/data/color/svg/1F388.svg', ARRAY['festa', 'balao', 'bexiga']), + ('sticker', 'Estrela Brilhante', 'https://openmoji.org/data/color/svg/1F31F.svg', ARRAY['estrela', 'brilho', 'premio']), + ('sticker', 'Coração', 'https://openmoji.org/data/color/svg/1F496.svg', ARRAY['amor', 'coracao', 'carinho']), + ('sticker', 'Balão de Fala', 'https://openmoji.org/data/color/svg/1F4AC.svg', ARRAY['fala', 'dialogo', 'comunicacao']), + ('sticker', 'Estrela de Ouro', 'https://openmoji.org/data/color/svg/2B50.svg', ARRAY['estrela', 'ouro', 'premio']), + ('sticker', 'Medalha', 'https://openmoji.org/data/color/svg/1F3C5.svg', ARRAY['medalha', 'premio', 'vitoria']), + ('sticker', 'Troféu', 'https://openmoji.org/data/color/svg/1F3C6.svg', ARRAY['trofeu', 'premio', 'campeao']), + ('sticker', 'Lâmpada (Ideia)', 'https://openmoji.org/data/color/svg/1F4A1.svg', ARRAY['lampada', 'ideia', 'pensamento']), + ('sticker', 'Sol', 'https://openmoji.org/data/color/svg/2600.svg', ARRAY['sol', 'dia', 'tempo']), + ('sticker', 'Nuvem', 'https://openmoji.org/data/color/svg/2601.svg', ARRAY['nuvem', 'chuva', 'tempo']), + ('sticker', 'Arco-íris', 'https://openmoji.org/data/color/svg/1F308.svg', ARRAY['arco-iris', 'cores', 'natureza']), + ('sticker', 'Planta/Folha', 'https://openmoji.org/data/color/svg/1F331.svg', ARRAY['planta', 'folha', 'natureza', 'crescer']), + ('sticker', 'Livros', 'https://openmoji.org/data/color/svg/1F4DA.svg', ARRAY['livros', 'leitura', 'estudo']), + ('sticker', 'Lupa', 'https://openmoji.org/data/color/svg/1F50D.svg', ARRAY['lupa', 'pesquisa', 'detetive']), + ('sticker', 'Globo', 'https://openmoji.org/data/color/svg/1F30D.svg', ARRAY['globo', 'terra', 'mapa', 'mundo']), + ('sticker', 'Relógio', 'https://openmoji.org/data/color/svg/231A.svg', ARRAY['relogio', 'tempo', 'hora']), + ('sticker', 'Tesoura', 'https://openmoji.org/data/color/svg/2702.svg', ARRAY['tesoura', 'recorte', 'escola']), + ('sticker', 'Pincel', 'https://openmoji.org/data/color/svg/1F58C.svg', ARRAY['pincel', 'pintura', 'arte']), + ('sticker', 'Régua', 'https://openmoji.org/data/color/svg/1F4CF.svg', ARRAY['regua', 'medida', 'escola']), + + ('forma', 'Retângulo', 'rect', ARRAY['forma', 'retangulo', 'fundo']), + ('forma', 'Círculo', 'circle', ARRAY['forma', 'circulo', 'bola', 'redondo']), + ('forma', 'Elipse', 'ellipse', ARRAY['forma', 'elipse', 'oval']), + ('forma', 'Linha Horizontal', 'line', ARRAY['forma', 'linha', 'divisoria']), + ('forma', 'Quadrado', 'square', ARRAY['forma', 'quadrado']), + ('forma', 'Triângulo', 'triangle', ARRAY['forma', 'triangulo']), + ('forma', 'Estrela', 'star', ARRAY['forma', 'estrela']), + ('forma', 'Seta', 'arrow', ARRAY['forma', 'seta', 'direcao']) + `); // Garantir que a coluna character_description_english exista na tabela projetos_comics await dbPool.query(`ALTER TABLE escola.projetos_comics ADD COLUMN IF NOT EXISTS character_description_english TEXT;`);