Skip to content

Commit 130d612

Browse files
authored
feat: allow empty task log comments (#35)
1 parent 2102413 commit 130d612

File tree

9 files changed

+108
-49
lines changed

9 files changed

+108
-49
lines changed

internal/persistence/queries.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ WHERE active=true;
6969
return err
7070
}
7171

72-
func UpdateActiveTL(db *sql.DB, taskLogID int, taskID int, beginTs, endTs time.Time, secsSpent int, comment string) error {
72+
func UpdateActiveTL(db *sql.DB, taskLogID int, taskID int, beginTs, endTs time.Time, secsSpent int, comment *string) error {
7373
return runInTx(db, func(tx *sql.Tx) error {
7474
stmt, err := tx.Prepare(`
7575
UPDATE task_log
@@ -108,7 +108,7 @@ WHERE id = ?;
108108
})
109109
}
110110

111-
func InsertManualTL(db *sql.DB, taskID int, beginTs time.Time, endTs time.Time, comment string) (int, error) {
111+
func InsertManualTL(db *sql.DB, taskID int, beginTs time.Time, endTs time.Time, comment *string) (int, error) {
112112
return runInTxAndReturnID(db, func(tx *sql.Tx) (int, error) {
113113
stmt, err := tx.Prepare(`
114114
INSERT INTO task_log (task_id, begin_ts, end_ts, secs_spent, comment, active)

internal/persistence/queries_test.go

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func TestRepository(t *testing.T) {
7171

7272
// WHEN
7373
comment := "a task log"
74-
err = UpdateActiveTL(testDB, tlID, taskID, beginTS, endTS, numSeconds, comment)
74+
err = UpdateActiveTL(testDB, tlID, taskID, beginTS, endTS, numSeconds, &comment)
7575

7676
// THEN
7777
require.NoError(t, err, "failed to update task log")
@@ -83,7 +83,8 @@ func TestRepository(t *testing.T) {
8383
require.NoError(t, err, "failed to fetch task")
8484

8585
assert.Equal(t, numSeconds, taskLog.SecsSpent)
86-
assert.Equal(t, comment, taskLog.Comment)
86+
require.NotNil(t, taskLog.Comment)
87+
assert.Equal(t, comment, *taskLog.Comment)
8788
assert.Equal(t, numSecondsBefore+numSeconds, taskAfter.SecsSpent)
8889
})
8990

@@ -105,7 +106,7 @@ func TestRepository(t *testing.T) {
105106
numSeconds := 60 * 90
106107
endTS := time.Now()
107108
beginTS := endTS.Add(time.Second * -1 * time.Duration(numSeconds))
108-
tlID, err := InsertManualTL(testDB, taskID, beginTS, endTS, comment)
109+
tlID, err := InsertManualTL(testDB, taskID, beginTS, endTS, &comment)
109110

110111
// THEN
111112
require.NoError(t, err, "failed to insert task log")
@@ -117,10 +118,36 @@ func TestRepository(t *testing.T) {
117118
require.NoError(t, err, "failed to fetch task")
118119

119120
assert.Equal(t, numSeconds, taskLog.SecsSpent)
120-
assert.Equal(t, comment, taskLog.Comment)
121+
require.NotNil(t, taskLog.Comment)
122+
assert.Equal(t, comment, *taskLog.Comment)
121123
assert.Equal(t, numSecondsBefore+numSeconds, taskAfter.SecsSpent)
122124
})
123125

126+
t.Run("TestInsertManualTL can insert TL with empty comment", func(t *testing.T) {
127+
t.Cleanup(func() { cleanupDB(t, testDB) })
128+
129+
// GIVEN
130+
referenceTS := time.Now()
131+
seedData := getTestData(referenceTS)
132+
seedDB(t, testDB, seedData)
133+
taskID := 1
134+
135+
// WHEN
136+
numSeconds := 60 * 90
137+
endTS := time.Now()
138+
beginTS := endTS.Add(time.Second * -1 * time.Duration(numSeconds))
139+
tlID, err := InsertManualTL(testDB, taskID, beginTS, endTS, nil)
140+
141+
// THEN
142+
require.NoError(t, err, "failed to insert task log")
143+
144+
taskLog, err := fetchTLByID(testDB, tlID)
145+
require.NoError(t, err, "failed to fetch task log")
146+
147+
assert.Equal(t, numSeconds, taskLog.SecsSpent)
148+
assert.Nil(t, taskLog.Comment)
149+
})
150+
124151
t.Run("TestDeleteTaskLogEntry", func(t *testing.T) {
125152
t.Cleanup(func() { cleanupDB(t, testDB) })
126153

@@ -160,7 +187,8 @@ func TestRepository(t *testing.T) {
160187
numSeconds := 60 * 90
161188
tlEndTS := referenceTS.Add(time.Hour * 2)
162189
tlBeginTS := tlEndTS.Add(time.Second * -1 * time.Duration(numSeconds))
163-
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, taskLogComment)
190+
comment := taskLogComment
191+
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, &comment)
164192
require.NoError(t, err, "failed to insert task log")
165193

166194
// WHEN
@@ -185,7 +213,7 @@ func TestRepository(t *testing.T) {
185213
numSeconds := 60 * 90
186214
tlEndTS := referenceTS.Add(time.Hour * 2)
187215
tlBeginTS := tlEndTS.Add(time.Second * -1 * time.Duration(numSeconds))
188-
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, comment)
216+
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, &comment)
189217
require.NoError(t, err, "failed to insert task log")
190218

191219
// WHEN
@@ -216,7 +244,8 @@ func TestRepository(t *testing.T) {
216244
numSeconds := 60 * 90
217245
tlEndTS := referenceTS.Add(time.Hour * 2)
218246
tlBeginTS := tlEndTS.Add(time.Second * -1 * time.Duration(numSeconds))
219-
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, taskLogComment)
247+
comment := taskLogComment
248+
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, &comment)
220249
require.NoError(t, err, "failed to insert task log")
221250

222251
// WHEN
@@ -248,7 +277,8 @@ func TestRepository(t *testing.T) {
248277
numSeconds := 60 * 90
249278
tlEndTS := referenceTS.Add(time.Hour * 2)
250279
tlBeginTS := tlEndTS.Add(time.Second * -1 * time.Duration(numSeconds))
251-
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, taskLogComment)
280+
comment := taskLogComment
281+
_, err = InsertManualTL(testDB, taskID, tlBeginTS, tlEndTS, &comment)
252282
require.NoError(t, err, "failed to insert task log")
253283

254284
// WHEN
@@ -312,30 +342,33 @@ func getTestData(referenceTS time.Time) testData {
312342
},
313343
}
314344

345+
commentTask1TL1 := "task 1 tl 1"
346+
commentTask1TL2 := "task 1 tl 2"
347+
commentTask2TL1 := "task 2 tl 1"
315348
taskLogs := []types.TaskLogEntry{
316349
{
317350
ID: 1,
318351
TaskID: 1,
319352
BeginTS: ca.Add(time.Hour * 2),
320353
EndTS: ca.Add(time.Hour * 4),
321354
SecsSpent: 2 * secsInOneHour,
322-
Comment: "task 1 tl 1",
355+
Comment: &commentTask1TL1,
323356
},
324357
{
325358
ID: 2,
326359
TaskID: 1,
327360
BeginTS: ca.Add(time.Hour * 6),
328361
EndTS: ca.Add(time.Hour * 9),
329362
SecsSpent: 3 * secsInOneHour,
330-
Comment: "task 1 tl 2",
363+
Comment: &commentTask1TL2,
331364
},
332365
{
333366
ID: 3,
334367
TaskID: 2,
335368
BeginTS: ca.Add(time.Hour * 2),
336369
EndTS: ca.Add(time.Hour * 6),
337370
SecsSpent: 4 * secsInOneHour,
338-
Comment: "task 2 tl 1",
371+
Comment: &commentTask2TL1,
339372
},
340373
}
341374

internal/types/types.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type TaskLogEntry struct {
2828
BeginTS time.Time
2929
EndTS time.Time
3030
SecsSpent int
31-
Comment string
31+
Comment *string
3232
TLTitle string
3333
TLDesc string
3434
}
@@ -69,7 +69,7 @@ func (t *Task) UpdateDesc() {
6969
}
7070

7171
func (tl *TaskLogEntry) UpdateTitle() {
72-
tl.TLTitle = utils.Trim(tl.Comment, 60)
72+
tl.TLTitle = utils.Trim(tl.GetComment(), 60)
7373
}
7474

7575
func (tl *TaskLogEntry) UpdateDesc() {
@@ -98,6 +98,14 @@ func (tl *TaskLogEntry) UpdateDesc() {
9898
tl.TLDesc = fmt.Sprintf("%s %s", utils.RightPadTrim("["+tl.TaskSummary+"]", 60, true), timeStr)
9999
}
100100

101+
func (tl *TaskLogEntry) GetComment() string {
102+
if tl.Comment == nil {
103+
return "∅"
104+
}
105+
106+
return *tl.Comment
107+
}
108+
101109
func (t Task) Title() string {
102110
return t.TaskTitle
103111
}
@@ -119,7 +127,7 @@ func (tl TaskLogEntry) Description() string {
119127
}
120128

121129
func (tl TaskLogEntry) FilterValue() string {
122-
return tl.Comment
130+
return fmt.Sprintf("%d", tl.ID)
123131
}
124132

125133
func HumanizeDuration(durationInSecs int) string {

internal/ui/cmds.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func toggleTracking(db *sql.DB,
1515
taskID int,
1616
beginTs time.Time,
1717
endTs time.Time,
18-
comment string,
18+
comment *string,
1919
) tea.Cmd {
2020
return func() tea.Msg {
2121
row := db.QueryRow(`
@@ -66,7 +66,7 @@ func updateTLBeginTS(db *sql.DB, beginTS time.Time) tea.Cmd {
6666
}
6767
}
6868

69-
func insertManualTL(db *sql.DB, taskID int, beginTS time.Time, endTS time.Time, comment string) tea.Cmd {
69+
func insertManualTL(db *sql.DB, taskID int, beginTS time.Time, endTS time.Time, comment *string) tea.Cmd {
7070
return func() tea.Msg {
7171
_, err := pers.InsertManualTL(db, taskID, beginTS, endTS, comment)
7272
return manualTLInsertedMsg{taskID, err}

internal/ui/generate.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
pers "github.com/dhth/hours/internal/persistence"
1010
)
1111

12+
const nonEmptyCommentChance = 0.8
13+
1214
var (
1315
tasks = []string{
1416
".net",
@@ -103,7 +105,11 @@ func GenerateData(db *sql.DB, numDays, numTasks uint8) error {
103105
beginTs := randomTimestamp(int(numDays))
104106
numMinutes := 30 + rand.Intn(60)
105107
endTs := beginTs.Add(time.Minute * time.Duration(numMinutes))
106-
comment := fmt.Sprintf("%s %s", verbs[rand.Intn(len(verbs))], nouns[rand.Intn(len(nouns))])
108+
var comment *string
109+
commentStr := fmt.Sprintf("%s %s", verbs[rand.Intn(len(verbs))], nouns[rand.Intn(len(nouns))])
110+
if rand.Float64() < nonEmptyCommentChance {
111+
comment = &commentStr
112+
}
107113
_, err = pers.InsertManualTL(db, int(i+1), beginTs, endTs, comment)
108114
if err != nil {
109115
return err

internal/ui/handle.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ func (m *Model) getCmdToSaveActiveTL() tea.Cmd {
7373
return nil
7474
}
7575

76-
if m.trackingInputs[entryComment].Value() == "" {
77-
m.message = "Comment cannot be empty"
78-
return nil
76+
commentValue := m.trackingInputs[entryComment].Value()
77+
var comment *string
78+
if isCommentValid(commentValue) {
79+
comment = &commentValue
7980
}
8081

81-
comment := m.trackingInputs[entryComment].Value()
8282
for i := range m.trackingInputs {
8383
m.trackingInputs[i].SetValue("")
8484
}
@@ -104,11 +104,10 @@ func (m *Model) getCmdToSaveOrUpdateTL() tea.Cmd {
104104
return nil
105105
}
106106

107-
comment := m.trackingInputs[entryComment].Value()
108-
109-
if len(comment) == 0 {
110-
m.message = "Comment cannot be empty"
111-
return nil
107+
commentValue := m.trackingInputs[entryComment].Value()
108+
var comment *string
109+
if isCommentValid(commentValue) {
110+
comment = &commentValue
112111
}
113112

114113
task, ok := m.activeTasksList.SelectedItem().(*types.Task)
@@ -361,7 +360,7 @@ func (m *Model) getCmdToStartTracking() tea.Cmd {
361360

362361
m.changesLocked = true
363362
m.activeTLBeginTS = time.Now()
364-
return toggleTracking(m.db, task.ID, m.activeTLBeginTS, m.activeTLEndTS, "")
363+
return toggleTracking(m.db, task.ID, m.activeTLBeginTS, m.activeTLEndTS, nil)
365364
}
366365

367366
func (m *Model) handleRequestToStopTracking() {

internal/ui/log.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func getTaskLog(db *sql.DB, start, end time.Time, limit int, plain bool) (string
9494
if plain {
9595
data[i] = []string{
9696
utils.RightPadTrim(entry.TaskSummary, 20, false),
97-
utils.RightPadTrim(entry.Comment, 40, false),
97+
utils.RightPadTrim(entry.GetComment(), 40, false),
9898
fmt.Sprintf("%s ... %s", entry.BeginTS.Format(timeFormat), entry.EndTS.Format(timeFormat)),
9999
utils.RightPadTrim(timeSpentStr, logTimeCharsBudget, false),
100100
}
@@ -106,7 +106,7 @@ func getTaskLog(db *sql.DB, start, end time.Time, limit int, plain bool) (string
106106
}
107107
data[i] = []string{
108108
rowStyle.Render(utils.RightPadTrim(entry.TaskSummary, 20, false)),
109-
rowStyle.Render(utils.RightPadTrim(entry.Comment, 40, false)),
109+
rowStyle.Render(utils.RightPadTrim(entry.GetComment(), 40, false)),
110110
rowStyle.Render(fmt.Sprintf("%s ... %s", entry.BeginTS.Format(timeFormat), entry.EndTS.Format(timeFormat))),
111111
rowStyle.Render(utils.RightPadTrim(timeSpentStr, logTimeCharsBudget, false)),
112112
}

internal/ui/utils.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ui
22

33
import (
4+
"strings"
5+
46
"github.com/charmbracelet/lipgloss"
57
)
68

@@ -24,3 +26,7 @@ func getReportStyles(plain bool) reportStyles {
2426
recordsBorderStyle,
2527
}
2628
}
29+
30+
func isCommentValid(comment string) bool {
31+
return strings.TrimSpace(comment) != ""
32+
}

0 commit comments

Comments
 (0)