Skip to content

Commit

Permalink
Merge pull request #48 from markusressel/feature/table-container-mult…
Browse files Browse the repository at this point in the history
…i-selection

Feature/table container multi selection
  • Loading branch information
markusressel authored Nov 4, 2024
2 parents 75e1e91 + 6291b38 commit 97722a9
Show file tree
Hide file tree
Showing 15 changed files with 459 additions and 40 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
module zfs-file-history

go 1.22.6
go 1.23

toolchain go1.23.1

require (
github.com/dustin/go-humanize v1.0.1
github.com/fsnotify/fsnotify v1.7.0
github.com/fsnotify/fsnotify v1.8.0
github.com/gdamore/tcell/v2 v2.7.4
github.com/kraudcloud/go-libzfs v0.0.0-20231123113403-200c58c27e62
github.com/mistifyio/go-zfs v2.1.1+incompatible
github.com/mitchellh/go-homedir v1.1.0
github.com/navidys/tvxwidgets v0.9.0
github.com/oklog/run v1.1.0
github.com/pterm/pterm v0.12.79
github.com/rivo/tview v0.0.0-20241016194538-c5e4fb24af13
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
Expand Down
16 changes: 6 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
Expand Down Expand Up @@ -101,10 +101,8 @@ github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5b
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
github.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4=
github.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo=
github.com/rivo/tview v0.0.0-20240728114935-65571ae51e71 h1:lU8yiVCOA/uS4fRto0Xxw2oUWVvJyAJBBJz8LhuhVys=
github.com/rivo/tview v0.0.0-20240728114935-65571ae51e71/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss=
github.com/rivo/tview v0.0.0-20241016194538-c5e4fb24af13 h1:SG5LUOAzLU9svb9HTLJI2WnLHQDEe86fXWJ4h2fQg0s=
github.com/rivo/tview v0.0.0-20241016194538-c5e4fb24af13/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss=
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592 h1:YIJ+B1hePP6AgynC5TcqpO0H9k3SSoZa2BGyL6vDUzM=
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
Expand Down Expand Up @@ -152,8 +150,6 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
Expand Down Expand Up @@ -200,8 +196,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
4 changes: 4 additions & 0 deletions internal/data/file_browser_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ type FileBrowserEntry struct {
DiffState diff_state.DiffState
}

func (entry FileBrowserEntry) TableRowId() string {
return entry.GetRealPath()
}

func (entry *FileBrowserEntry) Equal(e FileBrowserEntry) bool {
return entry.GetRealPath() == e.GetRealPath()
}
Expand Down
4 changes: 4 additions & 0 deletions internal/data/snapshot_browser_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ type SnapshotBrowserEntry struct {
Snapshot *zfs.Snapshot
DiffState diff_state.DiffState
}

func (s SnapshotBrowserEntry) TableRowId() string {
return s.Snapshot.Path
}
2 changes: 1 addition & 1 deletion internal/ui/dialog/delete_file_dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"golang.org/x/exp/slices"
"slices"
"zfs-file-history/internal/data"
"zfs-file-history/internal/ui/util"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/dialog/delete_snapshot_dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"golang.org/x/exp/slices"
"slices"
"zfs-file-history/internal/data"
"zfs-file-history/internal/ui/util"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/dialog/file_action_dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"golang.org/x/exp/slices"
"os/exec"
"slices"
"zfs-file-history/internal/data"
"zfs-file-history/internal/data/diff_state"
"zfs-file-history/internal/ui/util"
Expand Down
3 changes: 2 additions & 1 deletion internal/ui/dialog/help_dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (p *HelpPage) createLayout() {
{Key: "down, j", Value: "Moves cursor down"},
{Key: "left, h", Value: "Opens parent directory"},
{Key: "right", Value: "Enters selected directory"},
{Key: "space", Value: "Toggle Multi-Selection"},
{Key: "enter", Value: "Opens file action dialog"},
{Key: "d", Value: "Delete selection"},
{Key: "tab, shift+tab", Value: "Cycles window focus"},
Expand Down Expand Up @@ -71,7 +72,7 @@ func (p *HelpPage) createLayout() {
}
}

p.layout = createModal(" Help ", helpTable, 60, 13)
p.layout = createModal(" Help ", helpTable, 60, 14)
}

func (p *HelpPage) GetLayout() *tview.Flex {
Expand Down
177 changes: 177 additions & 0 deletions internal/ui/dialog/snapshot_multi_action_dialog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package dialog

import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"zfs-file-history/internal/data"
"zfs-file-history/internal/ui/util"
)

const (
MultiSnapshotActionDialogPage util.Page = "MultiSnapshotActionDialog"

MultiSnapshotDialogClearSelectionActionId DialogActionId = iota
MultiSnapshotDialogDestroySnapshotActionId
MultiSnapshotDialogDestroySnapshotRecursivelyActionId
)

type MultiSnapshotActionDialog struct {
application *tview.Application
snapshots []*data.SnapshotBrowserEntry
layout *tview.Flex
actionChannel chan DialogActionId
}

