You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

216 lines
5.4 KiB

package assets
import (
"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_ASSET = "delete_asset"
)
type Assets struct {
*tview.Box
client *api.APIClient
title string
logger *zap.Logger
assetTable *tview.Table
assetList assetListReport
shelfLocationCache shelfListReport
assetTableHeaders []string
assetTableExpansions []int
cmdDialog *dialogs.CommandDialog
confirmDialog *dialogs.ConfirmDialog
errorDialog *dialogs.ErrorDialog
progressDialog *dialogs.ProgressDialog
messageDialog *dialogs.MessageDialog
allDialogs []dialogs.Dialog
confirmData string
assetListFunc func() ([]types.Asset, error)
shelfListFunc func() (map[uint64]types.ShelfLocation, error)
}
type assetSelectedItem struct {
id string
item string
quantity string
shelfLocation string
manufacturer string
model string
category string
}
type assetListReport struct {
mu sync.Mutex
report []types.Asset
dirty bool
}
type shelfListReport struct {
mu sync.Mutex
report map[uint64]types.ShelfLocation
}
func NewAssets(logger *zap.Logger, client *api.APIClient) *Assets {
assets := &Assets{
Box: tview.NewBox(),
client: client,
title: "assets",
logger: logger,
assetTable: tview.NewTable(),
assetTableHeaders: []string{"id", "item", "quantity", "shelf location", "manufacturer", "model", "category"},
assetTableExpansions: []int{1, 4, 1, 2, 2, 2, 2},
confirmDialog: dialogs.NewConfirmDialog(logger),
errorDialog: dialogs.NewErrorDialog(logger),
progressDialog: dialogs.NewProgressDialog(logger),
messageDialog: dialogs.NewMessageDialog(logger, ""),
}
assets.assetTable.SetBackgroundColor(style.BgColor)
assets.assetTable.SetBorder(true)
assets.updateAssetTableTitle(0)
assets.assetTable.SetTitleColor(style.FgColor)
assets.assetTable.SetBorderColor(style.BorderColor)
assets.assetTable.SetFixed(1, 1)
assets.assetTable.SetSelectable(true, false)
assets.writeTableHeaders()
assets.assetTable.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if assets.assetTable.GetRowCount() <= 1 {
return nil
}
return event
})
assets.cmdDialog = dialogs.NewCommandDialog(logger, [][]string{
{"create asset", "create a new asset"},
{"view asset", "view the selected asset"},
{"delete asset", "delete the selected asset"},
{"refresh", "refresh the page"},
})
assets.cmdDialog.SetSelectedFunc(func() {
assets.cmdDialog.Hide()
assets.runCommand(assets.cmdDialog.GetSelectedItem())
}).SetCancelFunc(func() {
assets.cmdDialog.Hide()
})
assets.confirmDialog.SetSelectedFunc(func() {
assets.confirmDialog.Hide()
switch assets.confirmData {
case status_CONFIRM_DELETE_ASSET:
assets.delete()
}
}).SetCancelFunc(func() {
assets.confirmDialog.Hide()
})
assets.messageDialog.SetCancelFunc(func() {
assets.messageDialog.Hide()
})
assets.SetAssetListFunc(func() ([]types.Asset, error) {
if asp, err := assets.client.RetrieveAllAssets(); err != nil {
return nil, err
} else {
var aso []types.Asset
for _, a := range asp {
aso = append(aso, *a)
}
return aso, nil
}
})
assets.SetShelfListFunc(func() (map[uint64]types.ShelfLocation, error) {
if resp, err := assets.client.RetrieveAllShelves(); err != nil {
return nil, err
} else {
shelves := map[uint64]types.ShelfLocation{}
for _, a := range resp {
shelves[a.ID] = *a
}
return shelves, nil
}
})
assets.allDialogs = []dialogs.Dialog{
assets.errorDialog,
assets.messageDialog,
assets.progressDialog,
assets.confirmDialog,
assets.cmdDialog,
}
return assets
}
func (a *Assets) GetTitle() string {
return a.title
}
func (a *Assets) HasFocus() bool {
return dialogs.CheckDialogFocus(a.allDialogs...) || utils.CheckFocus(a.assetTable, a.Box)
}
func (a *Assets) SubDialogHasFocus() bool {
return dialogs.CheckDialogFocus(a.allDialogs...)
}
func (a *Assets) Focus(delegate func(tview.Primitive)) {
for _, dialog := range a.allDialogs {
if dialog.IsDisplay() {
delegate(dialog)
return
}
}
delegate(a.assetTable)
}
func (a *Assets) SetAssetListFunc(list func() ([]types.Asset, error)) {
a.assetListFunc = list
}
func (a *Assets) SetShelfListFunc(list func() (map[uint64]types.ShelfLocation, error)) {
a.shelfListFunc = list
}
func (a *Assets) hideAllDialogs() {
for _, dialog := range a.allDialogs {
dialog.Hide()
}
}
func (a *Assets) getSelectedItem() *assetSelectedItem {
selectedItem := assetSelectedItem{}
if a.assetTable.GetRowCount() <= 1 {
return nil
}
row, _ := a.assetTable.GetSelection()
selectedItem.id = a.assetTable.GetCell(row, 0).Text
selectedItem.item = a.assetTable.GetCell(row, 1).Text
selectedItem.quantity = a.assetTable.GetCell(row, 2).Text
selectedItem.shelfLocation = a.assetTable.GetCell(row, 3).Text
selectedItem.manufacturer = a.assetTable.GetCell(row, 4).Text
selectedItem.model = a.assetTable.GetCell(row, 5).Text
selectedItem.category = a.assetTable.GetCell(row, 6).Text
return &selectedItem
}