tagliatelle

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

general.go (3640B)


      1 package app
      2 
      3 import (
      4 	"log"
      5 	"net/http"
      6 	"net/url"
      7 	"strings"
      8 )
      9 
     10 type TagDisplay struct {
     11 	Value string
     12 	Count int
     13 }
     14 
     15 type ListData struct {
     16 	Tagged      []File
     17 	Untagged    []File
     18 	Breadcrumbs []Breadcrumb
     19 }
     20 
     21 type PageData struct {
     22 	Title         string
     23 	Data          interface{}
     24 	Query         string
     25 	IP            string
     26 	Port          string
     27 	Files         []File
     28 	Tags          map[string][]TagDisplay
     29 	Properties    map[string][]PropertyDisplay
     30 	Breadcrumbs   []Breadcrumb
     31 	Pagination    *Pagination
     32 	GallerySize   string
     33 	UntaggedCount int
     34 }
     35 
     36 type File struct {
     37 	ID              int
     38 	Filename        string
     39 	EscapedFilename string
     40 	Path            string
     41 	Description     string
     42 	Tags            map[string][]string
     43 }
     44 
     45 func sanitizeFilename(filename string) string {
     46 	if filename == "" {
     47 		return "file"
     48 	}
     49 	filename = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(filename, "/", "_"), "\\", "_"), "..", "_")
     50 	if filename == "" {
     51 		return "file"
     52 	}
     53 	return filename
     54 }
     55 
     56 func renderError(w http.ResponseWriter, message string, statusCode int) {
     57 	http.Error(w, message, statusCode)
     58 }
     59 
     60 func renderTemplate(w http.ResponseWriter, tmplName string, data PageData) {
     61 	if err := Tmpl.ExecuteTemplate(w, tmplName, data); err != nil {
     62 		log.Printf("Error: renderTemplate: failed to execute template %s: %v", tmplName, err)
     63 		renderError(w, "Template rendering failed", http.StatusInternalServerError)
     64 	}
     65 }
     66 
     67 func redirectWithWarning(w http.ResponseWriter, r *http.Request, baseURL, warningMsg string) {
     68 	redirectURL := baseURL
     69 	if warningMsg != "" {
     70 		redirectURL += "?warning=" + url.QueryEscape(warningMsg)
     71 	}
     72 	http.Redirect(w, r, redirectURL, http.StatusSeeOther)
     73 }
     74 
     75 func errorString(err error) string {
     76 	if err != nil {
     77 		return err.Error()
     78 	}
     79 	return ""
     80 }
     81 
     82 func successString(err error, msg string) string {
     83 	if err == nil {
     84 		return msg
     85 	}
     86 	return ""
     87 }
     88 
     89 func buildPageData(title string, data interface{}) PageData {
     90 	tagMap, err := getTagData()
     91 	if err != nil {
     92 		log.Printf("Warning: buildPageData: failed to load tag data for page %q: %v", title, err)
     93 	}
     94 	propMap, err := getPropertyNav()
     95 	if err != nil {
     96 		log.Printf("Warning: buildPageData: failed to load property nav for page %q: %v", title, err)
     97 	}
     98 	return PageData{
     99 		Title:         title,
    100 		Data:          data,
    101 		Tags:          tagMap,
    102 		Properties:    propMap,
    103 		GallerySize:   Cfg.GallerySize,
    104 		UntaggedCount: getUntaggedCount(),
    105 	}
    106 }
    107 
    108 func getTagData() (map[string][]TagDisplay, error) {
    109 	rows, err := DB.Query(`
    110 		SELECT c.name, t.value, COUNT(ft.file_id)
    111 		FROM tags t
    112 		JOIN categories c ON c.id = t.category_id
    113 		LEFT JOIN file_tags ft ON ft.tag_id = t.id
    114 		GROUP BY t.id
    115 		HAVING COUNT(ft.file_id) > 0
    116 		ORDER BY c.name, t.value`)
    117 	if err != nil {
    118 		return nil, err
    119 	}
    120 	defer rows.Close()
    121 
    122 	tagMap := make(map[string][]TagDisplay)
    123 	for rows.Next() {
    124 		var cat, val string
    125 		var count int
    126 		if err := rows.Scan(&cat, &val, &count); err != nil {
    127 			log.Printf("Warning: getTagData: failed to scan row: %v", err)
    128 			continue
    129 		}
    130 		tagMap[cat] = append(tagMap[cat], TagDisplay{Value: val, Count: count})
    131 	}
    132 	if err := rows.Err(); err != nil {
    133 		return tagMap, err
    134 	}
    135 	return tagMap, nil
    136 }
    137 
    138 func tagsHandler(w http.ResponseWriter, r *http.Request) {
    139 	pageData := buildPageData("All Tags", nil)
    140 	pageData.Data = pageData.Tags
    141 	renderTemplate(w, "tags.html", pageData)
    142 }
    143 
    144 func getUntaggedCount() int {
    145 	var count int
    146 
    147 	err := DB.QueryRow(`
    148 		SELECT COUNT(*)
    149 		FROM files f
    150 		LEFT JOIN file_tags ft ON ft.file_id = f.id
    151 		WHERE ft.file_id IS NULL
    152 	`).Scan(&count)
    153 
    154 	if err != nil {
    155 		log.Printf("Warning: getUntaggedCount: %v", err)
    156 		return 0
    157 	}
    158 	return count
    159 }