package list
import (
"fmt"
"net/http"
"github.com/MakeNowJust/heredoc/v2"
"github.com/spf13/cobra"
"gitcode.com/gitcode-cli/cli/api"
"gitcode.com/gitcode-cli/cli/pkg/cmd/discussions/render"
cmdutil "gitcode.com/gitcode-cli/cli/pkg/cmdutil"
"gitcode.com/gitcode-cli/cli/pkg/iostreams"
)
type ListOptions struct {
IO *iostreams.IOStreams
HttpClient func() (*http.Client, error)
Org string
Limit int
LimitSet bool
Page int
PerPage int
Sort string
Direction string
Search string
JSON bool
}
func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
opts := &ListOptions{
IO: f.IOStreams,
HttpClient: f.HttpClient,
}
cmd := &cobra.Command{
Use: "list",
Short: "List organization discussions",
Long: heredoc.Doc(`
List discussions (discuss) in a GitCode organization via the v5 API
(GET /api/v5/orgs/{org}/discuss). Filters are applied server-side.
Use --json for machine-readable output.
`),
Example: heredoc.Doc(`
# List discussions in an organization
$ gc discussions list --org my-org
# Search by title/description
$ gc discussions list --org my-org --search "release plan"
# Sort by comment count, descending
$ gc discussions list --org my-org --sort comment_size --direction desc
# Output as JSON
$ gc discussions list --org my-org --json
`),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
if runF != nil {
return runF(opts)
}
opts.LimitSet = cmd.Flags().Changed("limit")
return listRun(opts)
},
}
cmd.Flags().StringVar(&opts.Org, "org", "", "Organization path (required)")
cmd.MarkFlagRequired("org")
cmd.Flags().IntVarP(&opts.Limit, "limit", "L", 30, "Maximum number of discussions to list")
cmd.Flags().IntVar(&opts.Page, "page", 0, "Page number (1-based)")
cmd.Flags().IntVar(&opts.PerPage, "per-page", 0, "Page size (max 100, default 20)")
cmd.Flags().StringVar(&opts.Sort, "sort", "", "Sort field: created (default) or comment_size")
cmd.Flags().StringVar(&opts.Direction, "direction", "", "Sort direction: asc or desc (default desc)")
cmd.Flags().StringVar(&opts.Search, "search", "", "Filter by title/description")
cmdutil.AddJSONFlag(cmd, &opts.JSON)
return cmd
}
func listRun(opts *ListOptions) error {
if opts.Org == "" {
return cmdutil.NewUsageError("--org is required")
}
if opts.Limit <= 0 {
return cmdutil.NewUsageError("--limit must be greater than 0")
}
if opts.Page < 0 {
return cmdutil.NewUsageError("--page must be greater than or equal to 0")
}
if opts.PerPage < 0 || opts.PerPage > 100 {
return cmdutil.NewUsageError("--per-page must be between 0 and 100")
}
if opts.Sort != "" && opts.Sort != "created" && opts.Sort != "comment_size" {
return cmdutil.NewUsageError("--sort must be created or comment_size")
}
if opts.Direction != "" && opts.Direction != "asc" && opts.Direction != "desc" {
return cmdutil.NewUsageError("--direction must be asc or desc")
}
httpClient, err := opts.HttpClient()
if err != nil {
return fmt.Errorf("failed to create HTTP client: %w", err)
}
client, err := cmdutil.AuthenticatedClient(httpClient)
if err != nil {
return err
}
discussions, err := api.ListOrgDiscussions(client, opts.Org, &api.ListOrgDiscussionsOptions{
Page: opts.Page,
PerPage: opts.PerPage,
Sort: opts.Sort,
Direction: opts.Direction,
Search: opts.Search,
})
if err != nil {
return err
}
discussions = trimDiscussions(discussions, opts)
if opts.JSON {
return cmdutil.WriteJSON(opts.IO.Out, discussions)
}
render.PrintDiscussions(opts.IO, discussions)
return nil
}
func trimDiscussions(discussions []*api.Discussion, opts *ListOptions) []*api.Discussion {
if len(discussions) > opts.Limit {
return discussions[:opts.Limit]
}
return discussions
}