package main import ( "fmt" "strconv" "strings" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/widget" ) func createDockerTab(server outputStruct) *container.AppTabs { dockerTabs := container.NewAppTabs() dockerTabs.Append(container.NewTabItem("docker ps", createDockerPsTab(server))) dockerTabs.Append(container.NewTabItem("docker stats", createDockerStats(server))) dockerTabs.Append(container.NewTabItem("supervisor status", createDockerSupervisorTab(server))) return dockerTabs } // type dockerStats struct { // BlockIO string `json:"BlockIO"` // CPUPerc string `json:"CPUPerc"` // Container string `json:"Container"` // ID string `json:"ID"` // MemPerc string `json:"MemPerc"` // MemUsage string `json:"MemUsage"` // Name string `json:"Name"` // NetIO string `json:"NetIO"` // PIDs string `json:"PIDs"` // } func shortId(id string) string { if len(id) > 12 { return id[:12] } return id } func parsePercent(percent string) float64 { var val float64 fmt.Sscanf(percent, "%f%%", &val) return val } func createDockerStats(server outputStruct) *fyne.Container { // Заголовки таблицы headers := []string{"CONTAINER", "NAME", "CPU %", "MEM %", "MEM USAGE", "NET I/O", "BLOCK I/O", "PIDs"} // Данные stats := server.DockerStats // Создаю таблицу table := widget.NewTable( func() (rows int, cols int) { return len(stats) + 1, len(headers) }, func() fyne.CanvasObject { label := widget.NewLabel("Template") label.Selectable = true label.Alignment = fyne.TextAlignCenter return label }, func(id widget.TableCellID, obj fyne.CanvasObject) { label := obj.(*widget.Label) // Заголовки if id.Row == 0 { label.SetText(headers[id.Col]) label.TextStyle.Bold = true label.Alignment = fyne.TextAlignCenter } // Данные row := id.Row - 1 // if row < len(stats) { if len(stats) > 0 && row >= 0 && row < len(stats) { switch id.Col { case 0: // label.SetText(shortId(stats[row].Container)) label.SetText(stats[row].Container) case 1: label.SetText(stats[row].Name) case 2: label.SetText(stats[row].CPUPerc) case 3: label.SetText(stats[row].MemPerc) if memPercent := parsePercent(stats[row].MemPerc); memPercent > 50 { label.Importance = widget.HighImportance } case 4: label.SetText(stats[row].MemUsage) case 5: label.SetText(stats[row].NetIO) case 6: label.SetText(stats[row].BlockIO) case 7: label.SetText(stats[row].PIDs) } } }, ) //Размер колонок table.SetColumnWidth(0, 100) table.SetColumnWidth(1, 150) table.SetColumnWidth(2, 70) table.SetColumnWidth(3, 70) table.SetColumnWidth(4, 140) table.SetColumnWidth(5, 140) table.SetColumnWidth(6, 140) table.SetColumnWidth(7, 50) table.Refresh() tab := container.NewBorder( widget.NewSeparator(), nil, nil, nil, container.NewScroll(table), ) return tab } func createDockerPsTab(server outputStruct) *fyne.Container { searchDockerEntry := widget.NewEntry() searchDockerEntry.SetPlaceHolder("Поиск контейнеров ...") filteredDockers := server.DockerPsA // type dockerPs struct { // Id string `json:"id"` // Image string `json:"image"` // Names []string `json:"names"` // Created int64 `json:"running_for"` // State string `json:"state"` // Status string `json:"status"` // } dockerList := widget.NewList( func() int { return len(filteredDockers) }, func() fyne.CanvasObject { return container.NewHBox( widget.NewLabel("id"), widget.NewLabel("image"), widget.NewLabel("names"), widget.NewLabel("created"), widget.NewLabel("state"), widget.NewLabel("status"), ) }, func(id widget.ListItemID, obj fyne.CanvasObject) { hbox := obj.(*fyne.Container) dock := filteredDockers[id] idLabel := hbox.Objects[0].(*widget.Label) imageLabel := hbox.Objects[1].(*widget.Label) namesLabel := hbox.Objects[2].(*widget.Label) createdLabel := hbox.Objects[3].(*widget.Label) stateLabel := hbox.Objects[4].(*widget.Label) statusLabel := hbox.Objects[5].(*widget.Label) idLabel.SetText(dock.Id) imageLabel.SetText(dock.Image) namesLabel.SetText(fmt.Sprintf("%s", dock.Names)) createdLabel.SetText(strconv.Itoa(int(dock.Created))) stateLabel.SetText(dock.State) statusLabel.SetText(dock.Status) }, ) searchDockerEntry.OnChanged = func(text string) { if text == "" { filteredDockers = server.DockerPsA } else { filtered := []dockerPs{} lowerText := strings.ToLower(text) for _, d := range server.DockerPsA { if strings.Contains(strings.ToLower(d.Image), lowerText) || strings.Contains(strings.ToLower(d.State), lowerText) || strings.Contains(strings.ToLower(fmt.Sprintf("%s", d.Names)), lowerText) || strings.Contains(strings.ToLower(d.Status), lowerText) { filtered = append(filtered, d) } } filteredDockers = filtered } dockerList.Refresh() } dockerTab := container.NewBorder( container.NewVBox( searchDockerEntry, widget.NewSeparator(), ), nil, nil, nil, container.NewScroll(dockerList), ) return dockerTab } func createDockerSupervisorTab(server outputStruct) *fyne.Container { searchEntry := widget.NewEntry() searchEntry.SetPlaceHolder("Поиск ...") filtered := server.DockerSupervisor list := widget.NewList( func() int { return len(filtered) }, func() fyne.CanvasObject { entry := widget.NewMultiLineEntry() entry.SetMinRowsVisible(10) entry.Wrapping = fyne.TextWrapWord return container.NewVBox( widget.NewLabel("container_name"), entry, ) }, func(id widget.ListItemID, obj fyne.CanvasObject) { box := obj.(*fyne.Container) e := filtered[id] containerName := box.Objects[0].(*widget.Label) containerName.SetText(e.Name) containerName.TextStyle.Bold = true containerName.Selectable = true supervisorStatus := box.Objects[1].(*widget.Entry) supervisorStatus.SetText(e.SupStatus) }, ) searchEntry.OnChanged = func(text string) { if text == "" { filtered = server.DockerSupervisor } else { var f []dockerSupervisor lText := strings.ToLower(text) for _, elem := range server.DockerSupervisor { if strings.Contains(strings.ToLower(elem.Name), lText) { f = append(f, elem) } } filtered = f } list.Refresh() } tab := container.NewBorder( container.NewVBox( searchEntry, widget.NewSeparator(), ), nil, nil, nil, container.NewScroll(list), ) return tab }