taskPane modified as a Component (type)
This commit is contained in:
18
app/cli.go
18
app/cli.go
@@ -11,15 +11,14 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
app *tview.Application
|
||||
newTask *tview.InputField
|
||||
taskList *tview.List
|
||||
projectDetailPane *tview.Flex
|
||||
taskPane, taskDetailPane *tview.Flex
|
||||
layout, contents *tview.Flex
|
||||
app *tview.Application
|
||||
projectDetailPane *tview.Flex
|
||||
taskDetailPane *tview.Flex
|
||||
layout, contents *tview.Flex
|
||||
|
||||
statusBar *StatusBar
|
||||
projectPane *ProjectPane
|
||||
taskPane *TaskPane
|
||||
|
||||
db *storm.DB
|
||||
projectRepo repository.ProjectRepository
|
||||
@@ -44,7 +43,8 @@ func main() {
|
||||
|
||||
statusBar = makeStatusBar(app)
|
||||
projectPane = NewProjectPane(projectRepo)
|
||||
prepareTaskPane()
|
||||
// prepareTaskPane()
|
||||
taskPane = NewTaskPane(projectRepo, taskRepo)
|
||||
prepareProjectDetail()
|
||||
prepareDetailPane()
|
||||
|
||||
@@ -75,7 +75,7 @@ func setKeyboardShortcuts() *tview.Application {
|
||||
case projectPane.HasFocus():
|
||||
event = projectPane.handleShortcuts(event)
|
||||
case taskPane.HasFocus():
|
||||
event = handleTaskPaneShortcuts(event)
|
||||
event = taskPane.handleShortcuts(event)
|
||||
case taskDetailPane.HasFocus():
|
||||
event = handleDetailPaneShortcuts(event)
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func setKeyboardShortcuts() *tview.Application {
|
||||
app.SetFocus(taskPane)
|
||||
case 'f':
|
||||
// @TODO : Remove
|
||||
//statusBar.showForSeconds(reflect.TypeOf(app.GetFocus()).String(), 5)
|
||||
// statusBar.showForSeconds(reflect.TypeOf(app.GetFocus()).String(), 5)
|
||||
statusBar.showForSeconds(projectPane.activeProject.Title, 5)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ func prepareProjectDetail() {
|
||||
|
||||
deleteBtn.SetBackgroundColor(tcell.ColorRed)
|
||||
projectDetailPane = tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
// AddItem(activeProjectName, 1, 1, false).
|
||||
// AddItem(makeHorizontalLine(tcell.RuneS3, tcell.ColorGray), 1, 1, false).
|
||||
AddItem(deleteBtn, 3, 1, false).
|
||||
AddItem(blankCell, 1, 1, false).
|
||||
AddItem(clearBtn, 3, 1, false).
|
||||
@@ -26,9 +24,9 @@ func prepareProjectDetail() {
|
||||
// @TODO - Move to tasks pane
|
||||
func clearCompletedTasks() {
|
||||
count := 0
|
||||
for i, task := range tasks {
|
||||
if task.Completed && taskRepo.Delete(&tasks[i]) == nil {
|
||||
taskList.RemoveItem(i)
|
||||
for i, task := range taskPane.tasks {
|
||||
if task.Completed && taskRepo.Delete(&taskPane.tasks[i]) == nil {
|
||||
taskPane.list.RemoveItem(i)
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/asdine/storm/v3"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
@@ -119,24 +118,25 @@ func (pane *ProjectPane) handleShortcuts(event *tcell.EventKey) *tcell.EventKey
|
||||
|
||||
func (pane *ProjectPane) activateProject(idx int) {
|
||||
pane.activeProject = &pane.projects[idx]
|
||||
loadProjectTasks()
|
||||
taskPane.LoadProjectTasks(*pane.activeProject)
|
||||
|
||||
removeThirdCol()
|
||||
projectDetailPane.SetTitle("[::b]" + pane.activeProject.Title)
|
||||
contents.AddItem(projectDetailPane, 25, 0, false)
|
||||
app.SetFocus(taskPane)
|
||||
}
|
||||
|
||||
func (pane *ProjectPane) removeActivateProject() {
|
||||
if pane.activeProject != nil && pane.repo.Delete(pane.activeProject) == nil {
|
||||
|
||||
// @TODO - Move to tasks pane
|
||||
for i := range tasks {
|
||||
_ = taskRepo.Delete(&tasks[i])
|
||||
for i := range taskPane.tasks {
|
||||
_ = taskRepo.Delete(&taskPane.tasks[i])
|
||||
}
|
||||
taskPane.ClearList()
|
||||
|
||||
statusBar.showForSeconds("[lime]Removed Project: "+pane.activeProject.Title, 5)
|
||||
removeThirdCol()
|
||||
taskList.Clear()
|
||||
|
||||
pane.loadListItems(true)
|
||||
}
|
||||
@@ -153,17 +153,6 @@ func (pane *ProjectPane) loadListItems(focus bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO - Should be broken down into respective pane
|
||||
func loadProjectTasks() {
|
||||
taskList.Clear()
|
||||
app.SetFocus(taskPane)
|
||||
var err error
|
||||
|
||||
if tasks, err = taskRepo.GetAllByProject(*projectPane.activeProject); err != nil && err != storm.ErrNotFound {
|
||||
statusBar.showForSeconds("[red::]Error: "+err.Error(), 5)
|
||||
}
|
||||
|
||||
for i, task := range tasks {
|
||||
addTaskToList(task, i)
|
||||
}
|
||||
func (pane *ProjectPane) GetActiveProject() *model.Project {
|
||||
return pane.activeProject
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func makeDateRow() *tview.Flex {
|
||||
case tcell.KeyEnter:
|
||||
setTaskDate(parseDateInputOrCurrent(taskDate.GetText()).Unix(), true)
|
||||
case tcell.KeyEsc:
|
||||
setTaskDate(currentTask.DueDate, false)
|
||||
setTaskDate(taskPane.activeTask.DueDate, false)
|
||||
}
|
||||
app.SetFocus(taskDetailPane)
|
||||
})
|
||||
@@ -101,7 +101,7 @@ func makeDateRow() *tview.Flex {
|
||||
}
|
||||
|
||||
func setStatusToggle() {
|
||||
if currentTask.Completed {
|
||||
if taskPane.activeTask.Completed {
|
||||
taskStatusToggle.SetLabel("Resume").SetBackgroundColor(tcell.ColorMaroon)
|
||||
} else {
|
||||
taskStatusToggle.SetLabel("Complete").SetBackgroundColor(tcell.ColorDarkGreen)
|
||||
@@ -109,19 +109,19 @@ func setStatusToggle() {
|
||||
}
|
||||
|
||||
func toggleActiveTaskStatus() {
|
||||
status := !currentTask.Completed
|
||||
if taskRepo.UpdateField(currentTask, "Completed", status) == nil {
|
||||
currentTask.Completed = status
|
||||
loadTask(currentTaskIdx)
|
||||
taskList.SetItemText(currentTaskIdx, makeTaskListingTitle(*currentTask), "")
|
||||
status := !taskPane.activeTask.Completed
|
||||
if taskRepo.UpdateField(taskPane.activeTask, "Completed", status) == nil {
|
||||
taskPane.activeTask.Completed = status
|
||||
taskPane.ActivateTask(taskPane.list.GetCurrentItem())
|
||||
taskPane.list.SetItemText(taskPane.list.GetCurrentItem(), makeTaskListingTitle(*taskPane.activeTask), "")
|
||||
}
|
||||
}
|
||||
|
||||
// Display Task date in detail pane, and update date if asked to
|
||||
func setTaskDate(unixDate int64, update bool) {
|
||||
if update {
|
||||
currentTask.DueDate = unixDate
|
||||
if err := taskRepo.UpdateField(currentTask, "DueDate", unixDate); err != nil {
|
||||
taskPane.activeTask.DueDate = unixDate
|
||||
if err := taskRepo.UpdateField(taskPane.activeTask, "DueDate", unixDate); err != nil {
|
||||
statusBar.showForSeconds("Could not update due date: "+err.Error(), 5)
|
||||
return
|
||||
}
|
||||
@@ -160,8 +160,8 @@ func prepareDetailsEditor() {
|
||||
taskDetailView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Key() {
|
||||
case tcell.KeyEsc:
|
||||
currentTask.Details = taskDetailView.Buf.String()
|
||||
err := taskRepo.Update(currentTask)
|
||||
taskPane.activeTask.Details = taskDetailView.Buf.String()
|
||||
err := taskRepo.Update(taskPane.activeTask)
|
||||
if err == nil {
|
||||
statusBar.showForSeconds("[lime]Saved task detail", 5)
|
||||
} else {
|
||||
|
||||
167
app/tasks.go
167
app/tasks.go
@@ -2,107 +2,122 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/asdine/storm/v3"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/ajaxray/geek-life/model"
|
||||
"github.com/ajaxray/geek-life/repository"
|
||||
)
|
||||
|
||||
var (
|
||||
tasks []model.Task
|
||||
currentTask *model.Task
|
||||
currentTaskIdx int
|
||||
)
|
||||
type TaskPane struct {
|
||||
*tview.Flex
|
||||
list *tview.List
|
||||
tasks []model.Task
|
||||
activeTask *model.Task
|
||||
|
||||
func prepareTaskPane() {
|
||||
taskList = tview.NewList().ShowSecondaryText(false)
|
||||
taskList.SetDoneFunc(func() {
|
||||
newTask *tview.InputField
|
||||
projectRepo repository.ProjectRepository
|
||||
taskRepo repository.TaskRepository
|
||||
}
|
||||
|
||||
func NewTaskPane(projectRepo repository.ProjectRepository, taskRepo repository.TaskRepository) *TaskPane {
|
||||
pane := TaskPane{
|
||||
Flex: tview.NewFlex().SetDirection(tview.FlexRow),
|
||||
list: tview.NewList().ShowSecondaryText(false),
|
||||
newTask: makeLightTextInput("+[New Task]"),
|
||||
projectRepo: projectRepo,
|
||||
taskRepo: taskRepo,
|
||||
}
|
||||
|
||||
pane.list.SetDoneFunc(func() {
|
||||
app.SetFocus(projectPane)
|
||||
})
|
||||
|
||||
newTask = makeLightTextInput("+[New Task]").
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
if len(newTask.GetText()) < 3 {
|
||||
statusBar.showForSeconds("[red::]Task title should be at least 3 character", 5)
|
||||
return
|
||||
}
|
||||
|
||||
task, err := taskRepo.Create(*projectPane.activeProject, newTask.GetText(), "", "", 0)
|
||||
if err != nil {
|
||||
statusBar.showForSeconds("[red::]Could not create Task:"+err.Error(), 5)
|
||||
}
|
||||
|
||||
tasks = append(tasks, task)
|
||||
addTaskToList(task, len(tasks)-1)
|
||||
newTask.SetText("")
|
||||
case tcell.KeyEsc:
|
||||
app.SetFocus(taskPane)
|
||||
pane.newTask.SetDoneFunc(func(key tcell.Key) {
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
name := pane.newTask.GetText()
|
||||
if len(name) < 3 {
|
||||
statusBar.showForSeconds("[red::]Task title should be at least 3 character", 5)
|
||||
return
|
||||
}
|
||||
|
||||
})
|
||||
task, err := taskRepo.Create(*projectPane.activeProject, name, "", "", 0)
|
||||
if err != nil {
|
||||
statusBar.showForSeconds("[red::]Could not create Task:"+err.Error(), 5)
|
||||
}
|
||||
|
||||
taskPane = tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(taskList, 0, 1, true).
|
||||
AddItem(newTask, 1, 0, false)
|
||||
pane.tasks = append(pane.tasks, task)
|
||||
pane.addTaskToList(len(pane.tasks) - 1)
|
||||
pane.newTask.SetText("")
|
||||
case tcell.KeyEsc:
|
||||
app.SetFocus(pane)
|
||||
}
|
||||
|
||||
taskPane.SetBorder(true).SetTitle("[::u]T[::-]asks")
|
||||
})
|
||||
|
||||
pane.
|
||||
AddItem(pane.list, 0, 1, true).
|
||||
AddItem(pane.newTask, 1, 0, false)
|
||||
|
||||
pane.SetBorder(true).SetTitle("[::u]T[::-]asks")
|
||||
|
||||
return &pane
|
||||
}
|
||||
|
||||
func addTaskToList(task model.Task, i int) *tview.List {
|
||||
return taskList.AddItem(makeTaskListingTitle(task), "", 0, func(taskidx int) func() {
|
||||
return func() { loadTask(taskidx) }
|
||||
func (pane *TaskPane) ClearList() {
|
||||
pane.list.Clear()
|
||||
pane.tasks = nil
|
||||
}
|
||||
|
||||
func (pane *TaskPane) SetList(tasks []model.Task) {
|
||||
pane.ClearList()
|
||||
pane.tasks = tasks
|
||||
|
||||
for i := range pane.tasks {
|
||||
pane.addTaskToList(i)
|
||||
}
|
||||
}
|
||||
|
||||
func (pane *TaskPane) addTaskToList(i int) *tview.List {
|
||||
return pane.list.AddItem(makeTaskListingTitle(pane.tasks[i]), "", 0, func(taskidx int) func() {
|
||||
return func() { taskPane.ActivateTask(taskidx) }
|
||||
}(i))
|
||||
}
|
||||
|
||||
func loadTask(idx int) {
|
||||
removeThirdCol()
|
||||
currentTaskIdx = idx
|
||||
currentTask = &tasks[currentTaskIdx]
|
||||
func (pane *TaskPane) handleShortcuts(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Rune() {
|
||||
case 'n':
|
||||
app.SetFocus(pane.newTask)
|
||||
}
|
||||
|
||||
taskName.SetText(fmt.Sprintf("[%s::b]# %s", getTaskTitleColor(*currentTask), currentTask.Title))
|
||||
taskDetailView.Buf = makeBufferFromString(currentTask.Details)
|
||||
return event
|
||||
}
|
||||
|
||||
func (pane *TaskPane) LoadProjectTasks(project model.Project) {
|
||||
var tasks []model.Task
|
||||
var err error
|
||||
|
||||
if tasks, err = taskRepo.GetAllByProject(project); err != nil && err != storm.ErrNotFound {
|
||||
statusBar.showForSeconds("[red::]Error: "+err.Error(), 5)
|
||||
} else {
|
||||
pane.SetList(tasks)
|
||||
}
|
||||
}
|
||||
|
||||
func (pane *TaskPane) ActivateTask(idx int) {
|
||||
removeThirdCol()
|
||||
pane.activeTask = &pane.tasks[idx]
|
||||
|
||||
taskName.SetText(fmt.Sprintf("[%s::b]# %s", getTaskTitleColor(*pane.activeTask), pane.activeTask.Title))
|
||||
taskDetailView.Buf = makeBufferFromString(pane.activeTask.Details)
|
||||
taskDetailView.SetColorscheme(colorscheme)
|
||||
taskDetailView.Start()
|
||||
setTaskDate(currentTask.DueDate, false)
|
||||
setTaskDate(pane.activeTask.DueDate, false)
|
||||
setStatusToggle()
|
||||
|
||||
contents.AddItem(taskDetailPane, 0, 3, false)
|
||||
deactivateEditor()
|
||||
}
|
||||
|
||||
func removeThirdCol() {
|
||||
contents.RemoveItem(taskDetailPane)
|
||||
contents.RemoveItem(projectDetailPane)
|
||||
}
|
||||
|
||||
func getTaskTitleColor(task model.Task) string {
|
||||
colorName := "olive"
|
||||
if task.Completed {
|
||||
colorName = "lime"
|
||||
} else if task.DueDate != 0 && task.DueDate < time.Now().Truncate(24*time.Hour).Unix() {
|
||||
colorName = "red"
|
||||
}
|
||||
|
||||
return colorName
|
||||
}
|
||||
|
||||
func makeTaskListingTitle(task model.Task) string {
|
||||
checkbox := "[ []"
|
||||
if task.Completed {
|
||||
checkbox = "[x[]"
|
||||
}
|
||||
return fmt.Sprintf("[%s]%s %s", getTaskTitleColor(task), checkbox, task.Title)
|
||||
}
|
||||
|
||||
func handleTaskPaneShortcuts(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Rune() {
|
||||
case 'n':
|
||||
app.SetFocus(newTask)
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
25
app/util.go
25
app/util.go
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/ajaxray/geek-life/model"
|
||||
"github.com/ajaxray/geek-life/util"
|
||||
)
|
||||
|
||||
@@ -64,3 +65,27 @@ func yetToImplement(feature string) func() {
|
||||
message := fmt.Sprintf("[yellow]%s is yet to implement. Please Check in next version.", feature)
|
||||
return func() { statusBar.showForSeconds(message, 5) }
|
||||
}
|
||||
|
||||
func removeThirdCol() {
|
||||
contents.RemoveItem(taskDetailPane)
|
||||
contents.RemoveItem(projectDetailPane)
|
||||
}
|
||||
|
||||
func getTaskTitleColor(task model.Task) string {
|
||||
colorName := "olive"
|
||||
if task.Completed {
|
||||
colorName = "lime"
|
||||
} else if task.DueDate != 0 && task.DueDate < time.Now().Truncate(24*time.Hour).Unix() {
|
||||
colorName = "red"
|
||||
}
|
||||
|
||||
return colorName
|
||||
}
|
||||
|
||||
func makeTaskListingTitle(task model.Task) string {
|
||||
checkbox := "[ []"
|
||||
if task.Completed {
|
||||
checkbox = "[x[]"
|
||||
}
|
||||
return fmt.Sprintf("[%s]%s %s", getTaskTitleColor(task), checkbox, task.Title)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user