You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.6 KiB
Go
192 lines
5.6 KiB
Go
package gui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/jesseduffield/gocui"
|
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
|
"github.com/jesseduffield/lazydocker/pkg/gui/presentation"
|
|
"github.com/jesseduffield/lazydocker/pkg/gui/types"
|
|
"github.com/jesseduffield/lazydocker/pkg/tasks"
|
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
func (gui *Gui) getVolumesPanel() *panels.SideListPanel[*commands.Volume] {
|
|
return &panels.SideListPanel[*commands.Volume]{
|
|
ContextState: &panels.ContextState[*commands.Volume]{
|
|
GetMainTabs: func() []panels.MainTab[*commands.Volume] {
|
|
return []panels.MainTab[*commands.Volume]{
|
|
{
|
|
Key: "config",
|
|
Title: gui.Tr.ConfigTitle,
|
|
Render: gui.renderVolumeConfig,
|
|
},
|
|
}
|
|
},
|
|
GetItemContextCacheKey: func(volume *commands.Volume) string {
|
|
return "volumes-" + volume.Name
|
|
},
|
|
},
|
|
ListPanel: panels.ListPanel[*commands.Volume]{
|
|
List: panels.NewFilteredList[*commands.Volume](),
|
|
View: gui.Views.Volumes,
|
|
},
|
|
NoItemsMessage: gui.Tr.NoVolumes,
|
|
Gui: gui.intoInterface(),
|
|
// we're sorting these volumes based on whether they have labels defined,
|
|
// because those are the ones you typically care about.
|
|
// Within that, we also sort them alphabetically
|
|
Sort: func(a *commands.Volume, b *commands.Volume) bool {
|
|
if len(a.Volume.Labels) == 0 && len(b.Volume.Labels) > 0 {
|
|
return false
|
|
}
|
|
if len(a.Volume.Labels) > 0 && len(b.Volume.Labels) == 0 {
|
|
return true
|
|
}
|
|
return a.Name < b.Name
|
|
},
|
|
GetTableCells: presentation.GetVolumeDisplayStrings,
|
|
}
|
|
}
|
|
|
|
func (gui *Gui) renderVolumeConfig(volume *commands.Volume) tasks.TaskFunc {
|
|
return gui.NewSimpleRenderStringTask(func() string { return gui.volumeConfigStr(volume) })
|
|
}
|
|
|
|
func (gui *Gui) volumeConfigStr(volume *commands.Volume) string {
|
|
padding := 15
|
|
output := ""
|
|
output += utils.WithPadding("Name: ", padding) + volume.Name + "\n"
|
|
output += utils.WithPadding("Driver: ", padding) + volume.Volume.Driver + "\n"
|
|
output += utils.WithPadding("Scope: ", padding) + volume.Volume.Scope + "\n"
|
|
output += utils.WithPadding("Mountpoint: ", padding) + volume.Volume.Mountpoint + "\n"
|
|
output += utils.WithPadding("Labels: ", padding) + utils.FormatMap(padding, volume.Volume.Labels) + "\n"
|
|
output += utils.WithPadding("Options: ", padding) + utils.FormatMap(padding, volume.Volume.Options) + "\n"
|
|
|
|
output += utils.WithPadding("Status: ", padding)
|
|
if volume.Volume.Status != nil {
|
|
output += "\n"
|
|
for k, v := range volume.Volume.Status {
|
|
output += utils.FormatMapItem(padding, k, v)
|
|
}
|
|
} else {
|
|
output += "n/a"
|
|
}
|
|
|
|
if volume.Volume.UsageData != nil {
|
|
output += utils.WithPadding("RefCount: ", padding) + fmt.Sprintf("%d", volume.Volume.UsageData.RefCount) + "\n"
|
|
output += utils.WithPadding("Size: ", padding) + utils.FormatBinaryBytes(int(volume.Volume.UsageData.Size)) + "\n"
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
func (gui *Gui) reloadVolumes() error {
|
|
if err := gui.refreshStateVolumes(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return gui.Panels.Volumes.RerenderList()
|
|
}
|
|
|
|
func (gui *Gui) refreshStateVolumes() error {
|
|
volumes, err := gui.DockerCommand.RefreshVolumes()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
gui.Panels.Volumes.SetItems(volumes)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (gui *Gui) handleVolumesRemoveMenu(g *gocui.Gui, v *gocui.View) error {
|
|
volume, err := gui.Panels.Volumes.GetSelectedItem()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
type removeVolumeOption struct {
|
|
description string
|
|
command string
|
|
force bool
|
|
}
|
|
|
|
options := []*removeVolumeOption{
|
|
{
|
|
description: gui.Tr.Remove,
|
|
command: utils.WithShortSha("docker volume rm " + volume.Name),
|
|
force: false,
|
|
},
|
|
{
|
|
description: gui.Tr.ForceRemove,
|
|
command: utils.WithShortSha("docker volume rm --force " + volume.Name),
|
|
force: true,
|
|
},
|
|
}
|
|
|
|
menuItems := lo.Map(options, func(option *removeVolumeOption, _ int) *types.MenuItem {
|
|
return &types.MenuItem{
|
|
LabelColumns: []string{option.description, color.New(color.FgRed).Sprint(option.command)},
|
|
OnPress: func() error {
|
|
return gui.WithWaitingStatus(gui.Tr.RemovingStatus, func() error {
|
|
if err := volume.Remove(option.force); err != nil {
|
|
return gui.createErrorPanel(err.Error())
|
|
}
|
|
return nil
|
|
})
|
|
},
|
|
}
|
|
})
|
|
|
|
return gui.Menu(CreateMenuOptions{
|
|
Title: "",
|
|
Items: menuItems,
|
|
})
|
|
}
|
|
|
|
func (gui *Gui) handlePruneVolumes() error {
|
|
return gui.createConfirmationPanel(gui.Tr.Confirm, gui.Tr.ConfirmPruneVolumes, func(g *gocui.Gui, v *gocui.View) error {
|
|
return gui.WithWaitingStatus(gui.Tr.PruningStatus, func() error {
|
|
err := gui.DockerCommand.PruneVolumes()
|
|
if err != nil {
|
|
return gui.createErrorPanel(err.Error())
|
|
}
|
|
return nil
|
|
})
|
|
}, nil)
|
|
}
|
|
|
|
func (gui *Gui) handleVolumesCustomCommand(g *gocui.Gui, v *gocui.View) error {
|
|
volume, err := gui.Panels.Volumes.GetSelectedItem()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{
|
|
Volume: volume,
|
|
})
|
|
|
|
customCommands := gui.Config.UserConfig.CustomCommands.Volumes
|
|
|
|
return gui.createCustomCommandMenu(customCommands, commandObject)
|
|
}
|
|
|
|
func (gui *Gui) handleVolumesBulkCommand(g *gocui.Gui, v *gocui.View) error {
|
|
baseBulkCommands := []config.CustomCommand{
|
|
{
|
|
Name: gui.Tr.PruneVolumes,
|
|
InternalFunction: gui.handlePruneVolumes,
|
|
},
|
|
}
|
|
|
|
bulkCommands := append(baseBulkCommands, gui.Config.UserConfig.BulkCommands.Volumes...)
|
|
commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{})
|
|
|
|
return gui.createBulkCommandMenu(bulkCommands, commandObject)
|
|
}
|