From eb6946f7a4f61a97b5d953f13d83175d0bb0d9a9 Mon Sep 17 00:00:00 2001 From: John McBride Date: Wed, 28 Aug 2024 19:10:18 -0600 Subject: [PATCH] chore: Remove the show command (#110) Signed-off-by: John McBride --- cmd/show/constants.go | 63 -------- cmd/show/contributors.go | 268 -------------------------------- cmd/show/dashboard.go | 328 --------------------------------------- cmd/show/show.go | 97 ------------ cmd/show/tui.go | 95 ------------ go.mod | 5 +- go.sum | 6 - 7 files changed, 2 insertions(+), 860 deletions(-) delete mode 100644 cmd/show/constants.go delete mode 100644 cmd/show/contributors.go delete mode 100644 cmd/show/dashboard.go delete mode 100644 cmd/show/show.go delete mode 100644 cmd/show/tui.go diff --git a/cmd/show/constants.go b/cmd/show/constants.go deleted file mode 100644 index 9c68085..0000000 --- a/cmd/show/constants.go +++ /dev/null @@ -1,63 +0,0 @@ -package show - -import ( - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -// WindowSize stores the size of the terminal -var WindowSize tea.WindowSizeMsg - -// Keymaps -var OpenPR = key.NewBinding(key.WithKeys("O"), key.WithHelp("O", "open pr")) -var BackToDashboard = key.NewBinding(key.WithKeys("B"), key.WithHelp("B", "back")) -var ToggleHelpMenu = key.NewBinding(key.WithKeys("H"), key.WithHelp("H", "toggle help")) - -// STYLES -// Viewport: The viewport of the tui (my:2, mx:2) -var Viewport = lipgloss.NewStyle().Margin(1, 2) - -// Container: container styling (width: 80, py: 0, px: 5) -var Container = lipgloss.NewStyle().Width(80).Padding(0, 5) - -// WidgetContainer: container for tables, and graphs (py:2, px:2) -var WidgetContainer = lipgloss.NewStyle().Padding(2, 2) - -// SquareBorder: Style to draw a border around a section -var SquareBorder = lipgloss.NewStyle().BorderStyle(lipgloss.RoundedBorder()).BorderForeground(Color) - -// TextContainer: container for text -var TextContainer = lipgloss.NewStyle().Padding(1, 1) - -// TableTitle: The style for table titles (width:25, align-horizontal:center, bold:true) -var TableTitle = lipgloss.NewStyle().Width(25).AlignHorizontal(lipgloss.Center).Bold(true) - -// Color: the color palette (Light: #000000, Dark: #FF4500) -var Color = lipgloss.AdaptiveColor{Light: "#000000", Dark: "#FF4500"} - -// ActiveStyle: table when selected (border:normal, border-foreground:#FF4500) -var ActiveStyle = lipgloss.NewStyle(). - BorderStyle(lipgloss.NormalBorder()). - BorderForeground(lipgloss.Color("#FF4500")) - -// InactiveStyle: table when not selected (border:normal, border-foreground:#FFFFFF) -var InactiveStyle = lipgloss.NewStyle(). - BorderStyle(lipgloss.NormalBorder()). - BorderForeground(lipgloss.Color("#FFFFFF")) - -// ItemStyle: style applied to items in a list.Model -var ItemStyle = lipgloss.NewStyle().PaddingLeft(4) - -// SelectedItemStyle: style applied when the item is selected in a list.Model -var SelectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(Color) - -// ListItemTitle: style for the list.Model title -var ListItemTitleStyle = lipgloss.NewStyle().MarginLeft(2) - -// PaginationStyle: style for pagination of list.Model -var PaginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - -// HelpStyle: style for help menu -var HelpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) diff --git a/cmd/show/contributors.go b/cmd/show/contributors.go deleted file mode 100644 index 7e198cf..0000000 --- a/cmd/show/contributors.go +++ /dev/null @@ -1,268 +0,0 @@ -package show - -import ( - "context" - "errors" - "fmt" - "io" - "strings" - "sync" - - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/cli/browser" - client "github.com/open-sauced/go-api/client" -) - -// prItem: type for pull request to satisfy the list.Item interface -type prItem client.DbPullRequestGitHubEvents - -func (i prItem) FilterValue() string { return i.PrTitle } -func (i prItem) GetRepoName() string { - if i.RepoName != "" { - return i.RepoName - } - return "" -} - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 1 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(prItem) - if !ok { - return - } - - prTitle := i.PrTitle - if len(prTitle) >= 60 { - prTitle = fmt.Sprintf("%s...", prTitle[:60]) - } - - str := fmt.Sprintf("#%d %s\n%s\n(%s)", i.PrNumber, i.GetRepoName(), prTitle, i.PrState) - - fn := ItemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - return SelectedItemStyle.Render("🍕 " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} - -// ContributorModel holds all the information related to a contributor -type ContributorModel struct { - username string - userInfo *client.DbUser - prList list.Model - prVelocity float64 - APIClient *client.APIClient - serverContext context.Context -} - -type ( - // BackMsg: message to signal main model that we are back to dashboard when backspace is pressed - BackMsg struct{} - - // ContributorErrMsg: message to signal that an error occurred when fetching contributor information - ContributorErrMsg struct { - name string - err error - } -) - -// InitContributor: initializes the contributorModel -func InitContributor(opts *Options) (tea.Model, error) { - var model ContributorModel - model.APIClient = opts.APIClient - model.serverContext = opts.ServerContext - - return model, nil -} - -func (m ContributorModel) Init() tea.Cmd { return nil } - -func (m ContributorModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmd tea.Cmd - switch msg := msg.(type) { - case tea.WindowSizeMsg: - WindowSize = msg - case SelectMsg: - m.username = msg.contributorName - model, err := m.fetchUser() - if err != nil { - return m, func() tea.Msg { return ContributorErrMsg{name: msg.contributorName, err: err} } - } - return model, func() tea.Msg { return SuccessMsg{} } - case tea.KeyMsg: - switch msg.String() { - case "B": - if !m.prList.SettingFilter() { - return m, func() tea.Msg { return BackMsg{} } - } - case "H": - if !m.prList.SettingFilter() { - m.prList.SetShowHelp(!m.prList.ShowHelp()) - return m, nil - } - case "O": - if !m.prList.SettingFilter() { - pr, ok := m.prList.SelectedItem().(prItem) - if ok { - err := browser.OpenURL(fmt.Sprintf("https://github.com/%s/pull/%d", pr.GetRepoName(), pr.PrNumber)) - if err != nil { - fmt.Println("could not open pull request in browser") - } - } - } - case "q", "ctrl+c", "ctrl+d": - if !m.prList.SettingFilter() { - return m, tea.Quit - } - } - } - m.prList, cmd = m.prList.Update(msg) - return m, cmd -} - -func (m ContributorModel) View() string { - return m.drawContributorView() -} - -// fetchUser: fetches all the user information (general info, and pull requests) -func (m *ContributorModel) fetchUser() (tea.Model, error) { - var ( - wg sync.WaitGroup - errChan = make(chan error, 2) - ) - - wg.Add(1) - go func() { - defer wg.Done() - err := m.fetchContributorInfo(m.username) - if err != nil { - errChan <- err - return - } - }() - - wg.Add(1) - go func() { - defer wg.Done() - err := m.fetchContributorPRs(m.username) - if err != nil { - errChan <- err - return - } - }() - - wg.Wait() - close(errChan) - if len(errChan) > 0 { - var allErrors error - for err := range errChan { - allErrors = errors.Join(allErrors, err) - } - return m, allErrors - } - - return m, nil -} - -// fetchContributorInfo: fetches the contributor info -func (m *ContributorModel) fetchContributorInfo(name string) error { - resp, r, err := m.APIClient.UserServiceAPI.FindOneUserByUserame(m.serverContext, name).Execute() - if err != nil { - return err - } - - if r.StatusCode != 200 { - return fmt.Errorf("HTTP failed: %d", r.StatusCode) - } - - m.userInfo = resp - return nil -} - -// fetchContributorPRs: fetches the contributor pull requests and creates pull request list -func (m *ContributorModel) fetchContributorPRs(name string) error { - resp, r, err := m.APIClient.UserServiceAPI.FindContributorPullRequestGitHubEvents(m.serverContext, name).Range_(30).Execute() - if err != nil { - return err - } - - if r.StatusCode != 200 { - return fmt.Errorf("HTTP failed: %d", r.StatusCode) - } - - // create contributor pull request list - var items []list.Item - var mergedPullRequests int - for _, pr := range resp.Data { - if pr.PrIsMerged { - mergedPullRequests++ - } - items = append(items, prItem(pr)) - } - - // calculate pr velocity - if len(resp.Data) <= 0 { - m.prVelocity = 0.0 - } else { - m.prVelocity = (float64(mergedPullRequests) / float64(len(resp.Data))) * 100.0 - } - - l := list.New(items, itemDelegate{}, WindowSize.Width, 14) - l.Title = "✨ Latest Pull Requests" - l.Styles.Title = ListItemTitleStyle - l.Styles.HelpStyle = HelpStyle - l.Styles.NoItems = ItemStyle - l.SetShowStatusBar(false) - l.SetStatusBarItemName("pull request", "pull requests") - l.AdditionalShortHelpKeys = func() []key.Binding { - return []key.Binding{ - OpenPR, - BackToDashboard, - ToggleHelpMenu, - } - } - - m.prList = l - return nil -} - -// drawContributorView: view of the contributor model -func (m *ContributorModel) drawContributorView() string { - contributorInfo := m.drawContributorInfo() - - contributorView := lipgloss.JoinVertical(lipgloss.Left, lipgloss.NewStyle().PaddingLeft(2).Render(contributorInfo), - WidgetContainer.Render(m.prList.View())) - - _, h := lipgloss.Size(contributorView) - if WindowSize.Height < h { - contributorView = lipgloss.JoinHorizontal(lipgloss.Center, contributorInfo, m.prList.View()) - } - - return contributorView -} - -// drawContributorInfo: view of the contributor info (open issues, pr velocity, pr count, maintainer) -func (m *ContributorModel) drawContributorInfo() string { - userOpenIssues := fmt.Sprintf("📄 Issues: %d", m.userInfo.OpenIssues) - isUserMaintainer := fmt.Sprintf("🔨 Maintainer: %t", m.userInfo.GetIsMaintainer()) - prVelocity := fmt.Sprintf("🔥 PR Velocity (30d): %dd - %.0f%% merged", m.userInfo.RecentPullRequestVelocityCount, m.prVelocity) - prCount := fmt.Sprintf("🚀 PR Count (30d): %d", m.userInfo.RecentPullRequestsCount) - - prStats := lipgloss.JoinVertical(lipgloss.Left, TextContainer.Render(prVelocity), TextContainer.Render(prCount)) - issuesAndMaintainer := lipgloss.JoinVertical(lipgloss.Center, TextContainer.Render(userOpenIssues), TextContainer.Render(isUserMaintainer)) - - contributorInfo := lipgloss.JoinHorizontal(lipgloss.Center, prStats, issuesAndMaintainer) - contributorView := lipgloss.JoinVertical(lipgloss.Center, m.userInfo.Login, contributorInfo) - - return SquareBorder.Render(contributorView) -} diff --git a/cmd/show/dashboard.go b/cmd/show/dashboard.go deleted file mode 100644 index 92dece7..0000000 --- a/cmd/show/dashboard.go +++ /dev/null @@ -1,328 +0,0 @@ -package show - -import ( - "context" - "errors" - "fmt" - "strconv" - "sync" - - "github.com/charmbracelet/bubbles/table" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - client "github.com/open-sauced/go-api/client" -) - -const ( - newContributorsView = iota - alumniContributorsView -) - -// DashboardModel holds all the information related to the repository queried (issues, stars, new contributors, alumni contributors) -type DashboardModel struct { - newContributorsTable table.Model - alumniContributorsTable table.Model - RepositoryInfo *client.DbRepo - contributorErr string - tableView int - queryOptions [3]int - APIClient *client.APIClient - serverContext context.Context -} - -// SelectMsg: message to signal the main model that we want to go to the contributor model when 'enter' is pressed -type SelectMsg struct { - contributorName string -} - -// FetchRepoInfo: initializes the dashboard model -func InitDashboard(opts *Options) (tea.Model, error) { - var model DashboardModel - err := validateShowQuery(opts) - if err != nil { - return model, err - } - - resp, r, err := opts.APIClient.RepositoryServiceAPI.FindOneByOwnerAndRepo(opts.ServerContext, opts.Owner, opts.RepoName).Execute() - if err != nil { - return model, err - } - - if r.StatusCode != 200 { - return model, fmt.Errorf("HTTP status: %d", r.StatusCode) - } - - // configuring the dashboardModel - model.RepositoryInfo = resp - model.queryOptions = [3]int{opts.Page, opts.Limit, opts.Range} - model.APIClient = opts.APIClient - model.serverContext = opts.ServerContext - - // fetching the contributor tables - err = model.FetchAllContributors() - if err != nil { - return model, err - } - - return model, nil -} - -func (m DashboardModel) Init() tea.Cmd { - return nil -} - -func (m DashboardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmd tea.Cmd - switch msg := msg.(type) { - case tea.WindowSizeMsg: - WindowSize = msg - - case ErrMsg: - fmt.Printf("Failed to retrieve contributors table data: %s", msg.err.Error()) - return m, tea.Quit - - case ContributorErrMsg: - m.contributorErr = fmt.Sprintf("🚧 could not fetch %s: %s", msg.name, msg.err.Error()) - default: - m.contributorErr = "" - - case tea.KeyMsg: - switch msg.String() { - case "right", "l": - m.tableView = (m.tableView + 1) % 2 - case "left", "h": - if m.tableView-1 <= 0 { - m.tableView = 0 - } else { - m.tableView-- - } - case "q", "esc", "ctrl+c", "ctrl+d": - return m, tea.Quit - case "enter": - switch m.tableView { - case newContributorsView: - if len(m.newContributorsTable.Rows()) > 0 { - return m, func() tea.Msg { return SelectMsg{contributorName: m.newContributorsTable.SelectedRow()[1]} } - } - case alumniContributorsView: - if len(m.alumniContributorsTable.Rows()) > 0 { - return m, func() tea.Msg { return SelectMsg{contributorName: m.alumniContributorsTable.SelectedRow()[1]} } - } - } - } - - switch m.tableView { - case newContributorsView: - m.newContributorsTable, cmd = m.newContributorsTable.Update(msg) - case alumniContributorsView: - m.alumniContributorsTable, cmd = m.alumniContributorsTable.Update(msg) - } - } - - return m, cmd -} - -func (m DashboardModel) View() string { - return m.drawDashboardView() -} - -// drawTitle: view of PIZZA -func (m *DashboardModel) drawTitle() string { - titleRunes1 := []rune{'█', '█', '█', '█', '█', '█', '╗', ' ', '█', '█', '╗', '█', '█', '█', '█', '█', '█', '█', '╗', '█', '█', '█', '█', '█', '█', '█', '╗', ' ', '█', '█', '█', '█', '█', '╗', ' '} - titleRunes2 := []rune{'█', '█', '╔', '═', '═', '█', '█', '╗', '█', '█', '║', '╚', '═', '═', '█', '█', '█', '╔', '╝', '╚', '═', '═', '█', '█', '█', '╔', '╝', '█', '█', '╔', '═', '═', '█', '█', '╗'} - titleRunes3 := []rune{'█', '█', '█', '█', '█', '█', '╔', '╝', '█', '█', '║', ' ', ' ', '█', '█', '█', '╔', '╝', ' ', ' ', ' ', '█', '█', '█', '╔', '╝', ' ', '█', '█', '█', '█', '█', '█', '█', '║'} - titleRunes4 := []rune{'█', '█', '╔', '═', '═', '═', '╝', ' ', '█', '█', '║', ' ', '█', '█', '█', '╔', '╝', ' ', ' ', ' ', '█', '█', '█', '╔', '╝', ' ', ' ', '█', '█', '╔', '═', '═', '█', '█', '║'} - titleRunes5 := []rune{'█', '█', '║', ' ', ' ', ' ', ' ', ' ', '█', '█', '║', '█', '█', '█', '█', '█', '█', '█', '╗', '█', '█', '█', '█', '█', '█', '█', '╗', '█', '█', '║', ' ', ' ', '█', '█', '║'} - titleRunes6 := []rune{'╚', '═', '╝', ' ', ' ', ' ', ' ', ' ', '╚', '═', '╝', '╚', '═', '═', '═', '═', '═', '═', '╝', '╚', '═', '═', '═', '═', '═', '═', '╝', '╚', '═', '╝', ' ', ' ', '╚', '═', '╝'} - - title1 := lipgloss.JoinHorizontal(lipgloss.Left, string(titleRunes1)) - title2 := lipgloss.JoinHorizontal(lipgloss.Left, string(titleRunes2)) - title3 := lipgloss.JoinHorizontal(lipgloss.Left, string(titleRunes3)) - title4 := lipgloss.JoinHorizontal(lipgloss.Left, string(titleRunes4)) - title5 := lipgloss.JoinHorizontal(lipgloss.Left, string(titleRunes5)) - title6 := lipgloss.JoinHorizontal(lipgloss.Left, string(titleRunes6)) - title := lipgloss.JoinVertical(lipgloss.Center, title1, title2, title3, title4, title5, title6) - titleView := lipgloss.NewStyle().Foreground(Color).Render(title) - - return titleView -} - -// drawRepositoryInfo: view of the repository info (name, stars, size, and issues) -func (m *DashboardModel) drawRepositoryInfo() string { - repoName := lipgloss.NewStyle().Bold(true).AlignHorizontal(lipgloss.Center).Render(fmt.Sprintf("Repository: %s", m.RepositoryInfo.FullName)) - repoStars := fmt.Sprintf("🌟 stars: %d", m.RepositoryInfo.Stars) - repoSize := fmt.Sprintf("💾 size: %dB", m.RepositoryInfo.Size) - repoIssues := fmt.Sprintf("📄 issues: %d", m.RepositoryInfo.Issues) - repoForks := fmt.Sprintf("⑂ forks: %d", m.RepositoryInfo.Forks) - - issuesAndForks := lipgloss.JoinVertical(lipgloss.Center, TextContainer.Render(repoIssues), TextContainer.Render(repoForks)) - sizeAndStars := lipgloss.JoinVertical(lipgloss.Left, TextContainer.Render(repoSize), TextContainer.Render(repoStars)) - - repoGeneralSection := lipgloss.JoinHorizontal(lipgloss.Center, issuesAndForks, sizeAndStars) - repositoryInfoView := lipgloss.JoinVertical(lipgloss.Center, repoName, repoGeneralSection) - frame := SquareBorder.Render(repositoryInfoView) - - return frame -} - -// drawMetrics: view of metrics includes. -// - new contributors table -// - alumni contributors table -func (m *DashboardModel) drawMetrics() string { - var newContributorsDisplay, alumniContributorsDisplay string - - switch m.tableView { - case newContributorsView: - newContributorsDisplay = lipgloss.JoinVertical(lipgloss.Center, TableTitle.Render("🍕 New Contributors"), ActiveStyle.Render(m.newContributorsTable.View())) - alumniContributorsDisplay = lipgloss.JoinVertical(lipgloss.Center, TableTitle.Render("🍁 Alumni Contributors"), InactiveStyle.Render(m.alumniContributorsTable.View())) - case alumniContributorsView: - newContributorsDisplay = lipgloss.JoinVertical(lipgloss.Center, TableTitle.Render("🍕 New Contributors"), InactiveStyle.Render(m.newContributorsTable.View())) - alumniContributorsDisplay = lipgloss.JoinVertical(lipgloss.Center, TableTitle.Render("🍁 Alumni Contributors"), ActiveStyle.Render(m.alumniContributorsTable.View())) - } - - contributorsMetrics := lipgloss.JoinHorizontal(lipgloss.Center, WidgetContainer.Render(newContributorsDisplay), WidgetContainer.Render(alumniContributorsDisplay)) - - return contributorsMetrics -} - -// drawDashboardView: this is the main model view (shows repository info and tables) -func (m *DashboardModel) drawDashboardView() string { - if WindowSize.Width == 0 { - return "Loading..." - } - titleView, repoInfoView, metricsView := m.drawTitle(), m.drawRepositoryInfo(), m.drawMetrics() - mainView := lipgloss.JoinVertical(lipgloss.Center, titleView, repoInfoView, metricsView, m.contributorErr) - - _, h := lipgloss.Size(mainView) - if WindowSize.Height < h { - contentLeft := lipgloss.JoinVertical(lipgloss.Center, titleView, repoInfoView) - contentRight := lipgloss.JoinVertical(lipgloss.Center, metricsView, m.contributorErr) - mainView = lipgloss.JoinHorizontal(lipgloss.Center, contentLeft, contentRight) - } - frame := Viewport.Render(mainView) - return frame -} - -// validateShowQuery: validates fields set to query the contributor tables -func validateShowQuery(opts *Options) error { - if opts.Limit < 1 { - return errors.New("--limit flag must be a positive integer value") - } - if opts.Range < 1 { - return errors.New("--range flag must be a positive integer value") - } - - if opts.Page < 1 { - return errors.New("--page flag must be a positive integer value") - } - - return nil -} - -// FetchAllContributors: fetchs and sets all the contributors (new, alumni) -func (m *DashboardModel) FetchAllContributors() error { - var ( - errorChan = make(chan error, 2) - wg sync.WaitGroup - ) - - wg.Add(1) - go func() { - defer wg.Done() - newContributors, err := m.FetchNewContributors() - if err != nil { - errorChan <- err - return - } - m.newContributorsTable = setupContributorsTable(newContributors) - }() - - wg.Add(1) - go func() { - defer wg.Done() - alumniContributors, err := m.FetchAlumniContributors() - if err != nil { - errorChan <- err - return - } - m.alumniContributorsTable = setupContributorsTable(alumniContributors) - }() - - wg.Wait() - close(errorChan) - if len(errorChan) > 0 { - var allErrors error - for err := range errorChan { - allErrors = errors.Join(allErrors, err) - } - return allErrors - } - - return nil -} - -// FetchNewContributors: Returns all the new contributors -func (m *DashboardModel) FetchNewContributors() ([]client.DbPullRequestContributor, error) { - resp, r, err := m.APIClient.ContributorsServiceAPI.NewPullRequestContributors(m.serverContext).Page(int32(m.queryOptions[0])). - Limit(int32(m.queryOptions[1])).Repos(m.RepositoryInfo.FullName).Execute() - if err != nil { - return nil, err - } - - if r.StatusCode != 200 { - return nil, fmt.Errorf("HTTP status: %d", r.StatusCode) - } - - return resp.Data, nil - -} - -// FetchAlumniContributors: Returns all alumni contributors -func (m *DashboardModel) FetchAlumniContributors() ([]client.DbPullRequestContributor, error) { - resp, r, err := m.APIClient.ContributorsServiceAPI.FindAllChurnPullRequestContributors(m.serverContext). - Page(int32(m.queryOptions[0])).Limit(int32(m.queryOptions[1])). - Range_(int32(m.queryOptions[2])).Repos(m.RepositoryInfo.FullName).Execute() - if err != nil { - return nil, err - } - - if r.StatusCode != 200 { - return nil, fmt.Errorf("HTTP status: %d", r.StatusCode) - } - - return resp.Data, nil -} - -// setupContributorsTable: sets the contributor table UI -func setupContributorsTable(contributors []client.DbPullRequestContributor) table.Model { - columns := []table.Column{ - {Title: "ID", Width: 5}, - {Title: "Name", Width: 20}, - } - - rows := []table.Row{} - - for i, contributor := range contributors { - rows = append(rows, table.Row{strconv.Itoa(i), contributor.AuthorLogin}) - } - - contributorTable := table.New( - table.WithColumns(columns), - table.WithRows(rows), - table.WithFocused(true), - table.WithHeight(15), - ) - - s := table.DefaultStyles() - s.Header = s.Header. - BorderStyle(lipgloss.NormalBorder()). - BorderBottom(true). - Bold(true) - - s.Selected = s.Selected. - Foreground(lipgloss.Color("#FFFFFF")). - Background(lipgloss.Color("#FF4500")) - - contributorTable.SetStyles(s) - return contributorTable -} diff --git a/cmd/show/show.go b/cmd/show/show.go deleted file mode 100644 index cff76e6..0000000 --- a/cmd/show/show.go +++ /dev/null @@ -1,97 +0,0 @@ -// Package show contains the bootstrapping and tooling for the pizza show -// cobra command -package show - -import ( - "context" - "errors" - - client "github.com/open-sauced/go-api/client" - "github.com/spf13/cobra" - - "github.com/open-sauced/pizza-cli/pkg/api" - "github.com/open-sauced/pizza-cli/pkg/constants" - "github.com/open-sauced/pizza-cli/pkg/utils" -) - -// Options are the options for the pizza show command including user -// defined configurations -type Options struct { - // Owner: the owner of the repository - Owner string - - // RepoName: the name of the repository - RepoName string - - // Page is the page to be requested - Page int - - // Limit is the number of records to be retrieved - Limit int - - // Range is the number of days to take into account when retrieving statistics - Range int - - // APIClient is the api client to interface with open sauced api - APIClient *client.APIClient - - ServerContext context.Context -} - -const showLongDesc string = `WARNING: Proof of concept feature. - -The show command accepts the name of a git repository and uses OpenSauced api -to retrieve metrics of the repository to be displayed as a TUI.` - -// NewShowCommand returns a new cobra command for 'pizza show' -func NewShowCommand() *cobra.Command { - opts := &Options{} - - cmd := &cobra.Command{ - Use: "show repository-name [flags]", - Short: "Get visual metrics of a repository", - Long: showLongDesc, - Args: func(_ *cobra.Command, args []string) error { - if len(args) != 1 { - return errors.New("must specify the URL of a git repository to analyze") - } - - owner, name, err := utils.GetOwnerAndRepoFromURL(args[0]) - if err != nil { - return err - } - opts.Owner = owner - opts.RepoName = name - - return nil - }, - RunE: func(cmd *cobra.Command, _ []string) error { - var endpoint string - customEndpoint, _ := cmd.Flags().GetString("endpoint") - if customEndpoint != "" { - endpoint = customEndpoint - } - - useBeta, _ := cmd.Flags().GetBool("beta") - if useBeta { - endpoint = constants.EndpointBeta - } - - opts.APIClient = api.NewGoClient(endpoint) - opts.ServerContext = context.TODO() - return run(opts) - }, - } - - cmd.Flags().IntVarP(&opts.Range, "range", "r", 30, "The last N number of days to consider") - cmd.Flags().IntVarP(&opts.Limit, "limit", "l", 10, "The number of records to retrieve") - cmd.Flags().IntVarP(&opts.Page, "page", "p", 1, "The page number to retrieve") - - return cmd -} - -func run(opts *Options) error { - // Load the pizza TUI - err := pizzaTUI(opts) - return err -} diff --git a/cmd/show/tui.go b/cmd/show/tui.go deleted file mode 100644 index 141367e..0000000 --- a/cmd/show/tui.go +++ /dev/null @@ -1,95 +0,0 @@ -package show - -import ( - "fmt" - - tea "github.com/charmbracelet/bubbletea" -) - -const ( - dashboardView = iota - contributorView -) - -type ( - // sessionState serves as the variable to reference when looking for which model the user is in - sessionState int - - // SuccessMsg: message to represent success when fetching - SuccessMsg struct{} - - // ErrMsg: this message represents an error when fetching - ErrMsg struct { - err error - } -) - -// MainModel: the main model is the central state manager of the TUI, decides which model is focused based on certain commands -type MainModel struct { - state sessionState - dashboard tea.Model - contributor tea.Model -} - -// View: the view of the TUI -func (m MainModel) View() string { - switch m.state { - case contributorView: - return m.contributor.View() - default: - return m.dashboard.View() - } -} - -// Init: initial IO before program start -func (m MainModel) Init() tea.Cmd { - return nil -} - -// Update: Handle IO and Commands -func (m MainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmd tea.Cmd - var cmds []tea.Cmd - switch msg := msg.(type) { - case BackMsg: - m.state = dashboardView - case SuccessMsg: - m.state = contributorView - case SelectMsg: - newContributor, newCmd := m.contributor.Update(msg) - m.contributor = newContributor - cmds = append(cmds, newCmd) - } - - switch m.state { - case dashboardView: - newDashboard, newCmd := m.dashboard.Update(msg) - m.dashboard = newDashboard - cmd = newCmd - case contributorView: - newContributor, newCmd := m.contributor.Update(msg) - m.contributor = newContributor - cmd = newCmd - } - cmds = append(cmds, cmd) - return m, tea.Batch(cmds...) -} - -func pizzaTUI(opts *Options) error { - dashboardModel, err := InitDashboard(opts) - if err != nil { - return err - } - - contributorModel, err := InitContributor(opts) - if err != nil { - return err - } - - model := MainModel{dashboard: dashboardModel, contributor: contributorModel} - if _, err := tea.NewProgram(model, tea.WithAltScreen()).Run(); err != nil { - return fmt.Errorf("Error running program: %s", err.Error()) - } - - return nil -} diff --git a/go.mod b/go.mod index bdc4c57..971cc6b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.22 require ( github.com/charmbracelet/bubbles v0.19.0 - github.com/charmbracelet/bubbletea v0.27.1 github.com/charmbracelet/lipgloss v0.13.0 github.com/cli/browser v1.3.0 github.com/go-git/go-git/v5 v5.12.0 @@ -17,11 +16,12 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require github.com/charmbracelet/bubbletea v0.27.1 // indirect + require ( dario.cat/mergo v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect - github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/charmbracelet/x/input v0.1.0 // indirect @@ -47,7 +47,6 @@ require ( github.com/muesli/termenv v0.15.2 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/sahilm/fuzzy v0.1.1 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect diff --git a/go.sum b/go.sum index d56ee97..6f949cf 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= @@ -80,8 +78,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -114,8 +110,6 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= -github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=