saçvar painel selecionado
This commit is contained in:
parent
a0dd05b518
commit
65118f2838
4 changed files with 170 additions and 0 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
|
|
@ -23,12 +24,128 @@ func main() {
|
||||||
js.Global().Set("__eli_nps_wasm_decidir", js.FuncOf(decidir))
|
js.Global().Set("__eli_nps_wasm_decidir", js.FuncOf(decidir))
|
||||||
js.Global().Set("__eli_nps_wasm_cooldown_ativo", js.FuncOf(cooldownAtivo))
|
js.Global().Set("__eli_nps_wasm_cooldown_ativo", js.FuncOf(cooldownAtivo))
|
||||||
js.Global().Set("__eli_nps_wasm_set_cooldown", js.FuncOf(setCooldown))
|
js.Global().Set("__eli_nps_wasm_set_cooldown", js.FuncOf(setCooldown))
|
||||||
|
js.Global().Set("__eli_nps_wasm_painel_init", js.FuncOf(painelInit))
|
||||||
js.Global().Set("__eli_nps_wasm_ready", true)
|
js.Global().Set("__eli_nps_wasm_ready", true)
|
||||||
|
|
||||||
// Mantém o módulo vivo.
|
// Mantém o módulo vivo.
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func painelInit(this js.Value, args []js.Value) any {
|
||||||
|
// Painel: persistência de filtros no localStorage.
|
||||||
|
// Regras (.agent): lógica no WASM (Go). Aqui é best-effort e fail-open.
|
||||||
|
//
|
||||||
|
// - Salva: produto selecionado + checkbox "baixas".
|
||||||
|
// - Restaura: se a URL não tiver parâmetros e houver valor salvo,
|
||||||
|
// redireciona para /painel?produto=...&baixas=1.
|
||||||
|
//
|
||||||
|
// Importante: não roda fora do /painel.
|
||||||
|
loc := js.Global().Get("location")
|
||||||
|
if loc.IsUndefined() || loc.IsNull() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
path := loc.Get("pathname").String()
|
||||||
|
if path == "" || !strings.HasPrefix(path, "/painel") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
storage := js.Global().Get("localStorage")
|
||||||
|
if storage.IsUndefined() || storage.IsNull() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyProd = "eli_nps_painel_produto"
|
||||||
|
const keyBaixas = "eli_nps_painel_baixas"
|
||||||
|
|
||||||
|
// Aguarda o DOM estar pronto para conseguirmos acessar o form/option list.
|
||||||
|
doc := js.Global().Get("document")
|
||||||
|
if doc.IsUndefined() || doc.IsNull() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := js.FuncOf(func(this js.Value, args []js.Value) any {
|
||||||
|
// Best-effort: evita exceptions se APIs não existirem.
|
||||||
|
defer func() { _ = recover() }()
|
||||||
|
|
||||||
|
form := doc.Call("querySelector", `form[action="/painel"]`)
|
||||||
|
if form.IsUndefined() || form.IsNull() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sel := form.Call("querySelector", `select[name="produto"]`)
|
||||||
|
chk := form.Call("querySelector", `input[name="baixas"]`)
|
||||||
|
|
||||||
|
// Helper: verifica se option existe.
|
||||||
|
optionExists := func(selectEl js.Value, value string) bool {
|
||||||
|
if selectEl.IsUndefined() || selectEl.IsNull() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
opts := selectEl.Get("options")
|
||||||
|
ln := opts.Get("length").Int()
|
||||||
|
for i := 0; i < ln; i++ {
|
||||||
|
opt := opts.Index(i)
|
||||||
|
if opt.Get("value").String() == value {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
persist := func() {
|
||||||
|
if !sel.IsUndefined() && !sel.IsNull() {
|
||||||
|
v := strings.TrimSpace(sel.Get("value").String())
|
||||||
|
if v != "" {
|
||||||
|
storage.Call("setItem", keyProd, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baixas := "0"
|
||||||
|
if !chk.IsUndefined() && !chk.IsNull() && chk.Get("checked").Truthy() {
|
||||||
|
baixas = "1"
|
||||||
|
}
|
||||||
|
storage.Call("setItem", keyBaixas, baixas)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restaura/redirect apenas se não há query string.
|
||||||
|
s := loc.Get("search").String()
|
||||||
|
if strings.TrimSpace(s) == "" {
|
||||||
|
storedProd := strings.TrimSpace(storage.Call("getItem", keyProd).String())
|
||||||
|
storedBaixas := strings.TrimSpace(storage.Call("getItem", keyBaixas).String())
|
||||||
|
if storedProd != "" && optionExists(sel, storedProd) {
|
||||||
|
q := "?produto=" + url.QueryEscape(storedProd)
|
||||||
|
if storedBaixas == "1" {
|
||||||
|
q += "&baixas=1"
|
||||||
|
}
|
||||||
|
loc.Call("replace", path+q)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Se só baixas estiver setado, aplica também.
|
||||||
|
if storedBaixas == "1" {
|
||||||
|
loc.Call("replace", path+"?baixas=1")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liga listeners para persistência.
|
||||||
|
onSubmit := js.FuncOf(func(this js.Value, args []js.Value) any { persist(); return nil })
|
||||||
|
onChange := js.FuncOf(func(this js.Value, args []js.Value) any { persist(); return nil })
|
||||||
|
form.Call("addEventListener", "submit", onSubmit)
|
||||||
|
form.Call("addEventListener", "change", onChange)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
// DOMContentLoaded
|
||||||
|
readyState := doc.Get("readyState").String()
|
||||||
|
if readyState != "loading" {
|
||||||
|
// Se o WASM foi carregado depois do DOM pronto (comum no painel),
|
||||||
|
// rodamos imediatamente.
|
||||||
|
handler.Invoke()
|
||||||
|
} else {
|
||||||
|
doc.Call("addEventListener", "DOMContentLoaded", handler)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func cooldownAtivo(this js.Value, args []js.Value) any {
|
func cooldownAtivo(this js.Value, args []js.Value) any {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,10 @@ th,td{padding:8px;border-bottom:1px solid #eee;text-align:left;vertical-align:to
|
||||||
|
|
||||||
b.WriteString("</div>")
|
b.WriteString("</div>")
|
||||||
|
|
||||||
|
// JS do painel: apenas bootstrap para executar a lógica no WASM.
|
||||||
|
// Regras (.agent): sem dependências externas. A lógica fica no WASM.
|
||||||
|
b.WriteString(`<script src="/static/wasm_exec.js"></script><script src="/static/painel.js"></script>`)
|
||||||
|
|
||||||
b.WriteString("</body></html>")
|
b.WriteString("</body></html>")
|
||||||
w.Write([]byte(b.String()))
|
w.Write([]byte(b.String()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
49
web/static/painel.js
Normal file
49
web/static/painel.js
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
(function(){
|
||||||
|
// Bootstrap mínimo do painel.
|
||||||
|
// Regra (.agent): a lógica fica no WASM; aqui apenas garantimos que o WASM
|
||||||
|
// esteja carregado/executando.
|
||||||
|
//
|
||||||
|
// Este arquivo existe para evitar JS inline no HTML do painel.
|
||||||
|
|
||||||
|
async function carregarWasmPainel(){
|
||||||
|
try{
|
||||||
|
if(window.__eli_nps_wasm_ready) return true;
|
||||||
|
if(window.__eli_nps_wasm_loading) return window.__eli_nps_wasm_loading;
|
||||||
|
|
||||||
|
window.__eli_nps_wasm_loading = (async function(){
|
||||||
|
try{
|
||||||
|
if(!window.Go){
|
||||||
|
// wasm_exec.js deve ter sido carregado pelo HTML.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const go = new Go();
|
||||||
|
const res = await fetch('/static/e-li.nps.wasm', {cache: 'no-cache'});
|
||||||
|
if(!res.ok) return false;
|
||||||
|
const bytes = await res.arrayBuffer();
|
||||||
|
const {instance} = await WebAssembly.instantiate(bytes, go.importObject);
|
||||||
|
go.run(instance);
|
||||||
|
return !!window.__eli_nps_wasm_ready;
|
||||||
|
}catch(e){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return window.__eli_nps_wasm_loading;
|
||||||
|
}catch(e){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function(){
|
||||||
|
carregarWasmPainel().then(function(ok){
|
||||||
|
if(!ok) return;
|
||||||
|
// Executa o init do painel no WASM (best-effort).
|
||||||
|
try{
|
||||||
|
if(typeof window.__eli_nps_wasm_painel_init === 'function'){
|
||||||
|
window.__eli_nps_wasm_painel_init();
|
||||||
|
}
|
||||||
|
}catch(e){}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue