Compare commits

..

No commits in common. "eb2ed4060af018e68728b04be9ca58772bc82d66" and "ee861e5426c6522caa5b71e3254761a0babbb2f3" have entirely different histories.

2 changed files with 37 additions and 139 deletions

View file

@ -1,50 +0,0 @@
package ui
import (
"fmt"
"time"
"github.com/rivo/tview"
)
type statusbarLogLevel int
const (
infoLevel statusbarLogLevel = iota
errorLevel
)
type statusbar struct {
*tview.TextView
duration time.Duration
}
func newStatusbar() *statusbar {
value := statusbar{
TextView: tview.NewTextView(),
duration: 5 * time.Second,
}
value.SetDynamicColors(true).SetBorder(false).SetBorderPadding(0, 0, 1, 1)
return &value
}
func (s *statusbar) displayMessage(level statusbarLogLevel, message string) {
go func() {
var colour string
switch level {
case infoLevel:
colour = "green"
case errorLevel:
colour = "red"
}
fmt.Fprintf(s, "[%s::b]%s[-:-:-:-]", colour, message)
time.Sleep(s.duration)
s.Clear()
}()
}

View file

@ -35,8 +35,7 @@ type UI struct {
*tview.Application *tview.Application
columns []*column columns []*column
baseFlex *tview.Flex flex *tview.Flex
columnFlex *tview.Flex
pages *tview.Pages pages *tview.Pages
focusedColumn int focusedColumn int
board board.Board board board.Board
@ -46,7 +45,6 @@ type UI struct {
deleteCardModal *tview.Modal deleteCardModal *tview.Modal
statusSelection statusSelection statusSelection statusSelection
view *cardView view *cardView
statusbar *statusbar
} }
// NewUI returns a new UI value. // NewUI returns a new UI value.
@ -59,8 +57,7 @@ func NewUI(path string) (UI, error) {
userInterface := UI{ userInterface := UI{
Application: tview.NewApplication(), Application: tview.NewApplication(),
pages: tview.NewPages(), pages: tview.NewPages(),
baseFlex: tview.NewFlex(), flex: tview.NewFlex(),
columnFlex: tview.NewFlex(),
quitModal: tview.NewModal(), quitModal: tview.NewModal(),
cardForm: newCardForm(), cardForm: newCardForm(),
focusedColumn: 0, focusedColumn: 0,
@ -70,7 +67,6 @@ func NewUI(path string) (UI, error) {
mode: normal, mode: normal,
statusSelection: statusSelection{0, 0, 0}, statusSelection: statusSelection{0, 0, 0},
view: newCardView(), view: newCardView(),
statusbar: newStatusbar(),
} }
if err := userInterface.init(); err != nil { if err := userInterface.init(); err != nil {
@ -87,19 +83,14 @@ func (u *UI) closeBoard() {
// init initialises the UI. // init initialises the UI.
func (u *UI) init() error { func (u *UI) init() error {
if err := u.initColumns(); err != nil { err := u.initColumns()
if err != nil {
return fmt.Errorf("error initialising the status columns; %w", err) return fmt.Errorf("error initialising the status columns; %w", err)
} }
u.columnFlex.SetInputCapture(u.inputCapture()) u.flex.SetInputCapture(u.inputCapture())
u.initStatusbar() u.pages.AddPage(mainPage, u.flex, true, true)
u.baseFlex.SetDirection(tview.FlexRow)
u.baseFlex.AddItem(u.columnFlex, 0, 1, true)
u.baseFlex.AddItem(u.statusbar, 2, 1, false)
u.pages.AddPage(mainPage, u.baseFlex, true, true)
u.initQuitModal() u.initQuitModal()
u.pages.AddPage(quitPage, u.quitModal, false, false) u.pages.AddPage(quitPage, u.quitModal, false, false)
@ -115,7 +106,9 @@ func (u *UI) init() error {
u.SetRoot(u.pages, true) u.SetRoot(u.pages, true)
u.refresh(false) if err := u.refresh(false); err != nil {
return fmt.Errorf("error refreshing the board; %w", err)
}
return nil return nil
} }
@ -146,12 +139,7 @@ func (u *UI) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
case letter == 'e': case letter == 'e':
if u.mode == normal { if u.mode == normal {
u.cardForm.mode = edit u.cardForm.mode = edit
card, _ := u.getFocusedCard()
card, ok := u.getFocusedCard()
if !ok {
break
}
u.cardForm.updateInputFields(card.Title, card.Description) u.cardForm.updateInputFields(card.Title, card.Description)
u.cardForm.frame.SetTitle(" Edit Card ") u.cardForm.frame.SetTitle(" Edit Card ")
u.pages.ShowPage(cardFormPage) u.pages.ShowPage(cardFormPage)
@ -159,11 +147,7 @@ func (u *UI) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
} }
case key == tcell.KeyCtrlD: case key == tcell.KeyCtrlD:
if u.mode == normal { if u.mode == normal {
card, ok := u.getFocusedCard() card, _ := u.getFocusedCard()
if !ok {
break
}
text := fmt.Sprintf("Do you want to delete '%s'?", card.Title) text := fmt.Sprintf("Do you want to delete '%s'?", card.Title)
u.deleteCardModal.SetText(text) u.deleteCardModal.SetText(text)
u.pages.ShowPage(deleteCardModalPage) u.pages.ShowPage(deleteCardModalPage)
@ -181,11 +165,7 @@ func (u *UI) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
case key == tcell.KeyEnter: case key == tcell.KeyEnter:
switch u.mode { switch u.mode {
case normal: case normal:
card, ok := u.getFocusedCard() card, _ := u.getFocusedCard()
if !ok {
break
}
status := u.focusedStatusName() status := u.focusedStatusName()
u.view.print(card.ID, card.Title, status, card.Created, card.Description) u.view.print(card.ID, card.Title, status, card.Created, card.Description)
u.pages.ShowPage(viewPage) u.pages.ShowPage(viewPage)
@ -198,7 +178,7 @@ func (u *UI) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
u.statusSelection = statusSelection{0, 0, 0} u.statusSelection = statusSelection{0, 0, 0}
u.mode = normal u.mode = normal
u.refresh(false) _ = u.refresh(false)
} }
} }
@ -212,9 +192,9 @@ func (u *UI) initCardForm() {
if success { if success {
switch mode { switch mode {
case create: case create:
u.saveCard(title, description) _ = u.newCard(title, description)
case edit: case edit:
u.editFocusedCard(title, description) _ = u.editFocusedCard(title, description)
} }
} }
@ -230,7 +210,7 @@ func (u *UI) initDeleteCardModal() {
doneFunc := func(_ int, buttonLabel string) { doneFunc := func(_ int, buttonLabel string) {
if buttonLabel == "Confirm" { if buttonLabel == "Confirm" {
u.deleteFocusedCard() u.deleteFocusedCard()
u.refresh(true) _ = u.refresh(true)
} }
u.pages.HidePage(deleteCardModalPage) u.pages.HidePage(deleteCardModalPage)
@ -275,35 +255,24 @@ func (u *UI) initView() {
u.view.setDoneFunc(doneFunc) u.view.setDoneFunc(doneFunc)
} }
func (u *UI) initStatusbar() { // newCard creates and saves a new card to the database.
changedFunc := func() { func (u *UI) newCard(title, description string) error {
u.Draw()
}
u.statusbar.SetChangedFunc(changedFunc)
}
// saveCard creates and saves a new card to the database.
func (u *UI) saveCard(title, description string) {
args := board.CardArgs{ args := board.CardArgs{
NewTitle: title, NewTitle: title,
NewDescription: description, NewDescription: description,
} }
_, err := u.board.CreateCard(args) if _, err := u.board.CreateCard(args); err != nil {
if err != nil { return fmt.Errorf("unable to create card, %w", err)
u.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to create card: %v.", err))
return
} }
u.statusbar.displayMessage(infoLevel, "Card created successfully.") _ = u.refresh(false)
u.refresh(false) return nil
} }
// editFocusedCard saves and edited card to the database. // editFocusedCard saves and edited card to the database.
func (u *UI) editFocusedCard(title, description string) { func (u *UI) editFocusedCard(title, description string) error {
cardID := u.focusedCardID() cardID := u.focusedCardID()
args := board.UpdateCardArgs{ args := board.UpdateCardArgs{
@ -315,31 +284,24 @@ func (u *UI) editFocusedCard(title, description string) {
} }
if err := u.board.UpdateCard(args); err != nil { if err := u.board.UpdateCard(args); err != nil {
u.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to edit card: %v.", err)) return fmt.Errorf("unable to edit card with ID: %d; %w", cardID, err)
return
} }
u.statusbar.displayMessage(infoLevel, "Card edited successfully.") _ = u.refresh(true)
u.refresh(true) return nil
} }
// getFocusedCard retrieves the details of the focused card. // getFocusedCard retrieves the details of the focused card.
func (u *UI) getFocusedCard() (board.Card, bool) { func (u *UI) getFocusedCard() (board.Card, error) {
cardID := u.focusedCardID() cardID := u.focusedCardID()
card, err := u.board.Card(cardID) card, err := u.board.Card(cardID)
if err != nil { if err != nil {
u.statusbar.displayMessage( return board.Card{}, fmt.Errorf("unable to retrieve the card with card ID %d, %w", cardID, err)
errorLevel,
fmt.Sprintf("Failed to retrieve the card with card ID %d, %v.", cardID, err),
)
return card, false
} }
return card, true return card, nil
} }
// deleteFocusedCard deletes the focused card from the board. // deleteFocusedCard deletes the focused card from the board.
@ -349,18 +311,12 @@ func (u *UI) deleteFocusedCard() {
StatusID: u.focusedStatusID(), StatusID: u.focusedStatusID(),
} }
if err := u.board.DeleteCard(args); err != nil { _ = u.board.DeleteCard(args)
u.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to delete card: %v.", err))
return
}
u.statusbar.displayMessage(infoLevel, "Card deleted successfully.")
} }
// initColumns initialises the columns of the Kanban board. // initColumns initialises the columns of the Kanban board.
func (u *UI) initColumns() error { func (u *UI) initColumns() error {
u.columnFlex.Clear() u.flex.Clear()
statusList, err := u.board.StatusList() statusList, err := u.board.StatusList()
if err != nil { if err != nil {
@ -371,7 +327,7 @@ func (u *UI) initColumns() error {
for i := range statusList { for i := range statusList {
column := newColumn(statusList[i].ID, statusList[i].Name, u.boardMode) column := newColumn(statusList[i].ID, statusList[i].Name, u.boardMode)
u.columnFlex.AddItem(column, 50, 1, true) u.flex.AddItem(column, 50, 1, true)
columns[i] = column columns[i] = column
} }
@ -422,28 +378,20 @@ func (u *UI) setColumnFocus() {
} }
// refresh refreshes the UI. // refresh refreshes the UI.
func (u *UI) refresh(updateFocusedColumnOnly bool) { func (u *UI) refresh(updateFocusedColumnOnly bool) error {
if updateFocusedColumnOnly { if updateFocusedColumnOnly {
if err := u.updateColumn(u.focusedColumn); err != nil { if err := u.updateColumn(u.focusedColumn); err != nil {
u.statusbar.displayMessage( return err
errorLevel,
fmt.Sprintf("Failed to update status column %q: %v", u.focusedStatusName(), err),
)
return
} }
} else { } else {
if err := u.updateAllColumns(); err != nil { if err := u.updateAllColumns(); err != nil {
u.statusbar.displayMessage( return err
errorLevel,
fmt.Sprintf("Failed to update status columns: %v", err),
)
return
} }
} }
u.setColumnFocus() u.setColumnFocus()
return nil
} }
// shutdown shuts down the application. // shutdown shuts down the application.