From 71acd75685665878cb1d6cf4f3f7b4713fa1f419 Mon Sep 17 00:00:00 2001
From: Leon Mika <lmika@lmika.org>
Date: Thu, 31 Mar 2022 22:01:19 +1100
Subject: [PATCH] dynamo-item-edit: started working on a screen to edit items

Didn't get far in it
---
 internal/dynamo-browse/ui/model.go            |  11 +-
 .../ui/teamodels/dynamoitemedit/itemmodel.go  |  31 +++++
 .../ui/teamodels/dynamoitemedit/model.go      | 109 ++++++++++++++++++
 .../ui/teamodels/utils/submodels.go           |  12 ++
 4 files changed, 162 insertions(+), 1 deletion(-)
 create mode 100644 internal/dynamo-browse/ui/teamodels/dynamoitemedit/itemmodel.go
 create mode 100644 internal/dynamo-browse/ui/teamodels/dynamoitemedit/model.go
 create mode 100644 internal/dynamo-browse/ui/teamodels/utils/submodels.go

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
+}