add "showing x of y organizations" header

This commit is contained in:
Josh Kraft 2023-04-05 15:36:45 -06:00
parent 37970f4863
commit ba37e2333d
3 changed files with 71 additions and 36 deletions

View file

@ -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 {

View file

@ -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"))
}

View file

@ -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())
})
}
}