Nayden Van
Nayden Van

Reputation: 1569

Duplicate mainSection and footer in TUI Application with Tview

I'm building a terminal user interface (TUI) application in Go using the tview library, and I'm encountering an issue with duplicate mainSection and footer entries being displayed in my grid layout.

func kubernetesLanding(app *tview.Application, clientset *kubernetes.Clientset) {
    newPrimitive := func(text string) tview.Primitive {
        return tview.NewTextView().
            SetTextAlign(tview.AlignCenter).
            SetText(text)
    }

    mainSection := tview.NewTextView().
        SetTextAlign(tview.AlignCenter).
        SetText("Main content")

    footer := newPrimitive("Footer")

    clusterInfo := ClusterInfo{
        Context:       "dev-context",
        Cluster:       "my-cluster",
        Memory:        "16Gi",
        CPU:           "4 cores",
        NumberOfNodes: 3,
    }

    commands := []Command{
        {"a", "Attach"},
        {"d", "Delete"},
    }

    header := renderHeader(clusterInfo, commands)

    grid := tview.NewGrid().
        SetRows(6, 0, 3).
        SetBorders(true)

    grid.AddItem(header, 0, 0, 1, 3, 0, 0, false).
        AddItem(mainSection, 1, 0, 1, 3, 0, 0, false).
        AddItem(footer, 2, 0, 1, 3, 0, 0, false)

    // Initialize watch for pods
    watchPods(clientset, "default", grid, app)

    if err := app.SetRoot(grid, true).EnableMouse(true).Run(); err != nil {
        logMessage("Error: " + err.Error())
        panic(err)
    }
}

and this is the watchPods function:

func watchPods(clientset *kubernetes.Clientset, namespace string, grid *tview.Grid, app *tview.Application) {
    // Create a list/watch pod request
    watchInterface, err := clientset.CoreV1().Pods(namespace).Watch(context.TODO(), metav1.ListOptions{})
    if err != nil {
        log.Fatalf("Error setting up watch: %v", err)
    }

    table := tview.NewTable().SetBorders(false).SetSelectable(true, false)
    grid.AddItem(table, 1, 0, 1, 3, 0, 0, true)

    // Watch for events in a goroutine
    go func() {
        for event := range watchInterface.ResultChan() {
            pod, ok := event.Object.(*v1.Pod)
            if !ok {
                logMessage("Error converting event object to Pod")
                continue
            }

            switch event.Type {
            case watch.Added:
                logMessage(fmt.Sprintf("Pod added: %s", pod.Name))
                // Update the pod list (You may want to maintain an array of Pods to keep track)
                displayPodsInTable(table, []Pod{convertToPod(pod)})
            case watch.Modified:
                logMessage(fmt.Sprintf("Pod modified: %s", pod.Name))
                // Update the pod list
                displayPodsInTable(table, []Pod{convertToPod(pod)})
            case watch.Deleted:
                logMessage(fmt.Sprintf("Pod deleted: %s", pod.Name))
                // Refresh the table (You may want to keep track of the pods for better handling)
                // You can clear and reload all pods
                refreshPods(clientset, namespace, table)
            }
        }
    }()

    // Initial load of pods
    refreshPods(clientset, namespace, table)
}

And here is the main function:

func main() {
    app := tview.NewApplication()
    clientset, err := GetClient()
    if err != nil {
        log.Fatalf("Failed to get Kubernetes client: %v", err)
    }
    list := tview.NewList().
        AddItem("Kubernetes", "Some explanatory text", 'a', func() {
            kubernetesLanding(app, clientset)
        }).
        AddItem("Quit", "Press to exit", 'q', func() {
            app.Stop()
        })

    // Set a uniform background color for the list
    list.SetBackgroundColor(tcell.ColorBlack) // Use your preferred color here

    if err := app.SetRoot(list, true).EnableMouse(true).Run(); err != nil {
        panic(err)
    }
}

To clarify better the issue. when i go to the kubernetes section: i should see the grid in this following format:

initially, before integrating any kubernetes code, this was working as expected, so i introduced the watchpod function to replicate the command kubectl get pods and start having some experience with those libraries. and this is where the weird behaviour start happening. At every events, instead of just updating the mainSection, it creates a new mainsection and footer. So lets assume i have 3 events firing, what i see in the terminal is:

i tried to remove the Items from the function so have always a new one added, but this seems not to work and the same outcome is happening.

I hope somebody can help me out with this and undertand what i am doing wrong here because i am quiet confused. And please if youhave any further question, just let me know.

thank you so much in advance

Upvotes: 1

Views: 29

Answers (0)

Related Questions