Working on Tag Editor

This commit is contained in:
2023-01-12 11:09:49 -06:00
parent 36d24ee5d3
commit 56f12e4a58
3 changed files with 439 additions and 90 deletions

View File

@@ -12,6 +12,13 @@ import (
"github.com/nsf/termbox-go"
)
const (
activeToggleActive = iota
activeToggleInactive
activeToggleAll
activeToggleErr
)
type listTimersScreen struct {
ui *Ui
@@ -21,10 +28,12 @@ type listTimersScreen struct {
cursor int
fullList *timertxt.TimerList
timerList *timertxt.TimerList
doneList *timertxt.TimerList
activeToggle int
fullList *timertxt.TimerList
timerList *timertxt.TimerList
doneList *timertxt.TimerList
fullFilterList *timertxt.TimerList
timerFilterList *timertxt.TimerList
doneFilterList *timertxt.TimerList
@@ -33,7 +42,9 @@ type listTimersScreen struct {
inputDialog *widdles.InputDialog
filter string
partManager *PartManager
choiceMenu *widdles.MenuV
tagEditor *PromptForTagWiddle
//partManager *PartManager
msg string
err error
@@ -49,7 +60,9 @@ func NewListTimersScreen(u *Ui) *listTimersScreen {
scrollbar: widdles.NewScrollbar(w-2, 2, 1, h-2),
selected: make(map[int]bool),
inputDialog: widdles.NewInputDialog("", ""),
partManager: NewPartManager("", 0, 0, 0, 0),
choiceMenu: widdles.NewMenuV(0, 0, 0, 0),
tagEditor: NewPromptForTagWiddle(0, 0, widdles.AUTO_SIZE, widdles.AUTO_SIZE, "", ""),
}
return &s
}
@@ -74,14 +87,23 @@ func (s *listTimersScreen) Init() wandle.Cmd {
s.fullList = timertxt.NewTimerList()
s.fullList.AddTimers(s.timerList.GetTimerSlice())
s.fullList.AddTimers(s.doneList.GetTimerSlice())
s.fullFilterList = s.fullList
s.timerFilterList, s.doneFilterList = s.timerList, s.doneList
s.fullFilterList.Sort(timertxt.SORT_START_DATE_DESC)
s.timerFilterList.Sort(timertxt.SORT_START_DATE_DESC)
s.doneFilterList.Sort(timertxt.SORT_START_DATE_DESC)
w, h := termbox.Size()
s.partManager.SetX(w / 4)
s.partManager.SetY(h / 4)
s.partManager.SetWidth(w / 2)
s.partManager.SetHeight(h / 2)
s.choiceMenu.SetBorder(wandle.BRD_CSIMPLE)
s.choiceMenu.SetX((w / 2) - 7)
s.choiceMenu.SetY((h / 2) - 7)
s.choiceMenu.SetWidth(widdles.AUTO_SIZE)
s.choiceMenu.SetHeight(widdles.AUTO_SIZE)
s.choiceMenu.SetPadding(0, 1, 0, 1)
s.tagEditor.SetX(w / 4)
s.tagEditor.SetY(h / 4)
s.tagEditor.SetWidth(w / 2)
s.tagEditor.SetHeight(h / 2)
s.updateFullFilterList()
return nil
}
@@ -98,44 +120,50 @@ func (s *listTimersScreen) Update(msg wandle.Msg) wandle.Cmd {
func (s *listTimersScreen) View(style wandle.Style) {
_, h := termbox.Size()
y := 2
wandle.Print(1, y, style.Bold(true), "Active Timers")
y++
for idx, tmr := range s.timerFilterList.GetTimerSlice() {
if y > h-2 {
break
}
st := style
if s.cursor == idx {
st = st.Invert()
}
if s.selected[idx] {
wandle.Print(1, y, st, "[✔] ")
} else {
wandle.Print(1, y, st, "[ ] ")
}
s.ViewTimer(5, y, st, tmr)
printedTimers := 0
if s.activeToggle == activeToggleAll || s.activeToggle == activeToggleActive {
wandle.Print(1, y, style.Bold(true), "Active Timers")
y++
}
y++
wandle.Print(1, y, style.Bold(true), "Done Timers")
y++
for idx, tmr := range s.doneFilterList.GetTimerSlice() {
if y > h-3 {
break
for idx, tmr := range s.timerFilterList.GetTimerSlice() {
if y > h-2 {
break
}
st := style
if s.cursor == idx {
st = st.Invert()
}
if s.selected[idx] {
wandle.Print(1, y, st, "[✔] ")
} else {
wandle.Print(1, y, st, "[ ] ")
}
s.ViewTimer(5, y, st, tmr)
y++
}
st := style
if s.cursor == s.timerFilterList.Size()+idx {
st = st.Invert()
}
if s.selected[s.timerFilterList.Size()+idx] {
wandle.Print(1, y, st, "[✔] ")
} else {
wandle.Print(1, y, st, "[ ] ")
}
s.ViewTimer(5, y, st, tmr)
y++
printedTimers = s.timerFilterList.Size()
}
wandle.Print(1, h-1, style, "[p]roject(+), [c]ontext(@), [t]ags(:)")
if s.activeToggle == activeToggleAll || s.activeToggle == activeToggleInactive {
wandle.Print(1, y, style.Bold(true), "Done Timers")
y++
for idx, tmr := range s.doneFilterList.GetTimerSlice() {
if y > h-3 {
break
}
st := style
if s.cursor == printedTimers+idx {
st = st.Invert()
}
if s.selected[printedTimers+idx] {
wandle.Print(1, y, st, "[✔] ")
} else {
wandle.Print(1, y, st, "[ ] ")
}
s.ViewTimer(5, y, st, tmr)
y++
}
}
wandle.Print(1, h-1, style, "[A]ctive toggle, [p]roject(+), [c]ontext(@), [t]ags(:)")
if len(s.selected) > 0 {
wandle.Print(39, h-1, style, fmt.Sprintf("(%d selected)", len(s.selected)))
}
@@ -144,7 +172,13 @@ func (s *listTimersScreen) View(style wandle.Style) {
if s.menu.IsActive() {
s.menu.View(style)
}
s.partManager.View(style)
if s.choiceMenu.IsActive() {
s.choiceMenu.View(style)
}
if s.tagEditor.IsActive() {
s.tagEditor.View(style)
}
wandle.Print(1, h-2, style, s.msg)
}
func (s *listTimersScreen) ViewTimer(x, y int, style wandle.Style, tmr *timertxt.Timer) {
@@ -157,26 +191,19 @@ func (s *listTimersScreen) ViewTimer(x, y int, style wandle.Style, tmr *timertxt
}
func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
if pmRes := s.partManager.Update(msg); pmRes != nil {
return pmRes
if s.choiceMenu.IsActive() {
return s.choiceMenu.Update(msg)
}
if s.tagEditor.IsActive() {
return s.tagEditor.Update(msg)
}
if (msg.Type == termbox.EventKey && msg.Key == termbox.KeyEsc) || s.menu.IsActive() {
return s.menu.Update(msg)
}
switch msg.Type {
case termbox.EventKey:
top := s.timerFilterList.Size() + s.doneFilterList.Size() - 2
selected := len(s.selected)
var selTimer *timertxt.Timer
if selected == 0 {
if s.cursor < s.timerFilterList.Size() {
selTimer, s.err = s.timerFilterList.GetTimer(s.cursor)
} else {
selTimer, s.err = s.doneFilterList.GetTimer(s.cursor)
}
}
if msg.Key == termbox.KeyEnter {
// Edit the entry
// TODO: Edit the entry
/*
if s.cursor >= 0 && s.cursor < s.timerFilterList.Size()+s.doneFilterList.Size() {
} else {
@@ -189,6 +216,12 @@ func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
} else {
s.selected[s.cursor] = true
}
if s.cursor < s.fullFilterList.Size()-1 {
s.cursor++
}
} else if msg.Ch == 'A' {
s.activeToggle = (s.activeToggle + 1) % activeToggleErr
s.updateFullFilterList()
} else if msg.Key == termbox.KeyArrowUp || msg.Ch == 'k' {
if s.cursor > 0 {
s.cursor--
@@ -197,60 +230,172 @@ func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
}
return nil
} else if msg.Key == termbox.KeyArrowDown || msg.Ch == 'j' {
if s.cursor < top {
if s.cursor < s.fullFilterList.Size()-1 {
s.cursor++
} else {
s.cursor = top
s.cursor = s.fullFilterList.Size() - 1
}
return nil
} else if msg.Ch == 'G' {
s.cursor = top
s.cursor = s.fullFilterList.Size() - 1
} else if msg.Ch == 't' {
// Edit tag(s)
tags := s.fullList.GetTagKeys()
s.partManager.SetOptions(tags)
if selected > 0 {
// TODO
//s.partManager.SetLabel(fmt.Sprintf("Manage Tags on %d Timers", selected))
} else {
s.partManager.SetLabel("Manage Tags for Timer")
s.partManager.SetType("Tag")
}
s.partManager.Show()
return s.showEditTagsChoice()
} else if msg.Ch == 'p' {
// Edit project(s)
// TODO: Prompt for Choice: Add/Edit/Remove
projs := s.fullList.GetProjects()
s.partManager.SetOptions(projs)
if selected > 0 {
// TODO
//s.partManager.SetLabel(fmt.Sprintf("Manage Projects on %d Timers", selected))
} else {
s.partManager.SetLabel("Manage Projects for Timer")
s.partManager.SetType("Project")
s.partManager.SetValue(strings.Join(selTimer.Projects, " "))
}
s.partManager.Show()
_ = projs
} else if msg.Ch == 'c' {
// Edit context(s)
// TODO: Prompt for choice: Add/Edit/Remove
ctxts := s.fullList.GetContexts()
s.partManager.SetOptions(ctxts)
if selected > 0 {
// TODO
//s.partManager.SetLabel(fmt.Sprintf("Manage Contexts on %d Timers", selected))
} else {
s.partManager.SetLabel("Manage Contexts for Timer")
s.partManager.SetType("Context")
s.partManager.SetValue(strings.Join(selTimer.Contexts, " "))
}
s.partManager.Show()
_ = ctxts
}
}
return nil
}
func (s *listTimersScreen) showEditTagsChoice() wandle.Cmd {
tags := s.getSelectedTimerTags()
var showTagEditor = func(key, val string) wandle.Cmd {
return func() wandle.Msg {
s.tagEditor.SetTag(key, val)
// TODO: Set Done & Cancel Commands
s.choiceMenu.SetActive(false)
s.tagEditor.SetActive(true)
return wandle.EmptyCmd
}
}
s.choiceMenu.SetTitle("")
s.choiceMenu.ClearOptions()
addTag := widdles.NewMenuItem("Add New Tag")
addTag.SetCommand(showTagEditor("", ""))
s.choiceMenu.AddOption(addTag)
editTag := widdles.NewMenuItem("Edit Tag")
editTag.SetEnabled(len(tags) > 0)
editTag.SetCommand(func() wandle.Msg {
s.choiceMenu.ClearOptions()
s.choiceMenu.SetTitle("Choose Tag to Edit")
for k, v := range tags {
var vals string
if len(v) == 1 {
vals = v[0]
} else {
vals = "..."
}
opt := widdles.NewMenuItem(fmt.Sprintf("%s (%s)", k, vals))
opt.SetCommand(showTagEditor(k, vals))
s.choiceMenu.AddOption(opt)
}
return wandle.EmptyCmd
})
s.choiceMenu.AddOption(editTag)
removeTag := widdles.NewMenuItem("Remove Tag")
removeTag.SetCommand(func() wandle.Msg {
s.choiceMenu.ClearOptions()
s.choiceMenu.SetTitle("Choose Tag to Remove")
return wandle.EmptyCmd
})
s.choiceMenu.AddOption(removeTag)
s.choiceMenu.SetActive(true)
//tags := s.fullList.GetTagKeys()
//_ = tags
return wandle.EmptyCmd
}
func (s *listTimersScreen) updateFullFilterList() {
s.fullFilterList = timertxt.NewTimerList()
switch s.activeToggle {
case activeToggleAll:
s.fullFilterList.Combine(s.timerFilterList)
s.fullFilterList.Combine(s.doneFilterList)
case activeToggleActive:
s.fullFilterList.Combine(s.timerFilterList)
case activeToggleInactive:
s.fullFilterList.Combine(s.doneFilterList)
}
if s.cursor >= s.fullFilterList.Size() {
s.cursor = s.fullFilterList.Size() - 1
}
}
func (s *listTimersScreen) gotoSettingsScreen() wandle.Msg {
return ScreenMsg{
source: ListTimersId,
command: CmdGotoSettings,
}
}
func (s *listTimersScreen) getSelectedTimerTags() map[string][]string {
ret := make(map[string][]string)
selected := len(s.selected)
var selTimer *timertxt.Timer
if selected == 0 {
if s.cursor < s.fullFilterList.Size() {
selTimer, s.err = s.fullFilterList.GetTimer(s.cursor)
for k, v := range selTimer.AdditionalTags {
ret[k] = []string{v}
}
}
} else {
for i := range s.selected {
if tmr, err := s.fullFilterList.GetTimer(i); err == nil {
for k, v := range tmr.AdditionalTags {
if !util.StringSliceContains(ret[k], v) {
ret[k] = append(ret[k], v)
}
}
}
}
}
return ret
}
func (s *listTimersScreen) getSelectedTimerProjects() []string {
var ret []string
selected := len(s.selected)
var selTimer *timertxt.Timer
if selected == 0 {
if s.cursor < s.fullFilterList.Size() {
selTimer, s.err = s.fullFilterList.GetTimer(s.cursor)
for _, v := range selTimer.Projects {
ret = append(ret, v)
}
}
} else {
for i := range s.selected {
if tmr, err := s.fullFilterList.GetTimer(i); err == nil {
for _, v := range tmr.Projects {
if !util.StringSliceContains(ret, v) {
ret = append(ret, v)
}
}
}
}
}
return ret
}
func (s *listTimersScreen) getSelectedTimerContexts() []string {
var ret []string
selected := len(s.selected)
var selTimer *timertxt.Timer
if selected == 0 {
if s.cursor < s.fullFilterList.Size() {
selTimer, s.err = s.fullFilterList.GetTimer(s.cursor)
for _, v := range selTimer.Contexts {
ret = append(ret, v)
}
}
} else {
for i := range s.selected {
if tmr, err := s.fullFilterList.GetTimer(i); err == nil {
for _, v := range tmr.Contexts {
if !util.StringSliceContains(ret, v) {
ret = append(ret, v)
}
}
}
}
}
return ret
}