pelican/internal/ui/app.go
Dan Anglin cf7c61637f
chore: update project
- update dependencies.
- a little bit of project restructuring.
- update test to make sure they pass.
- move magefile.go to magefiles directory.
2023-04-22 06:19:50 +01:00

155 lines
2.9 KiB
Go

package ui
import (
"fmt"
"codeflow.dananglin.me.uk/apollo/canal/internal/board"
"github.com/rivo/tview"
bolt "go.etcd.io/bbolt"
)
type shiftDirection int
const (
shiftLeft shiftDirection = iota
shiftRight
)
const (
mainPage string = "main"
quitPage string = "quit"
addPage string = "add"
)
// App does some magical stuff.
type App struct {
*tview.Application
columns []column
flex *tview.Flex
pages *tview.Pages
focusedColumn int
db *bolt.DB
}
// shutdown shuts down the application.
func (a *App) shutdown() {
a.closeDB()
a.Stop()
}
// closeDB closes the BoltDB database.
func (a *App) closeDB() {
if a.db != nil {
_ = a.db.Close()
}
}
// openProject opens the kanban project.
func (a *App) openProject(path string) error {
if a.db != nil && len(a.db.Path()) > 0 {
a.db.Close()
}
db, err := board.OpenProject(path)
if err != nil {
return fmt.Errorf("unable to load board, %w", err)
}
a.db = db
if err = a.refresh(); err != nil {
return err
}
return nil
}
// refresh refreshes the UI.
func (a *App) refresh() error {
statusList, err := board.ReadStatusList(a.db)
if err != nil {
return fmt.Errorf("unable to get the status list, %w", err)
}
a.updateBoard(statusList)
a.setColumnFocus()
return nil
}
func (a *App) updateBoard(statusList []board.Status) error {
a.flex.Clear()
columns := make([]column, len(statusList))
for i := range statusList {
columns[i] = a.newColumn(statusList[i].ID, statusList[i].Name)
if len(statusList[i].CardIds) > 0 {
cards, err := board.ReadCardList(a.db, statusList[i].CardIds)
if err != nil {
return fmt.Errorf("unable to get the card list. %w", err)
}
for _, c := range cards {
columns[i].cards.AddItem(fmt.Sprintf("[%d] %s", c.Id(), c.Title), "", 0, nil)
}
}
a.flex.AddItem(columns[i].cards, 0, 1, false)
}
a.columns = columns
return nil
}
func (a *App) shiftColumnFocus(s shiftDirection) {
switch s {
case shiftRight:
if a.focusedColumn == len(a.columns)-1 {
a.focusedColumn = 0
} else {
a.focusedColumn++
}
case shiftLeft:
if a.focusedColumn == 0 {
a.focusedColumn = len(a.columns) - 1
} else {
a.focusedColumn--
}
}
a.setColumnFocus()
}
func (a *App) setColumnFocus() {
a.SetFocus(a.columns[a.focusedColumn].cards)
}
// newCard creates a new card and saves it to the database.
func (a *App) newCard(title, content string) error {
args := board.CardArgs{
NewTitle: title,
NewContent: content,
}
if err := board.CreateCard(a.db, args); err != nil {
return fmt.Errorf("unable to create card, %w", err)
}
a.refresh()
return nil
}
// TODO: Move 'Add' to the centre of the app
// TODO: Customize list primitive or create a new one
// TODO: If customizing existing list primitive, wrap list around a column type. Add statusID to it.
// TODO: Update card status (card ID, oldStatus, newStatus)
//func viewCard() error {
//return nil
//}