diff --git a/internal/dynamo-browse/ui/model.go b/internal/dynamo-browse/ui/model.go index e28b8f7..8d63862 100644 --- a/internal/dynamo-browse/ui/model.go +++ b/internal/dynamo-browse/ui/model.go @@ -4,6 +4,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/lmika/awstools/internal/common/ui/commandctrl" "github.com/lmika/awstools/internal/dynamo-browse/controllers" + "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamoitemedit" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamoitemview" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamotableview" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout" @@ -15,6 +16,7 @@ type Model struct { tableReadController *controllers.TableReadController tableWriteController *controllers.TableWriteController commandController *commandctrl.CommandController + itemEdit *dynamoitemedit.Model statusAndPrompt *statusandprompt.StatusAndPrompt tableSelect *tableselect.Model @@ -25,7 +27,10 @@ type Model struct { func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteController, cc *commandctrl.CommandController) Model { dtv := dynamotableview.New() div := dynamoitemview.New() - statusAndPrompt := statusandprompt.New(layout.NewVBox(layout.LastChildFixedAt(17), dtv, div), "") + mainView := layout.NewVBox(layout.LastChildFixedAt(17), dtv, div) + + itemEdit := dynamoitemedit.NewModel(mainView) + statusAndPrompt := statusandprompt.New(itemEdit, "") tableSelect := tableselect.New(statusAndPrompt) cc.AddCommands(&commandctrl.CommandContext{ @@ -49,6 +54,7 @@ func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteCon tableReadController: rc, tableWriteController: wc, commandController: cc, + itemEdit: itemEdit, statusAndPrompt: statusAndPrompt, tableSelect: tableSelect, root: root, @@ -75,6 +81,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, m.tableReadController.Rescan() case "/": return m, m.tableReadController.Filter() + case "e": + m.itemEdit.Visible() + return m, nil case ":": return m, m.commandController.Prompt() case "ctrl+c", "esc": diff --git a/internal/dynamo-browse/ui/teamodels/dynamoitemedit/itemmodel.go b/internal/dynamo-browse/ui/teamodels/dynamoitemedit/itemmodel.go new file mode 100644 index 0000000..9fd25b8 --- /dev/null +++ b/internal/dynamo-browse/ui/teamodels/dynamoitemedit/itemmodel.go @@ -0,0 +1,31 @@ +package dynamoitemedit + +import ( + "fmt" + table "github.com/calyptia/go-bubble-table" + "io" +) + +type itemModel struct { + model *Model + name string + attrType string + attrValue string +} + +func (i itemModel) Render(w io.Writer, model table.Model, index int) { + var line string + if i.model.editMode != nil { + fmt.Fprint(w, i.model.editMode.textInput.View()) + return + //line = fmt.Sprintf("%s\t%s\t%s", i.name, i.attrType, i.model.editMode.textInput.View()) + } else { + line = fmt.Sprintf("%s\t%s\t%s", i.name, i.attrType, i.attrValue) + } + + if index == model.Cursor() { + fmt.Fprintln(w, model.Styles.SelectedRow.Render(line)) + } else { + fmt.Fprintln(w, line) + } +} diff --git a/internal/dynamo-browse/ui/teamodels/dynamoitemedit/model.go b/internal/dynamo-browse/ui/teamodels/dynamoitemedit/model.go new file mode 100644 index 0000000..42fda50 --- /dev/null +++ b/internal/dynamo-browse/ui/teamodels/dynamoitemedit/model.go @@ -0,0 +1,109 @@ +package dynamoitemedit + +import ( + table "github.com/calyptia/go-bubble-table" + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" + "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout" + "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/utils" +) + +type Model struct { + submodel tea.Model + table table.Model + textInput textinput.Model + + visible bool + editMode *editMode + w, h int +} + +type editMode struct { + index int + textInput textinput.Model +} + +func NewModel(submodel tea.Model) *Model { + tbl := table.New([]string{"name", "type", "value"}, 0, 0) + //rows := make([]table.Row, 0) + + model := &Model{ + submodel: submodel, + } + + rows := []table.Row{ + itemModel{model: model, name: "pk", attrType: "S", attrValue: "3baa4a4b-f977-4966-bed4-ba9243dbc942"}, + itemModel{model: model, name: "sk", attrType: "S", attrValue: "3baa4a4b-f977-4966-bed4-ba9243dbc942"}, + itemModel{model: model, name: "name", attrType: "S", attrValue: "My name"}, + } + tbl.SetRows(rows) + + model.table = tbl + + return model +} + +func (m *Model) Init() tea.Cmd { + return nil +} + +func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var cmd tea.Cmd + + switch msg := msg.(type) { + case tea.KeyMsg: + if m.editMode != nil { + switch msg.String() { + case "enter": + m.editMode = nil + case "ctrl+c", "esc": + m.editMode = nil + default: + m.editMode.textInput, cmd = utils.Update(m.editMode.textInput, msg) + } + return m, nil + } else if m.visible { + switch msg.String() { + case "i", "up": + m.table.GoUp() + case "k", "down": + m.table.GoDown() + case "enter": + m.enterEditMode() + case "ctrl+c", "esc": + m.visible = false + } + return m, nil + } + } + + m.submodel, cmd = utils.Update(m.submodel, msg) + return m, cmd +} + +func (m *Model) enterEditMode() { + m.editMode = &editMode{ + textInput: textinput.New(), + index: m.table.Cursor(), + } + m.editMode.textInput.Focus() +} + +func (m *Model) View() string { + if !m.visible { + return m.submodel.View() + } + + return m.table.View() +} + +func (m *Model) Resize(w, h int) layout.ResizingModel { + m.w, m.h = w, h + m.table.SetSize(w, h) + m.submodel = layout.Resize(m.submodel, w, h) + return m +} + +func (m *Model) Visible() { + m.visible = true +} diff --git a/internal/dynamo-browse/ui/teamodels/utils/submodels.go b/internal/dynamo-browse/ui/teamodels/utils/submodels.go new file mode 100644 index 0000000..c061e07 --- /dev/null +++ b/internal/dynamo-browse/ui/teamodels/utils/submodels.go @@ -0,0 +1,12 @@ +package utils + +import tea "github.com/charmbracelet/bubbletea" + +type Updatable[T any] interface { + Update(msg tea.Msg) (T, tea.Cmd) +} + +func Update[T Updatable[T]](model T, msg tea.Msg) (T, tea.Cmd) { + newModel, cmd := model.Update(msg) + return newModel, cmd +}