gitee_cli/utils/tui/table.go

208 lines
5.9 KiB
Go
Raw Normal View History

2024-04-07 17:49:39 +08:00
package tui
import (
"fmt"
"gitee_cli/config"
"gitee_cli/internal/api/enterprises"
"gitee_cli/internal/api/issue"
"gitee_cli/internal/api/issue_state"
2024-04-07 17:49:39 +08:00
"gitee_cli/internal/api/pull_request"
"gitee_cli/utils/git_utils"
"gitee_cli/utils/tui/selector_tui"
2024-04-07 17:49:39 +08:00
"github.com/atotto/clipboard"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/fatih/color"
"github.com/pkg/browser"
"os"
"strings"
)
var baseStyle = lipgloss.NewStyle().
BorderStyle(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("240"))
const (
Issue = iota
IssueType
PullRequest
Enterprise
SSHKey
)
// Table TODO 初始化改成 options 模式
type Table struct {
table table.Model
SelectedKey string
ViewMode bool
ResourceType int
Enterprise enterprises.Enterprise
}
func NewTableModel(enterprise enterprises.Enterprise, resourceType int, columns []table.Column, rows []table.Row) Table {
height := 5
if resourceType == PullRequest {
height = 10
}
t := table.New(
table.WithColumns(columns),
table.WithRows(rows),
table.WithFocused(true),
table.WithHeight(height),
)
s := table.DefaultStyles()
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("240")).
BorderBottom(true).
Bold(false)
s.Selected = s.Selected.
Foreground(lipgloss.Color("229")).
Background(lipgloss.Color("57")).
Bold(false)
if resourceType == PullRequest {
s.Selected = s.Selected.Background(lipgloss.Color("#8B4789"))
// 避免与 diff 快捷键冲突
t.KeyMap.HalfPageDown = key.NewBinding(
key.WithDisabled(),
)
}
t.SetStyles(s)
return Table{table: t, Enterprise: enterprise, ResourceType: resourceType}
}
func NewTable(enterprise enterprises.Enterprise, resourceType int, columns []table.Column, rows []table.Row) *tea.Program {
if resourceType == SSHKey || resourceType == Enterprise {
return tea.NewProgram(NewTableModel(enterprise, resourceType, columns, rows), tea.WithAltScreen())
}
return tea.NewProgram(NewTableModel(enterprise, resourceType, columns, rows))
}
func (t Table) Init() tea.Cmd { return nil }
func (t Table) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "esc":
if t.table.Focused() {
t.table.Blur()
} else {
t.table.Focus()
}
case "c":
if t.ResourceType == Issue || t.ResourceType == Enterprise {
clipboard.WriteAll(t.table.SelectedRow()[0])
} else if t.ResourceType == PullRequest {
clipboard.WriteAll(t.table.SelectedRow()[1])
}
case "q", "ctrl+c":
t.SelectedKey = ""
return t, tea.Quit
case "s":
if t.ResourceType == Issue {
targetIssue, err := issue.Detail(t.Enterprise.Id, t.table.SelectedRow()[0])
if err != nil {
color.Red("获取任务详情失败!")
return t, tea.Quit
}
if issueStates, err := issue_state.ListWithIssue(t.Enterprise.Id, targetIssue.Id); err == nil {
var model tea.Model
options := make([]string, 0)
optionMap := make(map[string]int, 0)
optionMap, options = issue_state.FillOptions(issueStates, optionMap, options)
promote := "请选择要变更的状态"
selector := selector_tui.NewMapSelector(optionMap, options, promote, true)
if model, err = selector.Run(); err != nil {
color.Red("任务状态选择器加载失败!")
os.Exit(1)
}
mapSelector, _ := model.(selector_tui.MapSelector)
issueStateId, err := mapSelector.SelectedValue()
if err != nil {
color.Red(err.Error())
os.Exit(1)
}
if targetIssue, err = issue.Update(t.Enterprise.Id, targetIssue.Id, map[string]interface{}{
"issue_state_id": issueStateId,
}); err != nil {
color.Red(err.Error())
os.Exit(1)
}
return t, tea.ClearScrollArea
} else {
color.Red("获取任务状态列表失败!")
os.Exit(1)
}
}
2024-04-07 17:49:39 +08:00
case "v":
if t.ResourceType == Issue {
if _issue, err := issue.Detail(t.Enterprise.Id, t.table.SelectedRow()[0]); err == nil {
NewPager(_issue.Title, _issue.Description, Markdown).Run()
} else {
color.Red("获取任务详情失败!")
return t, tea.Quit
}
} else if t.ResourceType == PullRequest {
path, _ := git_utils.ParseCurrentRepo()
if path == "" {
path = config.Conf.DefaultPathWithNamespace
}
t.SelectedKey = t.table.SelectedRow()[1]
if pullRequerst, err := pull_request.Detail(t.SelectedKey, path); err == nil {
NewPager(pullRequerst.Title, pullRequerst.Body, Markdown).Run()
} else {
color.Red("获取pr详情失败")
return t, tea.Quit
}
}
case "d":
if t.ResourceType == PullRequest {
path, _ := git_utils.ParseCurrentRepo()
t.SelectedKey = t.table.SelectedRow()[1]
if path == "" {
path = config.Conf.DefaultPathWithNamespace
}
if diff, err := pull_request.FetchPatchContent(t.SelectedKey, path); err == nil {
NewPager(t.table.SelectedRow()[0], diff, Diff).Run()
} else {
color.Red(err.Error())
return t, tea.Quit
}
}
case "enter":
t.SelectedKey = t.table.SelectedRow()[0]
if t.ResourceType == Issue {
url := fmt.Sprintf("https://e.gitee.com/%s/dashboard?issue=%s", t.Enterprise.Path, t.SelectedKey)
browser.OpenURL(url)
} else if t.ResourceType == PullRequest {
path, _ := git_utils.ParseCurrentRepo()
if path == "" {
path = config.Conf.DefaultPathWithNamespace
}
t.SelectedKey = t.table.SelectedRow()[1]
url := fmt.Sprintf("https://gitee.com/%s/pulls/%s", path, t.SelectedKey)
if os.Getenv("CONVERT_ENT_URL") != "" {
url = fmt.Sprintf("https://e.gitee.com/%s/repos/%s/pulls/%s", strings.Split(path, "/")[0], path, t.SelectedKey)
}
browser.OpenURL(url)
} else {
return t, tea.Quit
}
}
}
t.table, cmd = t.table.Update(msg)
return t, cmd
}
func (t Table) View() string {
return baseStyle.Render(t.table.View()) + "\n"
}