fix(search): open tasks and list items before completed ones
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m36s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m36s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2bb0dec744
commit
558fc46cf4
6 files changed
+38
-7
No files matched your search
+7
-1
@@ -6,6 +6,11 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
|
|||||||
|
|
||||||
## [Unreleased]
|
## [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
|
## [0.49.1] - 2026-11-01
|
||||||
|
|
||||||
### Fixed
|
### 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.
|
- 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.
|
- 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.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.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
|
[0.48.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.47.0...v0.48.0
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[](#)
|
[](#)
|
||||||
[](#-schnellstart)
|
[](#-schnellstart)
|
||||||
[](#-deine-daten-gehören-dir)
|
[](#-deine-daten-gehören-dir)
|
||||||
[](CHANGELOG.md)
|
[](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.
|
**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.
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "mindsift-frontend",
|
"name": "mindsift-frontend",
|
||||||
"version": "0.49.1",
|
"version": "0.49.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "mindsift-frontend",
|
"name": "mindsift-frontend",
|
||||||
"version": "0.49.1",
|
"version": "0.49.2",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/inter": "5.3.0",
|
"@fontsource-variable/inter": "5.3.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mindsift-frontend",
|
"name": "mindsift-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.49.1",
|
"version": "0.49.2",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -273,7 +273,8 @@ func (s *Store) SearchGlobal(userID, query string) (*SearchResults, error) {
|
|||||||
JOIN thoughts t ON t.id = f.thought_id
|
JOIN thoughts t ON t.id = f.thought_id
|
||||||
WHERE thoughts_fts MATCH ?
|
WHERE thoughts_fts MATCH ?
|
||||||
AND (t.user_id = ? OR t.task_list_id IN (`+s.accessibleTaskListIDsQuery()+`))
|
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
|
LIMIT 40
|
||||||
`, ftsQuery, userID, userID, userID, userID)
|
`, ftsQuery, userID, userID, userID, userID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -330,7 +331,7 @@ func (s *Store) SearchGlobal(userID, query string) (*SearchResults, error) {
|
|||||||
FROM list_items_fts f
|
FROM list_items_fts f
|
||||||
JOIN list_items li ON li.id = f.item_id
|
JOIN list_items li ON li.id = f.item_id
|
||||||
WHERE list_items_fts MATCH ?
|
WHERE list_items_fts MATCH ?
|
||||||
ORDER BY score ASC
|
ORDER BY li.is_completed ASC, score ASC
|
||||||
LIMIT 40
|
LIMIT 40
|
||||||
`, ftsQuery)
|
`, ftsQuery)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user