lots of functionality
This commit is contained in:
156
internal/ui/shelves/command.go
Normal file
156
internal/ui/shelves/command.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package shelves
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.brettb.xyz/goinv/client/internal/ui/dialogs"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/style"
|
||||
)
|
||||
|
||||
func (a *Shelves) runCommand(cmd string) {
|
||||
switch cmd {
|
||||
case "create shelf":
|
||||
a.createDialog.Display()
|
||||
case "edit shelf":
|
||||
a.cedit()
|
||||
case "delete shelf":
|
||||
a.cdelete()
|
||||
case "refresh":
|
||||
a.crefresh()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Shelves) cNotImplemented() {
|
||||
a.displayError("not implemented", fmt.Errorf("this command has not been implemented"))
|
||||
}
|
||||
|
||||
// Confirm deletion
|
||||
func (a *Shelves) cdelete() {
|
||||
selectedItem := a.getSelectedItem()
|
||||
|
||||
// Empty table
|
||||
if selectedItem == nil {
|
||||
a.displayError("DELETE SHELF ERROR", fmt.Errorf("no shelfs to delete"))
|
||||
return
|
||||
}
|
||||
|
||||
title := "delete shelf"
|
||||
a.confirmDialog.SetTitle(title)
|
||||
a.confirmData = status_CONFIRM_DELETE_SHELF
|
||||
bgColor := style.GetColorHex(style.DialogSubBoxBorderColor)
|
||||
fgColor := style.GetColorHex(style.DialogFgColor)
|
||||
|
||||
shelfName := fmt.Sprintf("[%s:%s:b]SHELF NAME:[:-:-] %s", fgColor, bgColor, selectedItem.name)
|
||||
|
||||
confirmMsg := fmt.Sprintf("%s\n%s\nAre you sure you want to delete the selected shelf ?", shelfName)
|
||||
a.confirmDialog.SetText(confirmMsg)
|
||||
a.confirmDialog.Display()
|
||||
}
|
||||
|
||||
func (a *Shelves) cedit() {
|
||||
selectedItem := a.getSelectedItem()
|
||||
if selectedItem == nil {
|
||||
a.displayError("DELETE SHELF ERROR", fmt.Errorf("no shelves to edit"))
|
||||
return
|
||||
}
|
||||
|
||||
shelf, err := a.client.RetrieveShelfByID(selectedItem.id)
|
||||
if err != nil {
|
||||
a.displayError("DELETE SHELF ERROR", fmt.Errorf("unable to retrieve shelf from server"))
|
||||
return
|
||||
}
|
||||
|
||||
a.editDialog.SetShelf(shelf)
|
||||
a.editDialog.Display()
|
||||
}
|
||||
|
||||
func (a *Shelves) edit() {
|
||||
selectedItem := a.getSelectedItem()
|
||||
createReq := a.editDialog.EditShelfOptions()
|
||||
if createReq.Name == "" {
|
||||
a.displayError("SHELF EDIT ERROR", fmt.Errorf("shelf name cannot be empty"))
|
||||
return
|
||||
}
|
||||
|
||||
_, err := a.client.UpdateShelf(selectedItem.id, createReq)
|
||||
if err != nil {
|
||||
a.displayError("SHELF EDIT ERROR", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
a.crefresh()
|
||||
}
|
||||
|
||||
func (a *Shelves) delete() {
|
||||
selectedItem := a.getSelectedItem()
|
||||
|
||||
a.progressDialog.SetTitle(fmt.Sprintf("deleting shelf %s", selectedItem.id))
|
||||
a.progressDialog.Display()
|
||||
|
||||
del := func() {
|
||||
_, err := a.client.DeleteShelfByID(selectedItem.id)
|
||||
|
||||
a.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
a.displayError("DELETE SHELF ERROR", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// display success message
|
||||
a.messageDialog.SetTitle(fmt.Sprintf("deleting shelf %s", selectedItem.id))
|
||||
a.messageDialog.SetText(dialogs.MessageGeneric, "Success!", fmt.Sprintf("Shelf %s successfully deleted.", selectedItem.id))
|
||||
a.messageDialog.Display()
|
||||
|
||||
a.UpdateShelfData()
|
||||
}
|
||||
|
||||
del()
|
||||
}
|
||||
|
||||
func (a *Shelves) crefresh() {
|
||||
a.progressDialog.SetTitle("refreshing shelfs")
|
||||
a.progressDialog.Display()
|
||||
|
||||
ref := func() {
|
||||
a.UpdateShelfData()
|
||||
a.UpdateShelfData()
|
||||
|
||||
a.progressDialog.Hide()
|
||||
|
||||
if !a.errorDialog.IsDisplay() {
|
||||
a.messageDialog.SetTitle("shelf refresh")
|
||||
a.messageDialog.SetText(dialogs.MessageGeneric, "Refreshed!", "Successfully refreshed page.")
|
||||
a.messageDialog.Display()
|
||||
}
|
||||
}
|
||||
|
||||
ref()
|
||||
}
|
||||
|
||||
func (a *Shelves) create() {
|
||||
createReq := a.createDialog.CreateShelfOptions()
|
||||
if createReq.Name == "" {
|
||||
a.displayError("SHELF CREATE ERROR", fmt.Errorf("shelf name cannot be empty"))
|
||||
return
|
||||
}
|
||||
|
||||
_, err := a.client.CreateShelf(createReq)
|
||||
if err != nil {
|
||||
a.displayError("SHELF CREATE ERROR", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
a.crefresh()
|
||||
a.shelfTable.ScrollToEnd()
|
||||
a.shelfTable.Select(a.shelfTable.GetRowCount(), 0)
|
||||
}
|
||||
|
||||
func (a *Shelves) displayError(title string, err error) {
|
||||
a.errorDialog.SetTitle(title)
|
||||
a.errorDialog.SetText(fmt.Sprintf("%v", err))
|
||||
a.errorDialog.Display()
|
||||
}
|
||||
48
internal/ui/shelves/data.go
Normal file
48
internal/ui/shelves/data.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package shelves
|
||||
|
||||
import "git.brettb.xyz/goinv/client/internal/types"
|
||||
|
||||
func (a *Shelves) UpdateData() {
|
||||
a.UpdateShelfData()
|
||||
a.UpdateBuildingData()
|
||||
}
|
||||
|
||||
func (a *Shelves) UpdateShelfData() {
|
||||
shelves, err := a.shelfListFunc()
|
||||
a.shelfList.mu.Lock()
|
||||
defer a.shelfList.mu.Unlock()
|
||||
if err != nil {
|
||||
a.displayError("could not retrieve shelves", err)
|
||||
a.shelfList.dirty = true
|
||||
return
|
||||
}
|
||||
a.shelfList.dirty = false
|
||||
a.shelfList.report = shelves
|
||||
}
|
||||
|
||||
func (a *Shelves) UpdateBuildingData() {
|
||||
buildings, err := a.buildingListFunc()
|
||||
if err != nil {
|
||||
a.displayError("could not retrieve buildings", err)
|
||||
return
|
||||
}
|
||||
a.buildingCache.mu.Lock()
|
||||
a.buildingCache.report = buildings
|
||||
a.buildingCache.mu.Unlock()
|
||||
}
|
||||
|
||||
func (a *Shelves) getShelfData() []types.ShelfLocation {
|
||||
a.shelfList.mu.Lock()
|
||||
shelfReport := a.shelfList.report
|
||||
defer a.shelfList.mu.Unlock()
|
||||
|
||||
return shelfReport
|
||||
}
|
||||
|
||||
func (a *Shelves) getBuildingData() map[uint64]types.Building {
|
||||
a.buildingCache.mu.Lock()
|
||||
buildingReport := a.buildingCache.report
|
||||
defer a.buildingCache.mu.Unlock()
|
||||
|
||||
return buildingReport
|
||||
}
|
||||
24
internal/ui/shelves/draw.go
Normal file
24
internal/ui/shelves/draw.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package shelves
|
||||
|
||||
import "github.com/gdamore/tcell/v2"
|
||||
|
||||
func (a *Shelves) Draw(screen tcell.Screen) {
|
||||
a.refresh()
|
||||
a.Box.DrawForSubclass(screen, a)
|
||||
|
||||
x, y, width, height := a.GetInnerRect()
|
||||
|
||||
a.shelfTable.SetRect(x, y, width, height)
|
||||
a.shelfTable.Draw(screen)
|
||||
|
||||
x, y, width, height = a.shelfTable.GetInnerRect()
|
||||
|
||||
for _, diag := range a.allDialogs {
|
||||
if diag.IsDisplay() {
|
||||
diag.SetRect(x, y, width, height)
|
||||
diag.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
66
internal/ui/shelves/key.go
Normal file
66
internal/ui/shelves/key.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package shelves
|
||||
|
||||
import (
|
||||
"git.brettb.xyz/goinv/client/internal/ui/utils"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func (a *Shelves) InputHandler() func(*tcell.EventKey, func(tview.Primitive)) {
|
||||
return a.WrapInputHandler(func(event *tcell.EventKey, setFocus func(tview.Primitive)) {
|
||||
a.logger.Sugar().Debugf("assets event %v received", event)
|
||||
|
||||
if a.progressDialog.IsDisplay() {
|
||||
setFocus(a.progressDialog)
|
||||
return
|
||||
}
|
||||
|
||||
if a.errorDialog.HasFocus() {
|
||||
if errorHandler := a.errorDialog.InputHandler(); errorHandler != nil {
|
||||
errorHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
if a.messageDialog.HasFocus() {
|
||||
if messageHandler := a.messageDialog.InputHandler(); messageHandler != nil {
|
||||
messageHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
if a.confirmDialog.HasFocus() {
|
||||
if confirmHandler := a.confirmDialog.InputHandler(); confirmHandler != nil {
|
||||
confirmHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
if a.createDialog.HasFocus() {
|
||||
if createHandler := a.createDialog.InputHandler(); createHandler != nil {
|
||||
createHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
if a.editDialog.HasFocus() {
|
||||
if editHandler := a.editDialog.InputHandler(); editHandler != nil {
|
||||
editHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
if a.cmdDialog.HasFocus() {
|
||||
if cmdHandler := a.cmdDialog.InputHandler(); cmdHandler != nil {
|
||||
cmdHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
if a.shelfTable.HasFocus() {
|
||||
if event.Rune() == utils.CommandMenuKey.Rune() {
|
||||
a.cmdDialog.Display()
|
||||
} else {
|
||||
if tableHandler := a.shelfTable.InputHandler(); tableHandler != nil {
|
||||
tableHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFocus(a)
|
||||
})
|
||||
}
|
||||
72
internal/ui/shelves/refresh.go
Normal file
72
internal/ui/shelves/refresh.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package shelves
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.brettb.xyz/goinv/client/internal/ui/style"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
const tableHeaderOffset = 1
|
||||
|
||||
func (a *Shelves) refresh() {
|
||||
shelfs := a.getShelfData()
|
||||
a.shelfTable.Clear()
|
||||
a.updateShelfTableTitle(len(shelfs))
|
||||
|
||||
a.writeTableHeaders()
|
||||
|
||||
for i, shelf := range shelfs {
|
||||
row := i + tableHeaderOffset
|
||||
|
||||
// ID, Name, Building, Room
|
||||
|
||||
a.shelfTable.SetCell(row, 0,
|
||||
tview.NewTableCell(fmt.Sprintf("%d", shelf.ID)).
|
||||
SetExpansion(a.shelfTableExpansions[0]).
|
||||
SetAlign(tview.AlignLeft))
|
||||
|
||||
a.shelfTable.SetCell(row, 1,
|
||||
tview.NewTableCell(shelf.Name).
|
||||
SetExpansion(a.shelfTableExpansions[1]).
|
||||
SetAlign(tview.AlignLeft))
|
||||
|
||||
building := ""
|
||||
if shelf.Building != nil {
|
||||
building = shelf.Building.Name
|
||||
}
|
||||
|
||||
a.shelfTable.SetCell(row, 2,
|
||||
tview.NewTableCell(building).
|
||||
SetExpansion(a.shelfTableExpansions[2]).
|
||||
SetAlign(tview.AlignLeft))
|
||||
|
||||
a.shelfTable.SetCell(row, 2,
|
||||
tview.NewTableCell(shelf.RoomNumber).
|
||||
SetExpansion(a.shelfTableExpansions[3]).
|
||||
SetAlign(tview.AlignLeft))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Shelves) updateShelfTableTitle(count int) {
|
||||
dirtyFlag := ""
|
||||
if a.shelfList.dirty {
|
||||
dirtyFlag = "*"
|
||||
}
|
||||
title := fmt.Sprintf("[::b]SHELVES [%s%d]", dirtyFlag, count)
|
||||
a.shelfTable.SetTitle(title)
|
||||
}
|
||||
|
||||
func (a *Shelves) writeTableHeaders() {
|
||||
for i, headerText := range a.shelfTableHeaders {
|
||||
header := fmt.Sprintf("[::b]%s", strings.ToUpper(headerText))
|
||||
a.shelfTable.SetCell(0, i,
|
||||
tview.NewTableCell(header).
|
||||
SetExpansion(a.shelfTableExpansions[i]).
|
||||
SetBackgroundColor(style.TableHeaderBgColor).
|
||||
SetTextColor(style.TableHeaderFgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
}
|
||||
218
internal/ui/shelves/shelves.go
Normal file
218
internal/ui/shelves/shelves.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package shelves
|
||||
|
||||
import (
|
||||
"git.brettb.xyz/goinv/client/internal/ui/shelves/shlvdialogs"
|
||||
"sync"
|
||||
|
||||
"git.brettb.xyz/goinv/client/internal/api"
|
||||
"git.brettb.xyz/goinv/client/internal/types"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/dialogs"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/style"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/utils"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
status_CONFIRM_DELETE_SHELF = "delete_shelf"
|
||||
)
|
||||
|
||||
type Shelves struct {
|
||||
*tview.Box
|
||||
client *api.APIClient
|
||||
title string
|
||||
logger *zap.Logger
|
||||
shelfTable *tview.Table
|
||||
shelfList shelfListReport
|
||||
buildingCache buildingListReport
|
||||
shelfTableHeaders []string
|
||||
shelfTableExpansions []int
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
createDialog *shlvdialogs.ShelfCreateDialog
|
||||
editDialog *shlvdialogs.ShelfEditDialog
|
||||
allDialogs []dialogs.Dialog
|
||||
confirmData string
|
||||
shelfListFunc func() ([]types.ShelfLocation, error)
|
||||
buildingListFunc func() (map[uint64]types.Building, error)
|
||||
}
|
||||
|
||||
type shelfSelectedItem struct {
|
||||
id string
|
||||
name string
|
||||
building string
|
||||
roomNumber string
|
||||
}
|
||||
|
||||
type shelfListReport struct {
|
||||
mu sync.Mutex
|
||||
report []types.ShelfLocation
|
||||
dirty bool
|
||||
}
|
||||
|
||||
type buildingListReport struct {
|
||||
mu sync.Mutex
|
||||
report map[uint64]types.Building
|
||||
dirty bool
|
||||
}
|
||||
|
||||
func NewShelves(logger *zap.Logger, client *api.APIClient) *Shelves {
|
||||
shelves := &Shelves{
|
||||
Box: tview.NewBox(),
|
||||
client: client,
|
||||
title: "shelves",
|
||||
logger: logger,
|
||||
shelfTable: tview.NewTable(),
|
||||
shelfTableHeaders: []string{"id", "name", "building", "room number"},
|
||||
shelfTableExpansions: []int{1, 4, 2, 2},
|
||||
confirmDialog: dialogs.NewConfirmDialog(logger),
|
||||
errorDialog: dialogs.NewErrorDialog(logger),
|
||||
progressDialog: dialogs.NewProgressDialog(logger),
|
||||
messageDialog: dialogs.NewMessageDialog(logger, ""),
|
||||
createDialog: shlvdialogs.NewShelfCreateDialog(logger, client),
|
||||
editDialog: shlvdialogs.NewShelfEditDialog(logger, client),
|
||||
}
|
||||
|
||||
shelves.shelfTable.SetBackgroundColor(style.BgColor)
|
||||
shelves.shelfTable.SetBorder(true)
|
||||
shelves.updateShelfTableTitle(0)
|
||||
shelves.shelfTable.SetTitleColor(style.FgColor)
|
||||
shelves.shelfTable.SetBorderColor(style.BorderColor)
|
||||
shelves.shelfTable.SetFixed(1, 1)
|
||||
shelves.shelfTable.SetSelectable(true, false)
|
||||
|
||||
shelves.writeTableHeaders()
|
||||
|
||||
shelves.shelfTable.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if shelves.shelfTable.GetRowCount() <= 1 {
|
||||
return nil
|
||||
}
|
||||
return event
|
||||
})
|
||||
|
||||
shelves.cmdDialog = dialogs.NewCommandDialog(logger, [][]string{
|
||||
{"create shelf", "create a new shelf"},
|
||||
{"edit shelf", "edit the selected shelf"},
|
||||
{"delete shelf", "delete the selected shelf"},
|
||||
{"refresh", "refresh the page"},
|
||||
})
|
||||
|
||||
shelves.cmdDialog.SetSelectedFunc(func() {
|
||||
shelves.cmdDialog.Hide()
|
||||
shelves.runCommand(shelves.cmdDialog.GetSelectedItem())
|
||||
}).SetCancelFunc(func() {
|
||||
shelves.cmdDialog.Hide()
|
||||
})
|
||||
|
||||
shelves.confirmDialog.SetSelectedFunc(func() {
|
||||
shelves.confirmDialog.Hide()
|
||||
switch shelves.confirmData {
|
||||
case status_CONFIRM_DELETE_SHELF:
|
||||
shelves.delete()
|
||||
}
|
||||
}).SetCancelFunc(func() {
|
||||
shelves.confirmDialog.Hide()
|
||||
})
|
||||
|
||||
shelves.messageDialog.SetCancelFunc(func() {
|
||||
shelves.messageDialog.Hide()
|
||||
})
|
||||
|
||||
shelves.createDialog.SetCancelFunc(func() {
|
||||
shelves.createDialog.Hide()
|
||||
}).SetCreateFunc(func() {
|
||||
shelves.createDialog.Hide()
|
||||
shelves.create()
|
||||
})
|
||||
|
||||
shelves.editDialog.SetCancelFunc(func() {
|
||||
shelves.editDialog.Hide()
|
||||
}).SetEditFunc(func() {
|
||||
shelves.editDialog.Hide()
|
||||
shelves.edit()
|
||||
})
|
||||
|
||||
shelves.SetBuildingListFunc(func() (map[uint64]types.Building, error) {
|
||||
if resp, err := shelves.client.RetrieveAllBuildings(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
buildings := map[uint64]types.Building{}
|
||||
|
||||
for _, a := range resp {
|
||||
buildings[a.ID] = *a
|
||||
}
|
||||
|
||||
return buildings, nil
|
||||
}
|
||||
})
|
||||
|
||||
shelves.allDialogs = []dialogs.Dialog{
|
||||
shelves.errorDialog,
|
||||
shelves.messageDialog,
|
||||
shelves.progressDialog,
|
||||
shelves.confirmDialog,
|
||||
shelves.createDialog,
|
||||
shelves.editDialog,
|
||||
shelves.cmdDialog,
|
||||
}
|
||||
|
||||
return shelves
|
||||
}
|
||||
|
||||
func (a *Shelves) GetTitle() string {
|
||||
return a.title
|
||||
}
|
||||
|
||||
func (a *Shelves) HasFocus() bool {
|
||||
return dialogs.CheckDialogFocus(a.allDialogs...) || utils.CheckFocus(a.shelfTable, a.Box)
|
||||
}
|
||||
|
||||
func (a *Shelves) SubDialogHasFocus() bool {
|
||||
return dialogs.CheckDialogFocus(a.allDialogs...)
|
||||
}
|
||||
|
||||
func (a *Shelves) Focus(delegate func(tview.Primitive)) {
|
||||
|
||||
for _, dialog := range a.allDialogs {
|
||||
if dialog.IsDisplay() {
|
||||
delegate(dialog)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
delegate(a.shelfTable)
|
||||
}
|
||||
|
||||
func (a *Shelves) SetBuildingListFunc(list func() (map[uint64]types.Building, error)) {
|
||||
a.buildingListFunc = list
|
||||
}
|
||||
|
||||
func (a *Shelves) SetShelfListFunc(list func() ([]types.ShelfLocation, error)) {
|
||||
a.shelfListFunc = list
|
||||
}
|
||||
|
||||
func (a *Shelves) hideAllDialogs() {
|
||||
for _, dialog := range a.allDialogs {
|
||||
dialog.Hide()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Shelves) getSelectedItem() *shelfSelectedItem {
|
||||
selectedItem := shelfSelectedItem{}
|
||||
|
||||
if a.shelfTable.GetRowCount() <= 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
row, _ := a.shelfTable.GetSelection()
|
||||
selectedItem.id = a.shelfTable.GetCell(row, 0).Text
|
||||
selectedItem.name = a.shelfTable.GetCell(row, 1).Text
|
||||
selectedItem.building = a.shelfTable.GetCell(row, 2).Text
|
||||
selectedItem.roomNumber = a.shelfTable.GetCell(row, 3).Text
|
||||
|
||||
return &selectedItem
|
||||
}
|
||||
605
internal/ui/shelves/shlvdialogs/create.go
Normal file
605
internal/ui/shelves/shlvdialogs/create.go
Normal file
@@ -0,0 +1,605 @@
|
||||
package shlvdialogs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.brettb.xyz/goinv/client/internal/api"
|
||||
"git.brettb.xyz/goinv/client/internal/types"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/dialogs"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/style"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/utils"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
shelfCreateDialogMaxWidth = 100
|
||||
shelfCreateDialogHeight = 17
|
||||
)
|
||||
|
||||
const (
|
||||
createShelfFormFocus = 0 + iota
|
||||
createCategoriesFocus
|
||||
createCategoryPagesFocus
|
||||
createShelfNameFieldFocus
|
||||
createShelfRoomFieldFocus
|
||||
createShelfBuildingFieldFocus
|
||||
createShelfDescriptionFieldFocus
|
||||
)
|
||||
|
||||
const (
|
||||
generalPageIndex = 0 + iota
|
||||
locationPageIndex
|
||||
commentPageIndex
|
||||
)
|
||||
|
||||
type ShelfCreateDialog struct {
|
||||
*tview.Box
|
||||
layout *tview.Flex
|
||||
createCategoryLabels []string
|
||||
categories *tview.TextView
|
||||
categoryPages *tview.Pages
|
||||
generalInfoPage *tview.Flex
|
||||
locationPage *tview.Flex
|
||||
commentsPage *tview.Flex
|
||||
form *tview.Form
|
||||
|
||||
display bool
|
||||
activePageIndex int
|
||||
focusElement int
|
||||
logger *zap.Logger
|
||||
client *api.APIClient
|
||||
shelf *types.ShelfLocation
|
||||
buildingList []*types.Building
|
||||
|
||||
shelfNameField *tview.InputField
|
||||
shelfRoomField *tview.InputField
|
||||
shelfDescriptionArea *tview.TextArea
|
||||
shelfBuildingField *tview.DropDown
|
||||
|
||||
focusMap map[int]tview.Primitive
|
||||
|
||||
cancelHandler func()
|
||||
createHandler func()
|
||||
}
|
||||
|
||||
func NewShelfCreateDialog(logger *zap.Logger, client *api.APIClient) *ShelfCreateDialog {
|
||||
createDialog := ShelfCreateDialog{
|
||||
Box: tview.NewBox(),
|
||||
layout: tview.NewFlex(),
|
||||
createCategoryLabels: []string{
|
||||
"General",
|
||||
"Location",
|
||||
"Comments",
|
||||
},
|
||||
categories: tview.NewTextView(),
|
||||
categoryPages: tview.NewPages(),
|
||||
generalInfoPage: tview.NewFlex(),
|
||||
locationPage: tview.NewFlex(),
|
||||
commentsPage: tview.NewFlex(),
|
||||
form: tview.NewForm(),
|
||||
display: false,
|
||||
activePageIndex: 0,
|
||||
logger: logger,
|
||||
client: client,
|
||||
shelfNameField: tview.NewInputField(),
|
||||
shelfRoomField: tview.NewInputField(),
|
||||
shelfBuildingField: tview.NewDropDown(),
|
||||
shelfDescriptionArea: tview.NewTextArea(),
|
||||
}
|
||||
|
||||
createDialog.focusMap = map[int]tview.Primitive{
|
||||
createShelfNameFieldFocus: createDialog.shelfNameField,
|
||||
createShelfRoomFieldFocus: createDialog.shelfRoomField,
|
||||
createShelfBuildingFieldFocus: createDialog.shelfBuildingField,
|
||||
createShelfDescriptionFieldFocus: createDialog.shelfDescriptionArea,
|
||||
}
|
||||
|
||||
createDialog.setupLayout()
|
||||
createDialog.setActiveCategory(0)
|
||||
createDialog.initCustomInputHandlers()
|
||||
|
||||
return &createDialog
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) Display() {
|
||||
d.display = true
|
||||
d.initData()
|
||||
d.focusElement = createCategoryPagesFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) IsDisplay() bool {
|
||||
return d.display
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) Hide() {
|
||||
d.display = false
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) HasFocus() bool {
|
||||
return utils.CheckFocus(d.categories, d.categoryPages, d.Box, d.form)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) Focus(delegate func(tview.Primitive)) {
|
||||
switch d.focusElement {
|
||||
case createShelfFormFocus:
|
||||
button := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
button.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
|
||||
d.Focus(delegate)
|
||||
d.form.SetFocus(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyEnter {
|
||||
return nil
|
||||
}
|
||||
|
||||
return event
|
||||
})
|
||||
delegate(d.form)
|
||||
case createCategoriesFocus:
|
||||
d.categories.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.focusElement = createCategoryPagesFocus
|
||||
d.Focus(delegate)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.focusElement = createShelfFormFocus
|
||||
d.Focus(delegate)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
event = utils.ParseKeyEventKey(d.logger, event)
|
||||
if event.Key() == tcell.KeyDown {
|
||||
d.nextCategory()
|
||||
}
|
||||
if event.Key() == tcell.KeyUp {
|
||||
d.previousCategory()
|
||||
}
|
||||
|
||||
return event
|
||||
})
|
||||
delegate(d.categories)
|
||||
case createCategoryPagesFocus:
|
||||
delegate(d.categoryPages)
|
||||
default:
|
||||
delegate(d.focusMap[d.focusElement])
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) InputHandler() func(*tcell.EventKey, func(tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(tview.Primitive)) {
|
||||
d.logger.Sugar().Debugf("shelf create dialog event %v received", event)
|
||||
|
||||
if event.Key() == utils.CloseDialogKey.EventKey() && !d.dropdownHasFocus() {
|
||||
d.cancelHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if d.generalInfoPage.HasFocus() {
|
||||
if handler := d.generalInfoPage.InputHandler(); handler != nil {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.setGeneralInfoNextFocus()
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.setGeneralInfoPrevFocus()
|
||||
}
|
||||
|
||||
handler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.locationPage.HasFocus() {
|
||||
if handler := d.locationPage.InputHandler(); handler != nil {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.setLocationNextFocus()
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.setLocationPrevFocus()
|
||||
}
|
||||
|
||||
handler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.commentsPage.HasFocus() {
|
||||
if handler := d.commentsPage.InputHandler(); handler != nil {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.setCommentsNextFocus()
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.setCommentsPrevFocus()
|
||||
}
|
||||
|
||||
handler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.categories.HasFocus() {
|
||||
if categoryHandler := d.categories.InputHandler(); categoryHandler != nil {
|
||||
categoryHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.form.HasFocus() {
|
||||
if formHandler := d.form.InputHandler(); formHandler != nil {
|
||||
if event.Key() == tcell.KeyEnter {
|
||||
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
if enterButton.HasFocus() {
|
||||
d.createHandler()
|
||||
}
|
||||
}
|
||||
|
||||
formHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) SetRect(x, y, width, height int) {
|
||||
if width > shelfCreateDialogMaxWidth {
|
||||
emptySpace := (width - shelfCreateDialogMaxWidth) / 2
|
||||
x += emptySpace
|
||||
width = shelfCreateDialogMaxWidth
|
||||
}
|
||||
|
||||
if height > shelfCreateDialogHeight {
|
||||
emptySpace := (height - shelfCreateDialogHeight) / 2
|
||||
y += emptySpace
|
||||
height = shelfCreateDialogHeight
|
||||
}
|
||||
|
||||
d.Box.SetRect(x, y, width, height)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) Draw(screen tcell.Screen) {
|
||||
if !d.display {
|
||||
return
|
||||
}
|
||||
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) SetCreateFunc(f func()) *ShelfCreateDialog {
|
||||
d.createHandler = f
|
||||
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
|
||||
enterButton.SetSelectedFunc(f)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) SetCancelFunc(f func()) *ShelfCreateDialog {
|
||||
d.cancelHandler = f
|
||||
cancelButton := d.form.GetButton(d.form.GetButtonCount() - 2)
|
||||
|
||||
cancelButton.SetSelectedFunc(f)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) dropdownHasFocus() bool {
|
||||
return utils.CheckFocus(d.shelfBuildingField)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) SetShelf(a *types.ShelfLocation) {
|
||||
d.shelf = a
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) initData() {
|
||||
|
||||
// Get available buildings
|
||||
buildingList, _ := d.client.RetrieveAllBuildings()
|
||||
d.buildingList = buildingList
|
||||
|
||||
buildingOptions := []string{""}
|
||||
for _, building := range d.buildingList {
|
||||
buildingOptions = append(buildingOptions, building.Name) // In case we want to do custom formatting later
|
||||
}
|
||||
|
||||
d.setActiveCategory(0)
|
||||
|
||||
// General category
|
||||
|
||||
if d.shelf == nil {
|
||||
d.shelfNameField.SetText("")
|
||||
|
||||
// Location category
|
||||
d.shelfBuildingField.SetOptions(buildingOptions, nil)
|
||||
d.shelfRoomField.SetText("")
|
||||
|
||||
// Comments category
|
||||
d.shelfDescriptionArea.SetText("", true)
|
||||
} else {
|
||||
d.shelfNameField.SetText(d.shelf.Name)
|
||||
|
||||
// Location category
|
||||
d.shelfBuildingField.SetOptions(buildingOptions, nil)
|
||||
if d.shelf.Building != nil {
|
||||
d.shelfBuildingField.SetCurrentOption(findOption(buildingOptions, d.shelf.Building.Name))
|
||||
}
|
||||
d.shelfRoomField.SetText("")
|
||||
|
||||
// Comments category
|
||||
d.shelfDescriptionArea.SetText("", true)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setupLayout() {
|
||||
bgColor := style.DialogBgColor
|
||||
fgColor := style.DialogFgColor
|
||||
|
||||
d.categories.SetDynamicColors(true).
|
||||
SetWrap(true).
|
||||
SetTextAlign(tview.AlignLeft)
|
||||
d.categories.SetBackgroundColor(fgColor)
|
||||
d.categories.SetTextColor(bgColor)
|
||||
d.categories.SetBorder(true)
|
||||
d.categories.SetBorderColor(style.DialogSubBoxBorderColor)
|
||||
|
||||
d.categoryPages.SetBackgroundColor(bgColor)
|
||||
d.categoryPages.SetBorder(true)
|
||||
d.categoryPages.SetBorderColor(style.DialogSubBoxBorderColor)
|
||||
|
||||
d.setupGeneralInfoPageUI()
|
||||
d.setupLocationPageUI()
|
||||
d.setupCommentsPageUI()
|
||||
|
||||
activatedStyle := tcell.StyleDefault.
|
||||
Background(style.ButtonSelectedBgColor).
|
||||
Foreground(style.ButtonSelectedFgColor)
|
||||
|
||||
d.form.SetBackgroundColor(bgColor)
|
||||
d.form.AddButton("Cancel", nil)
|
||||
d.form.AddButton("Create", nil)
|
||||
d.form.SetButtonsAlign(tview.AlignRight)
|
||||
d.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
||||
d.form.SetButtonTextColor(style.ButtonFgColor)
|
||||
d.form.SetButtonActivatedStyle(activatedStyle)
|
||||
|
||||
d.categoryPages.AddPage(d.createCategoryLabels[generalPageIndex], d.generalInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.createCategoryLabels[locationPageIndex], d.locationPage, true, true)
|
||||
d.categoryPages.AddPage(d.createCategoryLabels[commentPageIndex], d.commentsPage, true, true)
|
||||
|
||||
d.layout.SetBackgroundColor(bgColor)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(style.DialogBorderColor)
|
||||
d.layout.SetTitle("SHELF CREATE")
|
||||
d.layout.SetTitleColor(style.DialogFgColor)
|
||||
|
||||
_, layoutWidth := utils.AlignStringListWidth(d.createCategoryLabels)
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
|
||||
layout.AddItem(d.categories, layoutWidth+6, 0, true)
|
||||
layout.AddItem(d.categoryPages, 0, 1, true)
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
d.layout.SetDirection(tview.FlexRow)
|
||||
d.layout.AddItem(layout, 0, 1, true)
|
||||
|
||||
d.layout.AddItem(d.form, dialogs.DialogFormHeight, 0, true)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setupGeneralInfoPageUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
inputFieldBgColor := style.InputFieldBgColor
|
||||
pageLabelWidth := 14
|
||||
|
||||
d.shelfNameField.SetLabel("name:")
|
||||
d.shelfNameField.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfNameField.SetLabelColor(bgColor)
|
||||
d.shelfNameField.SetBackgroundColor(style.DialogFgColor)
|
||||
d.shelfNameField.SetFieldBackgroundColor(inputFieldBgColor)
|
||||
|
||||
d.generalInfoPage.SetDirection(tview.FlexRow)
|
||||
d.generalInfoPage.AddItem(d.shelfNameField, 1, 0, true)
|
||||
d.generalInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setupLocationPageUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
inputFieldBgColor := style.InputFieldBgColor
|
||||
pageLabelWidth := 12
|
||||
ddUnselectedStyle := style.DropdownUnselected
|
||||
ddSelectedStyle := style.DropdownSelected
|
||||
|
||||
d.shelfRoomField.SetLabel("room:")
|
||||
d.shelfRoomField.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfRoomField.SetLabelColor(bgColor)
|
||||
d.shelfRoomField.SetBackgroundColor(style.DialogFgColor)
|
||||
d.shelfRoomField.SetFieldBackgroundColor(inputFieldBgColor)
|
||||
|
||||
d.shelfBuildingField.SetLabel("building:")
|
||||
d.shelfBuildingField.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfBuildingField.SetBackgroundColor(bgColor)
|
||||
d.shelfBuildingField.SetLabelColor(style.DialogFgColor)
|
||||
d.shelfBuildingField.SetListStyles(ddUnselectedStyle, ddSelectedStyle)
|
||||
d.shelfBuildingField.SetFieldBackgroundColor(inputFieldBgColor)
|
||||
|
||||
d.locationPage.SetDirection(tview.FlexRow)
|
||||
d.locationPage.AddItem(d.shelfRoomField, 1, 0, true)
|
||||
d.locationPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.locationPage.AddItem(d.shelfBuildingField, 1, 0, true)
|
||||
d.locationPage.SetBackgroundColor(bgColor)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setupCommentsPageUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
inputFieldBgColor := style.InputFieldBgColor
|
||||
pageLabelWidth := 12
|
||||
|
||||
d.shelfDescriptionArea.SetLabel("comments:")
|
||||
d.shelfDescriptionArea.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfDescriptionArea.SetBackgroundColor(inputFieldBgColor)
|
||||
d.shelfDescriptionArea.SetLabelStyle(tcell.StyleDefault.Foreground(style.DialogFgColor).Background(bgColor))
|
||||
d.shelfDescriptionArea.SetWrap(true)
|
||||
|
||||
d.commentsPage.AddItem(d.shelfDescriptionArea, 0, 1, true)
|
||||
d.commentsPage.SetBackgroundColor(bgColor)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setActiveCategory(idx int) {
|
||||
fgColor := style.ButtonSelectedFgColor
|
||||
bgBolor := style.ButtonSelectedBgColor
|
||||
ctgTextColor := style.GetColorHex(fgColor)
|
||||
ctgBgColor := style.GetColorHex(bgBolor)
|
||||
|
||||
d.activePageIndex = idx
|
||||
|
||||
d.categories.Clear()
|
||||
|
||||
alignedList, _ := utils.AlignStringListWidth(d.createCategoryLabels)
|
||||
|
||||
var ctgList []string
|
||||
|
||||
for i, lbl := range alignedList {
|
||||
if i == idx {
|
||||
ctgList = append(ctgList, fmt.Sprintf("[%s:%s:b]-> %s ", ctgTextColor, ctgBgColor, lbl))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
ctgList = append(ctgList, fmt.Sprintf("[-:-:-] %s ", lbl))
|
||||
}
|
||||
|
||||
d.categories.SetText(strings.Join(ctgList, "\n"))
|
||||
|
||||
d.categoryPages.SwitchToPage(d.createCategoryLabels[idx])
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) nextCategory() {
|
||||
activePage := d.activePageIndex
|
||||
if d.activePageIndex < len(d.createCategoryLabels)-1 {
|
||||
activePage++
|
||||
|
||||
d.setActiveCategory(activePage)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.setActiveCategory(0)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) previousCategory() {
|
||||
activePage := d.activePageIndex
|
||||
if d.activePageIndex > 0 {
|
||||
activePage--
|
||||
|
||||
d.setActiveCategory(activePage)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.setActiveCategory(len(d.createCategoryLabels) - 1)
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) initCustomInputHandlers() {
|
||||
d.shelfBuildingField.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
event = utils.ParseKeyEventKey(d.logger, event)
|
||||
|
||||
return event
|
||||
})
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setGeneralInfoNextFocus() {
|
||||
// Name -> Quantity -> Length -> Manufacturer -> Model -> Price
|
||||
if d.shelfNameField.HasFocus() {
|
||||
d.focusElement = createShelfFormFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = createShelfFormFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setGeneralInfoPrevFocus() {
|
||||
if d.shelfNameField.HasFocus() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = createShelfNameFieldFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setLocationNextFocus() {
|
||||
// Category -> Shelf
|
||||
if d.shelfRoomField.HasFocus() {
|
||||
d.focusElement = createShelfBuildingFieldFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = createShelfFormFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setLocationPrevFocus() {
|
||||
if d.shelfRoomField.HasFocus() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if d.shelfBuildingField.HasFocus() {
|
||||
d.focusElement = createShelfRoomFieldFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = createShelfBuildingFieldFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setCommentsNextFocus() {
|
||||
d.focusElement = createShelfFormFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) setCommentsPrevFocus() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
}
|
||||
|
||||
func (d *ShelfCreateDialog) CreateShelfOptions() types.CreateShelfRequest {
|
||||
var (
|
||||
buildingID *uint64
|
||||
)
|
||||
|
||||
selectedBuildingIndex, _ := d.shelfBuildingField.GetCurrentOption()
|
||||
if len(d.buildingList) > 0 && selectedBuildingIndex > 0 {
|
||||
buildingID = &d.buildingList[selectedBuildingIndex-1].ID
|
||||
}
|
||||
|
||||
req := types.CreateShelfRequest{
|
||||
Name: d.shelfNameField.GetText(),
|
||||
RoomNumber: d.shelfRoomField.GetText(),
|
||||
Description: d.shelfDescriptionArea.GetText(),
|
||||
BuildingID: buildingID,
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
604
internal/ui/shelves/shlvdialogs/edit.go
Normal file
604
internal/ui/shelves/shlvdialogs/edit.go
Normal file
@@ -0,0 +1,604 @@
|
||||
package shlvdialogs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.brettb.xyz/goinv/client/internal/api"
|
||||
"git.brettb.xyz/goinv/client/internal/types"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/dialogs"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/style"
|
||||
"git.brettb.xyz/goinv/client/internal/ui/utils"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
shelfEditDialogMaxWidth = 100
|
||||
shelfEditDialogHeight = 17
|
||||
)
|
||||
|
||||
const (
|
||||
editShelfFormFocus = 0 + iota
|
||||
editCategoriesFocus
|
||||
editCategoryPagesFocus
|
||||
editShelfNameFieldFocus
|
||||
editShelfRoomFieldFocus
|
||||
editShelfBuildingFieldFocus
|
||||
editShelfDescriptionFieldFocus
|
||||
)
|
||||
|
||||
type ShelfEditDialog struct {
|
||||
*tview.Box
|
||||
layout *tview.Flex
|
||||
editCategoryLabels []string
|
||||
categories *tview.TextView
|
||||
categoryPages *tview.Pages
|
||||
generalInfoPage *tview.Flex
|
||||
locationPage *tview.Flex
|
||||
commentsPage *tview.Flex
|
||||
form *tview.Form
|
||||
|
||||
display bool
|
||||
activePageIndex int
|
||||
focusElement int
|
||||
logger *zap.Logger
|
||||
client *api.APIClient
|
||||
shelf *types.ShelfLocation
|
||||
buildingList []*types.Building
|
||||
|
||||
shelfNameField *tview.InputField
|
||||
shelfRoomField *tview.InputField
|
||||
shelfDescriptionArea *tview.TextArea
|
||||
shelfBuildingField *tview.DropDown
|
||||
|
||||
focusMap map[int]tview.Primitive
|
||||
|
||||
cancelHandler func()
|
||||
editHandler func()
|
||||
}
|
||||
|
||||
func NewShelfEditDialog(logger *zap.Logger, client *api.APIClient) *ShelfEditDialog {
|
||||
editDialog := ShelfEditDialog{
|
||||
Box: tview.NewBox(),
|
||||
layout: tview.NewFlex(),
|
||||
editCategoryLabels: []string{
|
||||
"General",
|
||||
"Location",
|
||||
"Comments",
|
||||
},
|
||||
categories: tview.NewTextView(),
|
||||
categoryPages: tview.NewPages(),
|
||||
generalInfoPage: tview.NewFlex(),
|
||||
locationPage: tview.NewFlex(),
|
||||
commentsPage: tview.NewFlex(),
|
||||
form: tview.NewForm(),
|
||||
display: false,
|
||||
activePageIndex: 0,
|
||||
logger: logger,
|
||||
client: client,
|
||||
shelfNameField: tview.NewInputField(),
|
||||
shelfRoomField: tview.NewInputField(),
|
||||
shelfBuildingField: tview.NewDropDown(),
|
||||
shelfDescriptionArea: tview.NewTextArea(),
|
||||
}
|
||||
|
||||
editDialog.focusMap = map[int]tview.Primitive{
|
||||
editShelfNameFieldFocus: editDialog.shelfNameField,
|
||||
editShelfRoomFieldFocus: editDialog.shelfRoomField,
|
||||
editShelfBuildingFieldFocus: editDialog.shelfBuildingField,
|
||||
editShelfDescriptionFieldFocus: editDialog.shelfDescriptionArea,
|
||||
}
|
||||
|
||||
editDialog.setupLayout()
|
||||
editDialog.setActiveCategory(0)
|
||||
editDialog.initCustomInputHandlers()
|
||||
|
||||
return &editDialog
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) Display() {
|
||||
d.display = true
|
||||
d.initData()
|
||||
d.focusElement = editCategoryPagesFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) IsDisplay() bool {
|
||||
return d.display
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) Hide() {
|
||||
d.display = false
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) HasFocus() bool {
|
||||
return utils.CheckFocus(d.categories, d.categoryPages, d.Box, d.form)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) Focus(delegate func(tview.Primitive)) {
|
||||
switch d.focusElement {
|
||||
case editShelfFormFocus:
|
||||
button := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
button.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.focusElement = editCategoriesFocus
|
||||
|
||||
d.Focus(delegate)
|
||||
d.form.SetFocus(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyEnter {
|
||||
return nil
|
||||
}
|
||||
|
||||
return event
|
||||
})
|
||||
delegate(d.form)
|
||||
case editCategoriesFocus:
|
||||
d.categories.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.focusElement = editCategoryPagesFocus
|
||||
d.Focus(delegate)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.focusElement = editShelfFormFocus
|
||||
d.Focus(delegate)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
event = utils.ParseKeyEventKey(d.logger, event)
|
||||
if event.Key() == tcell.KeyDown {
|
||||
d.nextCategory()
|
||||
}
|
||||
if event.Key() == tcell.KeyUp {
|
||||
d.previousCategory()
|
||||
}
|
||||
|
||||
return event
|
||||
})
|
||||
delegate(d.categories)
|
||||
case editCategoryPagesFocus:
|
||||
delegate(d.categoryPages)
|
||||
default:
|
||||
delegate(d.focusMap[d.focusElement])
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) InputHandler() func(*tcell.EventKey, func(tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(tview.Primitive)) {
|
||||
d.logger.Sugar().Debugf("shelf edit dialog event %v received", event)
|
||||
|
||||
if event.Key() == utils.CloseDialogKey.EventKey() && !d.dropdownHasFocus() {
|
||||
d.cancelHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if d.generalInfoPage.HasFocus() {
|
||||
if handler := d.generalInfoPage.InputHandler(); handler != nil {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.setGeneralInfoNextFocus()
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.setGeneralInfoPrevFocus()
|
||||
}
|
||||
|
||||
handler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.locationPage.HasFocus() {
|
||||
if handler := d.locationPage.InputHandler(); handler != nil {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.setLocationNextFocus()
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.setLocationPrevFocus()
|
||||
}
|
||||
|
||||
handler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.commentsPage.HasFocus() {
|
||||
if handler := d.commentsPage.InputHandler(); handler != nil {
|
||||
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
||||
d.setCommentsNextFocus()
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
d.setCommentsPrevFocus()
|
||||
}
|
||||
|
||||
handler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.categories.HasFocus() {
|
||||
if categoryHandler := d.categories.InputHandler(); categoryHandler != nil {
|
||||
categoryHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.form.HasFocus() {
|
||||
if formHandler := d.form.InputHandler(); formHandler != nil {
|
||||
if event.Key() == tcell.KeyEnter {
|
||||
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
if enterButton.HasFocus() {
|
||||
d.editHandler()
|
||||
}
|
||||
}
|
||||
|
||||
formHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) SetRect(x, y, width, height int) {
|
||||
if width > shelfEditDialogMaxWidth {
|
||||
emptySpace := (width - shelfEditDialogMaxWidth) / 2
|
||||
x += emptySpace
|
||||
width = shelfEditDialogMaxWidth
|
||||
}
|
||||
|
||||
if height > shelfEditDialogHeight {
|
||||
emptySpace := (height - shelfEditDialogHeight) / 2
|
||||
y += emptySpace
|
||||
height = shelfEditDialogHeight
|
||||
}
|
||||
|
||||
d.Box.SetRect(x, y, width, height)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) Draw(screen tcell.Screen) {
|
||||
if !d.display {
|
||||
return
|
||||
}
|
||||
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) SetEditFunc(f func()) *ShelfEditDialog {
|
||||
d.editHandler = f
|
||||
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
|
||||
enterButton.SetSelectedFunc(f)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) SetCancelFunc(f func()) *ShelfEditDialog {
|
||||
d.cancelHandler = f
|
||||
cancelButton := d.form.GetButton(d.form.GetButtonCount() - 2)
|
||||
|
||||
cancelButton.SetSelectedFunc(f)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) dropdownHasFocus() bool {
|
||||
return utils.CheckFocus(d.shelfBuildingField)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) SetShelf(a *types.ShelfLocation) {
|
||||
d.shelf = a
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) initData() {
|
||||
|
||||
// Get available buildings
|
||||
buildingList, _ := d.client.RetrieveAllBuildings()
|
||||
d.buildingList = buildingList
|
||||
|
||||
buildingOptions := []string{""}
|
||||
for _, building := range d.buildingList {
|
||||
buildingOptions = append(buildingOptions, building.Name) // In case we want to do custom formatting later
|
||||
}
|
||||
|
||||
d.setActiveCategory(0)
|
||||
|
||||
// General category
|
||||
|
||||
if d.shelf == nil {
|
||||
d.shelfNameField.SetText("")
|
||||
|
||||
// Location category
|
||||
d.shelfBuildingField.SetOptions(buildingOptions, nil)
|
||||
d.shelfRoomField.SetText("")
|
||||
|
||||
// Comments category
|
||||
d.shelfDescriptionArea.SetText("", true)
|
||||
} else {
|
||||
d.shelfNameField.SetText(d.shelf.Name)
|
||||
|
||||
// Location category
|
||||
d.shelfBuildingField.SetOptions(buildingOptions, nil)
|
||||
if d.shelf.Building != nil {
|
||||
d.shelfBuildingField.SetCurrentOption(findOption(buildingOptions, d.shelf.Building.Name))
|
||||
}
|
||||
d.shelfRoomField.SetText("")
|
||||
|
||||
// Comments category
|
||||
d.shelfDescriptionArea.SetText("", true)
|
||||
}
|
||||
}
|
||||
|
||||
func findOption(options []string, search string) int {
|
||||
return slices.Index(options, search)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setupLayout() {
|
||||
bgColor := style.DialogBgColor
|
||||
fgColor := style.DialogFgColor
|
||||
|
||||
d.categories.SetDynamicColors(true).
|
||||
SetWrap(true).
|
||||
SetTextAlign(tview.AlignLeft)
|
||||
d.categories.SetBackgroundColor(fgColor)
|
||||
d.categories.SetTextColor(bgColor)
|
||||
d.categories.SetBorder(true)
|
||||
d.categories.SetBorderColor(style.DialogSubBoxBorderColor)
|
||||
|
||||
d.categoryPages.SetBackgroundColor(bgColor)
|
||||
d.categoryPages.SetBorder(true)
|
||||
d.categoryPages.SetBorderColor(style.DialogSubBoxBorderColor)
|
||||
|
||||
d.setupGeneralInfoPageUI()
|
||||
d.setupLocationPageUI()
|
||||
d.setupCommentsPageUI()
|
||||
|
||||
activatedStyle := tcell.StyleDefault.
|
||||
Background(style.ButtonSelectedBgColor).
|
||||
Foreground(style.ButtonSelectedFgColor)
|
||||
|
||||
d.form.SetBackgroundColor(bgColor)
|
||||
d.form.AddButton("Cancel", nil)
|
||||
d.form.AddButton("Edit", nil)
|
||||
d.form.SetButtonsAlign(tview.AlignRight)
|
||||
d.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
||||
d.form.SetButtonTextColor(style.ButtonFgColor)
|
||||
d.form.SetButtonActivatedStyle(activatedStyle)
|
||||
|
||||
d.categoryPages.AddPage(d.editCategoryLabels[generalPageIndex], d.generalInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.editCategoryLabels[locationPageIndex], d.locationPage, true, true)
|
||||
d.categoryPages.AddPage(d.editCategoryLabels[commentPageIndex], d.commentsPage, true, true)
|
||||
|
||||
d.layout.SetBackgroundColor(bgColor)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(style.DialogBorderColor)
|
||||
d.layout.SetTitle("SHELF EDIT")
|
||||
d.layout.SetTitleColor(style.DialogFgColor)
|
||||
|
||||
_, layoutWidth := utils.AlignStringListWidth(d.editCategoryLabels)
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
|
||||
layout.AddItem(d.categories, layoutWidth+6, 0, true)
|
||||
layout.AddItem(d.categoryPages, 0, 1, true)
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
d.layout.SetDirection(tview.FlexRow)
|
||||
d.layout.AddItem(layout, 0, 1, true)
|
||||
|
||||
d.layout.AddItem(d.form, dialogs.DialogFormHeight, 0, true)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setupGeneralInfoPageUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
inputFieldBgColor := style.InputFieldBgColor
|
||||
pageLabelWidth := 14
|
||||
|
||||
d.shelfNameField.SetLabel("name:")
|
||||
d.shelfNameField.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfNameField.SetLabelColor(bgColor)
|
||||
d.shelfNameField.SetBackgroundColor(style.DialogFgColor)
|
||||
d.shelfNameField.SetFieldBackgroundColor(inputFieldBgColor)
|
||||
|
||||
d.generalInfoPage.SetDirection(tview.FlexRow)
|
||||
d.generalInfoPage.AddItem(d.shelfNameField, 1, 0, true)
|
||||
d.generalInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setupLocationPageUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
inputFieldBgColor := style.InputFieldBgColor
|
||||
pageLabelWidth := 12
|
||||
ddUnselectedStyle := style.DropdownUnselected
|
||||
ddSelectedStyle := style.DropdownSelected
|
||||
|
||||
d.shelfRoomField.SetLabel("room:")
|
||||
d.shelfRoomField.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfRoomField.SetLabelColor(bgColor)
|
||||
d.shelfRoomField.SetBackgroundColor(style.DialogFgColor)
|
||||
d.shelfRoomField.SetFieldBackgroundColor(inputFieldBgColor)
|
||||
|
||||
d.shelfBuildingField.SetLabel("building:")
|
||||
d.shelfBuildingField.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfBuildingField.SetBackgroundColor(bgColor)
|
||||
d.shelfBuildingField.SetLabelColor(style.DialogFgColor)
|
||||
d.shelfBuildingField.SetListStyles(ddUnselectedStyle, ddSelectedStyle)
|
||||
d.shelfBuildingField.SetFieldBackgroundColor(inputFieldBgColor)
|
||||
|
||||
d.locationPage.SetDirection(tview.FlexRow)
|
||||
d.locationPage.AddItem(d.shelfRoomField, 1, 0, true)
|
||||
d.locationPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.locationPage.AddItem(d.shelfBuildingField, 1, 0, true)
|
||||
d.locationPage.SetBackgroundColor(bgColor)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setupCommentsPageUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
inputFieldBgColor := style.InputFieldBgColor
|
||||
pageLabelWidth := 12
|
||||
|
||||
d.shelfDescriptionArea.SetLabel("comments:")
|
||||
d.shelfDescriptionArea.SetLabelWidth(pageLabelWidth)
|
||||
d.shelfDescriptionArea.SetBackgroundColor(inputFieldBgColor)
|
||||
d.shelfDescriptionArea.SetLabelStyle(tcell.StyleDefault.Foreground(style.DialogFgColor).Background(bgColor))
|
||||
d.shelfDescriptionArea.SetWrap(true)
|
||||
|
||||
d.commentsPage.AddItem(d.shelfDescriptionArea, 0, 1, true)
|
||||
d.commentsPage.SetBackgroundColor(bgColor)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setActiveCategory(idx int) {
|
||||
fgColor := style.ButtonSelectedFgColor
|
||||
bgBolor := style.ButtonSelectedBgColor
|
||||
ctgTextColor := style.GetColorHex(fgColor)
|
||||
ctgBgColor := style.GetColorHex(bgBolor)
|
||||
|
||||
d.activePageIndex = idx
|
||||
|
||||
d.categories.Clear()
|
||||
|
||||
alignedList, _ := utils.AlignStringListWidth(d.editCategoryLabels)
|
||||
|
||||
var ctgList []string
|
||||
|
||||
for i, lbl := range alignedList {
|
||||
if i == idx {
|
||||
ctgList = append(ctgList, fmt.Sprintf("[%s:%s:b]-> %s ", ctgTextColor, ctgBgColor, lbl))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
ctgList = append(ctgList, fmt.Sprintf("[-:-:-] %s ", lbl))
|
||||
}
|
||||
|
||||
d.categories.SetText(strings.Join(ctgList, "\n"))
|
||||
|
||||
d.categoryPages.SwitchToPage(d.editCategoryLabels[idx])
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) nextCategory() {
|
||||
activePage := d.activePageIndex
|
||||
if d.activePageIndex < len(d.editCategoryLabels)-1 {
|
||||
activePage++
|
||||
|
||||
d.setActiveCategory(activePage)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.setActiveCategory(0)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) previousCategory() {
|
||||
activePage := d.activePageIndex
|
||||
if d.activePageIndex > 0 {
|
||||
activePage--
|
||||
|
||||
d.setActiveCategory(activePage)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.setActiveCategory(len(d.editCategoryLabels) - 1)
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) initCustomInputHandlers() {
|
||||
d.shelfBuildingField.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
event = utils.ParseKeyEventKey(d.logger, event)
|
||||
|
||||
return event
|
||||
})
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setGeneralInfoNextFocus() {
|
||||
// Name -> Quantity -> Length -> Manufacturer -> Model -> Price
|
||||
if d.shelfNameField.HasFocus() {
|
||||
d.focusElement = editShelfFormFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = editShelfFormFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setGeneralInfoPrevFocus() {
|
||||
if d.shelfNameField.HasFocus() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = editShelfNameFieldFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setLocationNextFocus() {
|
||||
// Category -> Shelf
|
||||
if d.shelfRoomField.HasFocus() {
|
||||
d.focusElement = editShelfBuildingFieldFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = editShelfFormFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setLocationPrevFocus() {
|
||||
if d.shelfRoomField.HasFocus() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if d.shelfBuildingField.HasFocus() {
|
||||
d.focusElement = editShelfRoomFieldFocus
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = editShelfBuildingFieldFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setCommentsNextFocus() {
|
||||
d.focusElement = editShelfFormFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) setCommentsPrevFocus() {
|
||||
d.focusElement = createCategoriesFocus
|
||||
}
|
||||
|
||||
func (d *ShelfEditDialog) EditShelfOptions() types.CreateShelfRequest {
|
||||
var (
|
||||
buildingID *uint64
|
||||
)
|
||||
|
||||
selectedBuildingIndex, _ := d.shelfBuildingField.GetCurrentOption()
|
||||
if len(d.buildingList) > 0 && selectedBuildingIndex > 0 {
|
||||
buildingID = &d.buildingList[selectedBuildingIndex-1].ID
|
||||
}
|
||||
|
||||
req := types.CreateShelfRequest{
|
||||
Name: d.shelfNameField.GetText(),
|
||||
RoomNumber: d.shelfRoomField.GetText(),
|
||||
Description: d.shelfDescriptionArea.GetText(),
|
||||
BuildingID: buildingID,
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
Reference in New Issue
Block a user