tagliatelle

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

include-previews.go (3098B)


      1 package main
      2 
      3 import (
      4 	"fmt"
      5 	"strings"
      6 )
      7 
      8 // getPreviewFiles returns one representative file for each tag value in the specified category
      9 func getPreviewFiles(filters []filter) ([]File, error) {
     10 	// Find the preview filter category
     11 	var previewCategory string
     12 	for _, f := range filters {
     13 		if f.IsPreviews {
     14 			previewCategory = f.Category
     15 			break
     16 		}
     17 	}
     18 
     19 	if previewCategory == "" {
     20 		return []File{}, nil
     21 	}
     22 
     23 	// First, get all tag values for the preview category that have files
     24 	tagQuery := `
     25 		SELECT DISTINCT t.value
     26 		FROM tags t
     27 		JOIN categories c ON t.category_id = c.id
     28 		JOIN file_tags ft ON ft.tag_id = t.id
     29 		WHERE c.name = ?
     30 		ORDER BY t.value`
     31 
     32 	tagRows, err := db.Query(tagQuery, previewCategory)
     33 	if err != nil {
     34 		return nil, fmt.Errorf("failed to query tag values: %w", err)
     35 	}
     36 	defer tagRows.Close()
     37 
     38 	var tagValues []string
     39 	for tagRows.Next() {
     40 		var tagValue string
     41 		if err := tagRows.Scan(&tagValue); err != nil {
     42 			return nil, fmt.Errorf("failed to scan tag value: %w", err)
     43 		}
     44 		tagValues = append(tagValues, tagValue)
     45 	}
     46 
     47 
     48 	if len(tagValues) == 0 {
     49 		return []File{}, nil
     50 	}
     51 
     52 	// For each tag value, find one representative file
     53 	var allFiles []File
     54 	for _, tagValue := range tagValues {
     55 		// Build query for this specific tag value with all filters applied
     56 		query := `SELECT f.id, f.filename, f.path, COALESCE(f.description, '') as description
     57 			FROM files f
     58 			WHERE 1=1`
     59 		args := []interface{}{}
     60 
     61 		// Apply all filters (including the preview category with this specific value)
     62 		for _, filter := range filters {
     63 			if filter.IsPreviews {
     64 				// For the preview filter, use the current tag value we're iterating over
     65 				query += `
     66 					AND EXISTS (
     67 						SELECT 1
     68 						FROM file_tags ft
     69 						JOIN tags t ON ft.tag_id = t.id
     70 						JOIN categories c ON c.id = t.category_id
     71 						WHERE ft.file_id = f.id AND c.name = ? AND t.value = ?
     72 					)`
     73 				args = append(args, filter.Category, tagValue)
     74 			} else if filter.Value == "unassigned" {
     75 				query += `
     76 					AND NOT EXISTS (
     77 						SELECT 1
     78 						FROM file_tags ft
     79 						JOIN tags t ON ft.tag_id = t.id
     80 						JOIN categories c ON c.id = t.category_id
     81 						WHERE ft.file_id = f.id AND c.name = ?
     82 					)`
     83 				args = append(args, filter.Category)
     84 			} else {
     85 				// Normal filter with aliases
     86 				placeholders := make([]string, len(filter.Values))
     87 				for i := range filter.Values {
     88 					placeholders[i] = "?"
     89 				}
     90 
     91 				query += fmt.Sprintf(`
     92 					AND EXISTS (
     93 						SELECT 1
     94 						FROM file_tags ft
     95 						JOIN tags t ON ft.tag_id = t.id
     96 						JOIN categories c ON c.id = t.category_id
     97 						WHERE ft.file_id = f.id AND c.name = ? AND t.value IN (%s)
     98 					)`, strings.Join(placeholders, ","))
     99 
    100 				args = append(args, filter.Category)
    101 				for _, v := range filter.Values {
    102 					args = append(args, v)
    103 				}
    104 			}
    105 		}
    106 
    107 		query += ` ORDER BY f.id DESC LIMIT 1`
    108 
    109 		files, err := queryFilesWithTags(query, args...)
    110 		if err != nil {
    111 			return nil, fmt.Errorf("failed to query files for tag %s: %w", tagValue, err)
    112 		}
    113 
    114 		if len(files) > 0 {
    115 			allFiles = append(allFiles, files[0])
    116 		}
    117 	}
    118 
    119 	return allFiles, nil
    120 }