Implandação da customização das permissões dos usuarios e das notificaçoes
This commit is contained in:
@@ -82,22 +82,54 @@
|
||||
</div>
|
||||
|
||||
<%# ── Variáveis ─────────────────────────────────────── %>
|
||||
<%# ── EMOJIS ─────────────────────────────────────────
|
||||
Digitar emoji no teclado do computador é o passo que trava o ADM;
|
||||
aqui ele clica. A lista é curta e curada de propósito — um seletor
|
||||
completo viraria uma biblioteca externa (e CSP) para inserir 3
|
||||
caracteres. %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-4 mb-4">
|
||||
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Emojis</p>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<% %w[✅ ❌ ⚠️ 📌 📢 💰 💵 🧾 📅 🕒 🚚 📦 📍 👤 👍 🙏 ⭐ 🔴 🟢 🟡 ➡️ 📄 📷 🔔 ✍️ 😀 🎉].each do |emoji| %>
|
||||
<button type="button" class="chip-emoji w-9 h-9 rounded-lg bg-[#0a0a0a] border border-white/10
|
||||
hover:border-[#f97316] text-lg leading-none"
|
||||
data-emoji="<%= emoji %>" title="Inserir <%= emoji %>"><%= emoji %></button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-4">
|
||||
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Variáveis</p>
|
||||
<p class="text-xs text-gray-500 mb-3">
|
||||
Clique num campo da mensagem e depois numa variável para inseri-la ali.
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
<% @variaveis.each do |nome, meta| %>
|
||||
<button type="button" title="<%= meta[:descricao] %> (ex.: <%= meta[:amostra] %>)"
|
||||
class="chip-variavel px-2.5 py-1 rounded-full bg-[#f97316]/10 border border-[#f97316]/30
|
||||
text-xs font-mono text-[#f97316] hover:bg-[#f97316]/20 hover:border-[#f97316]
|
||||
transition-colors cursor-pointer"
|
||||
data-variavel="<%= nome %>">
|
||||
<%= "{{#{nome}}}" %>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# Agrupadas por ORIGEM e sem esconder o que não se aplica: a variável
|
||||
de outro gatilho aparece apagada, com o aviso de que sai em branco.
|
||||
Antes, a tela só listava as 6 do contexto — qualquer outro dado
|
||||
exigia deploy. %>
|
||||
<% @variaveis.each do |origem, itens| %>
|
||||
<% next if itens.empty? %>
|
||||
<p class="text-[11px] uppercase tracking-wider text-gray-500 mt-3 mb-1.5">
|
||||
<%= Notificacao::CatalogoVariaveis::ORIGENS[origem] %>
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
<% itens.each do |v| %>
|
||||
<button type="button"
|
||||
title="<%= v[:descricao] %> (ex.: <%= v[:amostra] %>)<%= ' — não existe neste gatilho: sai em branco' unless v[:aplicavel] %>"
|
||||
class="chip-variavel px-2.5 py-1 rounded-full text-xs font-mono transition-colors cursor-pointer
|
||||
<%= v[:aplicavel] ? 'bg-[#f97316]/10 border border-[#f97316]/30 text-[#f97316] hover:bg-[#f97316]/20 hover:border-[#f97316]' : 'bg-white/5 border border-white/10 text-gray-500 hover:border-gray-500' %>"
|
||||
data-variavel="<%= v[:chave] %>">
|
||||
{{<%= v[:chave] %>}}<%= ' ·' unless v[:aplicavel] %>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<p class="text-[11px] text-gray-500 mt-3 leading-relaxed">
|
||||
As apagadas (·) não existem neste gatilho e sairiam em branco.
|
||||
<%= link_to 'Criar variável própria', admin_variaveis_path, class: 'text-orange-500 hover:underline' %>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -312,20 +344,29 @@
|
||||
});
|
||||
}
|
||||
|
||||
// ── Variáveis: insere no cursor do último campo focado ─────
|
||||
// ── Inserção no cursor do último campo focado ──────────────
|
||||
// Serve para variável e para emoji: a mecânica é a mesma (recortar o valor
|
||||
// na posição do cursor e reemitir `input` para o JSON do editor atualizar).
|
||||
function inserirNoCampo(texto) {
|
||||
if (!ultimoCampo) { alert('Clique primeiro no campo onde o texto deve entrar.'); return; }
|
||||
var ini = ultimoCampo.selectionStart != null ? ultimoCampo.selectionStart : ultimoCampo.value.length;
|
||||
var fim = ultimoCampo.selectionEnd != null ? ultimoCampo.selectionEnd : ini;
|
||||
ultimoCampo.value = ultimoCampo.value.slice(0, ini) + texto + ultimoCampo.value.slice(fim);
|
||||
ultimoCampo.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
ultimoCampo.focus();
|
||||
ultimoCampo.selectionStart = ultimoCampo.selectionEnd = ini + texto.length;
|
||||
}
|
||||
|
||||
document.querySelectorAll('.chip-variavel').forEach(function (chip) {
|
||||
chip.addEventListener('click', function () {
|
||||
var texto = '{{' + chip.dataset.variavel + '}}';
|
||||
if (!ultimoCampo) { alert('Clique primeiro no campo onde a variável deve entrar.'); return; }
|
||||
var ini = ultimoCampo.selectionStart != null ? ultimoCampo.selectionStart : ultimoCampo.value.length;
|
||||
var fim = ultimoCampo.selectionEnd != null ? ultimoCampo.selectionEnd : ini;
|
||||
ultimoCampo.value = ultimoCampo.value.slice(0, ini) + texto + ultimoCampo.value.slice(fim);
|
||||
ultimoCampo.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
ultimoCampo.focus();
|
||||
ultimoCampo.selectionStart = ultimoCampo.selectionEnd = ini + texto.length;
|
||||
inserirNoCampo('{{' + chip.dataset.variavel + '}}');
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.chip-emoji').forEach(function (chip) {
|
||||
chip.addEventListener('click', function () { inserirNoCampo(chip.dataset.emoji); });
|
||||
});
|
||||
|
||||
// ── Preview: renderizado no servidor, pelo mesmo código do envio ──
|
||||
var token = document.querySelector('meta[name="csrf-token"]');
|
||||
document.getElementById('btn-preview').addEventListener('click', function () {
|
||||
|
||||
Reference in New Issue
Block a user