feat: add support for editing status columns #28
5 changed files with 166 additions and 7 deletions
|
@ -100,6 +100,8 @@ func (c *column) update(kanban board.Board) error {
|
|||
}
|
||||
}
|
||||
|
||||
c.statusName = status.Name
|
||||
|
||||
c.SetTitle(fmt.Sprintf(" %s (%d) ", c.statusName, numCardIDs))
|
||||
|
||||
return nil
|
||||
|
|
|
@ -97,6 +97,7 @@ func (a *App) initCardView() {
|
|||
a.cardView.setDoneFunc(doneFunc)
|
||||
}
|
||||
|
||||
// initStatusbar initialises the status bar.
|
||||
func (a *App) initStatusbar() {
|
||||
changedFunc := func() {
|
||||
a.Draw()
|
||||
|
@ -104,3 +105,16 @@ func (a *App) initStatusbar() {
|
|||
|
||||
a.statusbar.SetChangedFunc(changedFunc)
|
||||
}
|
||||
|
||||
func (a *App) initStatusForm() {
|
||||
doneFunc := func(name string, success bool) {
|
||||
if success {
|
||||
a.editFocusedStatusColumn(name)
|
||||
}
|
||||
|
||||
a.pages.HidePage(statusFormPage)
|
||||
a.setColumnFocus()
|
||||
}
|
||||
|
||||
a.statusForm.setDoneFunc(doneFunc)
|
||||
}
|
||||
|
|
|
@ -8,19 +8,21 @@ import (
|
|||
|
||||
func (a *App) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
|
||||
return func(event *tcell.EventKey) *tcell.EventKey {
|
||||
key, letter := event.Key(), event.Rune()
|
||||
key, character := event.Key(), event.Rune()
|
||||
|
||||
switch {
|
||||
case letter == 'h' || key == tcell.KeyLeft:
|
||||
case character == 'h' || key == tcell.KeyLeft:
|
||||
a.shiftColumnFocus(previous)
|
||||
case letter == 'l' || key == tcell.KeyRight:
|
||||
case character == 'l' || key == tcell.KeyRight:
|
||||
a.shiftColumnFocus(next)
|
||||
case letter == 'c':
|
||||
case character == 'c':
|
||||
a.create()
|
||||
case letter == 'm':
|
||||
case character == 'm':
|
||||
a.move()
|
||||
case letter == 'e':
|
||||
case character == 'e':
|
||||
a.edit()
|
||||
case character == 'b':
|
||||
a.updateBoardMode(boardEdit)
|
||||
case key == tcell.KeyCtrlD:
|
||||
a.delete()
|
||||
case key == tcell.KeyCtrlQ:
|
||||
|
@ -54,7 +56,8 @@ func (a *App) move() {
|
|||
}
|
||||
|
||||
func (a *App) edit() {
|
||||
if a.mode == normal {
|
||||
switch a.mode {
|
||||
case normal:
|
||||
a.cardForm.mode = edit
|
||||
|
||||
card, ok := a.getFocusedCard()
|
||||
|
@ -66,6 +69,12 @@ func (a *App) edit() {
|
|||
a.cardForm.frame.SetTitle(" Edit Card ")
|
||||
a.pages.ShowPage(cardFormPage)
|
||||
a.SetFocus(a.cardForm)
|
||||
case boardEdit:
|
||||
statusName := a.focusedStatusName()
|
||||
a.statusForm.updateInputFields(statusName)
|
||||
a.statusForm.frame.SetTitle(" Edit Status Name ")
|
||||
a.pages.ShowPage(statusFormPage)
|
||||
a.SetFocus(a.statusForm)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
103
internal/ui/statusform.go
Normal file
103
internal/ui/statusform.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
type statusForm struct {
|
||||
*tview.Form
|
||||
frame *tview.Frame
|
||||
nameLabel string
|
||||
done func(string, bool)
|
||||
}
|
||||
|
||||
func newStatusForm() *statusForm {
|
||||
var (
|
||||
background = tcell.ColorBlack.TrueColor()
|
||||
buttonBackground = tcell.ColorBlueViolet.TrueColor()
|
||||
textColour = tcell.ColorWhite.TrueColor()
|
||||
fieldBackground = tcell.ColorGrey.TrueColor()
|
||||
labelColour = tcell.ColorGreen.TrueColor()
|
||||
|
||||
form = tview.NewForm()
|
||||
)
|
||||
|
||||
obj := statusForm{
|
||||
Form: form,
|
||||
frame: tview.NewFrame(form),
|
||||
done: nil,
|
||||
nameLabel: "Name",
|
||||
}
|
||||
|
||||
// Stylise the buttons
|
||||
obj.SetButtonsAlign(tview.AlignCenter).
|
||||
SetButtonBackgroundColor(buttonBackground).
|
||||
SetButtonTextColor(textColour).
|
||||
SetBorderPadding(0, 0, 0, 0)
|
||||
|
||||
// Stylise the form
|
||||
obj.SetLabelColor(labelColour).
|
||||
SetFieldBackgroundColor(fieldBackground).
|
||||
SetFieldTextColor(textColour).
|
||||
SetBackgroundColor(background)
|
||||
|
||||
// Stylise the frame around the form
|
||||
obj.frame.SetBorders(0, 0, 1, 0, 0, 0).
|
||||
SetBorder(true).
|
||||
SetBorderColor(tcell.ColorOrangeRed.TrueColor()).
|
||||
SetBackgroundColor(background).
|
||||
SetBorderPadding(1, 1, 1, 1)
|
||||
|
||||
obj.AddButton("Save", func() {
|
||||
if obj.done != nil {
|
||||
name, ok := obj.GetFormItemByLabel(obj.nameLabel).(*tview.InputField)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
obj.done(name.GetText(), true)
|
||||
}
|
||||
})
|
||||
|
||||
obj.AddButton("Cancel", func() {
|
||||
if obj.done != nil {
|
||||
obj.done("", false)
|
||||
}
|
||||
})
|
||||
|
||||
return &obj
|
||||
}
|
||||
|
||||
func (s *statusForm) updateInputFields(name string) {
|
||||
s.Clear(false)
|
||||
s.AddInputField(s.nameLabel, name, 0, nil, nil)
|
||||
}
|
||||
|
||||
func (s *statusForm) setDoneFunc(handler func(string, bool)) *statusForm {
|
||||
s.done = handler
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *statusForm) Draw(screen tcell.Screen) {
|
||||
buttonsWidth := 20
|
||||
screenWidth, screenHeight := screen.Size()
|
||||
width := screenWidth / 3
|
||||
|
||||
if width < buttonsWidth {
|
||||
width = buttonsWidth
|
||||
}
|
||||
|
||||
height := 20
|
||||
width += 4
|
||||
|
||||
// Set the form's position and size.
|
||||
x := (screenWidth - width) / 2
|
||||
y := (screenHeight - height) / 2
|
||||
s.SetRect(x, y, width, height)
|
||||
|
||||
// Draw the frame.
|
||||
s.frame.SetRect(x, y, width, height)
|
||||
s.frame.Draw(screen)
|
||||
}
|
|
@ -23,9 +23,13 @@ const (
|
|||
cardFormPage string = "card form"
|
||||
deleteCardModalPage string = "delete card modal"
|
||||
viewPage string = "view"
|
||||
statusFormPage string = "status form"
|
||||
)
|
||||
|
||||
const (
|
||||
normal boardMode = "NORMAL"
|
||||
selection boardMode = "SELECTION"
|
||||
boardEdit boardMode = "BOARD EDIT"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
|
@ -45,6 +49,7 @@ type App struct {
|
|||
statusSelection statusSelection
|
||||
cardView *cardView
|
||||
statusbar *statusbar
|
||||
statusForm *statusForm
|
||||
}
|
||||
|
||||
// NewApp returns a new App value.
|
||||
|
@ -70,6 +75,7 @@ func NewApp(path string) (App, error) {
|
|||
statusSelection: statusSelection{0, 0, 0},
|
||||
cardView: newCardView(),
|
||||
statusbar: newStatusbar(),
|
||||
statusForm: newStatusForm(),
|
||||
}
|
||||
|
||||
return app, nil
|
||||
|
@ -106,6 +112,9 @@ func (a *App) Init() error {
|
|||
a.initCardView()
|
||||
a.pages.AddPage(viewPage, a.cardView, false, false)
|
||||
|
||||
a.initStatusForm()
|
||||
a.pages.AddPage(statusFormPage, a.statusForm, false, false)
|
||||
|
||||
a.SetRoot(a.pages, true)
|
||||
|
||||
a.refresh(false)
|
||||
|
@ -298,3 +307,25 @@ func (a *App) focusedStatusName() string {
|
|||
func (a *App) closeBoard() {
|
||||
_ = a.board.Close()
|
||||
}
|
||||
|
||||
// editFocusedStatusColumn updates the status column in focus and saves the changes to the database.
|
||||
func (a *App) editFocusedStatusColumn(newName string) {
|
||||
statusID := a.focusedStatusID()
|
||||
|
||||
args := board.UpdateStatusArgs{
|
||||
StatusID: statusID,
|
||||
StatusArgs: board.StatusArgs{
|
||||
Name: newName,
|
||||
},
|
||||
}
|
||||
|
||||
if err := a.board.UpdateStatus(args); err != nil {
|
||||
a.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to edit status: %v.", err))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
a.statusbar.displayMessage(infoLevel, "Status updated successfully.")
|
||||
|
||||
a.refresh(true)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue