Skip to content

Commit

Permalink
feat: allow saving comment for active task log (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhth authored Jan 17, 2025
1 parent 130d612 commit 51c4a6d
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 62 deletions.
23 changes: 11 additions & 12 deletions internal/persistence/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,20 @@ VALUES (?, ?, ?);
})
}

func UpdateTLBeginTS(db *sql.DB, beginTs time.Time) error {
func EditActiveTL(db *sql.DB, beginTs time.Time, comment *string) error {
stmt, err := db.Prepare(`
UPDATE task_log SET begin_ts=?
UPDATE task_log
SET begin_ts=?,
comment = ?
WHERE active is true;
`)
if err != nil {
return err
}
defer stmt.Close()

_, err = stmt.Exec(beginTs.UTC(), true)
if err != nil {
return err
}

return nil
_, err = stmt.Exec(beginTs.UTC(), comment)
return err
}

func DeleteActiveTL(db *sql.DB) error {
Expand Down Expand Up @@ -151,9 +149,9 @@ WHERE id = ?;
})
}

func FetchActiveTask(db *sql.DB) (types.ActiveTaskDetails, error) {
func FetchActiveTaskDetails(db *sql.DB) (types.ActiveTaskDetails, error) {
row := db.QueryRow(`
SELECT t.id, t.summary, tl.begin_ts
SELECT t.id, t.summary, tl.begin_ts, tl.comment
FROM task_log tl left join task t on tl.task_id = t.id
WHERE tl.active=true;
`)
Expand All @@ -162,15 +160,16 @@ WHERE tl.active=true;
err := row.Scan(
&activeTaskDetails.TaskID,
&activeTaskDetails.TaskSummary,
&activeTaskDetails.LastLogEntryBeginTS,
&activeTaskDetails.CurrentLogBeginTS,
&activeTaskDetails.CurrentLogComment,
)
if errors.Is(err, sql.ErrNoRows) {
activeTaskDetails.TaskID = -1
return activeTaskDetails, nil
} else if err != nil {
return activeTaskDetails, err
}
activeTaskDetails.LastLogEntryBeginTS = activeTaskDetails.LastLogEntryBeginTS.Local()
activeTaskDetails.CurrentLogBeginTS = activeTaskDetails.CurrentLogBeginTS.Local()
return activeTaskDetails, nil
}

Expand Down
37 changes: 37 additions & 0 deletions internal/persistence/queries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,43 @@ func TestRepository(t *testing.T) {
assert.Zero(t, task.SecsSpent)
})

t.Run("EditActiveTL", func(t *testing.T) {
t.Cleanup(func() { cleanupDB(t, testDB) })

// GIVEN
referenceTS := time.Now().Truncate(time.Second)
seedData := getTestData(referenceTS)
seedDB(t, testDB, seedData)
taskID := 1
numSeconds := 60 * 90
endTS := time.Now()
beginTS := endTS.Add(time.Second * -1 * time.Duration(numSeconds))
_, insertErr := InsertNewTL(testDB, taskID, beginTS)
require.NoError(t, insertErr, "failed to insert task log")

// WHEN
updatedBeginTS := endTS.Add(time.Second * -1 * time.Duration(numSeconds))
comment := "updated active TL"
err = EditActiveTL(testDB, updatedBeginTS, &comment)
activeTaskDetails, err := FetchActiveTaskDetails(testDB)
require.NoError(t, err, "failed to fetch active task details")

err = EditActiveTL(testDB, updatedBeginTS, nil)
require.NoError(t, err, "failed to update active task log the second time")
activeTaskDetailsTwo, err := FetchActiveTaskDetails(testDB)
require.NoError(t, err, "failed to fetch active task details the second time")

// THEN
assert.Equal(t, taskID, activeTaskDetails.TaskID)
assert.True(t, updatedBeginTS.Equal(activeTaskDetails.CurrentLogBeginTS))
require.NotNil(t, activeTaskDetails.CurrentLogComment)
assert.Equal(t, comment, *activeTaskDetails.CurrentLogComment)

assert.Equal(t, taskID, activeTaskDetailsTwo.TaskID)
assert.True(t, updatedBeginTS.Equal(activeTaskDetailsTwo.CurrentLogBeginTS))
require.Nil(t, activeTaskDetailsTwo.CurrentLogComment)
})

