264 lines
7.4 KiB
Go
264 lines
7.4 KiB
Go
package widget
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"git.ohea.xyz/cursorius/tui/queries"
|
|
|
|
"github.com/Khan/genqlient/graphql"
|
|
"github.com/charmbracelet/bubbles/list"
|
|
"github.com/charmbracelet/bubbles/viewport"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
type pipelineWidgetViewPage int
|
|
|
|
const (
|
|
topLevel pipelineWidgetViewPage = 0
|
|
viewRun = 1
|
|
viewRunBuildOutput = 2
|
|
viewRunStdout = 3
|
|
viewRunStderr = 4
|
|
)
|
|
|
|
type pipelineWidgetView struct {
|
|
client graphql.Client
|
|
page pipelineWidgetViewPage
|
|
pipeline queries.GetPipelinePipeline
|
|
runsList list.Model
|
|
viewRunSelector list.Model
|
|
viewRunBuildOutputPager viewport.Model
|
|
viewRunStdoutPager viewport.Model
|
|
viewRunStderrPager viewport.Model
|
|
}
|
|
|
|
func (m pipelineWidgetView) Init() tea.Cmd {
|
|
return nil
|
|
}
|
|
|
|
func (m pipelineWidgetView) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.WindowSizeMsg:
|
|
m.runsList.SetWidth(msg.Width - 20)
|
|
m.runsList.SetHeight(msg.Height - 20)
|
|
case tea.KeyMsg:
|
|
switch msg.String() {
|
|
case "r":
|
|
return m, func() tea.Msg {
|
|
view, err := createPipelineWidgetView(m.client, m.pipeline.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return pipelineWidgetScreenSwitch(view)
|
|
}
|
|
case "backspace":
|
|
switch m.page {
|
|
case topLevel:
|
|
return m, func() tea.Msg {
|
|
view, err := createPipelineWidgetList(m.client)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return pipelineWidgetScreenSwitch(view)
|
|
}
|
|
case viewRun:
|
|
m.page = topLevel
|
|
case viewRunBuildOutput:
|
|
m.page = viewRun
|
|
case viewRunStderr:
|
|
m.page = viewRun
|
|
case viewRunStdout:
|
|
m.page = viewRun
|
|
}
|
|
case "enter":
|
|
switch m.page {
|
|
case topLevel:
|
|
run := m.pipeline.Runs[m.runsList.Index()]
|
|
|
|
content := []list.Item{
|
|
pipelineWidgetViewRunsSelectorItem(fmt.Sprintf("ID: %v", run.Id)),
|
|
}
|
|
|
|
if run.InProgress != nil {
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem(fmt.Sprintf("In Progress: %v", *run.InProgress)))
|
|
} else {
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem("In Progress: null"))
|
|
}
|
|
if run.Result != nil {
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem(fmt.Sprintf("Result: %v", *run.Result)))
|
|
} else {
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem("Result: null"))
|
|
}
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem("View Build Output"))
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem("View Stdout"))
|
|
content = append(content, pipelineWidgetViewRunsSelectorItem("View Stderr"))
|
|
|
|
runOutputList := list.New(content, pipelineWigetViewRunsSelectorItemDelegate{}, m.runsList.Width(), m.runsList.Height())
|
|
runOutputList.SetShowStatusBar(false)
|
|
runOutputList.Title = "View Run"
|
|
runOutputList.DisableQuitKeybindings()
|
|
|
|
m.viewRunSelector = runOutputList
|
|
|
|
m.page = viewRun
|
|
case viewRun:
|
|
run := m.pipeline.Runs[m.runsList.Index()]
|
|
switch m.viewRunSelector.Index() {
|
|
case 3:
|
|
if run.BuildOutput == nil {
|
|
break
|
|
}
|
|
m.viewRunBuildOutputPager = viewport.New(m.runsList.Width(), m.runsList.Height())
|
|
m.viewRunBuildOutputPager.SetContent(*run.BuildOutput)
|
|
m.page = viewRunBuildOutput
|
|
case 4:
|
|
if run.Stdout == nil {
|
|
break
|
|
}
|
|
m.viewRunStdoutPager = viewport.New(m.runsList.Width(), m.runsList.Height())
|
|
m.viewRunStdoutPager.SetContent(*run.Stdout)
|
|
|
|
m.page = viewRunStdout
|
|
case 5:
|
|
if run.Stderr == nil {
|
|
break
|
|
}
|
|
m.viewRunStderrPager = viewport.New(m.runsList.Width(), m.runsList.Height())
|
|
m.viewRunStderrPager.SetContent(*run.Stderr)
|
|
|
|
m.page = viewRunStderr
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
var cmd tea.Cmd
|
|
switch m.page {
|
|
case topLevel:
|
|
m.runsList, cmd = m.runsList.Update(msg)
|
|
case viewRun:
|
|
m.viewRunSelector, cmd = m.viewRunSelector.Update(msg)
|
|
case viewRunBuildOutput:
|
|
m.viewRunBuildOutputPager, cmd = m.viewRunBuildOutputPager.Update(msg)
|
|
case viewRunStdout:
|
|
m.viewRunStdoutPager, cmd = m.viewRunStdoutPager.Update(msg)
|
|
case viewRunStderr:
|
|
m.viewRunStderrPager, cmd = m.viewRunStderrPager.Update(msg)
|
|
}
|
|
|
|
return m, cmd
|
|
}
|
|
|
|
func (m pipelineWidgetView) View() string {
|
|
s := ""
|
|
switch m.page {
|
|
case topLevel:
|
|
s += fmt.Sprintf("Pipeline: %v\n\n", m.pipeline.Name)
|
|
s += fmt.Sprintf("Id: %v\n", m.pipeline.Id)
|
|
s += fmt.Sprintf("Url: %v\n", m.pipeline.Url)
|
|
s += fmt.Sprintf("Poll Interval: %v\n", m.pipeline.PollInterval)
|
|
if m.pipeline.CloneCredential != nil {
|
|
s += fmt.Sprintf("Clone Credential: %v (%v)\n\n", m.pipeline.CloneCredential.Name, m.pipeline.CloneCredential.Type)
|
|
} else {
|
|
s += fmt.Sprintf("Clone Credential: None\n\n")
|
|
}
|
|
s += m.runsList.View()
|
|
case viewRun:
|
|
s += m.viewRunSelector.View()
|
|
case viewRunBuildOutput:
|
|
s += m.viewRunBuildOutputPager.View()
|
|
case viewRunStdout:
|
|
s += m.viewRunStdoutPager.View()
|
|
case viewRunStderr:
|
|
s += m.viewRunStderrPager.View()
|
|
|
|
}
|
|
return s
|
|
}
|
|
|
|
func createPipelineWidgetView(client graphql.Client, id string) (tea.Model, error) {
|
|
|
|
getPipelineResp, err := queries.GetPipeline(context.Background(), client, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if getPipelineResp.Pipeline == nil {
|
|
return nil, fmt.Errorf("Server did not give us a pipeline")
|
|
}
|
|
|
|
var content []list.Item
|
|
|
|
for _, run := range getPipelineResp.Pipeline.Runs {
|
|
content = append(content, pipelineWidgetViewRunsItem{
|
|
id: run.Id,
|
|
})
|
|
}
|
|
|
|
runsList := list.New(content, pipelineWigetViewRunsItemDelegate{}, 0, 0)
|
|
runsList.SetShowStatusBar(false)
|
|
runsList.Title = "Runs"
|
|
|
|
return pipelineWidgetView{
|
|
client: client,
|
|
page: topLevel,
|
|
pipeline: *getPipelineResp.Pipeline,
|
|
runsList: runsList,
|
|
}, nil
|
|
}
|
|
|
|
type pipelineWidgetViewRunsItem struct {
|
|
id string
|
|
}
|
|
|
|
func (i pipelineWidgetViewRunsItem) FilterValue() string { return "" }
|
|
|
|
type pipelineWigetViewRunsItemDelegate struct{}
|
|
|
|
func (d pipelineWigetViewRunsItemDelegate) Height() int { return 1 }
|
|
func (d pipelineWigetViewRunsItemDelegate) Spacing() int { return 0 }
|
|
func (d pipelineWigetViewRunsItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil }
|
|
func (d pipelineWigetViewRunsItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
|
|
switch i := listItem.(type) {
|
|
case pipelineWidgetViewRunsItem:
|
|
fn := itemStyle.Render
|
|
if index == m.Index() {
|
|
fn = func(s string) string {
|
|
return selectedItemStyle.Render("> " + s)
|
|
}
|
|
}
|
|
|
|
str := fn(i.id)
|
|
fmt.Fprint(w, str)
|
|
}
|
|
}
|
|
|
|
type pipelineWidgetViewRunsSelectorItem string
|
|
|
|
func (i pipelineWidgetViewRunsSelectorItem) FilterValue() string { return "" }
|
|
|
|
type pipelineWigetViewRunsSelectorItemDelegate struct{}
|
|
|
|
func (d pipelineWigetViewRunsSelectorItemDelegate) Height() int { return 1 }
|
|
func (d pipelineWigetViewRunsSelectorItemDelegate) Spacing() int { return 0 }
|
|
func (d pipelineWigetViewRunsSelectorItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
|
|
return nil
|
|
}
|
|
func (d pipelineWigetViewRunsSelectorItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
|
|
switch i := listItem.(type) {
|
|
case pipelineWidgetViewRunsSelectorItem:
|
|
fn := itemStyle.Render
|
|
if index == m.Index() {
|
|
fn = func(s string) string {
|
|
return selectedItemStyle.Render("> " + s)
|
|
}
|
|
}
|
|
|
|
str := fn(string(i))
|
|
fmt.Fprint(w, str)
|
|
}
|
|
}
|