tagliatelle

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

previews.go (3333B)


      1 package app
      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 	if len(tagValues) == 0 {
     48 		return []File{}, nil
     49 	}
     50 
     51 	// For each tag value, find one representative file
     52 	var allFiles []File
     53 	for _, tagValue := range tagValues {
     54 		// Build query for this specific tag value with all filters applied
     55 		query := `SELECT f.id, f.filename, f.path, COALESCE(f.description, '') as description
     56 			FROM files f
     57 			WHERE 1=1`
     58 		args := []interface{}{}
     59 
     60 		// Apply all filters (including the preview category with this specific value)
     61 		for _, filter := range filters {
     62 			if filter.IsPreviews {
     63 				// For the preview filter, use the current tag value we're iterating over
     64 				query += `
     65 					AND EXISTS (
     66 						SELECT 1
     67 						FROM file_tags ft
     68 						JOIN tags t ON ft.tag_id = t.id
     69 						JOIN categories c ON c.id = t.category_id
     70 						WHERE ft.file_id = f.id AND c.name = ? AND t.value = ?
     71 					)`
     72 				args = append(args, filter.Category, tagValue)
     73 			} else if filter.IsProperty {
     74 				query += `
     75 					AND EXISTS (
     76 						SELECT 1
     77 						FROM file_properties fp
     78 						WHERE fp.file_id = f.id AND fp.key = ? AND fp.value = ?
     79 					)`
     80 				args = append(args, filter.Category, filter.Value)
     81 			} else if filter.Value == "unassigned" {
     82 				query += `
     83 					AND NOT EXISTS (
     84 						SELECT 1
     85 						FROM file_tags ft
     86 						JOIN tags t ON ft.tag_id = t.id
     87 						JOIN categories c ON c.id = t.category_id
     88 						WHERE ft.file_id = f.id AND c.name = ?
     89 					)`
     90 				args = append(args, filter.Category)
     91 			} else {
     92 				// Normal filter with aliases
     93 				placeholders := make([]string, len(filter.Values))
     94 				for i := range filter.Values {
     95 					placeholders[i] = "?"
     96 				}
     97 
     98 				query += fmt.Sprintf(`
     99 					AND EXISTS (
    100 						SELECT 1
    101 						FROM file_tags ft
    102 						JOIN tags t ON ft.tag_id = t.id
    103 						JOIN categories c ON c.id = t.category_id
    104 						WHERE ft.file_id = f.id AND c.name = ? AND t.value IN (%s)
    105 					)`, strings.Join(placeholders, ","))
    106 
    107 				args = append(args, filter.Category)
    108 				for _, v := range filter.Values {
    109 					args = append(args, v)
    110 				}
    111 			}
    112 		}
    113 
    114 		query += ` ORDER BY f.id DESC LIMIT 1`
    115 
    116 		files, err := queryFilesWithTags(query, args...)
    117 		if err != nil {
    118 			return nil, fmt.Errorf("failed to query files for tag %s: %w", tagValue, err)
    119 		}
    120 
    121 		if len(files) > 0 {
    122 			allFiles = append(allFiles, files[0])
    123 		}
    124 	}
    125 
    126 	return allFiles, nil
    127 }