diff --git a/go.mod b/go.mod index da7b341..f77add4 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,8 @@ require ( github.com/aws/aws-sdk-go-v2/service/dynamodb v1.15.0 github.com/aws/aws-sdk-go-v2/service/sqs v1.16.0 github.com/brianvoe/gofakeit/v6 v6.15.0 - github.com/calyptia/go-bubble-table v0.1.0 - github.com/charmbracelet/bubbles v0.10.3 - github.com/charmbracelet/bubbletea v0.20.0 + github.com/charmbracelet/bubbles v0.11.0 + github.com/charmbracelet/bubbletea v0.21.0 github.com/charmbracelet/lipgloss v0.5.0 github.com/google/uuid v1.3.0 github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e @@ -42,18 +41,20 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc // indirect + github.com/lmika/go-bubble-table v0.2.2-0.20220608033210-61eeb29a6239 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect + github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect + github.com/muesli/cancelreader v0.2.0 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect + github.com/muesli/termenv v0.12.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/sahilm/fuzzy v0.1.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index 527818a..c730d98 100644 --- a/go.sum +++ b/go.sum @@ -62,12 +62,19 @@ github.com/brianvoe/gofakeit/v6 v6.15.0 h1:lJPGJZ2/07TRGDazyTzD5b18N3y4tmmJpdhCU github.com/brianvoe/gofakeit/v6 v6.15.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= github.com/calyptia/go-bubble-table v0.1.0 h1:mXpaaBlrHGH4K8v5PvM8YqBFT9jlysS1YOycU2u3gEQ= github.com/calyptia/go-bubble-table v0.1.0/go.mod h1:2nnweuFos+eEIIbgweXvZuX+ROOatsMwB3NHnX/vTC4= +github.com/calyptia/go-bubble-table v0.2.1 h1:NWcVRyGCLuP7QIA29uUFSY+IjmWcmUWHjy5J/CPb0Rk= +github.com/calyptia/go-bubble-table v0.2.1/go.mod h1:gJvzUOUzfQeA9JmgLumyJYWJMtuRQ7WxxTwc9tjEiGw= github.com/charmbracelet/bubbles v0.10.3 h1:fKarbRaObLn/DCsZO4Y3vKCwRUzynQD9L+gGev1E/ho= github.com/charmbracelet/bubbles v0.10.3/go.mod h1:jOA+DUF1rjZm7gZHcNyIVW+YrBPALKfpGVdJu8UiJsA= +github.com/charmbracelet/bubbles v0.11.0 h1:fBLyY0PvJnd56Vlu5L84JJH6f4axhgIJ9P3NET78f0Q= +github.com/charmbracelet/bubbles v0.11.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= github.com/charmbracelet/bubbletea v0.19.3/go.mod h1:VuXF2pToRxDUHcBUcPmCRUHRvFATM4Ckb/ql1rBl3KA= github.com/charmbracelet/bubbletea v0.20.0 h1:/b8LEPgCbNr7WWZ2LuE/BV1/r4t5PyYJtDb+J3vpwxc= github.com/charmbracelet/bubbletea v0.20.0/go.mod h1:zpkze1Rioo4rJELjRyGlm9T2YNou1Fm4LIJQSa5QMEM= +github.com/charmbracelet/bubbletea v0.21.0 h1:f3y+kanzgev5PA916qxmDybSHU3N804uOnKnhRPXTcI= +github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4= github.com/charmbracelet/harmonica v0.1.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= +github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM= github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= @@ -93,6 +100,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e h1:0QkUe2ejnT/i+xbgGylMU1b+XnZponQKiPVNi+C/xgA= github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e/go.mod h1:qtkBmNC9OfD0STtOR9sF55pQchjIfNlC3gzm4n8CrqM= +github.com/lmika/go-bubble-table v0.2.2-0.20220608033210-61eeb29a6239 h1:GGw5pZtEFnHtD7kKdWsiwgcIwZTnok60sShrHVYz4ok= +github.com/lmika/go-bubble-table v0.2.2-0.20220608033210-61eeb29a6239/go.mod h1:0RT1upgKZ6qZ6B1SqseE3wWsPjSQRv/G/HjpYK8jNsg= github.com/lmika/gopkgs v0.0.0-20211210041137-0dc91e939890 h1:mwl/exYV/WkBMeShqK7q+B2w2r+b0vP1TSA7clBn9kI= github.com/lmika/gopkgs v0.0.0-20211210041137-0dc91e939890/go.mod h1:FH6OJSvYcJ9xY8CGs9yGgR89kMCK1UimuUQ6kE5YuJQ= github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe h1:1UXS/6OFkbi6JrihPykmYO1VtsABB02QQ+YmYYzTY18= @@ -112,6 +121,10 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= +github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/cancelreader v0.2.0 h1:SOpr+CfyVNce341kKqvbhhzQhBPyJRXQaCtn03Pae1Q= +github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= @@ -119,6 +132,8 @@ github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtl github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 h1:QANkGiGr39l1EESqrE0gZw0/AJNYzIvoGLhIoVYtluI= github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc= +github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -140,11 +155,18 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/dynamo-browse/controllers/commands.go b/internal/dynamo-browse/controllers/commands.go new file mode 100644 index 0000000..5b7c630 --- /dev/null +++ b/internal/dynamo-browse/controllers/commands.go @@ -0,0 +1,25 @@ +package controllers + +import ( + tea "github.com/charmbracelet/bubbletea" + "github.com/lmika/awstools/internal/common/ui/events" +) + +type promptSequence struct { + prompts []string + receivedValues []string + onAllDone func(values []string) tea.Msg +} + +func (ps *promptSequence) next() tea.Msg { + if len(ps.receivedValues) < len(ps.prompts) { + return events.PromptForInputMsg{ + Prompt: ps.prompts[len(ps.receivedValues)], + OnDone: func(value string) tea.Cmd { + ps.receivedValues = append(ps.receivedValues, value) + return ps.next + }, + } + } + return ps.onAllDone(ps.receivedValues) +} diff --git a/internal/dynamo-browse/controllers/tableread_test.go b/internal/dynamo-browse/controllers/tableread_test.go index d061394..74ad025 100644 --- a/internal/dynamo-browse/controllers/tableread_test.go +++ b/internal/dynamo-browse/controllers/tableread_test.go @@ -114,13 +114,14 @@ func tempFile(t *testing.T) string { return tempFile.Name() } -func invokeCommand(t *testing.T, cmd tea.Cmd) { +func invokeCommand(t *testing.T, cmd tea.Cmd) tea.Msg { msg := cmd() err, isErr := msg.(events.ErrorMsg) if isErr { assert.Fail(t, fmt.Sprintf("expected no error but got one: %v", err)) } + return msg } func invokeCommandWithPrompt(t *testing.T, cmd tea.Cmd, promptValue string) { @@ -134,6 +135,35 @@ func invokeCommandWithPrompt(t *testing.T, cmd tea.Cmd, promptValue string) { invokeCommand(t, pi.OnDone(promptValue)) } +func invokeCommandWithPrompts(t *testing.T, cmd tea.Cmd, promptValues ...string) { + msg := cmd() + + for _, promptValue := range promptValues { + pi, isPi := msg.(events.PromptForInputMsg) + if !isPi { + assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one")) + } + + msg = invokeCommand(t, pi.OnDone(promptValue)) + } +} + +func invokeCommandWithPromptsExpectingError(t *testing.T, cmd tea.Cmd, promptValues ...string) { + msg := cmd() + + for _, promptValue := range promptValues { + pi, isPi := msg.(events.PromptForInputMsg) + if !isPi { + assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one")) + } + + msg = invokeCommand(t, pi.OnDone(promptValue)) + } + + _, isErr := msg.(events.ErrorMsg) + assert.True(t, isErr) +} + func invokeCommandExpectingError(t *testing.T, cmd tea.Cmd) { msg := cmd() diff --git a/internal/dynamo-browse/controllers/tablewrite.go b/internal/dynamo-browse/controllers/tablewrite.go index ca6abd6..7c90d90 100644 --- a/internal/dynamo-browse/controllers/tablewrite.go +++ b/internal/dynamo-browse/controllers/tablewrite.go @@ -37,13 +37,34 @@ func (twc *TableWriteController) ToggleMark(idx int) tea.Cmd { func (twc *TableWriteController) NewItem() tea.Cmd { return func() tea.Msg { - twc.state.withResultSet(func(set *models.ResultSet) { - set.AddNewItem(models.Item{}, models.ItemAttribute{ - New: true, - Dirty: true, + // Work out which keys we need to prompt for + rs := twc.state.ResultSet() + + keyPrompts := &promptSequence{ + prompts: []string{rs.TableInfo.Keys.PartitionKey + ": "}, + } + if rs.TableInfo.Keys.SortKey != "" { + keyPrompts.prompts = append(keyPrompts.prompts, rs.TableInfo.Keys.SortKey+": ") + } + keyPrompts.onAllDone = func(values []string) tea.Msg { + twc.state.withResultSet(func(set *models.ResultSet) { + newItem := models.Item{} + + // TODO: deal with keys of different type + newItem[rs.TableInfo.Keys.PartitionKey] = &types.AttributeValueMemberS{Value: values[0]} + if len(values) == 2 { + newItem[rs.TableInfo.Keys.SortKey] = &types.AttributeValueMemberS{Value: values[1]} + } + + set.AddNewItem(newItem, models.ItemAttribute{ + New: true, + Dirty: true, + }) }) - }) - return NewResultSet{twc.state.ResultSet()} + return NewResultSet{twc.state.ResultSet()} + } + + return keyPrompts.next() } } diff --git a/internal/dynamo-browse/controllers/tablewrite_test.go b/internal/dynamo-browse/controllers/tablewrite_test.go index 3eea9a5..de08093 100644 --- a/internal/dynamo-browse/controllers/tablewrite_test.go +++ b/internal/dynamo-browse/controllers/tablewrite_test.go @@ -181,13 +181,13 @@ func setupController(t *testing.T) (*controllers.TableWriteController, controlle */ func TestTableWriteController_NewItem(t *testing.T) { - client, cleanupFn := testdynamo.SetupTestTable(t, testData) - defer cleanupFn() + t.Run("should add an item with pk and sk set at the end of the result set", func(t *testing.T) { + client, cleanupFn := testdynamo.SetupTestTable(t, testData) + defer cleanupFn() - provider := dynamo.NewProvider(client) - service := tables.NewService(provider) + provider := dynamo.NewProvider(client) + service := tables.NewService(provider) - t.Run("should add a new empty item at the end of the result set", func(t *testing.T) { state := controllers.NewState() readController := controllers.NewTableReadController(state, service, "alpha-table") writeController := controllers.NewTableWriteController(state, service, readController) @@ -195,10 +195,17 @@ func TestTableWriteController_NewItem(t *testing.T) { invokeCommand(t, readController.Init()) assert.Len(t, state.ResultSet().Items(), 3) - invokeCommand(t, writeController.NewItem()) + // Prompt for keys + invokeCommandWithPrompts(t, writeController.NewItem(), "pk-value", "sk-value") + newResultSet := state.ResultSet() assert.Len(t, newResultSet.Items(), 4) - assert.Len(t, newResultSet.Items()[3], 0) + assert.Len(t, newResultSet.Items()[3], 2) + + pk, _ := newResultSet.Items()[3].AttributeValueAsString("pk") + sk, _ := newResultSet.Items()[3].AttributeValueAsString("sk") + assert.Equal(t, "pk-value", pk) + assert.Equal(t, "sk-value", sk) assert.True(t, newResultSet.IsNew(3)) assert.True(t, newResultSet.IsDirty(3)) }) diff --git a/internal/dynamo-browse/providers/dynamo/provider.go b/internal/dynamo-browse/providers/dynamo/provider.go index 4c74d74..1e46e72 100644 --- a/internal/dynamo-browse/providers/dynamo/provider.go +++ b/internal/dynamo-browse/providers/dynamo/provider.go @@ -64,17 +64,27 @@ func NewProvider(client *dynamodb.Client) *Provider { return &Provider{client: client} } -func (p *Provider) ScanItems(ctx context.Context, tableName string) ([]models.Item, error) { - res, err := p.client.Scan(ctx, &dynamodb.ScanInput{ +func (p *Provider) ScanItems(ctx context.Context, tableName string, maxItems int) ([]models.Item, error) { + paginator := dynamodb.NewScanPaginator(p.client, &dynamodb.ScanInput{ TableName: aws.String(tableName), + Limit: aws.Int32(int32(maxItems)), }) - if err != nil { - return nil, errors.Wrapf(err, "cannot execute scan on table %v", tableName) - } - items := make([]models.Item, len(res.Items)) - for i, itm := range res.Items { - items[i] = itm + items := make([]models.Item, 0) + +outer: + for paginator.HasMorePages() { + res, err := paginator.NextPage(ctx) + if err != nil { + return nil, errors.Wrapf(err, "cannot execute scan on table %v", tableName) + } + + for _, itm := range res.Items { + items = append(items, itm) + if len(items) >= maxItems { + break outer + } + } } return items, nil diff --git a/internal/dynamo-browse/services/tables/iface.go b/internal/dynamo-browse/services/tables/iface.go index 2dddc6c..8548115 100644 --- a/internal/dynamo-browse/services/tables/iface.go +++ b/internal/dynamo-browse/services/tables/iface.go @@ -10,7 +10,7 @@ import ( type TableProvider interface { ListTables(ctx context.Context) ([]string, error) DescribeTable(ctx context.Context, tableName string) (*models.TableInfo, error) - ScanItems(ctx context.Context, tableName string) ([]models.Item, error) + ScanItems(ctx context.Context, tableName string, maxItems int) ([]models.Item, error) DeleteItem(ctx context.Context, tableName string, key map[string]types.AttributeValue) error PutItem(ctx context.Context, name string, item models.Item) error } diff --git a/internal/dynamo-browse/services/tables/service.go b/internal/dynamo-browse/services/tables/service.go index 8e3a54d..f6b56e5 100644 --- a/internal/dynamo-browse/services/tables/service.go +++ b/internal/dynamo-browse/services/tables/service.go @@ -28,7 +28,7 @@ func (s *Service) Describe(ctx context.Context, table string) (*models.TableInfo } func (s *Service) Scan(ctx context.Context, tableInfo *models.TableInfo) (*models.ResultSet, error) { - results, err := s.provider.ScanItems(ctx, tableInfo.Name) + results, err := s.provider.ScanItems(ctx, tableInfo.Name, 1000) if err != nil { return nil, errors.Wrapf(err, "unable to scan table %v", tableInfo.Name) } diff --git a/internal/dynamo-browse/ui/model.go b/internal/dynamo-browse/ui/model.go index 7d4081b..2e9d9ba 100644 --- a/internal/dynamo-browse/ui/model.go +++ b/internal/dynamo-browse/ui/model.go @@ -51,6 +51,12 @@ func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteCon // TEMP "new-item": commandctrl.NoArgCommand(wc.NewItem()), + "set-s": func(args []string) tea.Cmd { + if len(args) == 0 { + return events.SetError(errors.New("expected field")) + } + return wc.SetStringValue(dtv.SelectedItemIndex(), args[0]) + }, "put": func(args []string) tea.Cmd { return wc.PutItem(dtv.SelectedItemIndex()) diff --git a/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go b/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go index c3b3777..971e99d 100644 --- a/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go +++ b/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go @@ -1,7 +1,6 @@ package dynamotableview import ( - table "github.com/calyptia/go-bubble-table" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" @@ -10,6 +9,7 @@ import ( "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamoitemview" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout" + table "github.com/lmika/go-bubble-table" ) var ( @@ -42,8 +42,20 @@ type Model struct { resultSet *models.ResultSet } +type columnModel struct { + m *Model +} + +func (cm columnModel) Len() int { + return len(cm.m.resultSet.Columns[cm.m.colOffset:]) +} + +func (cm columnModel) Header(index int) string { + return cm.m.resultSet.Columns[cm.m.colOffset+index] +} + func New() *Model { - tbl := table.New([]string{"pk", "sk"}, 100, 100) + tbl := table.New(table.SimpleColumns([]string{"pk", "sk"}), 100, 100) rows := make([]table.Row, 0) tbl.SetRows(rows) @@ -116,7 +128,9 @@ func (m *Model) setLeftmostDisplayedColumn(newCol int) { } else { m.colOffset = newCol } - m.rebuildTable() + // TEMP + m.table.GoDown() + m.table.GoUp() } func (m *Model) View() string { @@ -141,7 +155,7 @@ func (m *Model) updateTable() { func (m *Model) rebuildTable() { resultSet := m.resultSet - newTbl := table.New(resultSet.Columns[m.colOffset:], m.w, m.h-m.frameTitle.HeaderHeight()) + newTbl := table.New(columnModel{m}, m.w, m.h-m.frameTitle.HeaderHeight()) newRows := make([]table.Row, 0) for i, r := range resultSet.Items() { if resultSet.Hidden(i) { @@ -149,22 +163,24 @@ func (m *Model) rebuildTable() { } newRows = append(newRows, itemTableRow{ + model: m, resultSet: resultSet, itemIndex: i, - colOffset: m.colOffset, item: r, }) } m.rows = newRows newTbl.SetRows(newRows) - for newTbl.Cursor() != m.table.Cursor() { - if newTbl.Cursor() < m.table.Cursor() { - newTbl.GoDown() - } else if newTbl.Cursor() > m.table.Cursor() { - newTbl.GoUp() + /* + for newTbl.Cursor() != m.table.Cursor() { + if newTbl.Cursor() < m.table.Cursor() { + newTbl.GoDown() + } else if newTbl.Cursor() > m.table.Cursor() { + newTbl.GoUp() + } } - } + */ m.table = newTbl } diff --git a/internal/dynamo-browse/ui/teamodels/dynamotableview/tblmodel.go b/internal/dynamo-browse/ui/teamodels/dynamotableview/tblmodel.go index 4ef82f4..69d599f 100644 --- a/internal/dynamo-browse/ui/teamodels/dynamotableview/tblmodel.go +++ b/internal/dynamo-browse/ui/teamodels/dynamotableview/tblmodel.go @@ -6,13 +6,13 @@ import ( "io" "strings" - table "github.com/calyptia/go-bubble-table" "github.com/lmika/awstools/internal/dynamo-browse/models" + table "github.com/lmika/go-bubble-table" ) var ( markedRowStyle = lipgloss.NewStyle(). - Background(lipgloss.Color("#e1e1e1")) + Background(lipgloss.AdaptiveColor{Dark: "#e1e1e1", Light: "#414141"}) dirtyRowStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#e13131")) newRowStyle = lipgloss.NewStyle(). @@ -23,9 +23,9 @@ var ( ) type itemTableRow struct { + model *Model resultSet *models.ResultSet itemIndex int - colOffset int item models.Item } @@ -50,7 +50,7 @@ func (mtr itemTableRow) Render(w io.Writer, model table.Model, index int) { metaInfoStyle := style.Copy().Inherit(metaInfoStyle) sb := strings.Builder{} - for i, colName := range mtr.resultSet.Columns[mtr.colOffset:] { + for i, colName := range mtr.resultSet.Columns[mtr.model.colOffset:] { if i > 0 { sb.WriteString(style.Render("\t")) } diff --git a/internal/slog-view/ui/loglines/model.go b/internal/slog-view/ui/loglines/model.go index dd878aa..10fc6c1 100644 --- a/internal/slog-view/ui/loglines/model.go +++ b/internal/slog-view/ui/loglines/model.go @@ -1,7 +1,7 @@ package loglines import ( - table "github.com/calyptia/go-bubble-table" + table "github.com/lmika/go-bubble-table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame" diff --git a/internal/slog-view/ui/loglines/tblmodel.go b/internal/slog-view/ui/loglines/tblmodel.go index 6adc5d8..2cd53ee 100644 --- a/internal/slog-view/ui/loglines/tblmodel.go +++ b/internal/slog-view/ui/loglines/tblmodel.go @@ -2,7 +2,7 @@ package loglines import ( "fmt" - table "github.com/calyptia/go-bubble-table" + table "github.com/lmika/go-bubble-table" "github.com/lmika/awstools/internal/slog-view/models" "io" "strings" diff --git a/internal/sqs-browse/ui/model.go b/internal/sqs-browse/ui/model.go index 3063cab..f60c69b 100644 --- a/internal/sqs-browse/ui/model.go +++ b/internal/sqs-browse/ui/model.go @@ -7,7 +7,7 @@ import ( "log" "strings" - table "github.com/calyptia/go-bubble-table" + table "github.com/lmika/go-bubble-table" "github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" diff --git a/internal/sqs-browse/ui/tblmodel.go b/internal/sqs-browse/ui/tblmodel.go index b4fc15c..0eff075 100644 --- a/internal/sqs-browse/ui/tblmodel.go +++ b/internal/sqs-browse/ui/tblmodel.go @@ -5,7 +5,7 @@ import ( "io" "strings" - table "github.com/calyptia/go-bubble-table" + table "github.com/lmika/go-bubble-table" "github.com/lmika/awstools/internal/sqs-browse/models" ) diff --git a/internal/ssm-browse/ui/ssmlist/ssmlist.go b/internal/ssm-browse/ui/ssmlist/ssmlist.go index e304e66..b481148 100644 --- a/internal/ssm-browse/ui/ssmlist/ssmlist.go +++ b/internal/ssm-browse/ui/ssmlist/ssmlist.go @@ -1,7 +1,7 @@ package ssmlist import ( - table "github.com/calyptia/go-bubble-table" + table "github.com/lmika/go-bubble-table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame" diff --git a/internal/ssm-browse/ui/ssmlist/tblmodel.go b/internal/ssm-browse/ui/ssmlist/tblmodel.go index 6a28598..df35ccc 100644 --- a/internal/ssm-browse/ui/ssmlist/tblmodel.go +++ b/internal/ssm-browse/ui/ssmlist/tblmodel.go @@ -2,7 +2,7 @@ package ssmlist import ( "fmt" - table "github.com/calyptia/go-bubble-table" + table "github.com/lmika/go-bubble-table" "github.com/lmika/awstools/internal/ssm-browse/models" "io" "strings" diff --git a/test/cmd/load-test-table/main.go b/test/cmd/load-test-table/main.go index dba36e8..a09d047 100644 --- a/test/cmd/load-test-table/main.go +++ b/test/cmd/load-test-table/main.go @@ -20,7 +20,7 @@ import ( func main() { ctx := context.Background() tableName := "awstools-test" - totalItems := 10 + totalItems := 5000 cfg, err := config.LoadDefaultConfig(ctx) if err != nil {