Merge pull request #12 from lmika/chore/ctrlret
ctrlret: replaced return types of controllers from tea.Cmd to tea.Msg
This commit is contained in:
commit
f0bd3022cc
|
@ -50,7 +50,7 @@ func main() {
|
||||||
cmdController := commandctrl.NewCommandController()
|
cmdController := commandctrl.NewCommandController()
|
||||||
cmdController.AddCommands(&commandctrl.CommandContext{
|
cmdController.AddCommands(&commandctrl.CommandContext{
|
||||||
Commands: map[string]commandctrl.Command{
|
Commands: map[string]commandctrl.Command{
|
||||||
"cd": func(args []string) tea.Cmd {
|
"cd": func(args []string) tea.Msg {
|
||||||
return ctrl.ChangePrefix(args[0])
|
return ctrl.ChangePrefix(args[0])
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,18 +25,16 @@ func (c *CommandController) AddCommands(ctx *CommandContext) {
|
||||||
c.commandList = ctx
|
c.commandList = ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandController) Prompt() tea.Cmd {
|
func (c *CommandController) Prompt() tea.Msg {
|
||||||
return func() tea.Msg {
|
return events.PromptForInputMsg{
|
||||||
return events.PromptForInputMsg{
|
Prompt: ":",
|
||||||
Prompt: ":",
|
OnDone: func(value string) tea.Msg {
|
||||||
OnDone: func(value string) tea.Cmd {
|
return c.Execute(value)
|
||||||
return c.Execute(value)
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandController) Execute(commandInput string) tea.Cmd {
|
func (c *CommandController) Execute(commandInput string) tea.Msg {
|
||||||
input := strings.TrimSpace(commandInput)
|
input := strings.TrimSpace(commandInput)
|
||||||
if input == "" {
|
if input == "" {
|
||||||
return nil
|
return nil
|
||||||
|
@ -46,18 +44,18 @@ func (c *CommandController) Execute(commandInput string) tea.Cmd {
|
||||||
command := c.lookupCommand(tokens[0])
|
command := c.lookupCommand(tokens[0])
|
||||||
if command == nil {
|
if command == nil {
|
||||||
log.Println("No such command: ", tokens)
|
log.Println("No such command: ", tokens)
|
||||||
return events.SetError(errors.New("no such command: " + tokens[0]))
|
return events.Error(errors.New("no such command: " + tokens[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return command(tokens[1:])
|
return command(tokens[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandController) Alias(commandName string) Command {
|
func (c *CommandController) Alias(commandName string) Command {
|
||||||
return func(args []string) tea.Cmd {
|
return func(args []string) tea.Msg {
|
||||||
command := c.lookupCommand(commandName)
|
command := c.lookupCommand(commandName)
|
||||||
if command == nil {
|
if command == nil {
|
||||||
log.Println("No such command: ", commandName)
|
log.Println("No such command: ", commandName)
|
||||||
return events.SetError(errors.New("no such command: " + commandName))
|
return events.Error(errors.New("no such command: " + commandName))
|
||||||
}
|
}
|
||||||
|
|
||||||
return command(args)
|
return command(args)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package commandctrl_test
|
package commandctrl_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/lmika/audax/internal/common/ui/events"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lmika/audax/internal/common/ui/commandctrl"
|
"github.com/lmika/audax/internal/common/ui/commandctrl"
|
||||||
"github.com/lmika/audax/internal/common/ui/events"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ func TestCommandController_Prompt(t *testing.T) {
|
||||||
t.Run("prompt user for a command", func(t *testing.T) {
|
t.Run("prompt user for a command", func(t *testing.T) {
|
||||||
cmd := commandctrl.NewCommandController()
|
cmd := commandctrl.NewCommandController()
|
||||||
|
|
||||||
res := cmd.Prompt()()
|
res := cmd.Prompt()
|
||||||
|
|
||||||
promptForInputMsg, ok := res.(events.PromptForInputMsg)
|
promptForInputMsg, ok := res.(events.PromptForInputMsg)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
|
@ -2,16 +2,16 @@ package commandctrl
|
||||||
|
|
||||||
import tea "github.com/charmbracelet/bubbletea"
|
import tea "github.com/charmbracelet/bubbletea"
|
||||||
|
|
||||||
type Command func(args []string) tea.Cmd
|
type Command func(args []string) tea.Msg
|
||||||
|
|
||||||
func NoArgCommand(cmd tea.Cmd) Command {
|
func NoArgCommand(cmd tea.Cmd) Command {
|
||||||
return func(args []string) tea.Cmd {
|
return func(args []string) tea.Msg {
|
||||||
return cmd
|
return cmd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandContext struct {
|
type CommandContext struct {
|
||||||
Commands map[string]Command
|
Commands map[string]Command
|
||||||
|
|
||||||
parent *CommandContext
|
parent *CommandContext
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,29 +10,19 @@ func Error(err error) tea.Msg {
|
||||||
return ErrorMsg(err)
|
return ErrorMsg(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetError(err error) tea.Cmd {
|
func SetStatus(msg string) tea.Msg {
|
||||||
return func() tea.Msg {
|
return StatusMsg(msg)
|
||||||
return Error(err)
|
}
|
||||||
|
|
||||||
|
func PromptForInput(prompt string, onDone func(value string) tea.Msg) tea.Msg {
|
||||||
|
return PromptForInputMsg{
|
||||||
|
Prompt: prompt,
|
||||||
|
OnDone: onDone,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetStatus(msg string) tea.Cmd {
|
func Confirm(prompt string, onYes func() tea.Msg) tea.Msg {
|
||||||
return func() tea.Msg {
|
return PromptForInput(prompt, func(value string) tea.Msg {
|
||||||
return StatusMsg(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func PromptForInput(prompt string, onDone func(value string) tea.Cmd) tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
return PromptForInputMsg{
|
|
||||||
Prompt: prompt,
|
|
||||||
OnDone: onDone,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Confirm(prompt string, onYes func() tea.Cmd) tea.Cmd {
|
|
||||||
return PromptForInput(prompt, func(value string) tea.Cmd {
|
|
||||||
if value == "y" {
|
if value == "y" {
|
||||||
return onYes()
|
return onYes()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,5 @@ type ModeMessage string
|
||||||
// PromptForInput indicates that the context is requesting a line of input
|
// PromptForInput indicates that the context is requesting a line of input
|
||||||
type PromptForInputMsg struct {
|
type PromptForInputMsg struct {
|
||||||
Prompt string
|
Prompt string
|
||||||
OnDone func(value string) tea.Cmd
|
OnDone func(value string) tea.Msg
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ func (ps *promptSequence) next() tea.Msg {
|
||||||
if len(ps.receivedValues) < len(ps.prompts) {
|
if len(ps.receivedValues) < len(ps.prompts) {
|
||||||
return events.PromptForInputMsg{
|
return events.PromptForInputMsg{
|
||||||
Prompt: ps.prompts[len(ps.receivedValues)],
|
Prompt: ps.prompts[len(ps.receivedValues)],
|
||||||
OnDone: func(value string) tea.Cmd {
|
OnDone: func(value string) tea.Msg {
|
||||||
ps.receivedValues = append(ps.receivedValues, value)
|
ps.receivedValues = append(ps.receivedValues, value)
|
||||||
return ps.next
|
return ps.next()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ type SetReadWrite struct {
|
||||||
|
|
||||||
type PromptForTableMsg struct {
|
type PromptForTableMsg struct {
|
||||||
Tables []string
|
Tables []string
|
||||||
OnSelected func(tableName string) tea.Cmd
|
OnSelected func(tableName string) tea.Msg
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResultSetUpdated struct {
|
type ResultSetUpdated struct {
|
||||||
|
|
|
@ -35,7 +35,7 @@ func NewTableReadController(state *State, tableService TableReadService, workspa
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init does an initial scan of the table. If no table is specified, it prompts for a table, then does a scan.
|
// Init does an initial scan of the table. If no table is specified, it prompts for a table, then does a scan.
|
||||||
func (c *TableReadController) Init() tea.Cmd {
|
func (c *TableReadController) Init() tea.Msg {
|
||||||
if c.tableName == "" {
|
if c.tableName == "" {
|
||||||
return c.ListTables()
|
return c.ListTables()
|
||||||
} else {
|
} else {
|
||||||
|
@ -43,51 +43,43 @@ func (c *TableReadController) Init() tea.Cmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) ListTables() tea.Cmd {
|
func (c *TableReadController) ListTables() tea.Msg {
|
||||||
return func() tea.Msg {
|
tables, err := c.tableService.ListTables(context.Background())
|
||||||
tables, err := c.tableService.ListTables(context.Background())
|
if err != nil {
|
||||||
if err != nil {
|
return events.Error(err)
|
||||||
return events.Error(err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return PromptForTableMsg{
|
return PromptForTableMsg{
|
||||||
Tables: tables,
|
Tables: tables,
|
||||||
OnSelected: func(tableName string) tea.Cmd {
|
OnSelected: func(tableName string) tea.Msg {
|
||||||
return c.ScanTable(tableName)
|
return c.ScanTable(tableName)
|
||||||
},
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) ScanTable(name string) tea.Cmd {
|
func (c *TableReadController) ScanTable(name string) tea.Msg {
|
||||||
return func() tea.Msg {
|
ctx := context.Background()
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
tableInfo, err := c.tableService.Describe(ctx, name)
|
tableInfo, err := c.tableService.Describe(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return events.Error(errors.Wrapf(err, "cannot describe %v", c.tableName))
|
return events.Error(errors.Wrapf(err, "cannot describe %v", c.tableName))
|
||||||
}
|
|
||||||
|
|
||||||
resultSet, err := c.tableService.Scan(ctx, tableInfo)
|
|
||||||
if err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
resultSet = c.tableService.Filter(resultSet, c.state.Filter())
|
|
||||||
|
|
||||||
return c.setResultSetAndFilter(resultSet, c.state.Filter(), true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resultSet, err := c.tableService.Scan(ctx, tableInfo)
|
||||||
|
if err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
resultSet = c.tableService.Filter(resultSet, c.state.Filter())
|
||||||
|
|
||||||
|
return c.setResultSetAndFilter(resultSet, c.state.Filter(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) PromptForQuery() tea.Cmd {
|
func (c *TableReadController) PromptForQuery() tea.Msg {
|
||||||
return func() tea.Msg {
|
return events.PromptForInputMsg{
|
||||||
return events.PromptForInputMsg{
|
Prompt: "query: ",
|
||||||
Prompt: "query: ",
|
OnDone: func(value string) tea.Msg {
|
||||||
OnDone: func(value string) tea.Cmd {
|
return c.runQuery(c.state.ResultSet().TableInfo, value, "", true)
|
||||||
return func() tea.Msg {
|
},
|
||||||
return c.runQuery(c.state.ResultSet().TableInfo, value, "", true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +99,7 @@ func (c *TableReadController) runQuery(tableInfo *models.TableInfo, query, newFi
|
||||||
|
|
||||||
expr, err := queryexpr.Parse(query)
|
expr, err := queryexpr.Parse(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return events.SetError(err)
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.doIfNoneDirty(func() tea.Msg {
|
return c.doIfNoneDirty(func() tea.Msg {
|
||||||
|
@ -135,58 +127,54 @@ func (c *TableReadController) doIfNoneDirty(cmd tea.Cmd) tea.Msg {
|
||||||
|
|
||||||
return events.PromptForInputMsg{
|
return events.PromptForInputMsg{
|
||||||
Prompt: "reset modified items? ",
|
Prompt: "reset modified items? ",
|
||||||
OnDone: func(value string) tea.Cmd {
|
OnDone: func(value string) tea.Msg {
|
||||||
if value != "y" {
|
if value != "y" {
|
||||||
return events.SetStatus("operation aborted")
|
return events.SetStatus("operation aborted")
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) Rescan() tea.Cmd {
|
func (c *TableReadController) Rescan() tea.Msg {
|
||||||
return func() tea.Msg {
|
return c.doIfNoneDirty(func() tea.Msg {
|
||||||
return c.doIfNoneDirty(func() tea.Msg {
|
resultSet := c.state.ResultSet()
|
||||||
resultSet := c.state.ResultSet()
|
return c.doScan(context.Background(), resultSet, resultSet.Query, true)
|
||||||
return c.doScan(context.Background(), resultSet, resultSet.Query, true)
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) ExportCSV(filename string) tea.Cmd {
|
func (c *TableReadController) ExportCSV(filename string) tea.Msg {
|
||||||
return func() tea.Msg {
|
resultSet := c.state.ResultSet()
|
||||||
resultSet := c.state.ResultSet()
|
if resultSet == nil {
|
||||||
if resultSet == nil {
|
return events.Error(errors.New("no result set"))
|
||||||
return events.Error(errors.New("no result set"))
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return events.Error(errors.Wrapf(err, "cannot export to '%v'", filename))
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
cw := csv.NewWriter(f)
|
|
||||||
defer cw.Flush()
|
|
||||||
|
|
||||||
columns := resultSet.Columns()
|
|
||||||
if err := cw.Write(columns); err != nil {
|
|
||||||
return events.Error(errors.Wrapf(err, "cannot export to '%v'", filename))
|
|
||||||
}
|
|
||||||
|
|
||||||
row := make([]string, len(columns))
|
|
||||||
for _, item := range resultSet.Items() {
|
|
||||||
for i, col := range columns {
|
|
||||||
row[i], _ = item.AttributeValueAsString(col)
|
|
||||||
}
|
|
||||||
if err := cw.Write(row); err != nil {
|
|
||||||
return events.Error(errors.Wrapf(err, "cannot export to '%v'", filename))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return events.Error(errors.Wrapf(err, "cannot export to '%v'", filename))
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
cw := csv.NewWriter(f)
|
||||||
|
defer cw.Flush()
|
||||||
|
|
||||||
|
columns := resultSet.Columns()
|
||||||
|
if err := cw.Write(columns); err != nil {
|
||||||
|
return events.Error(errors.Wrapf(err, "cannot export to '%v'", filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
row := make([]string, len(columns))
|
||||||
|
for _, item := range resultSet.Items() {
|
||||||
|
for i, col := range columns {
|
||||||
|
row[i], _ = item.AttributeValueAsString(col)
|
||||||
|
}
|
||||||
|
if err := cw.Write(row); err != nil {
|
||||||
|
return events.Error(errors.Wrapf(err, "cannot export to '%v'", filename))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) doScan(ctx context.Context, resultSet *models.ResultSet, query models.Queryable, pushBackstack bool) tea.Msg {
|
func (c *TableReadController) doScan(ctx context.Context, resultSet *models.ResultSet, query models.Queryable, pushBackstack bool) tea.Msg {
|
||||||
|
@ -211,66 +199,58 @@ func (c *TableReadController) setResultSetAndFilter(resultSet *models.ResultSet,
|
||||||
return c.state.buildNewResultSetMessage("")
|
return c.state.buildNewResultSetMessage("")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) Unmark() tea.Cmd {
|
func (c *TableReadController) Unmark() tea.Msg {
|
||||||
return func() tea.Msg {
|
c.state.withResultSet(func(resultSet *models.ResultSet) {
|
||||||
c.state.withResultSet(func(resultSet *models.ResultSet) {
|
for i := range resultSet.Items() {
|
||||||
for i := range resultSet.Items() {
|
resultSet.SetMark(i, false)
|
||||||
resultSet.SetMark(i, false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return ResultSetUpdated{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TableReadController) Filter() tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
return events.PromptForInputMsg{
|
|
||||||
Prompt: "filter: ",
|
|
||||||
OnDone: func(value string) tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
resultSet := c.state.ResultSet()
|
|
||||||
newResultSet := c.tableService.Filter(resultSet, value)
|
|
||||||
|
|
||||||
return c.setResultSetAndFilter(newResultSet, value, true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
return ResultSetUpdated{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TableReadController) Filter() tea.Msg {
|
||||||
|
return events.PromptForInputMsg{
|
||||||
|
Prompt: "filter: ",
|
||||||
|
OnDone: func(value string) tea.Msg {
|
||||||
|
resultSet := c.state.ResultSet()
|
||||||
|
newResultSet := c.tableService.Filter(resultSet, value)
|
||||||
|
|
||||||
|
return c.setResultSetAndFilter(newResultSet, value, true)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) ViewBack() tea.Cmd {
|
func (c *TableReadController) ViewBack() tea.Msg {
|
||||||
return func() tea.Msg {
|
viewSnapshot, err := c.workspaceService.PopSnapshot()
|
||||||
viewSnapshot, err := c.workspaceService.PopSnapshot()
|
if err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
} else if viewSnapshot == nil {
|
||||||
|
return events.StatusMsg("Backstack is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
currentResultSet := c.state.ResultSet()
|
||||||
|
|
||||||
|
var currentQueryExpr string
|
||||||
|
if currentResultSet.Query != nil {
|
||||||
|
currentQueryExpr = currentResultSet.Query.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if viewSnapshot.TableName == currentResultSet.TableInfo.Name && viewSnapshot.Query == currentQueryExpr {
|
||||||
|
log.Printf("backstack: setting filter to '%v'", viewSnapshot.Filter)
|
||||||
|
|
||||||
|
newResultSet := c.tableService.Filter(currentResultSet, viewSnapshot.Filter)
|
||||||
|
return c.setResultSetAndFilter(newResultSet, viewSnapshot.Filter, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
tableInfo := currentResultSet.TableInfo
|
||||||
|
if viewSnapshot.TableName != currentResultSet.TableInfo.Name {
|
||||||
|
tableInfo, err = c.tableService.Describe(context.Background(), viewSnapshot.TableName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return events.Error(err)
|
return events.Error(err)
|
||||||
} else if viewSnapshot == nil {
|
|
||||||
return events.StatusMsg("Backstack is empty")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentResultSet := c.state.ResultSet()
|
|
||||||
|
|
||||||
var currentQueryExpr string
|
|
||||||
if currentResultSet.Query != nil {
|
|
||||||
currentQueryExpr = currentResultSet.Query.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
if viewSnapshot.TableName == currentResultSet.TableInfo.Name && viewSnapshot.Query == currentQueryExpr {
|
|
||||||
log.Printf("backstack: setting filter to '%v'", viewSnapshot.Filter)
|
|
||||||
|
|
||||||
newResultSet := c.tableService.Filter(currentResultSet, viewSnapshot.Filter)
|
|
||||||
return c.setResultSetAndFilter(newResultSet, viewSnapshot.Filter, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
tableInfo := currentResultSet.TableInfo
|
|
||||||
if viewSnapshot.TableName != currentResultSet.TableInfo.Name {
|
|
||||||
tableInfo, err = c.tableService.Describe(context.Background(), viewSnapshot.TableName)
|
|
||||||
if err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("backstack: running query: table = '%v', query = '%v', filter = '%v'",
|
|
||||||
tableInfo.Name, viewSnapshot.Query, viewSnapshot.Filter)
|
|
||||||
return c.runQuery(tableInfo, viewSnapshot.Query, viewSnapshot.Filter, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("backstack: running query: table = '%v', query = '%v', filter = '%v'",
|
||||||
|
tableInfo.Name, viewSnapshot.Query, viewSnapshot.Filter)
|
||||||
|
return c.runQuery(tableInfo, viewSnapshot.Query, viewSnapshot.Filter, false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,7 @@ func TestTableReadController_InitTable(t *testing.T) {
|
||||||
t.Run("should prompt for table if no table name provided", func(t *testing.T) {
|
t.Run("should prompt for table if no table name provided", func(t *testing.T) {
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, "")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, "")
|
||||||
|
|
||||||
cmd := readController.Init()
|
event := readController.Init()
|
||||||
event := cmd()
|
|
||||||
|
|
||||||
assert.IsType(t, controllers.PromptForTableMsg{}, event)
|
assert.IsType(t, controllers.PromptForTableMsg{}, event)
|
||||||
})
|
})
|
||||||
|
@ -38,8 +37,7 @@ func TestTableReadController_InitTable(t *testing.T) {
|
||||||
t.Run("should scan table if table name provided", func(t *testing.T) {
|
t.Run("should scan table if table name provided", func(t *testing.T) {
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, "")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, "")
|
||||||
|
|
||||||
cmd := readController.Init()
|
event := readController.Init()
|
||||||
event := cmd()
|
|
||||||
|
|
||||||
assert.IsType(t, controllers.PromptForTableMsg{}, event)
|
assert.IsType(t, controllers.PromptForTableMsg{}, event)
|
||||||
})
|
})
|
||||||
|
@ -56,13 +54,11 @@ func TestTableReadController_ListTables(t *testing.T) {
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, "")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, "")
|
||||||
|
|
||||||
t.Run("returns a list of tables", func(t *testing.T) {
|
t.Run("returns a list of tables", func(t *testing.T) {
|
||||||
cmd := readController.ListTables()
|
event := readController.ListTables().(controllers.PromptForTableMsg)
|
||||||
event := cmd().(controllers.PromptForTableMsg)
|
|
||||||
|
|
||||||
assert.Equal(t, []string{"alpha-table", "bravo-table"}, event.Tables)
|
assert.Equal(t, []string{"alpha-table", "bravo-table"}, event.Tables)
|
||||||
|
|
||||||
selectedCmd := event.OnSelected("alpha-table")
|
selectedEvent := event.OnSelected("alpha-table")
|
||||||
selectedEvent := selectedCmd()
|
|
||||||
|
|
||||||
resultSet := selectedEvent.(controllers.NewResultSet)
|
resultSet := selectedEvent.(controllers.NewResultSet)
|
||||||
assert.Equal(t, "alpha-table", resultSet.ResultSet.TableInfo.Name)
|
assert.Equal(t, "alpha-table", resultSet.ResultSet.TableInfo.Name)
|
||||||
|
@ -208,9 +204,7 @@ func testWorkspace(t *testing.T) *workspaces.Workspace {
|
||||||
return ws
|
return ws
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeCommand(t *testing.T, cmd tea.Cmd) tea.Msg {
|
func invokeCommand(t *testing.T, msg tea.Msg) tea.Msg {
|
||||||
msg := cmd()
|
|
||||||
|
|
||||||
err, isErr := msg.(events.ErrorMsg)
|
err, isErr := msg.(events.ErrorMsg)
|
||||||
if isErr {
|
if isErr {
|
||||||
assert.Fail(t, fmt.Sprintf("expected no error but got one: %v", err))
|
assert.Fail(t, fmt.Sprintf("expected no error but got one: %v", err))
|
||||||
|
@ -218,9 +212,7 @@ func invokeCommand(t *testing.T, cmd tea.Cmd) tea.Msg {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeCommandWithPrompt(t *testing.T, cmd tea.Cmd, promptValue string) {
|
func invokeCommandWithPrompt(t *testing.T, msg tea.Msg, promptValue string) {
|
||||||
msg := cmd()
|
|
||||||
|
|
||||||
pi, isPi := msg.(events.PromptForInputMsg)
|
pi, isPi := msg.(events.PromptForInputMsg)
|
||||||
if !isPi {
|
if !isPi {
|
||||||
assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one"))
|
assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one"))
|
||||||
|
@ -229,22 +221,18 @@ func invokeCommandWithPrompt(t *testing.T, cmd tea.Cmd, promptValue string) {
|
||||||
invokeCommand(t, pi.OnDone(promptValue))
|
invokeCommand(t, pi.OnDone(promptValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeCommandWithPrompts(t *testing.T, cmd tea.Cmd, promptValues ...string) {
|
func invokeCommandWithPrompts(t *testing.T, msg tea.Msg, promptValues ...string) {
|
||||||
msg := cmd()
|
|
||||||
|
|
||||||
for _, promptValue := range promptValues {
|
for _, promptValue := range promptValues {
|
||||||
pi, isPi := msg.(events.PromptForInputMsg)
|
pi, isPi := msg.(events.PromptForInputMsg)
|
||||||
if !isPi {
|
if !isPi {
|
||||||
assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one"))
|
assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one: %T", msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = invokeCommand(t, pi.OnDone(promptValue))
|
msg = invokeCommand(t, pi.OnDone(promptValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeCommandWithPromptsExpectingError(t *testing.T, cmd tea.Cmd, promptValues ...string) {
|
func invokeCommandWithPromptsExpectingError(t *testing.T, msg tea.Msg, promptValues ...string) {
|
||||||
msg := cmd()
|
|
||||||
|
|
||||||
for _, promptValue := range promptValues {
|
for _, promptValue := range promptValues {
|
||||||
pi, isPi := msg.(events.PromptForInputMsg)
|
pi, isPi := msg.(events.PromptForInputMsg)
|
||||||
if !isPi {
|
if !isPi {
|
||||||
|
@ -258,9 +246,7 @@ func invokeCommandWithPromptsExpectingError(t *testing.T, cmd tea.Cmd, promptVal
|
||||||
assert.True(t, isErr)
|
assert.True(t, isErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeCommandExpectingError(t *testing.T, cmd tea.Cmd) {
|
func invokeCommandExpectingError(t *testing.T, msg tea.Msg) {
|
||||||
msg := cmd()
|
|
||||||
|
|
||||||
_, isErr := msg.(events.ErrorMsg)
|
_, isErr := msg.(events.ErrorMsg)
|
||||||
assert.True(t, isErr)
|
assert.True(t, isErr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,50 +27,46 @@ func NewTableWriteController(state *State, tableService *tables.Service, tableRe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) ToggleMark(idx int) tea.Cmd {
|
func (twc *TableWriteController) ToggleMark(idx int) tea.Msg {
|
||||||
return func() tea.Msg {
|
twc.state.withResultSet(func(resultSet *models.ResultSet) {
|
||||||
twc.state.withResultSet(func(resultSet *models.ResultSet) {
|
resultSet.SetMark(idx, !resultSet.Marked(idx))
|
||||||
resultSet.SetMark(idx, !resultSet.Marked(idx))
|
})
|
||||||
})
|
|
||||||
|
|
||||||
return ResultSetUpdated{}
|
return ResultSetUpdated{}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) NewItem() tea.Cmd {
|
func (twc *TableWriteController) NewItem() tea.Msg {
|
||||||
return func() tea.Msg {
|
// Work out which keys we need to prompt for
|
||||||
// Work out which keys we need to prompt for
|
rs := twc.state.ResultSet()
|
||||||
rs := twc.state.ResultSet()
|
|
||||||
|
|
||||||
keyPrompts := &promptSequence{
|
keyPrompts := &promptSequence{
|
||||||
prompts: []string{rs.TableInfo.Keys.PartitionKey + ": "},
|
prompts: []string{rs.TableInfo.Keys.PartitionKey + ": "},
|
||||||
}
|
}
|
||||||
if rs.TableInfo.Keys.SortKey != "" {
|
if rs.TableInfo.Keys.SortKey != "" {
|
||||||
keyPrompts.prompts = append(keyPrompts.prompts, rs.TableInfo.Keys.SortKey+": ")
|
keyPrompts.prompts = append(keyPrompts.prompts, rs.TableInfo.Keys.SortKey+": ")
|
||||||
}
|
}
|
||||||
keyPrompts.onAllDone = func(values []string) tea.Msg {
|
keyPrompts.onAllDone = func(values []string) tea.Msg {
|
||||||
twc.state.withResultSet(func(set *models.ResultSet) {
|
twc.state.withResultSet(func(set *models.ResultSet) {
|
||||||
newItem := models.Item{}
|
newItem := models.Item{}
|
||||||
|
|
||||||
// TODO: deal with keys of different type
|
// TODO: deal with keys of different type
|
||||||
newItem[rs.TableInfo.Keys.PartitionKey] = &types.AttributeValueMemberS{Value: values[0]}
|
newItem[rs.TableInfo.Keys.PartitionKey] = &types.AttributeValueMemberS{Value: values[0]}
|
||||||
if len(values) == 2 {
|
if len(values) == 2 {
|
||||||
newItem[rs.TableInfo.Keys.SortKey] = &types.AttributeValueMemberS{Value: values[1]}
|
newItem[rs.TableInfo.Keys.SortKey] = &types.AttributeValueMemberS{Value: values[1]}
|
||||||
}
|
}
|
||||||
|
|
||||||
set.AddNewItem(newItem, models.ItemAttribute{
|
set.AddNewItem(newItem, models.ItemAttribute{
|
||||||
New: true,
|
New: true,
|
||||||
Dirty: true,
|
Dirty: true,
|
||||||
})
|
|
||||||
})
|
})
|
||||||
return twc.state.buildNewResultSetMessage("New item added")
|
})
|
||||||
}
|
return twc.state.buildNewResultSetMessage("New item added")
|
||||||
|
|
||||||
return keyPrompts.next()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return keyPrompts.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) SetAttributeValue(idx int, itemType models.ItemType, key string) tea.Cmd {
|
func (twc *TableWriteController) SetAttributeValue(idx int, itemType models.ItemType, key string) tea.Msg {
|
||||||
apPath := newAttrPath(key)
|
apPath := newAttrPath(key)
|
||||||
|
|
||||||
var attrValue types.AttributeValue
|
var attrValue types.AttributeValue
|
||||||
|
@ -78,7 +74,7 @@ func (twc *TableWriteController) SetAttributeValue(idx int, itemType models.Item
|
||||||
attrValue, err = apPath.follow(set.Items()[idx])
|
attrValue, err = apPath.follow(set.Items()[idx])
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return events.SetError(err)
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch itemType {
|
switch itemType {
|
||||||
|
@ -91,7 +87,7 @@ func (twc *TableWriteController) SetAttributeValue(idx int, itemType models.Item
|
||||||
case *types.AttributeValueMemberBOOL:
|
case *types.AttributeValueMemberBOOL:
|
||||||
return twc.setBoolValue(idx, apPath)
|
return twc.setBoolValue(idx, apPath)
|
||||||
default:
|
default:
|
||||||
return events.SetError(errors.New("attribute type for key must be set"))
|
return events.Error(errors.New("attribute type for key must be set"))
|
||||||
}
|
}
|
||||||
case models.StringItemType:
|
case models.StringItemType:
|
||||||
return twc.setStringValue(idx, apPath)
|
return twc.setStringValue(idx, apPath)
|
||||||
|
@ -102,35 +98,31 @@ func (twc *TableWriteController) SetAttributeValue(idx int, itemType models.Item
|
||||||
case models.NullItemType:
|
case models.NullItemType:
|
||||||
return twc.setNullValue(idx, apPath)
|
return twc.setNullValue(idx, apPath)
|
||||||
default:
|
default:
|
||||||
return events.SetError(errors.New("unsupported attribute type"))
|
return events.Error(errors.New("unsupported attribute type"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) setStringValue(idx int, attr attrPath) tea.Cmd {
|
func (twc *TableWriteController) setStringValue(idx int, attr attrPath) tea.Msg {
|
||||||
return func() tea.Msg {
|
return events.PromptForInputMsg{
|
||||||
return events.PromptForInputMsg{
|
Prompt: "string value: ",
|
||||||
Prompt: "string value: ",
|
OnDone: func(value string) tea.Msg {
|
||||||
OnDone: func(value string) tea.Cmd {
|
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
||||||
return func() tea.Msg {
|
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
||||||
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
if err := attr.setAt(item, &types.AttributeValueMemberS{Value: value}); err != nil {
|
||||||
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
return err
|
||||||
if err := attr.setAt(item, &types.AttributeValueMemberS{Value: value}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.SetDirty(idx, true)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.RefreshColumns()
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
}
|
||||||
return ResultSetUpdated{}
|
set.SetDirty(idx, true)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
},
|
set.RefreshColumns()
|
||||||
}
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
return ResultSetUpdated{}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,294 +139,262 @@ func (twc *TableWriteController) applyToItems(rs *models.ResultSet, selectedInde
|
||||||
return applyFn(selectedIndex, rs.Items()[selectedIndex])
|
return applyFn(selectedIndex, rs.Items()[selectedIndex])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) setNumberValue(idx int, attr attrPath) tea.Cmd {
|
func (twc *TableWriteController) setNumberValue(idx int, attr attrPath) tea.Msg {
|
||||||
return func() tea.Msg {
|
return events.PromptForInputMsg{
|
||||||
return events.PromptForInputMsg{
|
Prompt: "number value: ",
|
||||||
Prompt: "number value: ",
|
OnDone: func(value string) tea.Msg {
|
||||||
OnDone: func(value string) tea.Cmd {
|
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
||||||
return func() tea.Msg {
|
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
||||||
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
if err := attr.setAt(item, &types.AttributeValueMemberN{Value: value}); err != nil {
|
||||||
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
return err
|
||||||
if err := attr.setAt(item, &types.AttributeValueMemberN{Value: value}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.SetDirty(idx, true)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.RefreshColumns()
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
}
|
||||||
return ResultSetUpdated{}
|
set.SetDirty(idx, true)
|
||||||
}
|
return nil
|
||||||
},
|
}); err != nil {
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (twc *TableWriteController) setBoolValue(idx int, attr attrPath) tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
return events.PromptForInputMsg{
|
|
||||||
Prompt: "bool value: ",
|
|
||||||
OnDone: func(value string) tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
b, err := strconv.ParseBool(value)
|
|
||||||
if err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
|
||||||
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
|
||||||
if err := attr.setAt(item, &types.AttributeValueMemberBOOL{Value: b}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.SetDirty(idx, true)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.RefreshColumns()
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
return ResultSetUpdated{}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (twc *TableWriteController) setNullValue(idx int, attr attrPath) tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
|
||||||
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
|
||||||
if err := attr.setAt(item, &types.AttributeValueMemberNULL{Value: true}); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
set.SetDirty(idx, true)
|
set.RefreshColumns()
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
set.RefreshColumns()
|
return ResultSetUpdated{}
|
||||||
return nil
|
},
|
||||||
}); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
return ResultSetUpdated{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) DeleteAttribute(idx int, key string) tea.Cmd {
|
func (twc *TableWriteController) setBoolValue(idx int, attr attrPath) tea.Msg {
|
||||||
return func() tea.Msg {
|
return events.PromptForInputMsg{
|
||||||
// Verify that the expression is valid
|
Prompt: "bool value: ",
|
||||||
apPath := newAttrPath(key)
|
OnDone: func(value string) tea.Msg {
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
|
||||||
_, err := apPath.follow(set.Items()[idx])
|
|
||||||
return err
|
|
||||||
}); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
|
||||||
err := apPath.deleteAt(set.Items()[idx])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
||||||
|
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
||||||
|
if err := attr.setAt(item, &types.AttributeValueMemberBOOL{Value: b}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
set.SetDirty(idx, true)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
set.RefreshColumns()
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
return ResultSetUpdated{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (twc *TableWriteController) setNullValue(idx int, attr attrPath) tea.Msg {
|
||||||
|
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
||||||
|
if err := twc.applyToItems(set, idx, func(idx int, item models.Item) error {
|
||||||
|
if err := attr.setAt(item, &types.AttributeValueMemberNULL{Value: true}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
set.SetDirty(idx, true)
|
set.SetDirty(idx, true)
|
||||||
set.RefreshColumns()
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return events.Error(err)
|
return err
|
||||||
|
}
|
||||||
|
set.RefreshColumns()
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
return ResultSetUpdated{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (twc *TableWriteController) DeleteAttribute(idx int, key string) tea.Msg {
|
||||||
|
// Verify that the expression is valid
|
||||||
|
apPath := newAttrPath(key)
|
||||||
|
|
||||||
|
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
||||||
|
_, err := apPath.follow(set.Items()[idx])
|
||||||
|
return err
|
||||||
|
}); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := twc.state.withResultSetReturningError(func(set *models.ResultSet) error {
|
||||||
|
err := apPath.deleteAt(set.Items()[idx])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSetUpdated{}
|
set.SetDirty(idx, true)
|
||||||
|
set.RefreshColumns()
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSetUpdated{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (twc *TableWriteController) PutItem(idx int) tea.Msg {
|
||||||
|
resultSet := twc.state.ResultSet()
|
||||||
|
if !resultSet.IsDirty(idx) {
|
||||||
|
return events.Error(errors.New("item is not dirty"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return events.PromptForInputMsg{
|
||||||
|
Prompt: "put item? ",
|
||||||
|
OnDone: func(value string) tea.Msg {
|
||||||
|
if value != "y" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := twc.tableService.PutItemAt(context.Background(), resultSet, idx); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
return ResultSetUpdated{}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) PutItem(idx int) tea.Cmd {
|
func (twc *TableWriteController) PutItems() tea.Msg {
|
||||||
return func() tea.Msg {
|
var (
|
||||||
resultSet := twc.state.ResultSet()
|
markedItemCount int
|
||||||
if !resultSet.IsDirty(idx) {
|
)
|
||||||
return events.Error(errors.New("item is not dirty"))
|
var itemsToPut []models.ItemIndex
|
||||||
}
|
|
||||||
|
|
||||||
return events.PromptForInputMsg{
|
twc.state.withResultSet(func(rs *models.ResultSet) {
|
||||||
Prompt: "put item? ",
|
if markedItems := rs.MarkedItems(); len(markedItems) > 0 {
|
||||||
OnDone: func(value string) tea.Cmd {
|
for _, mi := range markedItems {
|
||||||
return func() tea.Msg {
|
markedItemCount += 1
|
||||||
if value != "y" {
|
if rs.IsDirty(mi.Index) {
|
||||||
return nil
|
itemsToPut = append(itemsToPut, mi)
|
||||||
}
|
|
||||||
|
|
||||||
if err := twc.tableService.PutItemAt(context.Background(), resultSet, idx); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
return ResultSetUpdated{}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (twc *TableWriteController) PutItems() tea.Cmd {
|
|
||||||
return func() tea.Msg {
|
|
||||||
var (
|
|
||||||
markedItemCount int
|
|
||||||
)
|
|
||||||
var itemsToPut []models.ItemIndex
|
|
||||||
|
|
||||||
twc.state.withResultSet(func(rs *models.ResultSet) {
|
|
||||||
if markedItems := rs.MarkedItems(); len(markedItems) > 0 {
|
|
||||||
for _, mi := range markedItems {
|
|
||||||
markedItemCount += 1
|
|
||||||
if rs.IsDirty(mi.Index) {
|
|
||||||
itemsToPut = append(itemsToPut, mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i, itm := range rs.Items() {
|
|
||||||
if rs.IsDirty(i) {
|
|
||||||
itemsToPut = append(itemsToPut, models.ItemIndex{Item: itm, Index: i})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
if len(itemsToPut) == 0 {
|
|
||||||
if markedItemCount > 0 {
|
|
||||||
return events.StatusMsg("no marked items are modified")
|
|
||||||
} else {
|
|
||||||
return events.StatusMsg("no items are modified")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var promptMessage string
|
|
||||||
if markedItemCount > 0 {
|
|
||||||
promptMessage = applyToN("put ", len(itemsToPut), "marked item", "marked items", "? ")
|
|
||||||
} else {
|
} else {
|
||||||
promptMessage = applyToN("put ", len(itemsToPut), "item", "items", "? ")
|
for i, itm := range rs.Items() {
|
||||||
}
|
if rs.IsDirty(i) {
|
||||||
|
itemsToPut = append(itemsToPut, models.ItemIndex{Item: itm, Index: i})
|
||||||
return events.PromptForInputMsg{
|
|
||||||
Prompt: promptMessage,
|
|
||||||
OnDone: func(value string) tea.Cmd {
|
|
||||||
if value != "y" {
|
|
||||||
return events.SetStatus("operation aborted")
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return func() tea.Msg {
|
|
||||||
if err := twc.state.withResultSetReturningError(func(rs *models.ResultSet) error {
|
|
||||||
err := twc.tableService.PutSelectedItems(context.Background(), rs, itemsToPut)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return events.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResultSetUpdated{
|
|
||||||
statusMessage: applyToN("", len(itemsToPut), "item", "item", " put to table"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(itemsToPut) == 0 {
|
||||||
|
if markedItemCount > 0 {
|
||||||
|
return events.StatusMsg("no marked items are modified")
|
||||||
|
} else {
|
||||||
|
return events.StatusMsg("no items are modified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var promptMessage string
|
||||||
|
if markedItemCount > 0 {
|
||||||
|
promptMessage = applyToN("put ", len(itemsToPut), "marked item", "marked items", "? ")
|
||||||
|
} else {
|
||||||
|
promptMessage = applyToN("put ", len(itemsToPut), "item", "items", "? ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return events.PromptForInputMsg{
|
||||||
|
Prompt: promptMessage,
|
||||||
|
OnDone: func(value string) tea.Msg {
|
||||||
|
if value != "y" {
|
||||||
|
return events.SetStatus("operation aborted")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := twc.state.withResultSetReturningError(func(rs *models.ResultSet) error {
|
||||||
|
err := twc.tableService.PutSelectedItems(context.Background(), rs, itemsToPut)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSetUpdated{
|
||||||
|
statusMessage: applyToN("", len(itemsToPut), "item", "item", " put to table"),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) TouchItem(idx int) tea.Cmd {
|
func (twc *TableWriteController) TouchItem(idx int) tea.Msg {
|
||||||
return func() tea.Msg {
|
resultSet := twc.state.ResultSet()
|
||||||
resultSet := twc.state.ResultSet()
|
if resultSet.IsDirty(idx) {
|
||||||
if resultSet.IsDirty(idx) {
|
return events.Error(errors.New("cannot touch dirty items"))
|
||||||
return events.Error(errors.New("cannot touch dirty items"))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return events.PromptForInputMsg{
|
return events.PromptForInputMsg{
|
||||||
Prompt: "touch item? ",
|
Prompt: "touch item? ",
|
||||||
OnDone: func(value string) tea.Cmd {
|
OnDone: func(value string) tea.Msg {
|
||||||
return func() tea.Msg {
|
if value != "y" {
|
||||||
if value != "y" {
|
return nil
|
||||||
return nil
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if err := twc.tableService.PutItemAt(context.Background(), resultSet, idx); err != nil {
|
if err := twc.tableService.PutItemAt(context.Background(), resultSet, idx); err != nil {
|
||||||
return events.Error(err)
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
return ResultSetUpdated{}
|
return ResultSetUpdated{}
|
||||||
}
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) NoisyTouchItem(idx int) tea.Cmd {
|
func (twc *TableWriteController) NoisyTouchItem(idx int) tea.Msg {
|
||||||
return func() tea.Msg {
|
resultSet := twc.state.ResultSet()
|
||||||
resultSet := twc.state.ResultSet()
|
if resultSet.IsDirty(idx) {
|
||||||
if resultSet.IsDirty(idx) {
|
return events.Error(errors.New("cannot noisy touch dirty items"))
|
||||||
return events.Error(errors.New("cannot noisy touch dirty items"))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return events.PromptForInputMsg{
|
return events.PromptForInputMsg{
|
||||||
Prompt: "noisy touch item? ",
|
Prompt: "noisy touch item? ",
|
||||||
OnDone: func(value string) tea.Cmd {
|
OnDone: func(value string) tea.Msg {
|
||||||
return func() tea.Msg {
|
ctx := context.Background()
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
if value != "y" {
|
if value != "y" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
item := resultSet.Items()[0]
|
item := resultSet.Items()[0]
|
||||||
if err := twc.tableService.Delete(ctx, resultSet.TableInfo, []models.Item{item}); err != nil {
|
if err := twc.tableService.Delete(ctx, resultSet.TableInfo, []models.Item{item}); err != nil {
|
||||||
return events.Error(err)
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := twc.tableService.Put(ctx, resultSet.TableInfo, item); err != nil {
|
if err := twc.tableService.Put(ctx, resultSet.TableInfo, item); err != nil {
|
||||||
return events.Error(err)
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return twc.tableReadControllers.doScan(ctx, resultSet, resultSet.Query, false)
|
return twc.tableReadControllers.doScan(ctx, resultSet, resultSet.Query, false)
|
||||||
}
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (twc *TableWriteController) DeleteMarked() tea.Cmd {
|
func (twc *TableWriteController) DeleteMarked() tea.Msg {
|
||||||
return func() tea.Msg {
|
resultSet := twc.state.ResultSet()
|
||||||
resultSet := twc.state.ResultSet()
|
markedItems := resultSet.MarkedItems()
|
||||||
markedItems := resultSet.MarkedItems()
|
|
||||||
|
|
||||||
if len(markedItems) == 0 {
|
if len(markedItems) == 0 {
|
||||||
return events.StatusMsg("no marked items")
|
return events.StatusMsg("no marked items")
|
||||||
}
|
}
|
||||||
|
|
||||||
return events.PromptForInputMsg{
|
return events.PromptForInputMsg{
|
||||||
Prompt: applyToN("delete ", len(markedItems), "item", "items", "? "),
|
Prompt: applyToN("delete ", len(markedItems), "item", "items", "? "),
|
||||||
OnDone: func(value string) tea.Cmd {
|
OnDone: func(value string) tea.Msg {
|
||||||
if value != "y" {
|
if value != "y" {
|
||||||
return events.SetStatus("operation aborted")
|
return events.SetStatus("operation aborted")
|
||||||
}
|
}
|
||||||
|
|
||||||
return func() tea.Msg {
|
ctx := context.Background()
|
||||||
ctx := context.Background()
|
if err := twc.tableService.Delete(ctx, resultSet.TableInfo, sliceutils.Map(markedItems, func(index models.ItemIndex) models.Item {
|
||||||
if err := twc.tableService.Delete(ctx, resultSet.TableInfo, sliceutils.Map(markedItems, func(index models.ItemIndex) models.Item {
|
return index.Item
|
||||||
return index.Item
|
})); err != nil {
|
||||||
})); err != nil {
|
return events.Error(err)
|
||||||
return events.Error(err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return twc.tableReadControllers.doScan(ctx, resultSet, resultSet.Query, false)
|
return twc.tableReadControllers.doScan(ctx, resultSet, resultSet.Query, false)
|
||||||
}
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,27 +46,27 @@ func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteCon
|
||||||
cc.AddCommands(&commandctrl.CommandContext{
|
cc.AddCommands(&commandctrl.CommandContext{
|
||||||
Commands: map[string]commandctrl.Command{
|
Commands: map[string]commandctrl.Command{
|
||||||
"quit": commandctrl.NoArgCommand(tea.Quit),
|
"quit": commandctrl.NoArgCommand(tea.Quit),
|
||||||
"table": func(args []string) tea.Cmd {
|
"table": func(args []string) tea.Msg {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return rc.ListTables()
|
return rc.ListTables()
|
||||||
} else {
|
} else {
|
||||||
return rc.ScanTable(args[0])
|
return rc.ScanTable(args[0])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"export": func(args []string) tea.Cmd {
|
"export": func(args []string) tea.Msg {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return events.SetError(errors.New("expected filename"))
|
return events.Error(errors.New("expected filename"))
|
||||||
}
|
}
|
||||||
return rc.ExportCSV(args[0])
|
return rc.ExportCSV(args[0])
|
||||||
},
|
},
|
||||||
"unmark": commandctrl.NoArgCommand(rc.Unmark()),
|
"unmark": commandctrl.NoArgCommand(rc.Unmark),
|
||||||
"delete": commandctrl.NoArgCommand(wc.DeleteMarked()),
|
"delete": commandctrl.NoArgCommand(wc.DeleteMarked),
|
||||||
|
|
||||||
// TEMP
|
// TEMP
|
||||||
"new-item": commandctrl.NoArgCommand(wc.NewItem()),
|
"new-item": commandctrl.NoArgCommand(wc.NewItem),
|
||||||
"set-attr": func(args []string) tea.Cmd {
|
"set-attr": func(args []string) tea.Msg {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return events.SetError(errors.New("expected field"))
|
return events.Error(errors.New("expected field"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemType = models.UnsetItemType
|
var itemType = models.UnsetItemType
|
||||||
|
@ -81,27 +81,27 @@ func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteCon
|
||||||
case "-NULL":
|
case "-NULL":
|
||||||
itemType = models.NullItemType
|
itemType = models.NullItemType
|
||||||
default:
|
default:
|
||||||
return events.SetError(errors.New("unrecognised item type"))
|
return events.Error(errors.New("unrecognised item type"))
|
||||||
}
|
}
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return wc.SetAttributeValue(dtv.SelectedItemIndex(), itemType, args[0])
|
return wc.SetAttributeValue(dtv.SelectedItemIndex(), itemType, args[0])
|
||||||
},
|
},
|
||||||
"del-attr": func(args []string) tea.Cmd {
|
"del-attr": func(args []string) tea.Msg {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return events.SetError(errors.New("expected field"))
|
return events.Error(errors.New("expected field"))
|
||||||
}
|
}
|
||||||
return wc.DeleteAttribute(dtv.SelectedItemIndex(), args[0])
|
return wc.DeleteAttribute(dtv.SelectedItemIndex(), args[0])
|
||||||
},
|
},
|
||||||
|
|
||||||
"put": func(args []string) tea.Cmd {
|
"put": func(args []string) tea.Msg {
|
||||||
return wc.PutItems()
|
return wc.PutItems()
|
||||||
},
|
},
|
||||||
"touch": func(args []string) tea.Cmd {
|
"touch": func(args []string) tea.Msg {
|
||||||
return wc.TouchItem(dtv.SelectedItemIndex())
|
return wc.TouchItem(dtv.SelectedItemIndex())
|
||||||
},
|
},
|
||||||
"noisy-touch": func(args []string) tea.Cmd {
|
"noisy-touch": func(args []string) tea.Msg {
|
||||||
return wc.NoisyTouchItem(dtv.SelectedItemIndex())
|
return wc.NoisyTouchItem(dtv.SelectedItemIndex())
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ func NewModel(rc *controllers.TableReadController, wc *controllers.TableWriteCon
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) Init() tea.Cmd {
|
func (m Model) Init() tea.Cmd {
|
||||||
return m.tableReadController.Init()
|
return m.tableReadController.Init
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
@ -141,21 +141,21 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "m":
|
case "m":
|
||||||
if idx := m.tableView.SelectedItemIndex(); idx >= 0 {
|
if idx := m.tableView.SelectedItemIndex(); idx >= 0 {
|
||||||
return m, m.tableWriteController.ToggleMark(idx)
|
return m, func() tea.Msg { return m.tableWriteController.ToggleMark(idx) }
|
||||||
}
|
}
|
||||||
case "R":
|
case "R":
|
||||||
return m, m.tableReadController.Rescan()
|
return m, m.tableReadController.Rescan
|
||||||
case "?":
|
case "?":
|
||||||
return m, m.tableReadController.PromptForQuery()
|
return m, m.tableReadController.PromptForQuery
|
||||||
case "/":
|
case "/":
|
||||||
return m, m.tableReadController.Filter()
|
return m, m.tableReadController.Filter
|
||||||
case "backspace":
|
case "backspace":
|
||||||
return m, m.tableReadController.ViewBack()
|
return m, m.tableReadController.ViewBack
|
||||||
//case "e":
|
//case "e":
|
||||||
// m.itemEdit.Visible()
|
// m.itemEdit.Visible()
|
||||||
// return m, nil
|
// return m, nil
|
||||||
case ":":
|
case ":":
|
||||||
return m, m.commandController.Prompt()
|
return m, m.commandController.Prompt
|
||||||
case "ctrl+c", "esc":
|
case "ctrl+c", "esc":
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ func (s *StatusAndPrompt) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
pendingInput := s.pendingInput
|
pendingInput := s.pendingInput
|
||||||
s.pendingInput = nil
|
s.pendingInput = nil
|
||||||
|
|
||||||
return s, pendingInput.OnDone(s.textInput.Value())
|
return s, func() tea.Msg { return pendingInput.OnDone(s.textInput.Value()) }
|
||||||
default:
|
default:
|
||||||
if msg.Type == tea.KeyRunes {
|
if msg.Type == tea.KeyRunes {
|
||||||
msg.Runes = sliceutils.Filter(msg.Runes, func(r rune) bool { return r != '\x0d' && r != '\x0a' })
|
msg.Runes = sliceutils.Filter(msg.Runes, func(r rune) bool { return r != '\x0d' && r != '\x0a' })
|
||||||
|
|
|
@ -55,7 +55,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
var sel controllers.PromptForTableMsg
|
var sel controllers.PromptForTableMsg
|
||||||
sel, m.pendingSelection = *m.pendingSelection, nil
|
sel, m.pendingSelection = *m.pendingSelection, nil
|
||||||
|
|
||||||
return m, sel.OnSelected(m.listController.list.SelectedItem().(tableItem).name)
|
return m, func() tea.Msg { return sel.OnSelected(m.listController.list.SelectedItem().(tableItem).name) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
// TEMP
|
// TEMP
|
||||||
case ":":
|
case ":":
|
||||||
return m, m.cmdController.Prompt()
|
return m, func() tea.Msg { return m.cmdController.Prompt() }
|
||||||
case "w":
|
case "w":
|
||||||
return m, m.controller.ViewLogLineFullScreen(m.logLines.SelectedLogLine())
|
return m, m.controller.ViewLogLineFullScreen(m.logLines.SelectedLogLine())
|
||||||
// END TEMP
|
// END TEMP
|
||||||
|
|
|
@ -39,26 +39,24 @@ func (c *SSMController) Fetch() tea.Cmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SSMController) ChangePrefix(newPrefix string) tea.Cmd {
|
func (c *SSMController) ChangePrefix(newPrefix string) tea.Msg {
|
||||||
return func() tea.Msg {
|
res, err := c.service.List(context.Background(), newPrefix)
|
||||||
res, err := c.service.List(context.Background(), newPrefix)
|
if err != nil {
|
||||||
if err != nil {
|
return events.Error(err)
|
||||||
return events.Error(err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
c.prefix = newPrefix
|
c.prefix = newPrefix
|
||||||
|
|
||||||
return NewParameterListMsg{
|
return NewParameterListMsg{
|
||||||
Prefix: c.prefix,
|
Prefix: c.prefix,
|
||||||
Parameters: res,
|
Parameters: res,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SSMController) Clone(param models.SSMParameter) tea.Cmd {
|
func (c *SSMController) Clone(param models.SSMParameter) tea.Msg {
|
||||||
return events.PromptForInput("New key: ", func(value string) tea.Cmd {
|
return events.PromptForInput("New key: ", func(value string) tea.Msg {
|
||||||
return func() tea.Msg {
|
return func() tea.Msg {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if err := c.service.Clone(ctx, param, value); err != nil {
|
if err := c.service.Clone(ctx, param, value); err != nil {
|
||||||
|
@ -78,23 +76,21 @@ func (c *SSMController) Clone(param models.SSMParameter) tea.Cmd {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SSMController) DeleteParameter(param models.SSMParameter) tea.Cmd {
|
func (c *SSMController) DeleteParameter(param models.SSMParameter) tea.Msg {
|
||||||
return events.Confirm("delete parameter? ", func() tea.Cmd {
|
return events.Confirm("delete parameter? ", func() tea.Msg {
|
||||||
return func() tea.Msg {
|
ctx := context.Background()
|
||||||
ctx := context.Background()
|
if err := c.service.Delete(ctx, param); err != nil {
|
||||||
if err := c.service.Delete(ctx, param); err != nil {
|
return events.Error(err)
|
||||||
return events.Error(err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
res, err := c.service.List(context.Background(), c.prefix)
|
res, err := c.service.List(context.Background(), c.prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return events.Error(err)
|
return events.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewParameterListMsg{
|
return NewParameterListMsg{
|
||||||
Prefix: c.prefix,
|
Prefix: c.prefix,
|
||||||
Parameters: res,
|
Parameters: res,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,17 @@ func NewModel(controller *controllers.SSMController, cmdController *commandctrl.
|
||||||
|
|
||||||
cmdController.AddCommands(&commandctrl.CommandContext{
|
cmdController.AddCommands(&commandctrl.CommandContext{
|
||||||
Commands: map[string]commandctrl.Command{
|
Commands: map[string]commandctrl.Command{
|
||||||
"clone": func(args []string) tea.Cmd {
|
"clone": func(args []string) tea.Msg {
|
||||||
if currentParam := ssmList.CurrentParameter(); currentParam != nil {
|
if currentParam := ssmList.CurrentParameter(); currentParam != nil {
|
||||||
return controller.Clone(*currentParam)
|
return controller.Clone(*currentParam)
|
||||||
}
|
}
|
||||||
return events.SetError(errors.New("no parameter selected"))
|
return events.Error(errors.New("no parameter selected"))
|
||||||
},
|
},
|
||||||
"delete": func(args []string) tea.Cmd {
|
"delete": func(args []string) tea.Msg {
|
||||||
if currentParam := ssmList.CurrentParameter(); currentParam != nil {
|
if currentParam := ssmList.CurrentParameter(); currentParam != nil {
|
||||||
return controller.DeleteParameter(*currentParam)
|
return controller.DeleteParameter(*currentParam)
|
||||||
}
|
}
|
||||||
return events.SetError(errors.New("no parameter selected"))
|
return events.Error(errors.New("no parameter selected"))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -75,7 +75,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
// TEMP
|
// TEMP
|
||||||
case ":":
|
case ":":
|
||||||
return m, m.cmdController.Prompt()
|
return m, func() tea.Msg { return m.cmdController.Prompt() }
|
||||||
// END TEMP
|
// END TEMP
|
||||||
|
|
||||||
case "ctrl+c", "q":
|
case "ctrl+c", "q":
|
||||||
|
|
Loading…
Reference in a new issue