t.Run("TestUpdateActiveTL", func(t *testing.T) {
t.Cleanup(func() { cleanupDB(t, testDB) })

Expand Down
7 changes: 4 additions & 3 deletions internal/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ type TaskLogEntry struct {
}

type ActiveTaskDetails struct {
TaskID int
TaskSummary string
LastLogEntryBeginTS time.Time
TaskID int
TaskSummary string
CurrentLogBeginTS time.Time
CurrentLogComment *string
}

type TaskReportEntry struct {
Expand Down
4 changes: 2 additions & 2 deletions internal/ui/active.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const (
)

func ShowActiveTask(db *sql.DB, writer io.Writer, template string) error {
activeTaskDetails, err := pers.FetchActiveTask(db)
activeTaskDetails, err := pers.FetchActiveTaskDetails(db)
if err != nil {
return err
}
Expand All @@ -28,7 +28,7 @@ func ShowActiveTask(db *sql.DB, writer io.Writer, template string) error {
return nil
}

timeSpent := time.Since(activeTaskDetails.LastLogEntryBeginTS).Seconds()
timeSpent := time.Since(activeTaskDetails.CurrentLogBeginTS).Seconds()
var timeSpentStr string
if timeSpent <= activeSecsThreshold {
timeSpentStr = activeSecsThresholdStr
Expand Down
11 changes: 5 additions & 6 deletions internal/ui/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ LIMIT 1
}
}

func updateTLBeginTS(db *sql.DB, beginTS time.Time) tea.Cmd {
func updateActiveTL(db *sql.DB, beginTS time.Time, comment *string) tea.Cmd {
return func() tea.Msg {
err := pers.UpdateTLBeginTS(db, beginTS)
return tlBeginTSUpdatedMsg{beginTS, err}
err := pers.EditActiveTL(db, beginTS, comment)
return activeTLUpdatedMsg{beginTS, comment, err}
}
}

Expand All @@ -75,7 +75,7 @@ func insertManualTL(db *sql.DB, taskID int, beginTS time.Time, endTS time.Time,

func fetchActiveTask(db *sql.DB) tea.Cmd {
return func() tea.Msg {
activeTaskDetails, err := pers.FetchActiveTask(db)
activeTaskDetails, err := pers.FetchActiveTaskDetails(db)
if err != nil {
return activeTaskFetchedMsg{err: err}
}
Expand All @@ -85,8 +85,7 @@ func fetchActiveTask(db *sql.DB) tea.Cmd {
}

return activeTaskFetchedMsg{
activeTaskID: activeTaskDetails.TaskID,
beginTs: activeTaskDetails.LastLogEntryBeginTS,
activeTask: activeTaskDetails,
}
}
}
Expand Down
69 changes: 52 additions & 17 deletions internal/ui/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,14 @@ func (m *Model) getCmdToUpdateActiveTL() tea.Cmd {
m.message = err.Error()
return nil
}
commentValue := m.trackingInputs[entryComment].Value()
var comment *string
if isCommentValid(commentValue) {
comment = &commentValue
}

m.trackingInputs[entryBeginTS].SetValue("")
m.activeView = taskListView
return updateTLBeginTS(m.db, beginTS)
return updateActiveTL(m.db, beginTS, comment)
}

func (m *Model) getCmdToSaveActiveTL() tea.Cmd {
Expand Down Expand Up @@ -121,6 +125,7 @@ func (m *Model) getCmdToSaveOrUpdateTL() tea.Cmd {
for i := range m.trackingInputs {
m.trackingInputs[i].SetValue("")
}
m.activeTLComment = nil

m.activeView = taskListView
return insertManualTL(m.db, task.ID, beginTS, endTS, comment)
Expand Down Expand Up @@ -157,6 +162,16 @@ func (m *Model) goForwardInView() {
m.activeView = inactiveTaskListView
case inactiveTaskListView:
m.activeView = taskListView
case editActiveTLView:
switch m.trackingFocussedField {
case entryBeginTS:
m.trackingFocussedField = entryComment
m.trackingInputs[entryBeginTS].Blur()
case entryComment:
m.trackingFocussedField = entryBeginTS
m.trackingInputs[entryComment].Blur()
}
m.trackingInputs[m.trackingFocussedField].Focus()
case saveActiveTLView, manualTasklogEntryView:
switch m.trackingFocussedField {
case entryBeginTS:
Expand All @@ -181,6 +196,16 @@ func (m *Model) goBackwardInView() {
m.activeView = inactiveTaskListView
case inactiveTaskListView:
m.activeView = taskLogView
case editActiveTLView:
switch m.trackingFocussedField {
case entryBeginTS:
m.trackingFocussedField = entryComment
m.trackingInputs[entryBeginTS].Blur()
case entryComment:
m.trackingFocussedField = entryBeginTS
m.trackingInputs[entryComment].Blur()
}
m.trackingInputs[m.trackingFocussedField].Focus()
case saveActiveTLView, manualTasklogEntryView:
switch m.trackingFocussedField {
case entryBeginTS:
Expand Down Expand Up @@ -275,7 +300,7 @@ func (m *Model) goToActiveTask() {
if m.activeTasksList.IsFiltered() {
m.activeTasksList.ResetFilter()
}
activeIndex, ok := m.activeTaskIndexMap[m.activeTaskID]
activeIndex, ok := m.taskIndexMap[m.activeTaskID]
if !ok {
m.message = genericErrorMsg
return
Expand All @@ -284,10 +309,17 @@ func (m *Model) goToActiveTask() {
m.activeTasksList.Select(activeIndex)
}

func (m *Model) handleRequestToSaveActiveTL() {
func (m *Model) handleRequestToEditActiveTL() {
m.activeView = editActiveTLView
m.trackingFocussedField = entryBeginTS
m.trackingInputs[entryBeginTS].SetValue(m.activeTLBeginTS.Format(timeFormat))
if m.activeTLComment != nil {
m.trackingInputs[entryComment].SetValue(*m.activeTLComment)
} else {
m.trackingInputs[entryComment].SetValue("")
}

m.trackingInputs[entryComment].Blur()
m.trackingInputs[m.trackingFocussedField].Focus()
}

Expand Down Expand Up @@ -359,7 +391,7 @@ func (m *Model) getCmdToStartTracking() tea.Cmd {
}

m.changesLocked = true
m.activeTLBeginTS = time.Now()
m.activeTLBeginTS = time.Now().Truncate(time.Second)
return toggleTracking(m.db, task.ID, m.activeTLBeginTS, m.activeTLEndTS, nil)
}

Expand Down Expand Up @@ -459,15 +491,15 @@ func (m *Model) handleTasksFetchedMsg(msg tasksFetchedMsg) tea.Cmd {
var cmd tea.Cmd
switch msg.active {
case true:
m.activeTaskMap = make(map[int]*types.Task)
m.activeTaskIndexMap = make(map[int]int)
m.taskMap = make(map[int]*types.Task)
m.taskIndexMap = make(map[int]int)
tasks := make([]list.Item, len(msg.tasks))
for i, task := range msg.tasks {
task.UpdateTitle()
task.UpdateDesc()
tasks[i] = &task
m.activeTaskMap[task.ID] = &task
m.activeTaskIndexMap[task.ID] = i
m.taskMap[task.ID] = &task
m.taskIndexMap[task.ID] = i
}
m.activeTasksList.SetItems(tasks)
m.activeTasksList.Title = "Tasks"
Expand Down Expand Up @@ -495,7 +527,7 @@ func (m *Model) handleManualTLInsertedMsg(msg manualTLInsertedMsg) []tea.Cmd {
for i := range m.trackingInputs {
m.trackingInputs[i].SetValue("")
}
task, ok := m.activeTaskMap[msg.taskID]
task, ok := m.taskMap[msg.taskID]

var cmds []tea.Cmd
if ok {
Expand Down Expand Up @@ -532,16 +564,17 @@ func (m *Model) handleActiveTaskFetchedMsg(msg activeTaskFetchedMsg) {
return
}

m.activeTaskID = msg.activeTaskID
m.lastTrackingChange = trackingStarted
m.activeTLBeginTS = msg.beginTs
activeTask, ok := m.activeTaskMap[m.activeTaskID]
m.activeTaskID = msg.activeTask.TaskID
m.activeTLBeginTS = msg.activeTask.CurrentLogBeginTS
m.activeTLComment = msg.activeTask.CurrentLogComment
activeTask, ok := m.taskMap[m.activeTaskID]
if ok {
activeTask.TrackingActive = true
activeTask.UpdateTitle()

// go to tracked item on startup
activeIndex, aOk := m.activeTaskIndexMap[msg.activeTaskID]
activeIndex, aOk := m.taskIndexMap[msg.activeTask.TaskID]
if aOk {
m.activeTasksList.Select(activeIndex)
}
Expand All @@ -558,7 +591,7 @@ func (m *Model) handleTrackingToggledMsg(msg trackingToggledMsg) []tea.Cmd {

m.changesLocked = false

task, ok := m.activeTaskMap[msg.taskID]
task, ok := m.taskMap[msg.taskID]

if !ok {
m.message = genericErrorMsg
Expand All @@ -570,6 +603,7 @@ func (m *Model) handleTrackingToggledMsg(msg trackingToggledMsg) []tea.Cmd {
case true:
m.lastTrackingChange = trackingFinished
task.TrackingActive = false
m.activeTLComment = nil
m.trackingActive = false
m.activeTaskID = -1
cmds = append(cmds, updateTaskRep(m.db, task))
Expand All @@ -593,7 +627,7 @@ func (m *Model) handleTLDeleted(msg tLDeletedMsg) []tea.Cmd {
}

var cmds []tea.Cmd
task, ok := m.activeTaskMap[msg.entry.TaskID]
task, ok := m.taskMap[msg.entry.TaskID]
if ok {
cmds = append(cmds, updateTaskRep(m.db, task))
}
Expand All @@ -608,7 +642,7 @@ func (m *Model) handleActiveTLDeletedMsg(msg activeTaskLogDeletedMsg) {
return
}

activeTask, ok := m.activeTaskMap[m.activeTaskID]
activeTask, ok := m.taskMap[m.activeTaskID]
if !ok {
m.message = genericErrorMsg
return
Expand All @@ -618,5 +652,6 @@ func (m *Model) handleActiveTLDeletedMsg(msg activeTaskLogDeletedMsg) {
activeTask.UpdateTitle()
m.lastTrackingChange = trackingFinished
m.trackingActive = false
m.activeTLComment = nil
m.activeTaskID = -1
}
18 changes: 9 additions & 9 deletions internal/ui/initial.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ func InitialModel(db *sql.DB) Model {
taskInputs[entryBeginTS].Width = 60

m := Model{
db: db,
activeTasksList: list.New(activeTaskItems, newItemDelegate(lipgloss.Color(activeTaskListColor)), listWidth, 0),
inactiveTasksList: list.New(inactiveTaskItems, newItemDelegate(lipgloss.Color(inactiveTaskListColor)), listWidth, 0),
activeTaskMap: make(map[int]*types.Task),
activeTaskIndexMap: make(map[int]int),
taskLogList: list.New(tasklogListItems, newItemDelegate(lipgloss.Color(taskLogListColor)), listWidth, 0),
showHelpIndicator: true,
trackingInputs: trackingInputs,
taskInputs: taskInputs,
db: db,
activeTasksList: list.New(activeTaskItems, newItemDelegate(lipgloss.Color(activeTaskListColor)), listWidth, 0),
inactiveTasksList: list.New(inactiveTaskItems, newItemDelegate(lipgloss.Color(inactiveTaskListColor)), listWidth, 0),
taskMap: make(map[int]*types.Task),
taskIndexMap: make(map[int]int),
taskLogList: list.New(tasklogListItems, newItemDelegate(lipgloss.Color(taskLogListColor)), listWidth, 0),
showHelpIndicator: true,
trackingInputs: trackingInputs,
taskInputs: taskInputs,
}
m.activeTasksList.Title = "Tasks"
m.activeTasksList.SetStatusBarItemName("task", "tasks")
Expand Down
5 changes: 3 additions & 2 deletions internal/ui/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ type Model struct {
db *sql.DB
activeTasksList list.Model
inactiveTasksList list.Model
activeTaskMap map[int]*types.Task
activeTaskIndexMap map[int]int
taskMap map[int]*types.Task
taskIndexMap map[int]int
activeTLBeginTS time.Time
activeTLEndTS time.Time
activeTLComment *string
tasksFetched bool
taskLogList list.Model
trackingInputs []textinput.Model
Expand Down
Loading

0 comments on commit 51c4a6d

Please # to comment.