taggart

Simple golang tagging filesystem webapp
Log | Files | Refs

commit 40d7b0a18047e7c294229d172ca0f9f59a0dc198
parent dd3f7e7ff47fa8ad30cc19115bafc3b738d2bedf
Author: breadcat <breadcat@users.noreply.github.com>
Date:   Sun, 21 Sep 2025 11:04:07 +0100

Rudimentary search feature

Diffstat:
Mmain.go | 42++++++++++++++++++++++++++++++++++++++++++
Mtemplates/_header.html | 2+-
Atemplates/search.html | 38++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/main.go b/main.go @@ -92,12 +92,54 @@ func main() { http.HandleFunc("/tags", tagsHandler) http.HandleFunc("/tag/", tagFilterHandler) http.HandleFunc("/untagged", untaggedFilesHandler) + http.HandleFunc("/search", searchHandler) http.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir("uploads")))) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) log.Println("Server started at http://localhost:8080") http.ListenAndServe(":8080", nil) +func searchHandler(w http.ResponseWriter, r *http.Request) { + query := strings.TrimSpace(r.URL.Query().Get("q")) + + var files []File + var searchTitle string + + if query != "" { + // Convert wildcards to SQL LIKE pattern + // * becomes % and ? becomes _ (standard SQL wildcards) + sqlPattern := strings.ReplaceAll(query, "*", "%") + sqlPattern = strings.ReplaceAll(sqlPattern, "?", "_") + + // Search for files matching the pattern + rows, err := db.Query("SELECT id, filename, path FROM files WHERE filename LIKE ? ORDER BY filename", sqlPattern) + if err != nil { + http.Error(w, "Search failed", http.StatusInternalServerError) + return + } + defer rows.Close() + + for rows.Next() { + var f File + rows.Scan(&f.ID, &f.Filename, &f.Path) + files = append(files, f) + } + + searchTitle = fmt.Sprintf("Search Results for: %s", query) + } else { + searchTitle = "Search Files" + } + + // Always initialize the data structure properly + pageData := PageData{ + Title: searchTitle, + Data: struct { + Files []File + Query string + }{files, query}, + } + + tmpl.ExecuteTemplate(w, "search.html", pageData) } // Upload file from URL diff --git a/templates/_header.html b/templates/_header.html @@ -23,5 +23,5 @@ ul.tag-menu li ul li a:hover{background:#ddd} </style> </head> <body> -<p><a href="/upload">Upload new file</a> | <a href="/">Files</a> | <a href="/tags">Tags</a> | <a href="/untagged">Untagged</a></p> +<p><a href="/upload">Upload new file</a> | <a href="/">Files</a> | <a href="/tags">Tags</a> | <a href="/untagged">Untagged</a> | <a href="/search">Search</a></p> {{end}} \ No newline at end of file diff --git a/templates/search.html b/templates/search.html @@ -0,0 +1,37 @@ +{{template "_header" .}} +<h1>Search Files</h1> + +<form method="get" action="/search" style="margin-bottom: 30px;"> + <input type="text" name="q" value="{{.Data.Query}}" placeholder="Search filenames (use * for wildcards)" style="width: 400px; padding: 8px; font-size: 16px;"> + <button type="submit" style="padding: 8px 16px; font-size: 16px;">Search</button> +</form> + +<div style="background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 20px;"> + <h3>Wildcard Examples:</h3> + <ul> + <li><code>*class*.jpg</code> - finds files containing "class" and ending with ".jpg"</li> + <li><code>photo*</code> - finds files starting with "photo"</li> + <li><code>*.pdf</code> - finds all PDF files</li> + <li><code>IMG_????_*.jpg</code> - finds files like "IMG_2023_vacation.jpg" (? matches single character)</li> + <li><code>*vacation*</code> - finds files containing "vacation" anywhere</li> + </ul> +</div> + +{{if .Data.Files}} + <h2>Found {{len .Data.Files}} file{{if ne (len .Data.Files) 1}}s{{end}}</h2> + <div class="file-grid"> + {{range .Data.Files}} + <div class="file-item"> + <a href="/file/{{.ID}}">{{.Filename}}</a> + {{if hasAnySuffix .Filename ".jpg" ".jpeg" ".png" ".gif" ".webp"}} + <br><img src="/uploads/{{.Filename}}" style="max-width: 100%; height: auto;" /> + {{end}} + </div> + {{end}} + </div> +{{else if .Data.Query}} + <p>No files found matching "<strong>{{.Data.Query}}</strong>"</p> + <p>Try using wildcards like <code>*{{.Data.Query}}*</code> for broader results.</p> +{{end}} + +{{template "_footer"}} +\ No newline at end of file