package assets import ( "sync" "git.brettb.xyz/goinv/client/internal/ui/assets/astdialogs" "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 createDialog *astdialogs.AssetCreateDialog editDialog *astdialogs.AssetEditDialog 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, ""), createDialog: astdialogs.NewAssetCreateDialog(logger, client), editDialog: astdialogs.NewAssetEditDialog(logger, client), } 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"}, {"edit asset", "edit 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.createDialog.SetCancelFunc(func() { assets.createDialog.Hide() }).SetCreateFunc(func() { assets.createDialog.Hide() assets.create() }) assets.editDialog.SetCancelFunc(func() { assets.editDialog.Hide() }).SetEditFunc(func() { assets.editDialog.Hide() assets.edit() }) 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.createDialog, assets.editDialog, 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 }