Skip to content

Commit

Permalink
feat(#56): show counter of filtered rows (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
hedhyw authored May 27, 2024
1 parent 144f8b8 commit 6b8948a
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 107 deletions.
2 changes: 1 addition & 1 deletion internal/app/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (h helper) handleLogEntriesLoadedMsg(

func (h helper) handleOpenJSONRowRequestedMsg(
msg events.OpenJSONRowRequestedMsg,
previousState state,
previousState stateModel,
) (tea.Model, tea.Cmd) {
if msg.Index < 0 || msg.Index >= len(msg.LogEntries) {
return previousState, nil
Expand Down
4 changes: 2 additions & 2 deletions internal/app/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
tea "github.com/charmbracelet/bubbletea"
)

type state interface {
type stateModel interface {
tea.Model
fmt.Stringer

withApplication(application Application) (state, tea.Cmd)
withApplication(application Application) (stateModel, tea.Cmd)
}
16 changes: 8 additions & 8 deletions internal/app/stateerror.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,32 @@ import (
tea "github.com/charmbracelet/bubbletea"
)

// StateError is a failure message state.
type StateError struct {
// StateErrorModel is a failure message state.
type StateErrorModel struct {
helper

err error
}

func newStateError(application Application, err error) StateError {
return StateError{
func newStateError(application Application, err error) StateErrorModel {
return StateErrorModel{
helper: helper{Application: application},
err: err,
}
}

// Init initializes component. It implements tea.Model.
func (s StateError) Init() tea.Cmd {
func (s StateErrorModel) Init() tea.Cmd {
return nil
}

// View renders component. It implements tea.Model.
func (s StateError) View() string {
func (s StateErrorModel) View() string {
return fmt.Sprintf("Something went wrong: %s.", s.err)
}

// Update handles events. It implements tea.Model.
func (s StateError) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (s StateErrorModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
s.helper = s.helper.Update(msg)

switch msg.(type) {
Expand All @@ -43,6 +43,6 @@ func (s StateError) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

// String implements fmt.Stringer.
func (s StateError) String() string {
func (s StateErrorModel) String() string {
return modelValue(s)
}
4 changes: 2 additions & 2 deletions internal/app/stateerror_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestStateError(t *testing.T) {
model := newTestModel(t, assets.ExampleJSONLog())
model = handleUpdate(model, events.ErrorOccuredMsg{Err: errTest})

_, ok := model.(app.StateError)
_, ok := model.(app.StateErrorModel)
assert.Truef(t, ok, "%s", model)

t.Run("rendered", func(t *testing.T) {
Expand Down Expand Up @@ -52,7 +52,7 @@ func TestStateError(t *testing.T) {

model := handleUpdate(model, events.ViewRowsReloadRequestedMsg{})

_, ok := model.(app.StateError)
_, ok := model.(app.StateErrorModel)
require.Truef(t, ok, "%s", model)
})
}
34 changes: 19 additions & 15 deletions internal/app/statefiltered.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package app

import (
"fmt"

"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"

"github.com/hedhyw/json-log-viewer/internal/pkg/events"
"github.com/hedhyw/json-log-viewer/internal/pkg/source"
)

// StateFiltered is a state that shows filtered records.
type StateFiltered struct {
// StateFilteredModel is a state that shows filtered records.
type StateFilteredModel struct {
helper

previousState StateLoaded
previousState StateLoadedModel
table logsTableModel
logEntries source.LazyLogEntries

Expand All @@ -22,10 +24,10 @@ type StateFiltered struct {

func newStateFiltered(
application Application,
previousState StateLoaded,
previousState StateLoadedModel,
filterText string,
) StateFiltered {
return StateFiltered{
) StateFilteredModel {
return StateFilteredModel{
helper: helper{Application: application},

previousState: previousState,
Expand All @@ -37,7 +39,7 @@ func newStateFiltered(
}

// Init initializes component. It implements tea.Model.
func (s StateFiltered) Init() tea.Cmd {
func (s StateFilteredModel) Init() tea.Cmd {
return func() tea.Msg {
return events.LogEntriesLoadedMsg(
s.previousState.logEntries.Filter(s.filterText),
Expand All @@ -46,14 +48,16 @@ func (s StateFiltered) Init() tea.Cmd {
}

// View renders component. It implements tea.Model.
func (s StateFiltered) View() string {
footer := s.Application.FooterStyle.Render(" filtered by: " + s.filterText)
func (s StateFilteredModel) View() string {
footer := s.Application.FooterStyle.Render(
fmt.Sprintf("filtered %d by: %s", len(s.logEntries), s.filterText),
)

return s.BaseStyle.Render(s.table.View()) + "\n" + footer
}

// Update handles events. It implements tea.Model.
func (s StateFiltered) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (s StateFilteredModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmdBatch []tea.Cmd

s.helper = s.helper.Update(msg)
Expand Down Expand Up @@ -86,7 +90,7 @@ func (s StateFiltered) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return s, tea.Batch(cmdBatch...)
}

func (s StateFiltered) handleLogEntriesLoadedMsg(
func (s StateFilteredModel) handleLogEntriesLoadedMsg(
msg events.LogEntriesLoadedMsg,
) (tea.Model, tea.Cmd) {
s.logEntries = source.LazyLogEntries(msg)
Expand All @@ -95,7 +99,7 @@ func (s StateFiltered) handleLogEntriesLoadedMsg(
return s, s.table.Init()
}

func (s StateFiltered) handleFilterKeyClickedMsg() (tea.Model, tea.Cmd) {
func (s StateFilteredModel) handleFilterKeyClickedMsg() (tea.Model, tea.Cmd) {
state := newStateFiltering(
s.Application,
s.previousState,
Expand All @@ -104,15 +108,15 @@ func (s StateFiltered) handleFilterKeyClickedMsg() (tea.Model, tea.Cmd) {
return initializeModel(state)
}

func (s StateFiltered) handleRequestOpenJSON() (tea.Model, tea.Cmd) {
func (s StateFilteredModel) handleRequestOpenJSON() (tea.Model, tea.Cmd) {
if len(s.logEntries) == 0 {
return s, events.BackKeyClicked
}

return s, events.OpenJSONRowRequested(s.logEntries, s.table.Cursor())
}

func (s StateFiltered) withApplication(application Application) (state, tea.Cmd) {
func (s StateFilteredModel) withApplication(application Application) (stateModel, tea.Cmd) {
s.Application = application

var cmd tea.Cmd
Expand All @@ -122,6 +126,6 @@ func (s StateFiltered) withApplication(application Application) (state, tea.Cmd)
}

// String implements fmt.Stringer.
func (s StateFiltered) String() string {
func (s StateFilteredModel) String() string {
return modelValue(s)
}
17 changes: 9 additions & 8 deletions internal/app/statefiltered_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestStateFiltered(t *testing.T) {
lines := strings.Split(model.View(), "\n")
assert.Contains(t, lines[len(lines)-1], ">")

_, ok := model.(app.StateFiltering)
_, ok := model.(app.StateFilteringModel)
assert.Truef(t, ok, "%s", model)

// Write term to search by.
Expand All @@ -54,10 +54,11 @@ func TestStateFiltered(t *testing.T) {
Type: tea.KeyEnter,
})

_, ok = model.(app.StateFiltered)
_, ok = model.(app.StateFilteredModel)
if assert.Truef(t, ok, "%s", model) {
rendered = model.View()
assert.Contains(t, rendered, termIncluded)
assert.Contains(t, rendered, "filtered 1 by: "+termIncluded)
assert.NotContains(t, rendered, termExcluded)
}

Expand All @@ -69,7 +70,7 @@ func TestStateFiltered(t *testing.T) {
Runes: []rune{'f'},
})

_, ok := model.(app.StateFiltering)
_, ok := model.(app.StateFilteringModel)
assert.Truef(t, ok, "%s", model)
})

Expand All @@ -80,14 +81,14 @@ func TestStateFiltered(t *testing.T) {
Type: tea.KeyEnter,
})

_, ok := model.(app.StateViewRow)
_, ok := model.(app.StateViewRowModel)
assert.Truef(t, ok, "%s", model)

model = handleUpdate(model, tea.KeyMsg{
Type: tea.KeyEsc,
})

_, ok = model.(app.StateFiltered)
_, ok = model.(app.StateFilteredModel)
assert.Truef(t, ok, "%s", model)
})

Expand All @@ -96,7 +97,7 @@ func TestStateFiltered(t *testing.T) {

model := handleUpdate(model, events.ErrorOccuredMsg{Err: getTestError()})

_, ok := model.(app.StateError)
_, ok := model.(app.StateErrorModel)
assert.Truef(t, ok, "%s", model)
})

Expand All @@ -107,7 +108,7 @@ func TestStateFiltered(t *testing.T) {
Type: tea.KeyUp,
})

_, ok = model.(app.StateFiltered)
_, ok = model.(app.StateFilteredModel)
assert.Truef(t, ok, "%s", model)
})

Expand All @@ -118,7 +119,7 @@ func TestStateFiltered(t *testing.T) {
Type: tea.KeyEsc,
})

_, ok := model.(app.StateLoaded)
_, ok := model.(app.StateLoadedModel)
assert.Truef(t, ok, "%s", model)
})

Expand Down
24 changes: 12 additions & 12 deletions internal/app/statefiltering.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import (
"github.com/hedhyw/json-log-viewer/internal/pkg/events"
)

// StateFiltering is a state to prompt for filter term.
type StateFiltering struct {
// StateFilteringModel is a state to prompt for filter term.
type StateFilteringModel struct {
helper

previousState StateLoaded
previousState StateLoadedModel
table logsTableModel

textInput textinput.Model
Expand All @@ -21,12 +21,12 @@ type StateFiltering struct {

func newStateFiltering(
application Application,
previousState StateLoaded,
) StateFiltering {
previousState StateLoadedModel,
) StateFilteringModel {
textInput := textinput.New()
textInput.Focus()

return StateFiltering{
return StateFilteringModel{
helper: helper{Application: application},

previousState: previousState,
Expand All @@ -38,17 +38,17 @@ func newStateFiltering(
}

// Init initializes component. It implements tea.Model.
func (s StateFiltering) Init() tea.Cmd {
func (s StateFilteringModel) Init() tea.Cmd {
return nil
}

// View renders component. It implements tea.Model.
func (s StateFiltering) View() string {
func (s StateFilteringModel) View() string {
return s.BaseStyle.Render(s.table.View()) + "\n" + s.textInput.View()
}

// Update handles events. It implements tea.Model.
func (s StateFiltering) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (s StateFilteringModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmdBatch []tea.Cmd

s.helper = s.helper.Update(msg)
Expand Down Expand Up @@ -76,15 +76,15 @@ func (s StateFiltering) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return s, tea.Batch(cmdBatch...)
}

func (s StateFiltering) handleKeyMsg(msg tea.KeyMsg) tea.Cmd {
func (s StateFilteringModel) handleKeyMsg(msg tea.KeyMsg) tea.Cmd {
if len(msg.Runes) == 1 {
return nil
}

return s.helper.handleKeyMsg(msg)
}

func (s StateFiltering) handleEnterKeyClickedMsg() (tea.Model, tea.Cmd) {
func (s StateFilteringModel) handleEnterKeyClickedMsg() (tea.Model, tea.Cmd) {
if s.textInput.Value() == "" {
return s, events.BackKeyClicked
}
Expand All @@ -97,6 +97,6 @@ func (s StateFiltering) handleEnterKeyClickedMsg() (tea.Model, tea.Cmd) {
}

// String implements fmt.Stringer.
func (s StateFiltering) String() string {
func (s StateFilteringModel) String() string {
return modelValue(s)
}
Loading

0 comments on commit 6b8948a

Please sign in to comment.