diff --git a/CHANGELOG.md b/CHANGELOG.md index 614e872..6169ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V ## [Unreleased] +## [0.49.2] - 2026-11-01 + +### Fixed +- Globale Suche: Offene Aufgaben stehen vor erledigten, verworfene Gedanken ganz hinten; offene Listeneinträge vor abgehakten. Bisher zählte nur, wie gut der Text passte, sodass erledigte Aufgaben offene verdrängen konnten. + ## [0.49.1] - 2026-11-01 ### Fixed @@ -765,7 +770,8 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V - Geteilte Listen (Einkaufs-, Pack- und Checklisten) mit `#Kategorie`-Gruppierung, Mengenangaben und Echtzeit-Abhaken. - Benutzer-, Gruppen- und Admin-Verwaltung (Ersteinrichtungs-Assistent, Einladungscodes, Profilbilder, persönliche API-Keys & Webhook-Ingest `/api/v1/webhooks/ingest`, JSON-Datenexport) sowie CSS-Theme-Engine mit 4 Themes (`Dark`, `Light`, `High Contrast`, `Soft`) und PWA-Unterstützung. -[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.49.1...dev +[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.49.2...dev +[0.49.2]: https://git.dsit.me/sandrodach/MindSift/compare/v0.49.1...v0.49.2 [0.49.1]: https://git.dsit.me/sandrodach/MindSift/compare/v0.49.0...v0.49.1 [0.49.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.48.0...v0.49.0 [0.48.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.47.0...v0.48.0 diff --git a/README.md b/README.md index e486fb9..9bd8d33 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Self-Hosted](https://img.shields.io/badge/100%25-Self--Hosted-2563eb?style=flat-square)](#) [![Docker](https://img.shields.io/badge/Deployment-Single%20Container-2496ed?style=flat-square&logo=docker&logoColor=white)](#-schnellstart) [![SQLite](https://img.shields.io/badge/Daten-SQLite-003b57?style=flat-square&logo=sqlite&logoColor=white)](#-deine-daten-gehören-dir) -[![Version](https://img.shields.io/badge/Version-v0.49.1-16a34a?style=flat-square)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/Version-v0.49.2-16a34a?style=flat-square)](CHANGELOG.md) **MindSift** ist eine selbst gehostete Schaltstelle für spontane Gedanken, Aufgaben mit Kanban-Board, hierarchische Outliner-Notizen, die mehrere Personen gleichzeitig bearbeiten können, und gemeinsame Listen. Alles läuft als ein einzelner Container mit eingebetteter SQLite-Datenbank, auf deinem eigenen Server. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c060e15..a8f2cfa 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "mindsift-frontend", - "version": "0.49.1", + "version": "0.49.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mindsift-frontend", - "version": "0.49.1", + "version": "0.49.2", "license": "AGPL-3.0-only", "dependencies": { "@fontsource-variable/inter": "5.3.0", diff --git a/frontend/package.json b/frontend/package.json index 56e197b..bee07d3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "mindsift-frontend", "private": true, - "version": "0.49.1", + "version": "0.49.2", "license": "AGPL-3.0-only", "type": "module", "scripts": { diff --git a/internal/storage/search.go b/internal/storage/search.go index 8c5ce46..d9e4c3b 100644 --- a/internal/storage/search.go +++ b/internal/storage/search.go @@ -273,7 +273,8 @@ func (s *Store) SearchGlobal(userID, query string) (*SearchResults, error) { JOIN thoughts t ON t.id = f.thought_id WHERE thoughts_fts MATCH ? AND (t.user_id = ? OR t.task_list_id IN (`+s.accessibleTaskListIDsQuery()+`)) - ORDER BY score ASC + -- Open before completed, discarded thoughts last; within each by relevance + ORDER BY t.status = 'discarded' ASC, t.is_completed ASC, score ASC LIMIT 40 `, ftsQuery, userID, userID, userID, userID) if err == nil { @@ -330,7 +331,7 @@ func (s *Store) SearchGlobal(userID, query string) (*SearchResults, error) { FROM list_items_fts f JOIN list_items li ON li.id = f.item_id WHERE list_items_fts MATCH ? - ORDER BY score ASC + ORDER BY li.is_completed ASC, score ASC LIMIT 40 `, ftsQuery) if err == nil { diff --git a/internal/storage/search_test.go b/internal/storage/search_test.go index 412aa08..391e05b 100644 --- a/internal/storage/search_test.go +++ b/internal/storage/search_test.go @@ -212,3 +212,27 @@ func TestSearchPrefixAndSpecialCharacters(t *testing.T) { } } } + +// Open tasks come before completed ones, even when a completed one matches the words better. +func TestSearchListsOpenTasksFirst(t *testing.T) { + store, userA, _ := setupTestStore(t) + defer store.Close() + + done := doneTask(t, store, userA.ID, "", "Heizung Heizung Heizung entlüften", "") + open, _ := store.CreateThoughtWithDetails(userA.ID, "Heizung warten lassen, Termin mit dem Installateur ausmachen", "normal", "manual", "", "", "todo", "") + _, _ = store.UpdateThoughtTriage(userA.ID, open.ID, "keep", "task", "", "", "") + + res, err := store.SearchGlobal(userA.ID, "Heizung") + if err != nil { + t.Fatal(err) + } + var order []string + for _, h := range res.Hits { + if h.Type == "thought" { + order = append(order, h.ID) + } + } + if len(order) != 2 || order[0] != open.ID || order[1] != done { + t.Fatalf("open task should come first: %v (open %s, done %s)", order, open.ID, done) + } +}