Optimizacije — SQLite WAL, template keš, gzip kompresija, build skript
This commit is contained in:
@@ -2,9 +2,12 @@ package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ntech/internal/db/sqlite"
|
||||
@@ -25,6 +28,8 @@ type PodaciPodesavanja struct {
|
||||
LogoPutanja string
|
||||
Tema string
|
||||
Sacuvano bool
|
||||
Verzija string
|
||||
LogoGreska string
|
||||
}
|
||||
|
||||
// Podesavanja renderuje stranicu podešavanja
|
||||
@@ -55,23 +60,11 @@ func (h *Handler) Podesavanja(w http.ResponseWriter, r *http.Request) {
|
||||
LogoPutanja: podesavanja["logo_putanja"],
|
||||
Tema: podesavanja["tema"],
|
||||
Sacuvano: r.URL.Query().Get("sacuvano") == "1",
|
||||
Verzija: h.Verzija,
|
||||
LogoGreska: r.URL.Query().Get("logo_greska"),
|
||||
}
|
||||
|
||||
tmpl, err := template.ParseFiles(
|
||||
"web/templates/teme/podrazumevana/base.html",
|
||||
"web/templates/komponente/sidebar.html",
|
||||
"web/templates/komponente/topbar.html",
|
||||
"web/templates/stranice/podesavanja.html",
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, "Greška pri učitavanju stranice", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := tmpl.ExecuteTemplate(w, "base", podaci); err != nil {
|
||||
http.Error(w, "Greška pri prikazu stranice", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
h.renderujTemplate(w, "podesavanja", podaci)
|
||||
}
|
||||
|
||||
// SacuvajPodesavanja prima POST i čuva podešavanja u bazu
|
||||
@@ -120,13 +113,88 @@ func (h *Handler) BackupBaze(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, privremeni)
|
||||
}
|
||||
|
||||
// OtpremiLogo prima multipart upload slike loga i čuva je u web/static/uploads/
|
||||
func (h *Handler) OtpremiLogo(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseMultipartForm(2 << 20); err != nil {
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Fajl+je+prevelik+%28maksimum+2+MB%29", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
fajl, zaglavlje, err := r.FormFile("logo")
|
||||
if err != nil {
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Nije+odabran+fajl", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
defer fajl.Close()
|
||||
|
||||
// proveravamo ekstenziju
|
||||
ext := strings.ToLower(filepath.Ext(zaglavlje.Filename))
|
||||
dozvoljenoExt := map[string]string{
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".svg": "image/svg+xml",
|
||||
}
|
||||
ocekivaniMime, ok := dozvoljenoExt[ext]
|
||||
if !ok {
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Dozvoljeni+formati+su+PNG%2C+JPG+i+SVG", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// za binarne formate proveravamo i stvarni tip fajla (SVG je tekstualni, preskačemo)
|
||||
if ext != ".svg" {
|
||||
buf := make([]byte, 512)
|
||||
n, _ := fajl.Read(buf)
|
||||
stvarniMime := http.DetectContentType(buf[:n])
|
||||
if !strings.HasPrefix(stvarniMime, ocekivaniMime) {
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Sadržaj+fajla+ne+odgovara+odabranoj+ekstenziji", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
// vraćamo kursor na početak
|
||||
if _, err := fajl.Seek(0, io.SeekStart); err != nil {
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+obradi+fajla", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// brišemo stare logo fajlove
|
||||
stari, _ := filepath.Glob("web/static/uploads/logo.*")
|
||||
for _, s := range stari {
|
||||
os.Remove(s)
|
||||
}
|
||||
|
||||
odrediste := "web/static/uploads/logo" + ext
|
||||
dst, err := os.Create(odrediste)
|
||||
if err != nil {
|
||||
log.Printf("upload loga: ne mogu kreirati fajl: %v", err)
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+čuvanju+fajla", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, fajl); err != nil {
|
||||
log.Printf("upload loga: greška pri kopiranju: %v", err)
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+čuvanju+fajla", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
putanja := "/static/uploads/logo" + ext
|
||||
if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "logo_putanja", putanja); err != nil {
|
||||
log.Printf("upload loga: greška pri čuvanju putanje: %v", err)
|
||||
http.Redirect(w, r, "/podesavanja?logo_greska=Greška+pri+čuvanju+podešavanja", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/podesavanja?sacuvano=1", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// PromeniTemu menja aktivnu temu i vraća na prethodnu stranicu
|
||||
func (h *Handler) PromeniTemu(w http.ResponseWriter, r *http.Request) {
|
||||
tema := chi.URLParam(r, "tema")
|
||||
|
||||
// proveravamo da li je validna tema
|
||||
validne := map[string]bool{
|
||||
"tamna": true, "svetla": true, "zelena": true, "ljubicasta": true,
|
||||
"tamna": true, "svetla": true,
|
||||
}
|
||||
if !validne[tema] {
|
||||
http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
|
||||
|
||||
Reference in New Issue
Block a user