mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
convert services panel to use new struct
This commit is contained in:
parent
b80c8edcd0
commit
79a58c8d48
12 changed files with 194 additions and 289 deletions
|
|
@ -41,7 +41,6 @@ type DockerCommand struct {
|
||||||
ContainerMutex sync.Mutex
|
ContainerMutex sync.Mutex
|
||||||
ServiceMutex sync.Mutex
|
ServiceMutex sync.Mutex
|
||||||
|
|
||||||
Services []*Service
|
|
||||||
Containers []*Container
|
Containers []*Container
|
||||||
// DisplayContainers is the array of containers we will display in the containers panel. If Gui.ShowAllContainers is false, this will only be those containers which aren't based on a service. This reduces clutter and duplication in the UI
|
// DisplayContainers is the array of containers we will display in the containers panel. If Gui.ShowAllContainers is false, this will only be those containers which aren't based on a service. This reduces clutter and duplication in the UI
|
||||||
DisplayContainers []*Container
|
DisplayContainers []*Container
|
||||||
|
|
@ -174,16 +173,13 @@ func (c *DockerCommand) createClientStatMonitor(container *Container) {
|
||||||
container.MonitoringStats = false
|
container.MonitoringStats = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshContainersAndServices returns a slice of docker containers
|
func (c *DockerCommand) RefreshContainersAndServices(currentServices []*Service) ([]*Container, []*Service, error) {
|
||||||
func (c *DockerCommand) RefreshContainersAndServices() error {
|
|
||||||
c.ServiceMutex.Lock()
|
c.ServiceMutex.Lock()
|
||||||
defer c.ServiceMutex.Unlock()
|
defer c.ServiceMutex.Unlock()
|
||||||
|
|
||||||
currentServices := c.Services
|
|
||||||
|
|
||||||
containers, err := c.GetContainers()
|
containers, err := c.GetContainers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var services []*Service
|
var services []*Service
|
||||||
|
|
@ -193,7 +189,7 @@ func (c *DockerCommand) RefreshContainersAndServices() error {
|
||||||
} else {
|
} else {
|
||||||
services, err = c.GetServices()
|
services, err = c.GetServices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,27 +200,12 @@ func (c *DockerCommand) RefreshContainersAndServices() error {
|
||||||
displayContainers = c.obtainStandaloneContainers(containers, services)
|
displayContainers = c.obtainStandaloneContainers(containers, services)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort services first by whether they have a linked container, and second by alphabetical order
|
|
||||||
sort.Slice(services, func(i, j int) bool {
|
|
||||||
if services[i].Container != nil && services[j].Container == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if services[i].Container == nil && services[j].Container != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return services[i].Name < services[j].Name
|
|
||||||
})
|
|
||||||
|
|
||||||
c.Containers = containers
|
c.Containers = containers
|
||||||
c.Services = services
|
|
||||||
c.Services = c.filterOutIgnoredServices(c.Services)
|
|
||||||
c.DisplayContainers = c.filterOutExited(displayContainers)
|
c.DisplayContainers = c.filterOutExited(displayContainers)
|
||||||
c.DisplayContainers = c.filterOutIgnoredContainers(c.DisplayContainers)
|
c.DisplayContainers = c.filterOutIgnoredContainers(c.DisplayContainers)
|
||||||
c.DisplayContainers = c.sortedContainers(c.DisplayContainers)
|
c.DisplayContainers = c.sortedContainers(c.DisplayContainers)
|
||||||
|
|
||||||
return nil
|
return c.DisplayContainers, services, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DockerCommand) assignContainersToServices(containers []*Container, services []*Service) {
|
func (c *DockerCommand) assignContainersToServices(containers []*Container, services []*Service) {
|
||||||
|
|
@ -262,14 +243,6 @@ func (c *DockerCommand) filterOutIgnoredContainers(containers []*Container) []*C
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DockerCommand) filterOutIgnoredServices(services []*Service) []*Service {
|
|
||||||
return lo.Filter(services, func(service *Service, _ int) bool {
|
|
||||||
return !lo.SomeBy(c.Config.UserConfig.Ignore, func(ignore string) bool {
|
|
||||||
return strings.Contains(service.Name, ignore)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// sortedContainers returns containers sorted by state if c.SortContainersByState is true (follows 1- running, 2- exited, 3- created)
|
// sortedContainers returns containers sorted by state if c.SortContainersByState is true (follows 1- running, 2- exited, 3- created)
|
||||||
// and sorted by name if c.SortContainersByState is false
|
// and sorted by name if c.SortContainersByState is false
|
||||||
func (c *DockerCommand) sortedContainers(containers []*Container) []*Container {
|
func (c *DockerCommand) sortedContainers(containers []*Container) []*Container {
|
||||||
|
|
|
||||||
|
|
@ -233,25 +233,27 @@ func (gui *Gui) refreshContainersAndServices() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep track of current service selected so that we can reposition our cursor if it moves position in the list
|
// keep track of current service selected so that we can reposition our cursor if it moves position in the list
|
||||||
sl := gui.State.Panels.Services.SelectedLine
|
originalSelectedLineIdx := gui.Panels.Services.selectedIdx
|
||||||
var selectedService *commands.Service
|
selectedService, isServiceSelected := gui.Panels.Services.list.TryGet(originalSelectedLineIdx)
|
||||||
if len(gui.DockerCommand.Services) > 0 {
|
|
||||||
selectedService = gui.DockerCommand.Services[sl]
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := gui.DockerCommand.RefreshContainersAndServices(); err != nil {
|
_, services, err := gui.DockerCommand.RefreshContainersAndServices(
|
||||||
|
gui.Panels.Services.list.GetAllItems(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gui.Panels.Services.SetItems(services)
|
||||||
|
|
||||||
// see if our selected service has moved
|
// see if our selected service has moved
|
||||||
if selectedService != nil {
|
if isServiceSelected {
|
||||||
for i, service := range gui.DockerCommand.Services {
|
for i, service := range gui.Panels.Services.list.GetItems() {
|
||||||
if service.ID == selectedService.ID {
|
if service.ID == selectedService.ID {
|
||||||
if i == sl {
|
if i == originalSelectedLineIdx {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
gui.State.Panels.Services.SelectedLine = i
|
gui.Panels.Services.setSelectedLineIdx(i)
|
||||||
gui.focusY(i, len(gui.DockerCommand.Services), gui.getServicesView())
|
gui.Panels.Services.Refocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,20 +265,18 @@ func (gui *Gui) refreshContainersAndServices() error {
|
||||||
gui.State.Panels.Containers.SelectedLine = len(gui.DockerCommand.DisplayContainers) - 1
|
gui.State.Panels.Containers.SelectedLine = len(gui.DockerCommand.DisplayContainers) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// doing the exact same thing for services
|
|
||||||
if len(gui.DockerCommand.Services) > 0 && gui.State.Panels.Services.SelectedLine == -1 {
|
|
||||||
gui.State.Panels.Services.SelectedLine = 0
|
|
||||||
}
|
|
||||||
if len(gui.DockerCommand.Services)-1 < gui.State.Panels.Services.SelectedLine {
|
|
||||||
gui.State.Panels.Services.SelectedLine = len(gui.DockerCommand.Services) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.renderContainersAndServices()
|
gui.renderContainersAndServices()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderContainersAndServices() {
|
func (gui *Gui) renderContainersAndServices() {
|
||||||
|
if gui.DockerCommand.InDockerComposeProject {
|
||||||
|
if err := gui.Panels.Services.RerenderList(); err != nil {
|
||||||
|
gui.ErrorChan <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gui.g.Update(func(g *gocui.Gui) error {
|
gui.g.Update(func(g *gocui.Gui) error {
|
||||||
containersView := gui.getContainersView()
|
containersView := gui.getContainersView()
|
||||||
containersView.Clear()
|
containersView.Clear()
|
||||||
|
|
@ -294,22 +294,6 @@ func (gui *Gui) renderContainersAndServices() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// doing the exact same thing for services
|
|
||||||
if !gui.DockerCommand.InDockerComposeProject {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
servicesView := gui.getServicesView()
|
|
||||||
servicesView.Clear()
|
|
||||||
isFocused = gui.g.CurrentView().Name() == "services"
|
|
||||||
list, err = utils.RenderList(gui.DockerCommand.Services, utils.IsFocused(isFocused))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprint(servicesView, list)
|
|
||||||
|
|
||||||
if servicesView == g.CurrentView() {
|
|
||||||
return gui.handleServiceSelect(g, servicesView)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,3 +98,10 @@ func (self *FilteredList[T]) GetItems() []T {
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *FilteredList[T]) GetAllItems() []T {
|
||||||
|
self.mutex.RLock()
|
||||||
|
defer self.mutex.RUnlock()
|
||||||
|
|
||||||
|
return self.allItems
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ type Gui struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Panels struct {
|
type Panels struct {
|
||||||
Images *SideListPanel[*commands.Image]
|
Images *SideListPanel[*commands.Image]
|
||||||
|
Services *SideListPanel[*commands.Service]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutexes struct {
|
type Mutexes struct {
|
||||||
|
|
@ -83,11 +84,6 @@ type Mutexes struct {
|
||||||
ViewStackMutex sync.Mutex
|
ViewStackMutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type servicePanelState struct {
|
|
||||||
SelectedLine int
|
|
||||||
ContextIndex int // for specifying if you are looking at logs/stats/config/etc
|
|
||||||
}
|
|
||||||
|
|
||||||
type containerPanelState struct {
|
type containerPanelState struct {
|
||||||
SelectedLine int
|
SelectedLine int
|
||||||
ContextIndex int // for specifying if you are looking at logs/stats/config/etc
|
ContextIndex int // for specifying if you are looking at logs/stats/config/etc
|
||||||
|
|
@ -113,7 +109,6 @@ type volumePanelState struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type panelStates struct {
|
type panelStates struct {
|
||||||
Services *servicePanelState
|
|
||||||
Containers *containerPanelState
|
Containers *containerPanelState
|
||||||
Menu *menuPanelState
|
Menu *menuPanelState
|
||||||
Main *mainPanelState
|
Main *mainPanelState
|
||||||
|
|
@ -168,7 +163,6 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
|
||||||
initialState := guiState{
|
initialState := guiState{
|
||||||
Platform: *oSCommand.Platform,
|
Platform: *oSCommand.Platform,
|
||||||
Panels: &panelStates{
|
Panels: &panelStates{
|
||||||
Services: &servicePanelState{SelectedLine: -1, ContextIndex: 0},
|
|
||||||
Containers: &containerPanelState{SelectedLine: -1, ContextIndex: 0},
|
Containers: &containerPanelState{SelectedLine: -1, ContextIndex: 0},
|
||||||
Volumes: &volumePanelState{SelectedLine: -1, ContextIndex: 0},
|
Volumes: &volumePanelState{SelectedLine: -1, ContextIndex: 0},
|
||||||
Menu: &menuPanelState{SelectedLine: 0},
|
Menu: &menuPanelState{SelectedLine: 0},
|
||||||
|
|
@ -266,15 +260,6 @@ func (gui *Gui) Run() error {
|
||||||
go gui.listenForEvents(ctx, throttledRefresh.Trigger)
|
go gui.listenForEvents(ctx, throttledRefresh.Trigger)
|
||||||
go gui.DockerCommand.MonitorContainerStats(ctx)
|
go gui.DockerCommand.MonitorContainerStats(ctx)
|
||||||
|
|
||||||
go func() {
|
|
||||||
throttledRefresh.Trigger()
|
|
||||||
|
|
||||||
gui.goEvery(time.Millisecond*30, gui.reRenderMain)
|
|
||||||
gui.goEvery(time.Millisecond*1000, gui.DockerCommand.UpdateContainerDetails)
|
|
||||||
gui.goEvery(time.Millisecond*1000, gui.checkForContextChange)
|
|
||||||
gui.goEvery(time.Millisecond*1000, gui.rerenderContainersAndServices)
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for err := range gui.ErrorChan {
|
for err := range gui.ErrorChan {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -297,7 +282,8 @@ func (gui *Gui) Run() error {
|
||||||
|
|
||||||
// TODO: see if we can avoid the circular dependency
|
// TODO: see if we can avoid the circular dependency
|
||||||
gui.Panels = Panels{
|
gui.Panels = Panels{
|
||||||
Images: gui.getImagePanel(),
|
Images: gui.getImagesPanel(),
|
||||||
|
Services: gui.getServicesPanel(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = gui.keybindings(g); err != nil {
|
if err = gui.keybindings(g); err != nil {
|
||||||
|
|
@ -316,6 +302,15 @@ func (gui *Gui) Run() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
throttledRefresh.Trigger()
|
||||||
|
|
||||||
|
gui.goEvery(time.Millisecond*30, gui.reRenderMain)
|
||||||
|
gui.goEvery(time.Millisecond*1000, gui.DockerCommand.UpdateContainerDetails)
|
||||||
|
gui.goEvery(time.Millisecond*1000, gui.checkForContextChange)
|
||||||
|
gui.goEvery(time.Millisecond*1000, gui.rerenderContainersAndServices)
|
||||||
|
}()
|
||||||
|
|
||||||
err = g.MainLoop()
|
err = g.MainLoop()
|
||||||
if err == gocui.ErrQuit {
|
if err == gocui.ErrQuit {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,47 @@ import (
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (gui *Gui) getImagesPanel() *SideListPanel[*commands.Image] {
|
||||||
|
noneLabel := "<none>"
|
||||||
|
|
||||||
|
return &SideListPanel[*commands.Image]{
|
||||||
|
contextKeyPrefix: "images",
|
||||||
|
ListPanel: ListPanel[*commands.Image]{
|
||||||
|
list: NewFilteredList[*commands.Image](),
|
||||||
|
view: gui.Views.Images,
|
||||||
|
},
|
||||||
|
contextIdx: 0,
|
||||||
|
noItemsMessge: gui.Tr.NoImages,
|
||||||
|
gui: gui.intoInterface(),
|
||||||
|
contexts: []ContextConfig[*commands.Image]{
|
||||||
|
{
|
||||||
|
key: "config",
|
||||||
|
title: gui.Tr.ConfigTitle,
|
||||||
|
render: func(image *commands.Image) error {
|
||||||
|
return gui.renderImageConfig(image)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getSearchStrings: func(image *commands.Image) []string {
|
||||||
|
return []string{image.Name, image.Tag}
|
||||||
|
},
|
||||||
|
getContextCacheKey: func(image *commands.Image) string {
|
||||||
|
return image.ID
|
||||||
|
},
|
||||||
|
sort: func(a *commands.Image, b *commands.Image) bool {
|
||||||
|
if a.Name == noneLabel && b.Name != noneLabel {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Name != noneLabel && b.Name == noneLabel {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Name < b.Name
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderImageConfig(image *commands.Image) error {
|
func (gui *Gui) renderImageConfig(image *commands.Image) error {
|
||||||
return gui.T.NewTask(func(stop chan struct{}) {
|
return gui.T.NewTask(func(stop chan struct{}) {
|
||||||
padding := 10
|
padding := 10
|
||||||
|
|
@ -53,7 +94,7 @@ func (gui *Gui) refreshStateImages() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: think about also re-filtering/sorting
|
// TODO: think about also re-filtering/sorting
|
||||||
gui.Panels.Images.list.SetItems(images)
|
gui.Panels.Images.SetItems(images)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -363,14 +363,14 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
ViewName: "services",
|
ViewName: "services",
|
||||||
Key: '[',
|
Key: '[',
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: gui.handleServicesPrevContext,
|
Handler: wrappedHandler(gui.Panels.Services.OnPrevContext),
|
||||||
Description: gui.Tr.PreviousContext,
|
Description: gui.Tr.PreviousContext,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "services",
|
ViewName: "services",
|
||||||
Key: ']',
|
Key: ']',
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: gui.handleServicesNextContext,
|
Handler: wrappedHandler(gui.Panels.Services.OnNextContext),
|
||||||
Description: gui.Tr.NextContext,
|
Description: gui.Tr.NextContext,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -584,7 +584,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
onClick func(*gocui.Gui, *gocui.View) error
|
onClick func(*gocui.Gui, *gocui.View) error
|
||||||
}{
|
}{
|
||||||
"menu": {onKeyUpPress: gui.handleMenuPrevLine, onKeyDownPress: gui.handleMenuNextLine, onClick: gui.handleMenuClick},
|
"menu": {onKeyUpPress: gui.handleMenuPrevLine, onKeyDownPress: gui.handleMenuNextLine, onClick: gui.handleMenuClick},
|
||||||
"services": {onKeyUpPress: gui.handleServicesPrevLine, onKeyDownPress: gui.handleServicesNextLine, onClick: gui.handleServicesClick},
|
"services": {onKeyUpPress: wrappedHandler(gui.Panels.Services.OnPrevLine), onKeyDownPress: wrappedHandler(gui.Panels.Services.OnNextLine), onClick: wrappedHandler(gui.Panels.Services.OnClick)},
|
||||||
"containers": {onKeyUpPress: gui.handleContainersPrevLine, onKeyDownPress: gui.handleContainersNextLine, onClick: gui.handleContainersClick},
|
"containers": {onKeyUpPress: gui.handleContainersPrevLine, onKeyDownPress: gui.handleContainersNextLine, onClick: gui.handleContainersClick},
|
||||||
"images": {onKeyUpPress: wrappedHandler(gui.Panels.Images.OnPrevLine), onKeyDownPress: wrappedHandler(gui.Panels.Images.OnNextLine), onClick: wrappedHandler(gui.Panels.Images.OnClick)},
|
"images": {onKeyUpPress: wrappedHandler(gui.Panels.Images.OnPrevLine), onKeyDownPress: wrappedHandler(gui.Panels.Images.OnNextLine), onClick: wrappedHandler(gui.Panels.Images.OnClick)},
|
||||||
"volumes": {onKeyUpPress: gui.handleVolumesPrevLine, onKeyDownPress: gui.handleVolumesNextLine, onClick: gui.handleVolumesClick},
|
"volumes": {onKeyUpPress: gui.handleVolumesPrevLine, onKeyDownPress: gui.handleVolumesNextLine, onClick: gui.handleVolumesClick},
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,6 @@ func (gui *Gui) focusPointInView(view *gocui.View) {
|
||||||
listViews := map[string]listViewState{
|
listViews := map[string]listViewState{
|
||||||
"containers": {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.DockerCommand.DisplayContainers)},
|
"containers": {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.DockerCommand.DisplayContainers)},
|
||||||
"volumes": {selectedLine: gui.State.Panels.Volumes.SelectedLine, lineCount: len(gui.DockerCommand.Volumes)},
|
"volumes": {selectedLine: gui.State.Panels.Volumes.SelectedLine, lineCount: len(gui.DockerCommand.Volumes)},
|
||||||
"services": {selectedLine: gui.State.Panels.Services.SelectedLine, lineCount: len(gui.DockerCommand.Services)},
|
|
||||||
"menu": {selectedLine: gui.State.Panels.Menu.SelectedLine, lineCount: gui.State.MenuItemCount},
|
"menu": {selectedLine: gui.State.Panels.Menu.SelectedLine, lineCount: gui.State.MenuItemCount},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,6 +138,8 @@ func (gui *Gui) focusPointInView(view *gocui.View) {
|
||||||
switch view.Name() {
|
switch view.Name() {
|
||||||
case "images":
|
case "images":
|
||||||
gui.Panels.Images.Refocus()
|
gui.Panels.Images.Refocus()
|
||||||
|
case "services":
|
||||||
|
gui.Panels.Services.Refocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,11 @@ import (
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListPanel[T comparable] struct {
|
type ListPanel[T comparable] struct {
|
||||||
toColumns func(T) []string
|
|
||||||
|
|
||||||
selectedIdx int
|
selectedIdx int
|
||||||
list *FilteredList[T]
|
list *FilteredList[T]
|
||||||
view *gocui.View
|
view *gocui.View
|
||||||
|
|
@ -28,6 +25,14 @@ func (self *ListPanel[T]) setSelectedLineIdx(value int) {
|
||||||
self.selectedIdx = clampedValue
|
self.selectedIdx = clampedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ListPanel[T]) clampSelectedLineIdx() {
|
||||||
|
clamped := utils.Clamp(self.selectedIdx, 0, self.list.Len()-1)
|
||||||
|
|
||||||
|
if clamped != self.selectedIdx {
|
||||||
|
self.selectedIdx = clamped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// moves the cursor up or down by the given amount (up for negative values)
|
// moves the cursor up or down by the given amount (up for negative values)
|
||||||
func (self *ListPanel[T]) moveSelectedLine(delta int) {
|
func (self *ListPanel[T]) moveSelectedLine(delta int) {
|
||||||
self.setSelectedLineIdx(self.selectedIdx + delta)
|
self.setSelectedLineIdx(self.selectedIdx + delta)
|
||||||
|
|
@ -57,7 +62,8 @@ type SideListPanel[T comparable] struct {
|
||||||
|
|
||||||
// returns strings that can be filtered on
|
// returns strings that can be filtered on
|
||||||
getSearchStrings func(item T) []string
|
getSearchStrings func(item T) []string
|
||||||
getId func(item T) string
|
// this tells us whether we need to re-render to the main panel
|
||||||
|
getContextCacheKey func(item T) string
|
||||||
|
|
||||||
sort func(a, b T) bool
|
sort func(a, b T) bool
|
||||||
}
|
}
|
||||||
|
|
@ -86,54 +92,6 @@ func (gui *Gui) intoInterface() IGui {
|
||||||
return gui
|
return gui
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getImagePanel() *SideListPanel[*commands.Image] {
|
|
||||||
noneLabel := "<none>"
|
|
||||||
|
|
||||||
return &SideListPanel[*commands.Image]{
|
|
||||||
contextKeyPrefix: "images",
|
|
||||||
ListPanel: ListPanel[*commands.Image]{
|
|
||||||
toColumns: func(image *commands.Image) []string {
|
|
||||||
return []string{
|
|
||||||
image.Name,
|
|
||||||
image.Tag,
|
|
||||||
utils.FormatDecimalBytes(int(image.Image.Size)),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list: NewFilteredList[*commands.Image](),
|
|
||||||
view: gui.Views.Images,
|
|
||||||
},
|
|
||||||
contextIdx: 0,
|
|
||||||
noItemsMessge: gui.Tr.NoImages,
|
|
||||||
gui: gui.intoInterface(),
|
|
||||||
contexts: []ContextConfig[*commands.Image]{
|
|
||||||
{
|
|
||||||
key: "config",
|
|
||||||
title: gui.Tr.ConfigTitle,
|
|
||||||
render: func(image *commands.Image) error {
|
|
||||||
return gui.renderImageConfig(image)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
getSearchStrings: func(image *commands.Image) []string {
|
|
||||||
return []string{image.Name, image.Tag}
|
|
||||||
},
|
|
||||||
getId: func(image *commands.Image) string {
|
|
||||||
return image.ID
|
|
||||||
},
|
|
||||||
sort: func(a *commands.Image, b *commands.Image) bool {
|
|
||||||
if a.Name == noneLabel && b.Name != noneLabel {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Name != noneLabel && b.Name == noneLabel {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.Name < b.Name
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SideListPanel[T]) OnClick() error {
|
func (self *SideListPanel[T]) OnClick() error {
|
||||||
itemCount := self.list.Len()
|
itemCount := self.list.Len()
|
||||||
handleSelect := self.HandleSelect
|
handleSelect := self.HandleSelect
|
||||||
|
|
@ -154,7 +112,7 @@ func (self *SideListPanel[T]) HandleSelect() error {
|
||||||
|
|
||||||
self.Refocus()
|
self.Refocus()
|
||||||
|
|
||||||
key := self.contextKeyPrefix + "-" + self.getId(item) + "-" + self.contexts[self.contextIdx].key
|
key := self.contextKeyPrefix + "-" + self.getContextCacheKey(item) + "-" + self.contexts[self.contextIdx].key
|
||||||
if !self.gui.ShouldRefresh(key) {
|
if !self.gui.ShouldRefresh(key) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +183,12 @@ func (self *SideListPanel[T]) Refocus() {
|
||||||
self.gui.FocusY(self.selectedIdx, self.list.Len(), self.view)
|
self.gui.FocusY(self.selectedIdx, self.list.Len(), self.view)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideListPanel[T]) RerenderList() error {
|
func (self *SideListPanel[T]) SetItems(items []T) {
|
||||||
|
self.list.SetItems(items)
|
||||||
|
self.FilterAndSort()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *SideListPanel[T]) FilterAndSort() {
|
||||||
filterString := self.gui.FilterString(self.view)
|
filterString := self.gui.FilterString(self.view)
|
||||||
|
|
||||||
self.list.Filter(func(item T, index int) bool {
|
self.list.Filter(func(item T, index int) bool {
|
||||||
|
|
@ -248,10 +211,11 @@ func (self *SideListPanel[T]) RerenderList() error {
|
||||||
|
|
||||||
self.list.Sort(self.sort)
|
self.list.Sort(self.sort)
|
||||||
|
|
||||||
// TODO: use clamp?
|
self.clampSelectedLineIdx()
|
||||||
if self.list.Len()-1 < self.selectedIdx {
|
}
|
||||||
self.selectedIdx = self.list.Len() - 1
|
|
||||||
}
|
func (self *SideListPanel[T]) RerenderList() error {
|
||||||
|
self.FilterAndSort()
|
||||||
|
|
||||||
self.gui.Update(func() error {
|
self.gui.Update(func() error {
|
||||||
self.view.Clear()
|
self.view.Clear()
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ func (gui *Gui) onMainTabClick(tabIndex int) error {
|
||||||
gui.State.Panels.Project.ContextIndex = tabIndex
|
gui.State.Panels.Project.ContextIndex = tabIndex
|
||||||
return gui.handleProjectSelect(gui.g, gui.getProjectView())
|
return gui.handleProjectSelect(gui.g, gui.getProjectView())
|
||||||
case "services":
|
case "services":
|
||||||
gui.State.Panels.Services.ContextIndex = tabIndex
|
gui.Panels.Services.SetContextIndex(tabIndex)
|
||||||
return gui.handleServiceSelect(gui.g, gui.getServicesView())
|
return gui.Panels.Services.HandleSelect()
|
||||||
case "containers":
|
case "containers":
|
||||||
gui.State.Panels.Containers.ContextIndex = tabIndex
|
gui.State.Panels.Containers.ContextIndex = tabIndex
|
||||||
return gui.handleContainerSelect(gui.g, gui.getContainersView())
|
return gui.handleContainerSelect(gui.g, gui.getContainersView())
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func (gui *Gui) refreshProject() {
|
||||||
func (gui *Gui) getProjectName() string {
|
func (gui *Gui) getProjectName() string {
|
||||||
projectName := path.Base(gui.Config.ProjectDir)
|
projectName := path.Base(gui.Config.ProjectDir)
|
||||||
if gui.DockerCommand.InDockerComposeProject {
|
if gui.DockerCommand.InDockerComposeProject {
|
||||||
for _, service := range gui.DockerCommand.Services {
|
for _, service := range gui.Panels.Services.list.GetAllItems() {
|
||||||
container := service.Container
|
container := service.Container
|
||||||
if container != nil && container.DetailsLoaded() {
|
if container != nil && container.DetailsLoaded() {
|
||||||
return container.Details.Config.Labels["com.docker.compose.project"]
|
return container.Details.Config.Labels["com.docker.compose.project"]
|
||||||
|
|
|
||||||
|
|
@ -5,101 +5,89 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/go-errors/errors"
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// list panel functions
|
func (gui *Gui) getServicesPanel() *SideListPanel[*commands.Service] {
|
||||||
|
return &SideListPanel[*commands.Service]{
|
||||||
|
contextKeyPrefix: "services",
|
||||||
|
ListPanel: ListPanel[*commands.Service]{
|
||||||
|
list: NewFilteredList[*commands.Service](),
|
||||||
|
view: gui.Views.Services,
|
||||||
|
},
|
||||||
|
contextIdx: 0,
|
||||||
|
// TODO: i18n
|
||||||
|
noItemsMessge: "no service selected",
|
||||||
|
gui: gui.intoInterface(),
|
||||||
|
contexts: []ContextConfig[*commands.Service]{
|
||||||
|
{
|
||||||
|
key: "logs",
|
||||||
|
title: gui.Tr.LogsTitle,
|
||||||
|
render: gui.renderServiceLogs,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "stats",
|
||||||
|
title: gui.Tr.StatsTitle,
|
||||||
|
render: gui.renderServiceStats,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "container-env",
|
||||||
|
title: gui.Tr.ContainerEnvTitle,
|
||||||
|
render: gui.renderServiceContainerEnv,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "container-config",
|
||||||
|
title: gui.Tr.ContainerConfigTitle,
|
||||||
|
render: gui.renderServiceContainerConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "top",
|
||||||
|
title: gui.Tr.TopTitle,
|
||||||
|
render: gui.renderServiceTop,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getSearchStrings: func(service *commands.Service) []string {
|
||||||
|
// TODO: think about more things to search on
|
||||||
|
return []string{service.Name}
|
||||||
|
},
|
||||||
|
getContextCacheKey: func(service *commands.Service) string {
|
||||||
|
if service.Container == nil {
|
||||||
|
return service.ID
|
||||||
|
}
|
||||||
|
return service.ID + "-" + service.Container.ID + "-" + service.Container.Container.State
|
||||||
|
},
|
||||||
|
// sort services first by whether they have a linked container, and second by alphabetical order
|
||||||
|
sort: func(a *commands.Service, b *commands.Service) bool {
|
||||||
|
if a.Container != nil && b.Container == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) getServiceContexts() []string {
|
if a.Container == nil && b.Container != nil {
|
||||||
return []string{"logs", "stats", "container-env", "container-config", "top"}
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getServiceContextTitles() []string {
|
return a.Name < b.Name
|
||||||
return []string{
|
},
|
||||||
gui.Tr.LogsTitle,
|
|
||||||
gui.Tr.StatsTitle,
|
|
||||||
gui.Tr.ContainerEnvTitle,
|
|
||||||
gui.Tr.ContainerConfigTitle,
|
|
||||||
gui.Tr.TopTitle,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSelectedService() (*commands.Service, error) {
|
func (gui *Gui) renderServiceContainerConfig(service *commands.Service) error {
|
||||||
selectedLine := gui.State.Panels.Services.SelectedLine
|
if service.Container == nil {
|
||||||
if selectedLine == -1 {
|
return gui.renderStringMain(gui.Tr.NoContainer)
|
||||||
return &commands.Service{}, errors.New("no service selected")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.DockerCommand.Services[selectedLine], nil
|
return gui.renderContainerConfig(service.Container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesClick(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) renderServiceContainerEnv(service *commands.Service) error {
|
||||||
itemCount := len(gui.DockerCommand.Services)
|
if service.Container == nil {
|
||||||
handleSelect := gui.handleServiceSelect
|
return gui.renderStringMain(gui.Tr.NoContainer)
|
||||||
selectedLine := &gui.State.Panels.Services.SelectedLine
|
|
||||||
|
|
||||||
return gui.handleClick(v, itemCount, selectedLine, handleSelect)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleServiceSelect(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
service, err := gui.getSelectedService()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
containerID := ""
|
return gui.renderContainerEnv(service.Container)
|
||||||
if service.Container != nil {
|
|
||||||
containerID = service.Container.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.focusY(gui.State.Panels.Services.SelectedLine, len(gui.DockerCommand.Services), v)
|
|
||||||
|
|
||||||
key := "services-" + service.ID + "-" + containerID + "-" + gui.getServiceContexts()[gui.State.Panels.Services.ContextIndex]
|
|
||||||
if !gui.shouldRefresh(key) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mainView := gui.getMainView()
|
|
||||||
|
|
||||||
mainView.Tabs = gui.getServiceContextTitles()
|
|
||||||
mainView.TabIndex = gui.State.Panels.Services.ContextIndex
|
|
||||||
|
|
||||||
switch gui.getServiceContexts()[gui.State.Panels.Services.ContextIndex] {
|
|
||||||
case "logs":
|
|
||||||
if err := gui.renderServiceLogs(service); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "stats":
|
|
||||||
if err := gui.renderServiceStats(service); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "container-env":
|
|
||||||
if service.Container == nil {
|
|
||||||
return gui.renderString(gui.g, "main", gui.Tr.NoContainer)
|
|
||||||
}
|
|
||||||
if err := gui.renderContainerEnv(service.Container); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "container-config":
|
|
||||||
if service.Container == nil {
|
|
||||||
return gui.renderString(gui.g, "main", gui.Tr.NoContainer)
|
|
||||||
}
|
|
||||||
if err := gui.renderContainerConfig(service.Container); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "top":
|
|
||||||
if err := gui.renderServiceTop(service); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("Unknown context for services panel")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderServiceStats(service *commands.Service) error {
|
func (gui *Gui) renderServiceStats(service *commands.Service) error {
|
||||||
|
|
@ -135,54 +123,6 @@ func (gui *Gui) renderServiceLogs(service *commands.Service) error {
|
||||||
return gui.renderContainerLogsToMain(service.Container)
|
return gui.renderContainerLogsToMain(service.Container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesNextLine(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
if gui.popupPanelFocused() || gui.g.CurrentView() != v {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
panelState := gui.State.Panels.Services
|
|
||||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Services), false)
|
|
||||||
|
|
||||||
return gui.handleServiceSelect(gui.g, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleServicesPrevLine(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
if gui.popupPanelFocused() || gui.g.CurrentView() != v {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
panelState := gui.State.Panels.Services
|
|
||||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Services), true)
|
|
||||||
|
|
||||||
return gui.handleServiceSelect(gui.g, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleServicesNextContext(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
contexts := gui.getServiceContexts()
|
|
||||||
if gui.State.Panels.Services.ContextIndex >= len(contexts)-1 {
|
|
||||||
gui.State.Panels.Services.ContextIndex = 0
|
|
||||||
} else {
|
|
||||||
gui.State.Panels.Services.ContextIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = gui.handleServiceSelect(gui.g, v)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleServicesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
contexts := gui.getServiceContexts()
|
|
||||||
if gui.State.Panels.Services.ContextIndex <= 0 {
|
|
||||||
gui.State.Panels.Services.ContextIndex = len(contexts) - 1
|
|
||||||
} else {
|
|
||||||
gui.State.Panels.Services.ContextIndex--
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = gui.handleServiceSelect(gui.g, v)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type commandOption struct {
|
type commandOption struct {
|
||||||
description string
|
description string
|
||||||
command string
|
command string
|
||||||
|
|
@ -195,7 +135,7 @@ func (r *commandOption) GetDisplayStrings(isFocused bool) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceRemoveMenu(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceRemoveMenu(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +160,7 @@ func (gui *Gui) handleServiceRemoveMenu(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicePause(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicePause(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +172,7 @@ func (gui *Gui) handleServicePause(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceStop(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceStop(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +189,7 @@ func (gui *Gui) handleServiceStop(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceUp(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceUp(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +204,7 @@ func (gui *Gui) handleServiceUp(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceRestart(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceRestart(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -279,7 +219,7 @@ func (gui *Gui) handleServiceRestart(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceStart(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceStart(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +234,7 @@ func (gui *Gui) handleServiceStart(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +252,7 @@ func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceRenderLogsToMain(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceRenderLogsToMain(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +329,7 @@ func (gui *Gui) handleProjectDown(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServiceRestartMenu(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServiceRestartMenu(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -474,7 +414,7 @@ func (gui *Gui) createServiceCommandMenu(options []*commandOption, status string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesCustomCommand(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicesCustomCommand(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -518,7 +458,7 @@ func (gui *Gui) handleServicesBulkCommand(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesExecShell(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicesExecShell(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -532,7 +472,7 @@ func (gui *Gui) handleServicesExecShell(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesOpenInBrowserCommand(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicesOpenInBrowserCommand(g *gocui.Gui, v *gocui.View) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.Panels.Services.GetSelectedItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ func (gui *Gui) newLineFocused(v *gocui.View) error {
|
||||||
case "project":
|
case "project":
|
||||||
return gui.handleProjectSelect(gui.g, v)
|
return gui.handleProjectSelect(gui.g, v)
|
||||||
case "services":
|
case "services":
|
||||||
return gui.handleServiceSelect(gui.g, v)
|
return gui.Panels.Services.HandleSelect()
|
||||||
case "containers":
|
case "containers":
|
||||||
return gui.handleContainerSelect(gui.g, v)
|
return gui.handleContainerSelect(gui.g, v)
|
||||||
case "images":
|
case "images":
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue