Mudanças entre as edições de "Widget:Teste"
Ir para navegação
Ir para pesquisar
m |
|||
| (333 revisões intermediárias por 2 usuários não estão sendo mostradas) | |||
| Linha 1: | Linha 1: | ||
< | <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=https://wiki.gla.com.br | |||
--> | |||
</noinclude> | |||
<div class="gla-report-widget-root" data-gla-init="0" data-gla-api="{{{api_base|}}}" data-gla-wid="{{{wid|1}}}" | |||
data-gla-heading="{{{heading|}}}"></div> | |||
<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">' + | |||
} | '<h2 class="gla-reports-inline-h2" id="' + | ||
mid + | |||
'-tit">' + | |||
esc(HEADING) + | |||
"</h2>" + | |||
'<form id="' + | |||
mid + | |||
'-f" novalidate>' + | |||
'<div class="gla-r-field"><label for="' + | |||
mid + | |||
'-title">Título <span style="opacity:.65">(opcional, até ' + | |||
MAX_TITLE + | |||
" caracteres)</span></label>" + | |||
'<input type="text" id="' + | |||
mid + | |||
'-title" name="name" maxlength="' + | |||
MAX_TITLE + | |||
'" autocomplete="off" placeholder="Ex.: erro na página X"/></div>' + | |||
'<div class="gla-r-field"><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></div>" + | |||
'<div class="gla-r-field"><label for="' + | |||
mid + | |||
'-desc">Descrição <span style="color:#fca5a5">*</span></label>' + | |||
'<textarea id="' + | |||
mid + | |||
'-desc" name="description" maxlength="8000" required placeholder="Descrição detalhada"></textarea></div>' + | |||
'<div class="gla-r-field"><label for="' + | |||
mid + | |||
'-img">Imagem (opcional)</label>' + | |||
'<input type="file" id="' + | |||
mid + | |||
'-img" accept="image/png,image/jpeg,image/gif"/></div>' + | |||
'<div class="gla-r-actions">' + | |||
'<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></div>" + | |||
'<p class="gla-r-msg" id="' + | |||
mid + | |||
'-msg" role="status"></p>' + | |||
"</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> | |||
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>