Skip to content

Commit

Permalink
create pizza show
Browse files Browse the repository at this point in the history
testing go-client

Adding general repository info to TUI (issues, forks, size, stars)

centralized state manager structure with nested models, and start of contributors model

Added contributor model stats and interactivity through table selection in dashboard model

tidy

improving error handling flow, and adding basic dashboard responsiveness for horizontal layouts

tidy
  • Loading branch information
k1nho committed Sep 3, 2023
1 parent a73bf91 commit 3eaf9fc
Show file tree
Hide file tree
Showing 10 changed files with 837 additions and 3 deletions.
2 changes: 2 additions & 0 deletions cmd/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/open-sauced/pizza-cli/cmd/bake"
repoquery "github.com/open-sauced/pizza-cli/cmd/repo-query"
"github.com/open-sauced/pizza-cli/cmd/version"
"github.com/open-sauced/pizza-cli/cmd/show"
"github.com/open-sauced/pizza-cli/pkg/api"
)

Expand All @@ -30,6 +31,7 @@ func NewRootCommand() (*cobra.Command, error) {
cmd.AddCommand(repoquery.NewRepoQueryCommand())
cmd.AddCommand(auth.NewLoginCommand())
cmd.AddCommand(version.NewVersionCommand())
cmd.AddCommand(show.NewShowCommand())

return cmd, nil
}
Expand Down
190 changes: 190 additions & 0 deletions cmd/show/contributors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package show

import (
"context"
"errors"
"fmt"
"sync"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
client "github.com/open-sauced/go-api/client"
)

// ContributorModel holds all the information related to a contributor
type ContributorModel struct {
username string
userInfo *client.DbUser
userPrs []client.DbPullRequest
}

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(contributorName string) (ContributorModel, error) {
var contributorModel ContributorModel
contributorModel.username = contributorName

err := contributorModel.fetchUser()
if err != nil {
return contributorModel, err
}

return contributorModel, 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.KeyMsg:
switch msg.String() {
case "backspace":
return m, func() tea.Msg { return BackMsg{} }
case "q", "esc", "ctrl+c", "ctrl+d":
return m, tea.Quit
}
}
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() error {
var (
wg sync.WaitGroup
errChan = make(chan error, 2)
)

wg.Add(2)
go func() {
defer wg.Done()
userInfo, err := fetchContributorInfo(m.username)
if err != nil {
errChan <- err
return
}
m.userInfo = userInfo

}()

go func() {
defer wg.Done()
userPRs, err := fetchContributorPRs(m.username)
if err != nil {
errChan <- err
return
}
m.userPrs = userPRs
}()

wg.Wait()
close(errChan)
if len(errChan) > 0 {
var allErrors error
for err := range errChan {
allErrors = errors.Join(allErrors, err)
}
return allErrors
}

return nil
}

// fetchContributorInfo: fetches the contributor info
func fetchContributorInfo(name string) (*client.DbUser, error) {
config := client.NewConfiguration()
apiClient := client.NewAPIClient(config)
ctx := context.WithValue(context.Background(), client.ContextServerIndex, 1)

resp, r, err := apiClient.UserServiceAPI.FindOneUserByUserame(ctx, name).Execute()
if err != nil {
return nil, err
}

if r.StatusCode != 200 {
return nil, fmt.Errorf("HTTP failed: %d", r.StatusCode)
}

return resp, nil
}

// fetchContributorPRs: fetches the contributor pull requests
func fetchContributorPRs(name string) ([]client.DbPullRequest, error) {
config := client.NewConfiguration()
apiClient := client.NewAPIClient(config)
ctx := context.WithValue(context.Background(), client.ContextServerIndex, 1)

resp, r, err := apiClient.UserServiceAPI.FindContributorPullRequests(ctx, name).Execute()
if err != nil {
return nil, err
}

if r.StatusCode != 200 {
return nil, fmt.Errorf("HTTP failed: %d", r.StatusCode)
}

return resp.Data, nil
}

// drawContributorView: view of the contributor model
func (m *ContributorModel) drawContributorView() string {
return Viewport.Copy().Render(lipgloss.JoinVertical(lipgloss.Center, m.drawContributorInfo(), m.drawPullRequests()))
}

// 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): %d%%", m.userInfo.RecentPullRequestVelocityCount)
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)
}

// drawPullRequests: view of the contributor pull requests (draws the last 5 pull requests)
func (m *ContributorModel) drawPullRequests() string {
if len(m.userPrs) == 0 {
return ""
}

pullRequests := []string{}
var numberOfPrs int

if len(m.userPrs) > 5 {
numberOfPrs = 5
} else {
numberOfPrs = len(m.userPrs)
}

for i := 0; i < numberOfPrs; i++ {
prContainer := TextContainer.Render(fmt.Sprintf("#%d %s\n%s\n(%s)", m.userPrs[i].Number, m.userPrs[i].GetFullName(),
m.userPrs[i].Title, m.userPrs[i].State))
pullRequests = append(pullRequests, prContainer)
}

formattedPrs := lipgloss.JoinVertical(lipgloss.Left, pullRequests...)
title := lipgloss.NewStyle().AlignHorizontal(lipgloss.Center).Render("✨ Latest Pull Requests")

pullRequestView := lipgloss.JoinVertical(lipgloss.Center, title, formattedPrs)
return WidgetContainer.Render(pullRequestView)
}
Loading

0 comments on commit 3eaf9fc

Please sign in to comment.