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.SetShelfListFunc(func() ([]types.ShelfLocation, error) { if shlvr, err := shelves.client.RetrieveAllShelves(); err != nil { return nil, err } else { var shlvo []types.ShelfLocation for _, shelf := range shlvr { shlvo = append(shlvo, *shelf) } return shlvo, nil } }) 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 }