diff --git a/pkg/cmd/project/close/close.go b/pkg/cmd/project/close/close.go index 352a33615..9bac43af3 100644 --- a/pkg/cmd/project/close/close.go +++ b/pkg/cmd/project/close/close.go @@ -34,6 +34,7 @@ type updateProjectMutation struct { } `graphql:"updateProjectV2(input:$input)"` } +// NewCmdClose creates the cobra command for closing a project. func NewCmdClose(f *cmdutil.Factory, runF func(config closeConfig) error) *cobra.Command { opts := closeOpts{} closeCmd := &cobra.Command{ diff --git a/pkg/cmd/project/copy/copy.go b/pkg/cmd/project/copy/copy.go index f020451cc..0a32e334f 100644 --- a/pkg/cmd/project/copy/copy.go +++ b/pkg/cmd/project/copy/copy.go @@ -36,6 +36,7 @@ type copyProjectMutation struct { } `graphql:"copyProjectV2(input:$input)"` } +// NewCmdCopy creates the cobra command for copying a project. func NewCmdCopy(f *cmdutil.Factory, runF func(config copyConfig) error) *cobra.Command { opts := copyOpts{} copyCmd := &cobra.Command{ diff --git a/pkg/cmd/project/create/create.go b/pkg/cmd/project/create/create.go index bbaae8a64..0cd68ebcc 100644 --- a/pkg/cmd/project/create/create.go +++ b/pkg/cmd/project/create/create.go @@ -31,6 +31,7 @@ type createProjectMutation struct { } `graphql:"createProjectV2(input:$input)"` } +// NewCmdCreate creates the cobra command for creating a project. func NewCmdCreate(f *cmdutil.Factory, runF func(config createConfig) error) *cobra.Command { opts := createOpts{} createCmd := &cobra.Command{ diff --git a/pkg/cmd/project/delete/delete.go b/pkg/cmd/project/delete/delete.go index b396a2f1f..62b7c628a 100644 --- a/pkg/cmd/project/delete/delete.go +++ b/pkg/cmd/project/delete/delete.go @@ -32,6 +32,7 @@ type deleteProjectMutation struct { } `graphql:"deleteProjectV2(input:$input)"` } +// NewCmdDelete creates the cobra command for deleting a project. func NewCmdDelete(f *cmdutil.Factory, runF func(config deleteConfig) error) *cobra.Command { opts := deleteOpts{} deleteCmd := &cobra.Command{ diff --git a/pkg/cmd/project/edit/edit.go b/pkg/cmd/project/edit/edit.go index 2dc8aa572..8ca57f032 100644 --- a/pkg/cmd/project/edit/edit.go +++ b/pkg/cmd/project/edit/edit.go @@ -39,6 +39,7 @@ type updateProjectMutation struct { const projectVisibilityPublic = "PUBLIC" const projectVisibilityPrivate = "PRIVATE" +// NewCmdEdit creates the cobra command for editing a project. func NewCmdEdit(f *cmdutil.Factory, runF func(config editConfig) error) *cobra.Command { opts := editOpts{} editCmd := &cobra.Command{ diff --git a/pkg/cmd/project/field-create/field_create.go b/pkg/cmd/project/field-create/field_create.go index 143719f47..798766df4 100644 --- a/pkg/cmd/project/field-create/field_create.go +++ b/pkg/cmd/project/field-create/field_create.go @@ -35,6 +35,7 @@ type createProjectV2FieldMutation struct { } `graphql:"createProjectV2Field(input:$input)"` } +// NewCmdCreateField creates the cobra command for creating a project field. func NewCmdCreateField(f *cmdutil.Factory, runF func(config createFieldConfig) error) *cobra.Command { opts := createFieldOpts{} createFieldCmd := &cobra.Command{ diff --git a/pkg/cmd/project/field-delete/field_delete.go b/pkg/cmd/project/field-delete/field_delete.go index f8b97826b..7892a6f29 100644 --- a/pkg/cmd/project/field-delete/field_delete.go +++ b/pkg/cmd/project/field-delete/field_delete.go @@ -28,6 +28,7 @@ type deleteProjectV2FieldMutation struct { } `graphql:"deleteProjectV2Field(input:$input)"` } +// NewCmdDeleteField creates the cobra command for deleting a project field. func NewCmdDeleteField(f *cmdutil.Factory, runF func(config deleteFieldConfig) error) *cobra.Command { opts := deleteFieldOpts{} deleteFieldCmd := &cobra.Command{ diff --git a/pkg/cmd/project/field-list/field_list.go b/pkg/cmd/project/field-list/field_list.go index 51340c687..72ce60ea2 100644 --- a/pkg/cmd/project/field-list/field_list.go +++ b/pkg/cmd/project/field-list/field_list.go @@ -26,6 +26,7 @@ type listConfig struct { opts listOpts } +// NewCmdList creates the cobra command for listing fields in a project. func NewCmdList(f *cmdutil.Factory, runF func(config listConfig) error) *cobra.Command { opts := listOpts{} listCmd := &cobra.Command{ diff --git a/pkg/cmd/project/item-add/item_add.go b/pkg/cmd/project/item-add/item_add.go index 00c610f0d..4131d4b84 100644 --- a/pkg/cmd/project/item-add/item_add.go +++ b/pkg/cmd/project/item-add/item_add.go @@ -34,6 +34,7 @@ type addProjectItemMutation struct { } `graphql:"addProjectV2ItemById(input:$input)"` } +// NewCmdAddItem creates the cobra command for adding an item to a project. func NewCmdAddItem(f *cmdutil.Factory, runF func(config addItemConfig) error) *cobra.Command { opts := addItemOpts{} addItemCmd := &cobra.Command{ diff --git a/pkg/cmd/project/item-archive/item_archive.go b/pkg/cmd/project/item-archive/item_archive.go index ec19b4fcc..850afdaae 100644 --- a/pkg/cmd/project/item-archive/item_archive.go +++ b/pkg/cmd/project/item-archive/item_archive.go @@ -40,6 +40,7 @@ type unarchiveProjectItemMutation struct { } `graphql:"unarchiveProjectV2Item(input:$input)"` } +// NewCmdArchiveItem creates the cobra command for archiving a project item. func NewCmdArchiveItem(f *cmdutil.Factory, runF func(config archiveItemConfig) error) *cobra.Command { opts := archiveItemOpts{} archiveItemCmd := &cobra.Command{ diff --git a/pkg/cmd/project/item-create/item_create.go b/pkg/cmd/project/item-create/item_create.go index dc70fe8a4..dae7714a3 100644 --- a/pkg/cmd/project/item-create/item_create.go +++ b/pkg/cmd/project/item-create/item_create.go @@ -34,6 +34,7 @@ type createProjectDraftItemMutation struct { } `graphql:"addProjectV2DraftIssue(input:$input)"` } +// NewCmdCreateItem creates the cobra command for creating a draft issue in a project. func NewCmdCreateItem(f *cmdutil.Factory, runF func(config createItemConfig) error) *cobra.Command { opts := createItemOpts{} createItemCmd := &cobra.Command{ diff --git a/pkg/cmd/project/item-delete/item_delete.go b/pkg/cmd/project/item-delete/item_delete.go index df5df20e9..b6c741002 100644 --- a/pkg/cmd/project/item-delete/item_delete.go +++ b/pkg/cmd/project/item-delete/item_delete.go @@ -33,6 +33,7 @@ type deleteProjectItemMutation struct { } `graphql:"deleteProjectV2Item(input:$input)"` } +// NewCmdDeleteItem creates the cobra command for deleting a project item. func NewCmdDeleteItem(f *cmdutil.Factory, runF func(config deleteItemConfig) error) *cobra.Command { opts := deleteItemOpts{} deleteItemCmd := &cobra.Command{ diff --git a/pkg/cmd/project/item-edit/item_edit.go b/pkg/cmd/project/item-edit/item_edit.go index 6eb44caf4..dd0936274 100644 --- a/pkg/cmd/project/item-edit/item_edit.go +++ b/pkg/cmd/project/item-edit/item_edit.go @@ -41,30 +41,35 @@ type editItemConfig struct { opts editItemOpts } +// EditProjectDraftIssue is the GraphQL mutation response for updating a draft issue. type EditProjectDraftIssue struct { UpdateProjectV2DraftIssue struct { DraftIssue queries.DraftIssue `graphql:"draftIssue"` } `graphql:"updateProjectV2DraftIssue(input:$input)"` } +// DraftIssueQuery is the GraphQL query response for fetching a draft issue by ID. type DraftIssueQuery struct { DraftIssueNode struct { DraftIssue queries.DraftIssue `graphql:"... on DraftIssue"` } `graphql:"node(id: $id)"` } +// UpdateProjectV2FieldValue is the GraphQL mutation response for updating a project item field value. type UpdateProjectV2FieldValue struct { Update struct { Item queries.ProjectItem `graphql:"projectV2Item"` } `graphql:"updateProjectV2ItemFieldValue(input:$input)"` } +// ClearProjectV2FieldValue is the GraphQL mutation response for clearing a project item field value. type ClearProjectV2FieldValue struct { Clear struct { Item queries.ProjectItem `graphql:"projectV2Item"` } `graphql:"clearProjectV2ItemFieldValue(input:$input)"` } +// NewCmdEditItem creates the cobra command for editing a project item. func NewCmdEditItem(f *cmdutil.Factory, runF func(config editItemConfig) error) *cobra.Command { opts := editItemOpts{} editItemCmd := &cobra.Command{ diff --git a/pkg/cmd/project/item-list/item_list.go b/pkg/cmd/project/item-list/item_list.go index 1ff4c55ed..b0e8eb534 100644 --- a/pkg/cmd/project/item-list/item_list.go +++ b/pkg/cmd/project/item-list/item_list.go @@ -31,6 +31,7 @@ type listConfig struct { detector fd.Detector } +// NewCmdList creates the cobra command for listing items in a project. func NewCmdList(f *cmdutil.Factory, runF func(config listConfig) error) *cobra.Command { opts := listOpts{} listCmd := &cobra.Command{ diff --git a/pkg/cmd/project/link/link.go b/pkg/cmd/project/link/link.go index f2477dde4..6fde31602 100644 --- a/pkg/cmd/project/link/link.go +++ b/pkg/cmd/project/link/link.go @@ -37,6 +37,7 @@ type linkConfig struct { io *iostreams.IOStreams } +// NewCmdLink creates the cobra command for linking a project to a repository or team. func NewCmdLink(f *cmdutil.Factory, runF func(config linkConfig) error) *cobra.Command { opts := linkOpts{} linkCmd := &cobra.Command{ diff --git a/pkg/cmd/project/list/list.go b/pkg/cmd/project/list/list.go index 01868b4c3..75d6d05c2 100644 --- a/pkg/cmd/project/list/list.go +++ b/pkg/cmd/project/list/list.go @@ -29,6 +29,7 @@ type listConfig struct { io *iostreams.IOStreams } +// NewCmdList creates the cobra command for listing projects. func NewCmdList(f *cmdutil.Factory, runF func(config listConfig) error) *cobra.Command { opts := listOpts{} listCmd := &cobra.Command{ diff --git a/pkg/cmd/project/mark-template/mark_template.go b/pkg/cmd/project/mark-template/mark_template.go index 170dda821..8bb10c85b 100644 --- a/pkg/cmd/project/mark-template/mark_template.go +++ b/pkg/cmd/project/mark-template/mark_template.go @@ -38,6 +38,7 @@ type unmarkProjectTemplateMutation struct { } `graphql:"unmarkProjectV2AsTemplate(input:$input)"` } +// NewCmdMarkTemplate creates the cobra command for marking a project as a template. func NewCmdMarkTemplate(f *cmdutil.Factory, runF func(config markTemplateConfig) error) *cobra.Command { opts := markTemplateOpts{} markTemplateCmd := &cobra.Command{ diff --git a/pkg/cmd/project/project.go b/pkg/cmd/project/project.go index cddbad940..d6e276abf 100644 --- a/pkg/cmd/project/project.go +++ b/pkg/cmd/project/project.go @@ -25,6 +25,7 @@ import ( "github.com/spf13/cobra" ) +// NewCmdProject creates the top-level cobra command for working with GitHub Projects. func NewCmdProject(f *cmdutil.Factory) *cobra.Command { var cmd = &cobra.Command{ Use: "project ", diff --git a/pkg/cmd/project/shared/client/client.go b/pkg/cmd/project/shared/client/client.go index 1f5835a54..9aab0c500 100644 --- a/pkg/cmd/project/shared/client/client.go +++ b/pkg/cmd/project/shared/client/client.go @@ -7,6 +7,7 @@ import ( "github.com/cli/cli/v2/pkg/cmdutil" ) +// New creates a new project queries client from the given factory. func New(f *cmdutil.Factory) (*queries.Client, error) { if f.HttpClient == nil { // This is for compatibility with tests that exercise Cobra command functionality. diff --git a/pkg/cmd/project/shared/format/display.go b/pkg/cmd/project/shared/format/display.go index 498fd7f2b..7d676051a 100644 --- a/pkg/cmd/project/shared/format/display.go +++ b/pkg/cmd/project/shared/format/display.go @@ -4,6 +4,7 @@ import ( "github.com/cli/cli/v2/pkg/cmd/project/shared/queries" ) +// ProjectState returns the display state string ("open" or "closed") for a project. func ProjectState(project queries.Project) string { if project.Closed { return "closed" @@ -11,6 +12,7 @@ func ProjectState(project queries.Project) string { return "open" } +// ColorForProjectState returns the display color for a project based on its state. func ColorForProjectState(project queries.Project) string { if project.Closed { return "gray" diff --git a/pkg/cmd/project/shared/queries/queries.go b/pkg/cmd/project/shared/queries/queries.go index 9a3bd4909..24430b5a5 100644 --- a/pkg/cmd/project/shared/queries/queries.go +++ b/pkg/cmd/project/shared/queries/queries.go @@ -15,6 +15,7 @@ import ( "github.com/shurcooL/githubv4" ) +// NewClient creates a new project queries Client for the given HTTP client and hostname. func NewClient(httpClient *http.Client, hostname string, ios *iostreams.IOStreams) *Client { apiClient := &hostScopedClient{ hostname: hostname, @@ -37,6 +38,7 @@ func WithPrompter(p iprompter) TestClientOpt { } } +// NewTestClient creates a Client suitable for use in tests. func NewTestClient(opts ...TestClientOpt) *Client { apiClient := &hostScopedClient{ hostname: "github.com", @@ -64,10 +66,12 @@ type hostScopedClient struct { hostname string } +// Query executes a GraphQL query scoped to the client's hostname. func (c *hostScopedClient) Query(queryName string, query interface{}, variables map[string]interface{}) error { return c.Client.Query(c.hostname, queryName, query, variables) } +// Mutate executes a GraphQL mutation scoped to the client's hostname. func (c *hostScopedClient) Mutate(queryName string, query interface{}, variables map[string]interface{}) error { return c.Client.Mutate(c.hostname, queryName, query, variables) } @@ -77,6 +81,7 @@ type graphqlClient interface { Mutate(queryName string, query interface{}, variables map[string]interface{}) error } +// Client wraps a GraphQL API client for project operations. type Client struct { apiClient graphqlClient io *iostreams.IOStreams @@ -84,6 +89,7 @@ type Client struct { } const ( + // LimitDefault is the default number of items to fetch per page. LimitDefault = 30 LimitMax = 100 // https://docs.github.com/en/graphql/overview/resource-limitations#node-limit ) @@ -103,6 +109,7 @@ func (c *Client) Mutate(operationName string, query interface{}, variables map[s return handleError(err) } +// Query executes a raw GraphQL query with error handling. func (c *Client) Query(operationName string, query interface{}, variables map[string]interface{}) error { err := c.apiClient.Query(operationName, query, variables) return handleError(err) @@ -257,6 +264,7 @@ func newProjectFromQueryWithoutItemsQuery(source projectQueryWithoutQueryableIte return project } +// DetailedItems returns project items with their field values as a serializable map. func (p Project) DetailedItems() map[string]interface{} { return map[string]interface{}{ "items": serializeProjectWithItems(&p), @@ -264,6 +272,7 @@ func (p Project) DetailedItems() map[string]interface{} { } } +// ExportData returns the project data as a serializable map. func (p Project) ExportData(_ []string) map[string]interface{} { return map[string]interface{}{ "number": p.Number, @@ -287,10 +296,12 @@ func (p Project) ExportData(_ []string) map[string]interface{} { } } +// OwnerType returns the type name of the project owner. func (p Project) OwnerType() string { return p.Owner.TypeName } +// OwnerLogin returns the login of the project owner. func (p Project) OwnerLogin() string { if p.OwnerType() == "User" { return p.Owner.User.Login @@ -298,6 +309,7 @@ func (p Project) OwnerLogin() string { return p.Owner.Organization.Login } +// ExportData returns the mutation query project data as a serializable map. func (p ProjectMutationQuery) ExportData(_ []string) map[string]interface{} { return map[string]interface{}{ "number": p.Number, @@ -321,10 +333,12 @@ func (p ProjectMutationQuery) ExportData(_ []string) map[string]interface{} { } } +// OwnerType returns the type name of the mutation query project owner. func (p ProjectMutationQuery) OwnerType() string { return p.Owner.TypeName } +// OwnerLogin returns the login of the mutation query project owner. func (p ProjectMutationQuery) OwnerLogin() string { if p.OwnerType() == "User" { return p.Owner.User.Login @@ -332,11 +346,13 @@ func (p ProjectMutationQuery) OwnerLogin() string { return p.Owner.Organization.Login } +// Projects holds a paginated list of projects. type Projects struct { Nodes []Project TotalCount int } +// ExportData returns the projects list data as a serializable map. func (p Projects) ExportData(_ []string) map[string]interface{} { v := make([]map[string]interface{}, len(p.Nodes)) for i := range p.Nodes { @@ -357,6 +373,7 @@ type ProjectItem struct { } `graphql:"fieldValues(first: 100)"` // hardcoded to 100 for now on the assumption that this is a reasonable limit } +// ProjectItemContent holds the content union type of a project item. type ProjectItemContent struct { TypeName string `graphql:"__typename"` DraftIssue DraftIssue `graphql:"... on DraftIssue"` @@ -364,6 +381,7 @@ type ProjectItemContent struct { Issue Issue `graphql:"... on Issue"` } +// FieldValueNodes represents the value of a project item field. type FieldValueNodes struct { Type string `graphql:"__typename"` ProjectV2ItemFieldDateValue struct { @@ -443,6 +461,7 @@ type FieldValueNodes struct { } `graphql:"... on ProjectV2ItemFieldReviewerValue"` } +// ID returns the field ID associated with this field value node. func (v FieldValueNodes) ID() string { switch v.Type { case "ProjectV2ItemFieldDateValue": @@ -472,12 +491,14 @@ func (v FieldValueNodes) ID() string { return "" } +// DraftIssue represents a draft issue in a project. type DraftIssue struct { ID string Body string Title string } +// ExportData returns the draft issue data as a serializable map. func (i DraftIssue) ExportData(_ []string) map[string]interface{} { v := map[string]interface{}{ "title": i.Title, @@ -491,6 +512,7 @@ func (i DraftIssue) ExportData(_ []string) map[string]interface{} { return v } +// PullRequest represents a pull request linked to a project item. type PullRequest struct { Body string Title string @@ -501,6 +523,7 @@ type PullRequest struct { } } +// ExportData returns the pull request data as a serializable map. func (pr PullRequest) ExportData(_ []string) map[string]interface{} { return map[string]interface{}{ "type": "PullRequest", @@ -512,6 +535,7 @@ func (pr PullRequest) ExportData(_ []string) map[string]interface{} { } } +// Issue represents an issue linked to a project item. type Issue struct { Body string Title string @@ -522,6 +546,7 @@ type Issue struct { } } +// ExportData returns the issue data as a serializable map. func (i Issue) ExportData(_ []string) map[string]interface{} { return map[string]interface{}{ "type": "Issue", @@ -533,6 +558,7 @@ func (i Issue) ExportData(_ []string) map[string]interface{} { } } +// DetailedItem returns the underlying content of the project item as an exportable type. func (p ProjectItem) DetailedItem() exportable { switch p.Type() { case "DraftIssue": @@ -637,6 +663,7 @@ func (p ProjectItem) URL() string { return "" } +// ExportData returns the project item data as a serializable map. func (p ProjectItem) ExportData(_ []string) map[string]interface{} { v := map[string]interface{}{ "id": p.ID(), @@ -728,155 +755,182 @@ type pager[N projectAttribute] interface { Project() *Project } -// userOwnerWithItemsNoQuery +// userOwnerWithItemsNoQuery implements pager for user-owned projects without item query. func (q userOwnerWithItemsNoQuery) HasNextPage() bool { return q.Owner.Project.Items.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for items. func (q userOwnerWithItemsNoQuery) EndCursor() string { return string(q.Owner.Project.Items.PageInfo.EndCursor) } +// Nodes returns the project items. func (q userOwnerWithItemsNoQuery) Nodes() []ProjectItem { return q.Owner.Project.Items.Nodes } +// Project returns the project without items query data. func (q userOwnerWithItemsNoQuery) Project() *Project { return newProjectFromQueryWithoutItemsQuery(q.Owner.Project) } -// userOwnerWithItems +// userOwnerWithItems implements pager for user-owned projects with item query. func (q userOwnerWithItems) HasNextPage() bool { return q.Owner.Project.Items.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for items. func (q userOwnerWithItems) EndCursor() string { return string(q.Owner.Project.Items.PageInfo.EndCursor) } +// Nodes returns the project items. func (q userOwnerWithItems) Nodes() []ProjectItem { return q.Owner.Project.Items.Nodes } +// Project returns the project with items query data. func (q userOwnerWithItems) Project() *Project { return newProjectFromQueryWithItemsQuery(q.Owner.Project) } -// orgOwnerWithItems +// orgOwnerWithItems implements pager for org-owned projects with item query. func (q orgOwnerWithItems) HasNextPage() bool { return q.Owner.Project.Items.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for items. func (q orgOwnerWithItems) EndCursor() string { return string(q.Owner.Project.Items.PageInfo.EndCursor) } +// Nodes returns the project items. func (q orgOwnerWithItems) Nodes() []ProjectItem { return q.Owner.Project.Items.Nodes } +// Project returns the project with items query data. func (q orgOwnerWithItems) Project() *Project { return newProjectFromQueryWithItemsQuery(q.Owner.Project) } -// orgOwnerWithItemsNoQuery +// orgOwnerWithItemsNoQuery implements pager for org-owned projects without item query. func (q orgOwnerWithItemsNoQuery) HasNextPage() bool { return q.Owner.Project.Items.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for items. func (q orgOwnerWithItemsNoQuery) EndCursor() string { return string(q.Owner.Project.Items.PageInfo.EndCursor) } +// Nodes returns the project items. func (q orgOwnerWithItemsNoQuery) Nodes() []ProjectItem { return q.Owner.Project.Items.Nodes } +// Project returns the project without items query data. func (q orgOwnerWithItemsNoQuery) Project() *Project { return newProjectFromQueryWithoutItemsQuery(q.Owner.Project) } -// viewerOwnerWithItems +// viewerOwnerWithItems implements pager for viewer-owned projects with item query. func (q viewerOwnerWithItems) HasNextPage() bool { return q.Owner.Project.Items.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for items. func (q viewerOwnerWithItems) EndCursor() string { return string(q.Owner.Project.Items.PageInfo.EndCursor) } +// Nodes returns the project items. func (q viewerOwnerWithItems) Nodes() []ProjectItem { return q.Owner.Project.Items.Nodes } +// Project returns the project with items query data. func (q viewerOwnerWithItems) Project() *Project { return newProjectFromQueryWithItemsQuery(q.Owner.Project) } -// viewerOwnerWithItemsNoQuery +// viewerOwnerWithItemsNoQuery implements pager for viewer-owned projects without item query. func (q viewerOwnerWithItemsNoQuery) HasNextPage() bool { return q.Owner.Project.Items.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for items. func (q viewerOwnerWithItemsNoQuery) EndCursor() string { return string(q.Owner.Project.Items.PageInfo.EndCursor) } +// Nodes returns the project items. func (q viewerOwnerWithItemsNoQuery) Nodes() []ProjectItem { return q.Owner.Project.Items.Nodes } +// Project returns the project without items query data. func (q viewerOwnerWithItemsNoQuery) Project() *Project { return newProjectFromQueryWithoutItemsQuery(q.Owner.Project) } -// userOwnerWithFields +// userOwnerWithFields implements pager for user-owned projects with field query. func (q userOwnerWithFields) HasNextPage() bool { return q.Owner.Project.Fields.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for fields. func (q userOwnerWithFields) EndCursor() string { return string(q.Owner.Project.Fields.PageInfo.EndCursor) } +// Nodes returns the project fields. func (q userOwnerWithFields) Nodes() []ProjectField { return q.Owner.Project.Fields.Nodes } +// Project returns the project without items query data. func (q userOwnerWithFields) Project() *Project { return newProjectFromQueryWithoutItemsQuery(q.Owner.Project) } -// orgOwnerWithFields +// orgOwnerWithFields implements pager for org-owned projects with field query. func (q orgOwnerWithFields) HasNextPage() bool { return q.Owner.Project.Fields.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for fields. func (q orgOwnerWithFields) EndCursor() string { return string(q.Owner.Project.Fields.PageInfo.EndCursor) } +// Nodes returns the project fields. func (q orgOwnerWithFields) Nodes() []ProjectField { return q.Owner.Project.Fields.Nodes } +// Project returns the project without items query data. func (q orgOwnerWithFields) Project() *Project { return newProjectFromQueryWithoutItemsQuery(q.Owner.Project) } -// viewerOwnerWithFields +// viewerOwnerWithFields implements pager for viewer-owned projects with field query. func (q viewerOwnerWithFields) HasNextPage() bool { return q.Owner.Project.Fields.PageInfo.HasNextPage } +// EndCursor returns the pagination end cursor for fields. func (q viewerOwnerWithFields) EndCursor() string { return string(q.Owner.Project.Fields.PageInfo.EndCursor) } +// Nodes returns the project fields. func (q viewerOwnerWithFields) Nodes() []ProjectField { return q.Owner.Project.Fields.Nodes } +// Project returns the project without items query data. func (q viewerOwnerWithFields) Project() *Project { return newProjectFromQueryWithoutItemsQuery(q.Owner.Project) } @@ -971,11 +1025,13 @@ func (p ProjectField) Type() string { return p.TypeName } +// SingleSelectFieldOptions represents an option for a single-select project field. type SingleSelectFieldOptions struct { ID string Name string } +// ExportData returns the single-select field option data as a serializable map. func (f SingleSelectFieldOptions) ExportData(_ []string) map[string]interface{} { return map[string]interface{}{ "id": f.ID, @@ -983,6 +1039,7 @@ func (f SingleSelectFieldOptions) ExportData(_ []string) map[string]interface{} } } +// Options returns the available options for a single-select project field. func (p ProjectField) Options() []SingleSelectFieldOptions { if p.TypeName == "ProjectV2SingleSelectField" { var options []SingleSelectFieldOptions @@ -997,6 +1054,7 @@ func (p ProjectField) Options() []SingleSelectFieldOptions { return nil } +// ExportData returns the project field data as a serializable map. func (p ProjectField) ExportData(_ []string) map[string]interface{} { v := map[string]interface{}{ "id": p.ID(), @@ -1014,12 +1072,14 @@ func (p ProjectField) ExportData(_ []string) map[string]interface{} { return v } +// ProjectFields holds a paginated list of project fields. type ProjectFields struct { TotalCount int Nodes []ProjectField PageInfo PageInfo } +// ExportData returns the project fields data as a serializable map. func (p ProjectFields) ExportData(_ []string) map[string]interface{} { fields := make([]map[string]interface{}, len(p.Nodes)) for i := range p.Nodes { @@ -1181,9 +1241,9 @@ type viewerOwnerWithFields struct { // OwnerType is the type of the owner of a project, which can be either a user or an organization. Viewer is the current user. type OwnerType string -const UserOwner OwnerType = "USER" -const OrgOwner OwnerType = "ORGANIZATION" -const ViewerOwner OwnerType = "VIEWER" +const UserOwner OwnerType = "USER" // UserOwner represents a user-owned project. +const OrgOwner OwnerType = "ORGANIZATION" // OrgOwner represents an organization-owned project. +const ViewerOwner OwnerType = "VIEWER" // ViewerOwner represents a project owned by the current viewer. // ViewerLoginName returns the login name of the viewer. func (c *Client) ViewerLoginName() (string, error) { @@ -1385,6 +1445,7 @@ func (c *Client) paginateOrgLogins(l []loginTypes, cursor string) ([]loginTypes, return l, nil } +// Owner represents the owner of a project. type Owner struct { Login string Type OwnerType diff --git a/pkg/cmd/project/unlink/unlink.go b/pkg/cmd/project/unlink/unlink.go index 8cc2c0747..2dd0c76e0 100644 --- a/pkg/cmd/project/unlink/unlink.go +++ b/pkg/cmd/project/unlink/unlink.go @@ -37,6 +37,7 @@ type unlinkConfig struct { io *iostreams.IOStreams } +// NewCmdUnlink creates the cobra command for unlinking a project from a repository or team. func NewCmdUnlink(f *cmdutil.Factory, runF func(config unlinkConfig) error) *cobra.Command { opts := unlinkOpts{} linkCmd := &cobra.Command{ diff --git a/pkg/cmd/project/view/view.go b/pkg/cmd/project/view/view.go index 49056b8d7..d34c1e509 100644 --- a/pkg/cmd/project/view/view.go +++ b/pkg/cmd/project/view/view.go @@ -28,6 +28,7 @@ type viewConfig struct { URLOpener func(string) error } +// NewCmdView creates the cobra command for viewing a project. func NewCmdView(f *cmdutil.Factory, runF func(config viewConfig) error) *cobra.Command { opts := viewOpts{} viewCmd := &cobra.Command{