issue-8: added going forward in backstack and restoring last view
This commit is contained in:
parent
1109f2c9ee
commit
4c187ebb4d
|
@ -77,7 +77,7 @@ func main() {
|
||||||
itemRendererService := itemrenderer.NewService(uiStyles.ItemView.FieldType, uiStyles.ItemView.MetaInfo)
|
itemRendererService := itemrenderer.NewService(uiStyles.ItemView.FieldType, uiStyles.ItemView.MetaInfo)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
tableReadController := controllers.NewTableReadController(state, tableService, workspaceService, itemRendererService, *flagTable)
|
tableReadController := controllers.NewTableReadController(state, tableService, workspaceService, itemRendererService, *flagTable, true)
|
||||||
tableWriteController := controllers.NewTableWriteController(state, tableService, tableReadController)
|
tableWriteController := controllers.NewTableWriteController(state, tableService, tableReadController)
|
||||||
|
|
||||||
commandController := commandctrl.NewCommandController()
|
commandController := commandctrl.NewCommandController()
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/lmika/audax/internal/common/ui/events"
|
"github.com/lmika/audax/internal/common/ui/events"
|
||||||
"github.com/lmika/audax/internal/dynamo-browse/models"
|
"github.com/lmika/audax/internal/dynamo-browse/models"
|
||||||
"github.com/lmika/audax/internal/dynamo-browse/models/queryexpr"
|
"github.com/lmika/audax/internal/dynamo-browse/models/queryexpr"
|
||||||
|
"github.com/lmika/audax/internal/dynamo-browse/models/serialisable"
|
||||||
"github.com/lmika/audax/internal/dynamo-browse/services/itemrenderer"
|
"github.com/lmika/audax/internal/dynamo-browse/services/itemrenderer"
|
||||||
"github.com/lmika/audax/internal/dynamo-browse/services/workspaces"
|
"github.com/lmika/audax/internal/dynamo-browse/services/workspaces"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -23,6 +24,7 @@ type TableReadController struct {
|
||||||
workspaceService *workspaces.ViewSnapshotService
|
workspaceService *workspaces.ViewSnapshotService
|
||||||
itemRendererService *itemrenderer.Service
|
itemRendererService *itemrenderer.Service
|
||||||
tableName string
|
tableName string
|
||||||
|
loadFromLastView bool
|
||||||
|
|
||||||
// state
|
// state
|
||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
|
@ -36,6 +38,7 @@ func NewTableReadController(
|
||||||
workspaceService *workspaces.ViewSnapshotService,
|
workspaceService *workspaces.ViewSnapshotService,
|
||||||
itemRendererService *itemrenderer.Service,
|
itemRendererService *itemrenderer.Service,
|
||||||
tableName string,
|
tableName string,
|
||||||
|
loadFromLastView bool,
|
||||||
) *TableReadController {
|
) *TableReadController {
|
||||||
return &TableReadController{
|
return &TableReadController{
|
||||||
state: state,
|
state: state,
|
||||||
|
@ -49,6 +52,13 @@ func NewTableReadController(
|
||||||
|
|
||||||
// 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.Msg {
|
func (c *TableReadController) Init() tea.Msg {
|
||||||
|
// Restore previous view
|
||||||
|
if c.loadFromLastView {
|
||||||
|
if vs, err := c.workspaceService.ViewRestore(); err == nil && vs != nil {
|
||||||
|
return c.updateViewToSnapshot(vs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if c.tableName == "" {
|
if c.tableName == "" {
|
||||||
return c.ListTables()
|
return c.ListTables()
|
||||||
} else {
|
} else {
|
||||||
|
@ -234,15 +244,39 @@ func (c *TableReadController) Filter() tea.Msg {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TableReadController) ViewBack() tea.Msg {
|
func (c *TableReadController) ViewBack() tea.Msg {
|
||||||
viewSnapshot, err := c.workspaceService.PopSnapshot()
|
viewSnapshot, err := c.workspaceService.ViewBack()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return events.Error(err)
|
return events.Error(err)
|
||||||
} else if viewSnapshot == nil {
|
} else if viewSnapshot == nil {
|
||||||
return events.StatusMsg("Backstack is empty")
|
return events.StatusMsg("Backstack is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return c.updateViewToSnapshot(viewSnapshot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TableReadController) ViewForward() tea.Msg {
|
||||||
|
viewSnapshot, err := c.workspaceService.ViewForward()
|
||||||
|
if err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
} else if viewSnapshot == nil {
|
||||||
|
return events.StatusMsg("At top of view stack")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.updateViewToSnapshot(viewSnapshot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TableReadController) updateViewToSnapshot(viewSnapshot *serialisable.ViewSnapshot) tea.Msg {
|
||||||
|
var err error
|
||||||
currentResultSet := c.state.ResultSet()
|
currentResultSet := c.state.ResultSet()
|
||||||
|
|
||||||
|
if currentResultSet == nil {
|
||||||
|
tableInfo, err := c.tableService.Describe(context.Background(), viewSnapshot.TableName)
|
||||||
|
if err != nil {
|
||||||
|
return events.Error(err)
|
||||||
|
}
|
||||||
|
return c.runQuery(tableInfo, viewSnapshot.Query, viewSnapshot.Filter, false)
|
||||||
|
}
|
||||||
|
|
||||||
var currentQueryExpr string
|
var currentQueryExpr string
|
||||||
if currentResultSet.Query != nil {
|
if currentResultSet.Query != nil {
|
||||||
currentQueryExpr = currentResultSet.Query.String()
|
currentQueryExpr = currentResultSet.Query.String()
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestTableReadController_InitTable(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
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, itemRendererService, "")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "", false)
|
||||||
|
|
||||||
event := readController.Init()
|
event := readController.Init()
|
||||||
|
|
||||||
|
@ -37,7 +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, itemRendererService, "")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "", false)
|
||||||
|
|
||||||
event := readController.Init()
|
event := readController.Init()
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ func TestTableReadController_ListTables(t *testing.T) {
|
||||||
|
|
||||||
provider := dynamo.NewProvider(client)
|
provider := dynamo.NewProvider(client)
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "", false)
|
||||||
|
|
||||||
t.Run("returns a list of tables", func(t *testing.T) {
|
t.Run("returns a list of tables", func(t *testing.T) {
|
||||||
event := readController.ListTables().(controllers.PromptForTableMsg)
|
event := readController.ListTables().(controllers.PromptForTableMsg)
|
||||||
|
@ -80,7 +80,7 @@ func TestTableReadController_Rescan(t *testing.T) {
|
||||||
provider := dynamo.NewProvider(client)
|
provider := dynamo.NewProvider(client)
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "bravo-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "bravo-table", false)
|
||||||
|
|
||||||
t.Run("should perform a rescan", func(t *testing.T) {
|
t.Run("should perform a rescan", func(t *testing.T) {
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -117,7 +117,7 @@ func TestTableReadController_ExportCSV(t *testing.T) {
|
||||||
|
|
||||||
provider := dynamo.NewProvider(client)
|
provider := dynamo.NewProvider(client)
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "bravo-table")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "bravo-table", false)
|
||||||
|
|
||||||
t.Run("should export result set to CSV file", func(t *testing.T) {
|
t.Run("should export result set to CSV file", func(t *testing.T) {
|
||||||
tempFile := tempFile(t)
|
tempFile := tempFile(t)
|
||||||
|
@ -138,7 +138,7 @@ func TestTableReadController_ExportCSV(t *testing.T) {
|
||||||
|
|
||||||
t.Run("should return error if result set is not set", func(t *testing.T) {
|
t.Run("should return error if result set is not set", func(t *testing.T) {
|
||||||
tempFile := tempFile(t)
|
tempFile := tempFile(t)
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "non-existant-table")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "non-existant-table", false)
|
||||||
|
|
||||||
invokeCommandExpectingError(t, readController.Init())
|
invokeCommandExpectingError(t, readController.Init())
|
||||||
invokeCommandExpectingError(t, readController.ExportCSV(tempFile))
|
invokeCommandExpectingError(t, readController.ExportCSV(tempFile))
|
||||||
|
@ -156,7 +156,7 @@ func TestTableReadController_Query(t *testing.T) {
|
||||||
|
|
||||||
provider := dynamo.NewProvider(client)
|
provider := dynamo.NewProvider(client)
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "bravo-table")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "bravo-table", false)
|
||||||
|
|
||||||
t.Run("should run scan with filter based on user query", func(t *testing.T) {
|
t.Run("should run scan with filter based on user query", func(t *testing.T) {
|
||||||
tempFile := tempFile(t)
|
tempFile := tempFile(t)
|
||||||
|
@ -176,7 +176,7 @@ func TestTableReadController_Query(t *testing.T) {
|
||||||
|
|
||||||
t.Run("should return error if result set is not set", func(t *testing.T) {
|
t.Run("should return error if result set is not set", func(t *testing.T) {
|
||||||
tempFile := tempFile(t)
|
tempFile := tempFile(t)
|
||||||
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "non-existant-table")
|
readController := controllers.NewTableReadController(controllers.NewState(), service, workspaceService, itemRendererService, "non-existant-table", false)
|
||||||
|
|
||||||
invokeCommandExpectingError(t, readController.Init())
|
invokeCommandExpectingError(t, readController.Init())
|
||||||
invokeCommandExpectingError(t, readController.ExportCSV(tempFile))
|
invokeCommandExpectingError(t, readController.ExportCSV(tempFile))
|
||||||
|
|
|
@ -27,7 +27,7 @@ func TestTableWriteController_NewItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -91,7 +91,7 @@ func TestTableWriteController_SetAttributeValue(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -111,7 +111,7 @@ func TestTableWriteController_SetAttributeValue(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -165,7 +165,7 @@ func TestTableWriteController_SetAttributeValue(t *testing.T) {
|
||||||
for _, scenario := range scenarios {
|
for _, scenario := range scenarios {
|
||||||
t.Run(fmt.Sprintf("should change the value of a field to type %v", scenario.attrType), func(t *testing.T) {
|
t.Run(fmt.Sprintf("should change the value of a field to type %v", scenario.attrType), func(t *testing.T) {
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -186,7 +186,7 @@ func TestTableWriteController_SetAttributeValue(t *testing.T) {
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("should change value of nested field to type %v", scenario.attrType), func(t *testing.T) {
|
t.Run(fmt.Sprintf("should change value of nested field to type %v", scenario.attrType), func(t *testing.T) {
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -225,7 +225,7 @@ func TestTableWriteController_DeleteAttribute(t *testing.T) {
|
||||||
|
|
||||||
t.Run("should delete top level attribute", func(t *testing.T) {
|
t.Run("should delete top level attribute", func(t *testing.T) {
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -241,7 +241,7 @@ func TestTableWriteController_DeleteAttribute(t *testing.T) {
|
||||||
|
|
||||||
t.Run("should delete attribute of map", func(t *testing.T) {
|
t.Run("should delete attribute of map", func(t *testing.T) {
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -273,7 +273,7 @@ func TestTableWriteController_PutItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
@ -300,7 +300,7 @@ func TestTableWriteController_PutItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
@ -331,7 +331,7 @@ func TestTableWriteController_PutItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
@ -356,7 +356,7 @@ func TestTableWriteController_PutItems(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -384,7 +384,7 @@ func TestTableWriteController_PutItems(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -420,7 +420,7 @@ func TestTableWriteController_PutItems(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
invokeCommand(t, readController.Init())
|
invokeCommand(t, readController.Init())
|
||||||
|
@ -462,7 +462,7 @@ func TestTableWriteController_TouchItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
@ -488,7 +488,7 @@ func TestTableWriteController_TouchItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
@ -515,7 +515,7 @@ func TestTableWriteController_NoisyTouchItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
@ -541,7 +541,7 @@ func TestTableWriteController_NoisyTouchItem(t *testing.T) {
|
||||||
service := tables.NewService(provider)
|
service := tables.NewService(provider)
|
||||||
|
|
||||||
state := controllers.NewState()
|
state := controllers.NewState()
|
||||||
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table")
|
readController := controllers.NewTableReadController(state, service, workspaceService, itemRendererService, "alpha-table", false)
|
||||||
writeController := controllers.NewTableWriteController(state, service, readController)
|
writeController := controllers.NewTableWriteController(state, service, readController)
|
||||||
|
|
||||||
// Read the table
|
// Read the table
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
type ViewSnapshot struct {
|
type ViewSnapshot struct {
|
||||||
ID int64 `storm:"id,increment"`
|
ID int64 `storm:"id,increment"`
|
||||||
BackLink int64 `storm:"index"`
|
BackLink int64 `storm:"index"`
|
||||||
|
ForeLink int64 `storm:"index"`
|
||||||
Time time.Time
|
Time time.Time
|
||||||
TableName string
|
TableName string
|
||||||
Query string
|
Query string
|
||||||
|
|
|
@ -43,6 +43,55 @@ func (s *ResultSetSnapshotStore) SetAsHead(resultSetID int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ResultSetSnapshotStore) CurrentlyViewedSnapshot() (*serialisable.ViewSnapshot, error) {
|
||||||
|
var resultSetID int64
|
||||||
|
if err := s.ws.Get("viewIds", "current", &resultSetID); err != nil {
|
||||||
|
if errors.Is(err, storm.ErrNotFound) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.Wrap(err, "cannot get head")
|
||||||
|
}
|
||||||
|
|
||||||
|
var rss serialisable.ViewSnapshot
|
||||||
|
if err := s.ws.One("ID", resultSetID, &rss); err != nil {
|
||||||
|
if errors.Is(err, storm.ErrNotFound) {
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
return nil, errors.Wrap(err, "cannot get head")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rss, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ResultSetSnapshotStore) SetCurrentlyViewedSnapshot(resultSetID int64) error {
|
||||||
|
if resultSetID == 0 {
|
||||||
|
if err := s.ws.Delete("viewIds", "current"); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot remove head")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.ws.Set("viewIds", "current", resultSetID); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot set as head")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ResultSetSnapshotStore) Find(resultSetID int64) (*serialisable.ViewSnapshot, error) {
|
||||||
|
var rss serialisable.ViewSnapshot
|
||||||
|
if err := s.ws.One("ID", resultSetID, &rss); err != nil {
|
||||||
|
if errors.Is(err, storm.ErrNotFound) {
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
return nil, errors.Wrap(err, "cannot get head")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rss, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ResultSetSnapshotStore) Head() (*serialisable.ViewSnapshot, error) {
|
func (s *ResultSetSnapshotStore) Head() (*serialisable.ViewSnapshot, error) {
|
||||||
var headResultSetID int64
|
var headResultSetID int64
|
||||||
if err := s.ws.Get("head", "id", &headResultSetID); err != nil && !errors.Is(err, storm.ErrNotFound) {
|
if err := s.ws.Get("head", "id", &headResultSetID); err != nil && !errors.Is(err, storm.ErrNotFound) {
|
||||||
|
@ -61,6 +110,23 @@ func (s *ResultSetSnapshotStore) Head() (*serialisable.ViewSnapshot, error) {
|
||||||
return &rss, nil
|
return &rss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ResultSetSnapshotStore) Dehead(fromNode *serialisable.ViewSnapshot) error {
|
||||||
|
n := fromNode.ForeLink
|
||||||
|
for n != 0 {
|
||||||
|
node, err := s.Find(n)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot get node with ID: %v", n)
|
||||||
|
} else if node == nil {
|
||||||
|
return errors.Errorf("expected node with ID %v, but did not find it", n)
|
||||||
|
}
|
||||||
|
if err := s.Remove(node.ID); err != nil {
|
||||||
|
log.Printf("warn: cannot delete node with ID %v", node.ID)
|
||||||
|
}
|
||||||
|
n = node.ForeLink
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ResultSetSnapshotStore) Remove(resultSetId int64) error {
|
func (s *ResultSetSnapshotStore) Remove(resultSetId int64) error {
|
||||||
var rss serialisable.ViewSnapshot
|
var rss serialisable.ViewSnapshot
|
||||||
if err := s.ws.One("ID", resultSetId, &rss); err != nil {
|
if err := s.ws.One("ID", resultSetId, &rss); err != nil {
|
||||||
|
|
|
@ -5,6 +5,10 @@ import "github.com/lmika/audax/internal/dynamo-browse/models/serialisable"
|
||||||
type ViewSnapshotStore interface {
|
type ViewSnapshotStore interface {
|
||||||
Save(rs *serialisable.ViewSnapshot) error
|
Save(rs *serialisable.ViewSnapshot) error
|
||||||
SetAsHead(resultSetId int64) error
|
SetAsHead(resultSetId int64) error
|
||||||
|
CurrentlyViewedSnapshot() (*serialisable.ViewSnapshot, error)
|
||||||
|
SetCurrentlyViewedSnapshot(resultSetId int64) error
|
||||||
|
Find(resultSetID int64) (*serialisable.ViewSnapshot, error)
|
||||||
Head() (*serialisable.ViewSnapshot, error)
|
Head() (*serialisable.ViewSnapshot, error)
|
||||||
Remove(resultSetId int64) error
|
Remove(resultSetId int64) error
|
||||||
|
Dehead(fromNode *serialisable.ViewSnapshot) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,43 +27,89 @@ func (s *ViewSnapshotService) PushSnapshot(rs *models.ResultSet, filter string)
|
||||||
}
|
}
|
||||||
newSnapshot.Filter = filter
|
newSnapshot.Filter = filter
|
||||||
|
|
||||||
if head, err := s.store.Head(); head != nil {
|
oldHead, err := s.store.CurrentlyViewedSnapshot()
|
||||||
newSnapshot.BackLink = head.ID
|
if err != nil {
|
||||||
} else if err != nil {
|
return errors.Wrap(err, "cannot get snapshot head")
|
||||||
return errors.Wrap(err, "cannot get head result set")
|
}
|
||||||
|
|
||||||
|
if oldHead != nil {
|
||||||
|
newSnapshot.BackLink = oldHead.ID
|
||||||
|
|
||||||
|
// Remove all nodes from this point on the head
|
||||||
|
if err := s.store.Dehead(oldHead); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot remove head")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.store.Save(newSnapshot); err != nil {
|
if err := s.store.Save(newSnapshot); err != nil {
|
||||||
return errors.Wrap(err, "cannot save snapshot")
|
return errors.Wrap(err, "cannot save snapshot")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oldHead != nil {
|
||||||
|
oldHead.ForeLink = newSnapshot.ID
|
||||||
|
if err := s.store.Save(oldHead); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot update old head")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.store.SetAsHead(newSnapshot.ID); err != nil {
|
if err := s.store.SetAsHead(newSnapshot.ID); err != nil {
|
||||||
return errors.Wrap(err, "cannot set new snapshot as head")
|
return errors.Wrap(err, "cannot set new snapshot as head")
|
||||||
}
|
}
|
||||||
|
if err := s.store.SetCurrentlyViewedSnapshot(newSnapshot.ID); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot set new snapshot as head")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ViewSnapshotService) PopSnapshot() (*serialisable.ViewSnapshot, error) {
|
func (s *ViewSnapshotService) ViewRestore() (*serialisable.ViewSnapshot, error) {
|
||||||
vs, err := s.store.Head()
|
vs, err := s.store.CurrentlyViewedSnapshot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "cannot get snapshot head")
|
return nil, errors.Wrap(err, "cannot get snapshot head")
|
||||||
} else if vs == nil || vs.BackLink == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.store.SetAsHead(vs.BackLink); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "cannot set new head")
|
|
||||||
}
|
|
||||||
if err := s.store.Remove(vs.ID); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "cannot remove old ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
vs, err = s.store.Head()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "cannot get snapshot head")
|
|
||||||
} else if vs == nil || vs.BackLink == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return vs, nil
|
return vs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ViewSnapshotService) ViewBack() (*serialisable.ViewSnapshot, error) {
|
||||||
|
vs, err := s.store.CurrentlyViewedSnapshot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot get snapshot head")
|
||||||
|
} else if vs == nil || vs.BackLink == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vsToReturn, err := s.store.Find(vs.BackLink)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot get snapshot head")
|
||||||
|
} else if vsToReturn == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.store.SetCurrentlyViewedSnapshot(vsToReturn.ID); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot set new head")
|
||||||
|
}
|
||||||
|
|
||||||
|
return vsToReturn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ViewSnapshotService) ViewForward() (*serialisable.ViewSnapshot, error) {
|
||||||
|
vs, err := s.store.CurrentlyViewedSnapshot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot get snapshot head")
|
||||||
|
} else if vs == nil || vs.ForeLink == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vsToReturn, err := s.store.Find(vs.ForeLink)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot get snapshot head")
|
||||||
|
} else if vsToReturn == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.store.SetCurrentlyViewedSnapshot(vsToReturn.ID); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot set new head")
|
||||||
|
}
|
||||||
|
|
||||||
|
return vsToReturn, nil
|
||||||
|
}
|
||||||
|
|
|
@ -163,6 +163,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m, m.tableView.Refresh()
|
return m, m.tableView.Refresh()
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
if !m.statusAndPrompt.InPrompt() && !m.tableSelect.Visible() {
|
if !m.statusAndPrompt.InPrompt() && !m.tableSelect.Visible() {
|
||||||
|
log.Printf("key = %+v", msg)
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "m":
|
case "m":
|
||||||
if idx := m.tableView.SelectedItemIndex(); idx >= 0 {
|
if idx := m.tableView.SelectedItemIndex(); idx >= 0 {
|
||||||
|
@ -180,6 +181,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
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 "\\":
|
||||||
|
return m, m.tableReadController.ViewForward
|
||||||
case "w":
|
case "w":
|
||||||
return m, func() tea.Msg {
|
return m, func() tea.Msg {
|
||||||
return controllers.SetTableItemView{ViewIndex: utils.Cycle(m.mainViewIndex, 1, ViewModeCount)}
|
return controllers.SetTableItemView{ViewIndex: utils.Cycle(m.mainViewIndex, 1, ViewModeCount)}
|
||||||
|
|
Loading…
Reference in a new issue