From ba37e2333d3a4b8b404ae17aa6d65a683b98c425 Mon Sep 17 00:00:00 2001 From: Josh Kraft Date: Wed, 5 Apr 2023 15:36:45 -0600 Subject: [PATCH] add "showing x of y organizations" header --- pkg/cmd/org/list/http.go | 27 ++++++++++----- pkg/cmd/org/list/list.go | 18 ++++++++-- pkg/cmd/org/list/list_test.go | 62 ++++++++++++++++++++--------------- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/pkg/cmd/org/list/http.go b/pkg/cmd/org/list/http.go index 37f19f39c..5bd06d092 100644 --- a/pkg/cmd/org/list/http.go +++ b/pkg/cmd/org/list/http.go @@ -6,17 +6,24 @@ import ( "github.com/cli/cli/v2/api" ) +type OrganizationList struct { + Organizations []Organization + TotalCount int + User string +} + type Organization struct { Login string } -func listOrgs(httpClient *http.Client, hostname string, limit int) (*[]Organization, error) { +func listOrgs(httpClient *http.Client, hostname string, limit int) (*OrganizationList, error) { type response struct { User struct { Login string Organizations struct { - Nodes []Organization - PageInfo struct { + TotalCount int + Nodes []Organization + PageInfo struct { HasNextPage bool EndCursor string } @@ -28,6 +35,7 @@ func listOrgs(httpClient *http.Client, hostname string, limit int) (*[]Organizat user(login: $user) { login organizations(first: $limit, after: $endCursor) { + totalCount nodes { login } @@ -46,7 +54,8 @@ func listOrgs(httpClient *http.Client, hostname string, limit int) (*[]Organizat return nil, err } - orgs := []Organization{} + listResult := OrganizationList{} + listResult.User = user pageLimit := min(limit, 100) variables := map[string]interface{}{ "user": user, @@ -61,22 +70,24 @@ loop: return nil, err } + listResult.TotalCount = data.User.Organizations.TotalCount + for _, org := range data.User.Organizations.Nodes { - orgs = append(orgs, org) - if len(orgs) == limit { + listResult.Organizations = append(listResult.Organizations, org) + if len(listResult.Organizations) == limit { break loop } } if data.User.Organizations.PageInfo.HasNextPage { variables["endCursor"] = data.User.Organizations.PageInfo.EndCursor - pageLimit = min(pageLimit, limit-len(orgs)) + pageLimit = min(pageLimit, limit-len(listResult.Organizations)) } else { break } } - return &orgs, nil + return &listResult, nil } func min(a, b int) int { diff --git a/pkg/cmd/org/list/list.go b/pkg/cmd/org/list/list.go index 6006cf237..c30dc8b1a 100644 --- a/pkg/cmd/org/list/list.go +++ b/pkg/cmd/org/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/tableprinter" + "github.com/cli/cli/v2/internal/text" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" "github.com/spf13/cobra" @@ -78,9 +79,14 @@ func listRun(opts *ListOptions) error { } defer opts.IO.StopPager() + if opts.IO.IsStdoutTTY() { + header := listHeader(listResult.User, len(listResult.Organizations), listResult.TotalCount) + fmt.Fprintf(opts.IO.Out, "\n%s\n\n", header) + } + table := tableprinter.New(opts.IO) - table.HeaderRow("Name") - for _, org := range *listResult { + + for _, org := range listResult.Organizations { table.AddField(org.Login) table.EndRow() } @@ -92,3 +98,11 @@ func listRun(opts *ListOptions) error { return nil } + +func listHeader(user string, resultCount, totalCount int) string { + if totalCount == 0 { + return "There are no organizations associated with @" + user + } + + return fmt.Sprintf("Showing %d of %s", resultCount, text.Pluralize(totalCount, "organization")) +} diff --git a/pkg/cmd/org/list/list_test.go b/pkg/cmd/org/list/list_test.go index e8aa98cfc..8efc0a49e 100644 --- a/pkg/cmd/org/list/list_test.go +++ b/pkg/cmd/org/list/list_test.go @@ -2,11 +2,10 @@ package list import ( "bytes" - "fmt" "net/http" - "strings" "testing" + "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" @@ -82,7 +81,7 @@ func TestListRun(t *testing.T) { name string opts ListOptions isTTY bool - wantOut []string + wantOut string }{ { name: "no organizations found", @@ -97,7 +96,7 @@ func TestListRun(t *testing.T) { httpmock.GraphQL(`query OrganizationList\b`), httpmock.StringResponse(` { "data": { "user": { - "organizations": { "nodes": [] } + "organizations": { "nodes": [], "totalCount": 0 } } } }`, ), ) @@ -105,9 +104,11 @@ func TestListRun(t *testing.T) { return &http.Client{Transport: r}, nil }}, isTTY: true, - wantOut: []string{ - "NAME", - }, + wantOut: heredoc.Doc(` + +There are no organizations associated with @octocat + +`), }, { name: "default behavior", @@ -121,7 +122,9 @@ func TestListRun(t *testing.T) { r.Register( httpmock.GraphQL(`query OrganizationList\b`), httpmock.StringResponse(` - { "data": { "user": { "organizations": { "nodes": [ + { "data": { "user": { "organizations": { + "totalCount": 2, + "nodes": [ { "login": "github" }, @@ -135,11 +138,13 @@ func TestListRun(t *testing.T) { return &http.Client{Transport: r}, nil }}, isTTY: true, - wantOut: []string{ - "NAME", - "github", - "cli", - }, + wantOut: heredoc.Doc(` + +Showing 2 of 2 organizations + +github +cli +`), }, { name: "with limit", @@ -153,7 +158,9 @@ func TestListRun(t *testing.T) { r.Register( httpmock.GraphQL(`query OrganizationList\b`), httpmock.StringResponse(` - { "data": { "user": { "organizations": { "nodes": [ + { "data": { "user": { "organizations": { + "totalCount": 2, + "nodes": [ { "login": "github" }, @@ -167,10 +174,12 @@ func TestListRun(t *testing.T) { return &http.Client{Transport: r}, nil }}, isTTY: true, - wantOut: []string{ - "NAME", - "github", - }, + wantOut: heredoc.Doc(` + +Showing 1 of 2 organizations + +github +`), }, { name: "nontty output", @@ -184,7 +193,9 @@ func TestListRun(t *testing.T) { r.Register( httpmock.GraphQL(`query OrganizationList\b`), httpmock.StringResponse(` - { "data": { "user": { "organizations": { "nodes": [ + { "data": { "user": { "organizations": { + "totalCount": 2, + "nodes": [ { "login": "github" }, @@ -197,10 +208,10 @@ func TestListRun(t *testing.T) { return &http.Client{Transport: r}, nil }}, isTTY: false, - wantOut: []string{ - "github", - "cli", - }, + wantOut: heredoc.Doc(` +github +cli +`), }, } @@ -218,10 +229,9 @@ func TestListRun(t *testing.T) { } err := listRun(&tt.opts) - assert.NoError(t, err) - expected := fmt.Sprintf("%s\n", strings.Join(tt.wantOut, "\n")) - assert.Equal(t, expected, stdout.String()) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, stdout.String()) }) } }