Mudanças entre as edições de "Widget:Teste"
Ir para navegação
Ir para pesquisar
m |
m |
||
| Linha 1: | Linha 1: | ||
<noinclude> | <noinclude> | ||
<!-- | <!-- | ||
Widget:ReportModal — formulário embutido no corpo da página (sem overlay, sem botão extra). | |||
{{#widget:ReportModal|api_base=https://TEU_DEPLOY}} | |||
Opcionais: | |||
|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 | 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- | <div class="gla-report-widget-root" data-gla-init="0" data-gla-api="{{{api_base|}}}" data-gla-wid="{{{wid|1}}}" | ||
data-gla- | 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 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- | if (byId("gla-reports-inline-css-global")) return; | ||
var st = document.createElement("style"); | var st = document.createElement("style"); | ||
st.id = "gla-reports- | st.id = "gla-reports-inline-css-global"; | ||
st.textContent = | st.textContent = | ||
".gla-report-widget-root{ | ".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- | ".gla-reports-inline-h2{font-size:1.1rem;margin:0 0 14px;color:#fff;font-weight:600}" + | ||
".gla-reports- | |||
".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- | ".gla-r-muted{background:#374151;color:#e5e7eb}" + | ||
".gla-r-msg{margin-top: | ".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 | ".gla-r-msg.gla-r-err{color:#fca5a5}"; | ||
document.head.appendChild(st); | document.head.appendChild(st); | ||
} | } | ||
var mid = "gla-form-" + wid; | |||
var mid = "gla- | |||
function | function buildFormBody() { | ||
return ( | |||
'< | '<section class="gla-reports-inline" aria-labelledby="' + | ||
mid + | mid + | ||
'- | '-tit">' + | ||
'<h2 id="' + | '<h2 class="gla-reports-inline-h2" id="' + | ||
mid + | mid + | ||
'- | '-tit">' + | ||
esc( | 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=" | '" 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 type="reset" class="gla-r-muted" id="' + | ||
mid + | mid + | ||
'- | '-reset">' + | ||
esc(" | 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>" | ||
); | |||
} | } | ||
function | function localFileOk(f) { | ||
var t = (f.type || "").toLowerCase(); | |||
var | var n = (f.name || "").toLowerCase(); | ||
if ( | if (/^image\/(png|jpeg|gif)$/.test(t)) return true; | ||
if (/\.(png|jpe?g|gif)$/.test(n)) return true; | |||
return false; | |||
} | } | ||
css(); | css(); | ||
roots.innerHTML = buildFormBody(); | |||
var form = byId(mid + "-f"); | var form = byId(mid + "-f"); | ||
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) { | ||
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; | return; | ||
} | } | ||
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 | 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 (! | 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) { | ||
var body = {}; | |||
try { | |||
body = text ? JSON.parse(text) : {}; | |||
} | } catch (ignore) { | ||
body = { _raw: text }; | |||
return { ok: r.ok, status: r.status, body: | } | ||
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(); | ||
} else { | } else { | ||
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>