feat(workspace): journal with one note per day and a calendar
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m6s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m6s
- journal_days (migration 8) maps a person's day to an ordinary note;
GET /journal lists the days, POST /journal/{date} opens or creates one
- the journal sits on top of the notes sidebar: days below each other
(today first, older ones load while scrolling), a calendar with month
and year picker follows the day in view and jumps to any day
- the header shares the day in view; journal notes stay out of the folder
tree; can be switched off per device under Darstellung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
261579f0f2
commit
9008d7c915
19 files changed
+864
-19
No files matched your search
@@ -0,0 +1,65 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Journal: one note per person and day. The notes are ordinary documents (sharing, search, sync work as
|
||||
// usual); this table only remembers which note belongs to which day.
|
||||
|
||||
type JournalDay struct {
|
||||
Date string `json:"date"` // YYYY-MM-DD
|
||||
DocID string `json:"docId"`
|
||||
Empty bool `json:"empty"` // no text yet (the journal still shows today and days jumped to)
|
||||
}
|
||||
|
||||
func (s *Store) migrateJournal() error {
|
||||
return s.execInTx(
|
||||
stmt(`CREATE TABLE IF NOT EXISTS journal_days (
|
||||
user_id TEXT NOT NULL,
|
||||
day TEXT NOT NULL,
|
||||
doc_id TEXT NOT NULL,
|
||||
PRIMARY KEY (user_id, day)
|
||||
)`),
|
||||
stmt(`CREATE INDEX IF NOT EXISTS idx_journal_days_doc ON journal_days(doc_id)`),
|
||||
)
|
||||
}
|
||||
|
||||
// JournalDays lists the user's days whose note still exists (not in the trash), newest first.
|
||||
func (s *Store) JournalDays(userID string) ([]JournalDay, error) {
|
||||
rows, err := s.db.Query(`SELECT j.day, j.doc_id, TRIM(d.content) = ''
|
||||
FROM journal_days j JOIN documents d ON d.id = j.doc_id
|
||||
WHERE j.user_id = ? AND d.is_archived = 0
|
||||
ORDER BY j.day DESC`, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
days := []JournalDay{}
|
||||
for rows.Next() {
|
||||
var d JournalDay
|
||||
if err := rows.Scan(&d.Date, &d.DocID, &d.Empty); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
days = append(days, d)
|
||||
}
|
||||
return days, rows.Err()
|
||||
}
|
||||
|
||||
// JournalDocID returns the note of a day; "" when there is none or it was moved to the trash.
|
||||
func (s *Store) JournalDocID(userID, day string) (string, error) {
|
||||
var docID string
|
||||
err := s.db.QueryRow(`SELECT j.doc_id FROM journal_days j JOIN documents d ON d.id = j.doc_id
|
||||
WHERE j.user_id = ? AND j.day = ? AND d.is_archived = 0`, userID, day).Scan(&docID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return "", nil
|
||||
}
|
||||
return docID, err
|
||||
}
|
||||
|
||||
func (s *Store) SetJournalDay(userID, day, docID string) error {
|
||||
_, err := s.db.Exec(`INSERT INTO journal_days (user_id, day, doc_id) VALUES (?, ?, ?)
|
||||
ON CONFLICT(user_id, day) DO UPDATE SET doc_id = excluded.doc_id`, userID, day, docID)
|
||||
return err
|
||||
}
|
||||
Reference in new issue
Block a user