func NewMultiSnapshotActionDialog(application *tview.Application, snapshots []*data.SnapshotBrowserEntry) *MultiSnapshotActionDialog {
dialog := &MultiSnapshotActionDialog{
application: application,
snapshots: snapshots,
actionChannel: make(chan DialogActionId),
}

dialog.createLayout()

return dialog
}

func (d *MultiSnapshotActionDialog) createLayout() {
dialogTitle := " Select Action "

snapshotNames := make([]string, 0)
for _, snapshot := range d.snapshots {
snapshotNames = append(snapshotNames, snapshot.Snapshot.Name)
}

textDescription := fmt.Sprintf("What do you want to do with '%v'?", snapshotNames)
textDescriptionView := tview.NewTextView().SetText(textDescription)

optionTable := tview.NewTable()
optionTable.SetSelectable(true, false)
optionTable.Select(0, 0)

dialogOptions := []*DialogOption{
{
Id: MultiSnapshotDialogDestroySnapshotActionId,
Name: fmt.Sprintf("Destroy all"),
},
{
Id: MultiSnapshotDialogDestroySnapshotRecursivelyActionId,
Name: fmt.Sprintf("Destroy all (recursive)"),
},
{
Id: MultiSnapshotDialogClearSelectionActionId,
Name: fmt.Sprintf("Clear Selection"),
},
{
Id: DialogCloseActionId,
Name: "Close",
},
}

optionTable.SetMouseCapture(func(action tview.MouseAction, event *tcell.EventMouse) (tview.MouseAction, *tcell.EventMouse) {
switch action {
case tview.MouseLeftDoubleClick:
go func() {
row, _ := optionTable.GetSelection()
dialogOption := dialogOptions[row]
d.selectAction(dialogOption)
d.application.Draw()
}()
return action, nil
}
return action, event
})

_, rows := 1, len(dialogOptions)
fileIndex := 0
for row := 0; row < rows; row++ {
columnTitle := dialogOptions[row]

var cellColor = tcell.ColorWhite
var cellText string
var cellAlignment = tview.AlignLeft
var cellExpansion = 1

cellText = columnTitle.Name

optionTable.SetCell(row, 0,
tview.NewTableCell(cellText).
SetTextColor(cellColor).
SetAlign(cellAlignment).
SetExpansion(cellExpansion),
)
fileIndex = (fileIndex + 1) % rows
}

dialogContent := tview.NewFlex().SetDirection(tview.FlexRow)
dialogContent.AddItem(textDescriptionView, 0, 1, false)
dialogContent.AddItem(optionTable, 0, 1, true)

dialog := createModal(dialogTitle, dialogContent, 50, 10)
dialog.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEscape {
d.Close()
return nil
} else if event.Key() == tcell.KeyEnter {
row, _ := optionTable.GetSelection()
dialogOption := dialogOptions[row]
d.selectAction(dialogOption)
return nil
}
return event
})
d.layout = dialog
}

func (d *MultiSnapshotActionDialog) GetName() string {
return string(MultiSnapshotActionDialogPage)
}

func (d *MultiSnapshotActionDialog) GetLayout() *tview.Flex {
return d.layout
}

func (d *MultiSnapshotActionDialog) GetActionChannel() <-chan DialogActionId {
return d.actionChannel
}

func (d *MultiSnapshotActionDialog) Close() {
go func() {
d.actionChannel <- DialogCloseActionId
}()
}

func (d *MultiSnapshotActionDialog) selectAction(option *DialogOption) {
switch option.Id {
case MultiSnapshotDialogClearSelectionActionId:
d.ClearSelection()
case MultiSnapshotDialogDestroySnapshotActionId:
d.DestroyAllSnapshots()
case MultiSnapshotDialogDestroySnapshotRecursivelyActionId:
d.DestroyAllSnapshotsRecursively()
case DialogCloseActionId:
d.Close()
}
}

func (d MultiSnapshotActionDialog) ClearSelection() {
go func() {
d.actionChannel <- DialogCloseActionId
d.actionChannel <- MultiSnapshotDialogClearSelectionActionId
}()
}

func (d *MultiSnapshotActionDialog) DestroyAllSnapshots() {
go func() {
d.actionChannel <- DialogCloseActionId
d.actionChannel <- MultiSnapshotDialogDestroySnapshotActionId
}()
}

func (d *MultiSnapshotActionDialog) DestroyAllSnapshotsRecursively() {
go func() {
d.actionChannel <- DialogCloseActionId
d.actionChannel <- MultiSnapshotDialogDestroySnapshotRecursivelyActionId
}()
}
2 changes: 1 addition & 1 deletion internal/ui/file_browser/file_browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"github.com/dustin/go-humanize"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"golang.org/x/exp/slices"
"os"
path2 "path"
"slices"
"sort"
"strings"
"time"
Expand Down
Loading

0 comments on commit 97722a9

Please sign in to comment.