Mudanças entre as edições de "Widget:Teste"

De Wiki Gla
Ir para navegação Ir para pesquisar
m
m
 
Linha 1: Linha 1:
<noinclude>
<noinclude>
   <!--
   <!--
   GLA — Widget:ReportModal (Extension:Widgets)
   Widget:ReportModal — formulário embutido no corpo da página (sem overlay, sem botão extra).


   Cola **ISTO TUDO** em [[Widget:ReportModal]].
   {{#widget:ReportModal|api_base=https://TEU_DEPLOY}}
  A versão anterior (.html) estava **truncada** (id="gla-o-{{#widget:}}…") e:
  - quebrava o HTML da página inteira (tags abertas);
  - deixava o overlay visível sem `hidden` → fundo escuro em ecrã completo;
  - podia mostrar {{{...}}} sem expandir.


   Uso: {{#widget:ReportModal|api_base=https://TEU_DEPLOY}}
   Opcionais:
  Opcionais: |label=... |wid=2
    |wid=2      — vários widgets na mesma página (ids únicos)
    |heading=   — título da caixa (vazio → "Report ou sugestão")


   No servidor: REPORTS_CORS_ORIGINS com o origin da wiki.
   No servidor: REPORTS_CORS_ORIGINS=https://wiki.gla.com.br
-->
-->
</noinclude>
</noinclude>
<div class="gla-report-widget-root" data-gla-api="{{{api_base|}}}" data-gla-label="{{{label|Reportar}}}"
<div class="gla-report-widget-root" data-gla-init="0" data-gla-api="{{{api_base|}}}" data-gla-wid="{{{wid|1}}}"
   data-gla-wid="{{{wid|1}}}"></div>
   data-gla-heading="{{{heading|}}}"></div>
<script>
<script>
   /*<![CDATA[*/
   /*<![CDATA[*/
   (function () {
   (function () {
     "use strict";
     "use strict";
     var roots = document.currentScript.previousElementSibling;
     var roots = document.currentScript.previousElementSibling;
     if (!roots || !roots.classList || !roots.classList.contains("gla-report-widget-root")) {
     if (!roots || !roots.classList || !roots.classList.contains("gla-report-widget-root")) {
Linha 29: Linha 27:


     var REPORTS_API_BASE = (roots.getAttribute("data-gla-api") || "").replace(/\/$/, "");
     var REPORTS_API_BASE = (roots.getAttribute("data-gla-api") || "").replace(/\/$/, "");
    var BUTTON_LABEL = roots.getAttribute("data-gla-label") || "Reportar";
     var wid = String(roots.getAttribute("data-gla-wid") || "1").replace(/[^a-zA-Z0-9_-]/g, "");
     var wid = String(roots.getAttribute("data-gla-wid") || "1").replace(/[^a-zA-Z0-9_-]/g, "");
    var HEADING = roots.getAttribute("data-gla-heading") || "";
    if (!HEADING) HEADING = "Report ou sugestão";


     var MAX_TITLE = 60;
     var MAX_TITLE = 60;
Linha 46: Linha 45:


     function css() {
     function css() {
       if (byId("gla-reports-modal-css-global")) return;
       if (byId("gla-reports-inline-css-global")) return;
       var st = document.createElement("style");
       var st = document.createElement("style");
       st.id = "gla-reports-modal-css-global";
       st.id = "gla-reports-inline-css-global";
       st.textContent =
       st.textContent =
         ".gla-report-widget-root{display:inline-block;vertical-align:middle}" +
         ".gla-report-widget-root{width:100%;max-width:520px;margin:1rem 0;display:block;clear:both}" +
        ".gla-reports-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:2147483640;display:flex;align-items:center;justify-content:center;padding:16px}" +
         ".gla-reports-inline{max-width:100%;box-sizing:border-box;background:#111827;color:#f9fafb;border-radius:12px;padding:18px 20px;font:14px/1.45 system-ui,sans-serif;border:1px solid #374151;box-shadow:0 8px 24px rgba(0,0,0,.15)}" +
         ".gla-reports-overlay[hidden]{display:none!important}" +
         ".gla-reports-inline-h2{font-size:1.1rem;margin:0 0 14px;color:#fff;font-weight:600}" +
        ".gla-reports-modal-bx{max-width:480px;width:100%;max-height:90vh;overflow:auto;background:#111827;color:#f9fafb;border-radius:12px;padding:20px;font:14px/1.45 system-ui,sans-serif;box-shadow:0 24px 48px rgba(0,0,0,.4);border:1px solid #374151}" +
         ".gla-reports-modal-bx h2{font-size:1.1rem;margin:0 0 14px;color:#fff}" +
         ".gla-r-field{margin-bottom:12px}" +
         ".gla-r-field{margin-bottom:12px}" +
         ".gla-r-field label{display:block;font-size:.8rem;color:#d1d5db;margin-bottom:4px}" +
         ".gla-r-field label{display:block;font-size:.8rem;color:#d1d5db;margin-bottom:4px}" +
         ".gla-r-field input[type=text],.gla-r-field select,.gla-r-field textarea{width:100%;box-sizing:border-box;border-radius:8px;border:1px solid #4b5563;background:#1f2937;color:#fff;padding:8px 10px;font:inherit}" +
         ".gla-r-field input[type=text],.gla-r-field select,.gla-r-field textarea{width:100%;box-sizing:border-box;border-radius:8px;border:1px solid #4b5563;background:#1f2937;color:#fff;padding:8px 10px;font:inherit}" +
         ".gla-r-field textarea{min-height:120px;resize:vertical}" +
         ".gla-r-field textarea{min-height:120px;resize:vertical}" +
         ".gla-r-actions{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap}" +
         ".gla-r-actions{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap;align-items:center}" +
         ".gla-r-actions button{border-radius:8px;padding:10px 16px;font:inherit;border:0;cursor:pointer}" +
         ".gla-r-actions button{border-radius:8px;padding:10px 16px;font:inherit;border:0;cursor:pointer}" +
         ".gla-r-primary{background:#6366f1;color:#fff}" +
         ".gla-r-primary{background:#6366f1;color:#fff}" +
         ".gla-r-secondary{background:#374151;color:#e5e7eb}" +
         ".gla-r-muted{background:#374151;color:#e5e7eb}" +
         ".gla-r-msg{margin-top:10px;font-size:.85rem;min-height:1.2em}" +
         ".gla-r-msg{margin-top:12px;font-size:.85rem;min-height:1.2em}" +
         ".gla-r-msg.ok{color:#6ee7b7}" +
         ".gla-r-msg.gla-r-ok{color:#6ee7b7}" +
         ".gla-r-msg.err{color:#fca5a5}" +
         ".gla-r-msg.gla-r-err{color:#fca5a5}";
        ".gla-report-open-btn{font:inherit;cursor:pointer;border-radius:8px;padding:8px 14px;border:1px solid #4b5563;background:#1f2937;color:#e5e7eb}";
       document.head.appendChild(st);
       document.head.appendChild(st);
     }
     }


    var oid = "gla-o-" + wid;
     var mid = "gla-form-" + wid;
     var mid = "gla-m-" + wid;


     function buildModal(host) {
     function buildFormBody() {
       host.innerHTML =
       return (
         '<div class="gla-reports-overlay" id="' +
         '<section class="gla-reports-inline" aria-labelledby="' +
        oid +
        '" hidden role="presentation">' +
        '<div class="gla-reports-modal-bx" role="dialog" aria-modal="true" aria-labelledby="' +
         mid +
         mid +
         '-t">' +
         '-tit">' +
         '<h2 id="' +
         '<h2 class="gla-reports-inline-h2" id="' +
         mid +
         mid +
         '-t">' +
         '-tit">' +
         esc("Report ou sugestão") +
         esc(HEADING) +
         "</h2>" +
         "</h2>" +
         '<form id="' +
         '<form id="' +
Linha 91: Linha 83:
         '<div class="gla-r-field"><label for="' +
         '<div class="gla-r-field"><label for="' +
         mid +
         mid +
         '-title">Título <span style="opacity:.65">(até ' +
         '-title">Título <span style="opacity:.65">(opcional, até ' +
         MAX_TITLE +
         MAX_TITLE +
         " caracteres)</span></label>" +
         " caracteres)</span></label>" +
Linha 98: Linha 90:
         '-title" name="name" maxlength="' +
         '-title" name="name" maxlength="' +
         MAX_TITLE +
         MAX_TITLE +
         '" placeholder="Opcional"/></div>' +
         '" autocomplete="off" placeholder="Ex.: erro na página X"/></div>' +
         '<div class="gla-r-field"><label for="' +
         '<div class="gla-r-field"><label for="' +
         mid +
         mid +
Linha 130: Linha 122:
         esc("Enviar") +
         esc("Enviar") +
         "</button>" +
         "</button>" +
         '<button type="button" class="gla-r-secondary" id="' +
         '<button type="reset" class="gla-r-muted" id="' +
         mid +
         mid +
         '-cancel">' +
         '-reset">' +
         esc("Fechar") +
         esc("Limpar") +
         "</button></div>" +
         "</button></div>" +
         '<p class="gla-r-msg" id="' +
         '<p class="gla-r-msg" id="' +
         mid +
         mid +
         '-msg"></p>' +
         '-msg" role="status"></p>' +
         "</form>" +
         "</form></section>"
        "</div></div>";
       );
    }
 
    function openModal(overlay) {
      overlay.removeAttribute("hidden");
      var t = byId(mid + "-title");
       if (t) t.focus();
     }
     }


     function closeModal(overlay) {
     function localFileOk(f) {
       overlay.setAttribute("hidden", "");
       var t = (f.type || "").toLowerCase();
       var m = byId(mid + "-msg");
       var n = (f.name || "").toLowerCase();
       if (m) {
       if (/^image\/(png|jpeg|gif)$/.test(t)) return true;
        m.textContent = "";
      if (/\.(png|jpe?g|gif)$/.test(n)) return true;
        m.className = "gla-r-msg";
       return false;
       }
     }
     }


     css();
     css();
    roots.innerHTML = buildFormBody();


    var btn = document.createElement("button");
    btn.type = "button";
    btn.className = "gla-report-open-btn";
    btn.textContent = BUTTON_LABEL;
    roots.appendChild(btn);
    var modalHost = document.createElement("div");
    roots.appendChild(modalHost);
    buildModal(modalHost);
    var overlay = byId(oid);
     var form = byId(mid + "-f");
     var form = byId(mid + "-f");
    var btnCancel = byId(mid + "-cancel");
     var btnSend = byId(mid + "-send");
     var btnSend = byId(mid + "-send");
     var msg = byId(mid + "-msg");
     var msg = byId(mid + "-msg");


     if (!REPORTS_API_BASE) {
     if (!REPORTS_API_BASE) {
       btn.disabled = true;
       if (btnSend) btnSend.disabled = true;
       btn.title = "Define api_base no widget (api_base=https://...)";
       if (msg) {
        msg.textContent = "Configura api_base na wiki: api_base=https://…";
        msg.className = "gla-r-msg gla-r-err";
      }
       return;
       return;
     }
     }
    btn.addEventListener("click", function () {
      openModal(overlay);
    });
    btnCancel.addEventListener("click", function () {
      closeModal(overlay);
    });
    overlay.addEventListener("click", function (e) {
      if (e.target === overlay) closeModal(overlay);
    });


     form.addEventListener("submit", function (e) {
     form.addEventListener("submit", function (e) {
Linha 203: Linha 170:
       if (!desc) {
       if (!desc) {
         msg.textContent = "Preencha a descrição.";
         msg.textContent = "Preencha a descrição.";
         msg.className = "gla-r-msg err";
         msg.className = "gla-r-msg gla-r-err";
         return;
         return;
       }
       }
       if (title.length > MAX_TITLE) {
       if (title.length > MAX_TITLE) {
         msg.textContent = "Título muito longo.";
         msg.textContent = "Título longo demais.";
         msg.className = "gla-r-msg err";
         msg.className = "gla-r-msg gla-r-err";
         return;
         return;
       }
       }
Linha 220: Linha 187:
         if (f.size > MAX_BYTES) {
         if (f.size > MAX_BYTES) {
           msg.textContent = "Imagem acima de 5 MB.";
           msg.textContent = "Imagem acima de 5 MB.";
           msg.className = "gla-r-msg err";
           msg.className = "gla-r-msg gla-r-err";
           return;
           return;
         }
         }
         if (!/^image\/(png|jpeg|gif)$/i.test(f.type)) {
         if (!localFileOk(f)) {
           msg.textContent = "Só PNG, JPG ou GIF.";
           msg.textContent = "Só PNG, JPG ou GIF.";
           msg.className = "gla-r-msg err";
           msg.className = "gla-r-msg gla-r-err";
           return;
           return;
         }
         }
Linha 236: Linha 203:
       fetch(url, { method: "POST", body: fd })
       fetch(url, { method: "POST", body: fd })
         .then(function (r) {
         .then(function (r) {
           return r
           return r.text().then(function (text) {
            .json()
            var body = {};
            .catch(function () {
             try {
              return {};
              body = text ? JSON.parse(text) : {};
             })
             } catch (ignore) {
             .then(function (j) {
               body = { _raw: text };
               return { ok: r.ok, status: r.status, body: j };
            }
            });
            return { ok: r.ok, status: r.status, body: body, raw: text };
          });
         })
         })
         .then(function (result) {
         .then(function (result) {
           if (result.ok) {
           if (result.ok) {
             msg.textContent = "Enviado. Obrigado!";
             msg.textContent = "Enviado. Obrigado!";
             msg.className = "gla-r-msg ok";
             msg.className = "gla-r-msg gla-r-ok";
             form.reset();
             form.reset();
            setTimeout(function () {
              closeModal(overlay);
            }, 1500);
           } else {
           } else {
             msg.textContent =
             var detail =
               (result.body && result.body.error) || "Erro " + result.status;
               (result.body && result.body.error) ||
             msg.className = "gla-r-msg err";
              (result.raw && result.raw.slice(0, 200)) ||
              "";
            msg.textContent = detail
              ? detail + " (" + result.status + ")"
              : "Erro " + result.status;
             msg.className = "gla-r-msg gla-r-err";
           }
           }
         })
         })
Linha 262: Linha 232:
           msg.textContent =
           msg.textContent =
             "Rede ou CORS: confirma api_base e REPORTS_CORS_ORIGINS no servidor.";
             "Rede ou CORS: confirma api_base e REPORTS_CORS_ORIGINS no servidor.";
           msg.className = "gla-r-msg err";
           msg.className = "gla-r-msg gla-r-err";
         })
         })
         .then(function () {
         .then(function () {

Edição atual tal como às 16h07min de 28 de abril de 2026


<script>

 /*<![CDATA[*/
 (function () {
   "use strict";
   var roots = document.currentScript.previousElementSibling;
   if (!roots || !roots.classList || !roots.classList.contains("gla-report-widget-root")) {
     roots = document.querySelector(".gla-report-widget-root:not([data-gla-init])");
   }
   if (!roots || roots.getAttribute("data-gla-init")) return;
   roots.setAttribute("data-gla-init", "1");
   var REPORTS_API_BASE = (roots.getAttribute("data-gla-api") || "").replace(/\/$/, "");
   var wid = String(roots.getAttribute("data-gla-wid") || "1").replace(/[^a-zA-Z0-9_-]/g, "");
   var HEADING = roots.getAttribute("data-gla-heading") || "";
   if (!HEADING) HEADING = "Report ou sugestão";
   var MAX_TITLE = 60;
   var MAX_BYTES = 5 * 1024 * 1024;
   function esc(s) {
     var d = document.createElement("div");
     d.textContent = s == null ? "" : String(s);
     return d.innerHTML;
   }
   function byId(id) {
     return document.getElementById(id);
   }
   function css() {
     if (byId("gla-reports-inline-css-global")) return;
     var st = document.createElement("style");
     st.id = "gla-reports-inline-css-global";
     st.textContent =
       ".gla-report-widget-root{width:100%;max-width:520px;margin:1rem 0;display:block;clear:both}" +
       ".gla-reports-inline{max-width:100%;box-sizing:border-box;background:#111827;color:#f9fafb;border-radius:12px;padding:18px 20px;font:14px/1.45 system-ui,sans-serif;border:1px solid #374151;box-shadow:0 8px 24px rgba(0,0,0,.15)}" +
       ".gla-reports-inline-h2{font-size:1.1rem;margin:0 0 14px;color:#fff;font-weight:600}" +
       ".gla-r-field{margin-bottom:12px}" +
       ".gla-r-field label{display:block;font-size:.8rem;color:#d1d5db;margin-bottom:4px}" +
       ".gla-r-field input[type=text],.gla-r-field select,.gla-r-field textarea{width:100%;box-sizing:border-box;border-radius:8px;border:1px solid #4b5563;background:#1f2937;color:#fff;padding:8px 10px;font:inherit}" +
       ".gla-r-field textarea{min-height:120px;resize:vertical}" +
       ".gla-r-actions{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap;align-items:center}" +
       ".gla-r-actions button{border-radius:8px;padding:10px 16px;font:inherit;border:0;cursor:pointer}" +
       ".gla-r-primary{background:#6366f1;color:#fff}" +
       ".gla-r-muted{background:#374151;color:#e5e7eb}" +
       ".gla-r-msg{margin-top:12px;font-size:.85rem;min-height:1.2em}" +
       ".gla-r-msg.gla-r-ok{color:#6ee7b7}" +
       ".gla-r-msg.gla-r-err{color:#fca5a5}";
     document.head.appendChild(st);
   }
   var mid = "gla-form-" + wid;
   function buildFormBody() {
     return (
       '<section class="gla-reports-inline" aria-labelledby="' +
       mid +
       '-tit">' +

'

' + esc(HEADING) + "

" +

       '<form id="' +
       mid +
       '-f" novalidate>' +

'

<label for="' +
       mid +
       '-title">Título (opcional, até ' +
       MAX_TITLE +
       " caracteres)</label>" +
       '<input type="text" id="' +
       mid +
       '-title" name="name" maxlength="' +
       MAX_TITLE +
'" autocomplete="off" placeholder="Ex.: erro na página X"/>

' + '

<label for="' +
       mid +
       '-cat">Categoria</label>' +
       '<select id="' +
       mid +
       '-cat" name="category" required>' +
       '<option value="report">' +
       esc("Report") +
       "</option>" +
       '<option value="suggestion">' +
       esc("Sugestão") +
       "</option>" +
"</select>

" + '

<label for="' +
       mid +
       '-desc">Descrição *</label>' +
       '<textarea id="' +
       mid +
'-desc" name="description" maxlength="8000" required placeholder="Descrição detalhada"></textarea>

' + '

<label for="' +
       mid +
       '-img">Imagem (opcional)</label>' +
       '<input type="file" id="' +
       mid +
'-img" accept="image/png,image/jpeg,image/gif"/>

' + '

' +
       '<button type="submit" class="gla-r-primary" id="' +
       mid +
       '-send">' +
       esc("Enviar") +
       "</button>" +
       '<button type="reset" class="gla-r-muted" id="' +
       mid +
       '-reset">' +
       esc("Limpar") +
"</button>

" + '

' +

       "</form></section>"
     );
   }
   function localFileOk(f) {
     var t = (f.type || "").toLowerCase();
     var n = (f.name || "").toLowerCase();
     if (/^image\/(png|jpeg|gif)$/.test(t)) return true;
     if (/\.(png|jpe?g|gif)$/.test(n)) return true;
     return false;
   }
   css();
   roots.innerHTML = buildFormBody();
   var form = byId(mid + "-f");
   var btnSend = byId(mid + "-send");
   var msg = byId(mid + "-msg");
   if (!REPORTS_API_BASE) {
     if (btnSend) btnSend.disabled = true;
     if (msg) {
       msg.textContent = "Configura api_base na wiki: api_base=https://…";
       msg.className = "gla-r-msg gla-r-err";
     }
     return;
   }
   form.addEventListener("submit", function (e) {
     e.preventDefault();
     var title = (byId(mid + "-title").value || "").trim();
     var cat = byId(mid + "-cat").value;
     var desc = (byId(mid + "-desc").value || "").trim();
     var fileIn = byId(mid + "-img");
     msg.textContent = "";
     msg.className = "gla-r-msg";
     if (!desc) {
       msg.textContent = "Preencha a descrição.";
       msg.className = "gla-r-msg gla-r-err";
       return;
     }
     if (title.length > MAX_TITLE) {
       msg.textContent = "Título longo demais.";
       msg.className = "gla-r-msg gla-r-err";
       return;
     }
     var fd = new FormData();
     if (title) fd.append("name", title);
     fd.append("category", cat);
     fd.append("description", desc);
     if (fileIn.files && fileIn.files[0]) {
       var f = fileIn.files[0];
       if (f.size > MAX_BYTES) {
         msg.textContent = "Imagem acima de 5 MB.";
         msg.className = "gla-r-msg gla-r-err";
         return;
       }
       if (!localFileOk(f)) {
         msg.textContent = "Só PNG, JPG ou GIF.";
         msg.className = "gla-r-msg gla-r-err";
         return;
       }
       fd.append("image", f);
     }
     btnSend.disabled = true;
     var url = REPORTS_API_BASE + "/api/reports";
     fetch(url, { method: "POST", body: fd })
       .then(function (r) {
         return r.text().then(function (text) {
           var body = {};
           try {
             body = text ? JSON.parse(text) : {};
           } catch (ignore) {
             body = { _raw: text };
           }
           return { ok: r.ok, status: r.status, body: body, raw: text };
         });
       })
       .then(function (result) {
         if (result.ok) {
           msg.textContent = "Enviado. Obrigado!";
           msg.className = "gla-r-msg gla-r-ok";
           form.reset();
         } else {
           var detail =
             (result.body && result.body.error) ||
             (result.raw && result.raw.slice(0, 200)) ||
             "";
           msg.textContent = detail
             ? detail + " (" + result.status + ")"
             : "Erro " + result.status;
           msg.className = "gla-r-msg gla-r-err";
         }
       })
       .catch(function () {
         msg.textContent =
           "Rede ou CORS: confirma api_base e REPORTS_CORS_ORIGINS no servidor.";
         msg.className = "gla-r-msg gla-r-err";
       })
       .then(function () {
         btnSend.disabled = false;
       });
   });
 })();
 /*]]>*/

</script>