diff options
-rw-r--r-- | graphql/connections/connection_template.go | 3 | ||||
-rw-r--r-- | graphql/connections/connections.go | 5 | ||||
-rw-r--r-- | graphql/connections/gen_identity.go | 27 | ||||
-rw-r--r-- | graphql/connections/gen_lazy_bug.go (renamed from graphql/connections/gen_bug.go) | 0 | ||||
-rw-r--r-- | graphql/connections/gen_lazy_identity.go | 110 | ||||
-rw-r--r-- | graphql/graph/gen_graph.go | 340 | ||||
-rw-r--r-- | graphql/graphql_test.go | 75 | ||||
-rw-r--r-- | graphql/resolvers/bug.go | 54 | ||||
-rw-r--r-- | graphql/schema/bug.graphql | 27 |
9 files changed, 469 insertions, 172 deletions
diff --git a/graphql/connections/connection_template.go b/graphql/connections/connection_template.go index e98f53eb..412eb318 100644 --- a/graphql/connections/connection_template.go +++ b/graphql/connections/connection_template.go @@ -3,8 +3,9 @@ package connections import ( "fmt" - "github.com/MichaelMure/git-bug/graphql/models" "github.com/cheekybits/genny/generic" + + "github.com/MichaelMure/git-bug/graphql/models" ) // Name define the name of the connection diff --git a/graphql/connections/connections.go b/graphql/connections/connections.go index cdc6d07f..d54a5068 100644 --- a/graphql/connections/connections.go +++ b/graphql/connections/connections.go @@ -1,5 +1,6 @@ -//go:generate genny -in=connection_template.go -out=gen_bug.go gen "Name=LazyBug NodeType=string EdgeType=LazyBugEdge ConnectionType=models.BugConnection" -//go:generate genny -in=connection_template.go -out=gen_identity.go gen "Name=LazyIdentity NodeType=string EdgeType=LazyIdentityEdge ConnectionType=models.IdentityConnection" +//go:generate genny -in=connection_template.go -out=gen_lazy_bug.go gen "Name=LazyBug NodeType=string EdgeType=LazyBugEdge ConnectionType=models.BugConnection" +//go:generate genny -in=connection_template.go -out=gen_lazy_identity.go gen "Name=LazyIdentity NodeType=string EdgeType=LazyIdentityEdge ConnectionType=models.IdentityConnection" +//go:generate genny -in=connection_template.go -out=gen_identity.go gen "Name=Identity NodeType=identity.Interface EdgeType=models.IdentityEdge ConnectionType=models.IdentityConnection" //go:generate genny -in=connection_template.go -out=gen_operation.go gen "Name=Operation NodeType=bug.Operation EdgeType=models.OperationEdge ConnectionType=models.OperationConnection" //go:generate genny -in=connection_template.go -out=gen_comment.go gen "Name=Comment NodeType=bug.Comment EdgeType=models.CommentEdge ConnectionType=models.CommentConnection" //go:generate genny -in=connection_template.go -out=gen_timeline.go gen "Name=TimelineItem NodeType=bug.TimelineItem EdgeType=models.TimelineItemEdge ConnectionType=models.TimelineItemConnection" diff --git a/graphql/connections/gen_identity.go b/graphql/connections/gen_identity.go index 28501171..2ba2f98f 100644 --- a/graphql/connections/gen_identity.go +++ b/graphql/connections/gen_identity.go @@ -8,23 +8,24 @@ import ( "fmt" "github.com/MichaelMure/git-bug/graphql/models" + "github.com/MichaelMure/git-bug/identity" ) -// StringEdgeMaker define a function that take a string and an offset and +// IdentityInterfaceEdgeMaker define a function that take a identity.Interface and an offset and // create an Edge. -type LazyIdentityEdgeMaker func(value string, offset int) Edge +type IdentityEdgeMaker func(value identity.Interface, offset int) Edge -// LazyIdentityConMaker define a function that create a models.IdentityConnection -type LazyIdentityConMaker func( - edges []LazyIdentityEdge, - nodes []string, +// IdentityConMaker define a function that create a models.IdentityConnection +type IdentityConMaker func( + edges []models.IdentityEdge, + nodes []identity.Interface, info models.PageInfo, totalCount int) (models.IdentityConnection, error) -// LazyIdentityCon will paginate a source according to the input of a relay connection -func LazyIdentityCon(source []string, edgeMaker LazyIdentityEdgeMaker, conMaker LazyIdentityConMaker, input models.ConnectionInput) (models.IdentityConnection, error) { - var nodes []string - var edges []LazyIdentityEdge +// IdentityCon will paginate a source according to the input of a relay connection +func IdentityCon(source []identity.Interface, edgeMaker IdentityEdgeMaker, conMaker IdentityConMaker, input models.ConnectionInput) (models.IdentityConnection, error) { + var nodes []identity.Interface + var edges []models.IdentityEdge var cursors []string var pageInfo models.PageInfo var totalCount = len(source) @@ -56,18 +57,18 @@ func LazyIdentityCon(source []string, edgeMaker LazyIdentityEdgeMaker, conMaker break } - edges = append(edges, edge.(LazyIdentityEdge)) + edges = append(edges, edge.(models.IdentityEdge)) cursors = append(cursors, edge.GetCursor()) nodes = append(nodes, value) } } else { - edges = make([]LazyIdentityEdge, len(source)) + edges = make([]models.IdentityEdge, len(source)) cursors = make([]string, len(source)) nodes = source for i, value := range source { edge := edgeMaker(value, i+offset) - edges[i] = edge.(LazyIdentityEdge) + edges[i] = edge.(models.IdentityEdge) cursors[i] = edge.GetCursor() } } diff --git a/graphql/connections/gen_bug.go b/graphql/connections/gen_lazy_bug.go index ba0a65fa..ba0a65fa 100644 --- a/graphql/connections/gen_bug.go +++ b/graphql/connections/gen_lazy_bug.go diff --git a/graphql/connections/gen_lazy_identity.go b/graphql/connections/gen_lazy_identity.go new file mode 100644 index 00000000..28501171 --- /dev/null +++ b/graphql/connections/gen_lazy_identity.go @@ -0,0 +1,110 @@ +// This file was automatically generated by genny. +// Any changes will be lost if this file is regenerated. +// see https://github.com/cheekybits/genny + +package connections + +import ( + "fmt" + + "github.com/MichaelMure/git-bug/graphql/models" +) + +// StringEdgeMaker define a function that take a string and an offset and +// create an Edge. +type LazyIdentityEdgeMaker func(value string, offset int) Edge + +// LazyIdentityConMaker define a function that create a models.IdentityConnection +type LazyIdentityConMaker func( + edges []LazyIdentityEdge, + nodes []string, + info models.PageInfo, + totalCount int) (models.IdentityConnection, error) + +// LazyIdentityCon will paginate a source according to the input of a relay connection +func LazyIdentityCon(source []string, edgeMaker LazyIdentityEdgeMaker, conMaker LazyIdentityConMaker, input models.ConnectionInput) (models.IdentityConnection, error) { + var nodes []string + var edges []LazyIdentityEdge + var cursors []string + var pageInfo models.PageInfo + var totalCount = len(source) + + emptyCon, _ := conMaker(edges, nodes, pageInfo, 0) + + offset := 0 + + if input.After != nil { + for i, value := range source { + edge := edgeMaker(value, i) + if edge.GetCursor() == *input.After { + // remove all previous element including the "after" one + source = source[i+1:] + offset = i + 1 + pageInfo.HasPreviousPage = true + break + } + } + } + + if input.Before != nil { + for i, value := range source { + edge := edgeMaker(value, i+offset) + + if edge.GetCursor() == *input.Before { + // remove all after element including the "before" one + pageInfo.HasNextPage = true + break + } + + edges = append(edges, edge.(LazyIdentityEdge)) + cursors = append(cursors, edge.GetCursor()) + nodes = append(nodes, value) + } + } else { + edges = make([]LazyIdentityEdge, len(source)) + cursors = make([]string, len(source)) + nodes = source + + for i, value := range source { + edge := edgeMaker(value, i+offset) + edges[i] = edge.(LazyIdentityEdge) + cursors[i] = edge.GetCursor() + } + } + + if input.First != nil { + if *input.First < 0 { + return emptyCon, fmt.Errorf("first less than zero") + } + + if len(edges) > *input.First { + // Slice result to be of length first by removing edges from the end + edges = edges[:*input.First] + cursors = cursors[:*input.First] + nodes = nodes[:*input.First] + pageInfo.HasNextPage = true + } + } + + if input.Last != nil { + if *input.Last < 0 { + return emptyCon, fmt.Errorf("last less than zero") + } + + if len(edges) > *input.Last { + // Slice result to be of length last by removing edges from the start + edges = edges[len(edges)-*input.Last:] + cursors = cursors[len(cursors)-*input.Last:] + nodes = nodes[len(nodes)-*input.Last:] + pageInfo.HasPreviousPage = true + } + } + + // Fill up pageInfo cursors + if len(cursors) > 0 { + pageInfo.StartCursor = cursors[0] + pageInfo.EndCursor = cursors[len(cursors)-1] + } + + return conMaker(edges, nodes, pageInfo, totalCount) +} diff --git a/graphql/graph/gen_graph.go b/graphql/graph/gen_graph.go index 9da0c665..9c0003f2 100644 --- a/graphql/graph/gen_graph.go +++ b/graphql/graph/gen_graph.go @@ -87,10 +87,10 @@ type ComplexityRoot struct { Title func(childComplexity int) int Labels func(childComplexity int) int Author func(childComplexity int) int - Actors func(childComplexity int) int - Participants func(childComplexity int) int CreatedAt func(childComplexity int) int LastEdit func(childComplexity int) int + Actors func(childComplexity int, after *string, before *string, first *int, last *int) int + Participants func(childComplexity int, after *string, before *string, first *int, last *int) int Comments func(childComplexity int, after *string, before *string, first *int, last *int) int Timeline func(childComplexity int, after *string, before *string, first *int, last *int) int Operations func(childComplexity int, after *string, before *string, first *int, last *int) int @@ -295,10 +295,9 @@ type AddCommentTimelineItemResolver interface { type BugResolver interface { Status(ctx context.Context, obj *bug.Snapshot) (models.Status, error) - Actors(ctx context.Context, obj *bug.Snapshot) ([]*identity.Interface, error) - Participants(ctx context.Context, obj *bug.Snapshot) ([]*identity.Interface, error) - LastEdit(ctx context.Context, obj *bug.Snapshot) (time.Time, error) + Actors(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.IdentityConnection, error) + Participants(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.IdentityConnection, error) Comments(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.CommentConnection, error) Timeline(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.TimelineItemConnection, error) Operations(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.OperationConnection, error) @@ -367,6 +366,130 @@ type SetTitleTimelineItemResolver interface { Date(ctx context.Context, obj *bug.SetTitleTimelineItem) (time.Time, error) } +func field_Bug_actors_args(rawArgs map[string]interface{}) (map[string]interface{}, error) { + args := map[string]interface{}{} + var arg0 *string + if tmp, ok := rawArgs["after"]; ok { + var err error + var ptr1 string + if tmp != nil { + ptr1, err = graphql.UnmarshalString(tmp) + arg0 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["after"] = arg0 + var arg1 *string + if tmp, ok := rawArgs["before"]; ok { + var err error + var ptr1 string + if tmp != nil { + ptr1, err = graphql.UnmarshalString(tmp) + arg1 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["before"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["first"]; ok { + var err error + var ptr1 int + if tmp != nil { + ptr1, err = graphql.UnmarshalInt(tmp) + arg2 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["first"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["last"]; ok { + var err error + var ptr1 int + if tmp != nil { + ptr1, err = graphql.UnmarshalInt(tmp) + arg3 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["last"] = arg3 + return args, nil + +} + +func field_Bug_participants_args(rawArgs map[string]interface{}) (map[string]interface{}, error) { + args := map[string]interface{}{} + var arg0 *string + if tmp, ok := rawArgs["after"]; ok { + var err error + var ptr1 string + if tmp != nil { + ptr1, err = graphql.UnmarshalString(tmp) + arg0 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["after"] = arg0 + var arg1 *string + if tmp, ok := rawArgs["before"]; ok { + var err error + var ptr1 string + if tmp != nil { + ptr1, err = graphql.UnmarshalString(tmp) + arg1 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["before"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["first"]; ok { + var err error + var ptr1 int + if tmp != nil { + ptr1, err = graphql.UnmarshalInt(tmp) + arg2 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["first"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["last"]; ok { + var err error + var ptr1 int + if tmp != nil { + ptr1, err = graphql.UnmarshalInt(tmp) + arg3 = &ptr1 + } + + if err != nil { + return nil, err + } + } + args["last"] = arg3 + return args, nil + +} + func field_Bug_comments_args(rawArgs map[string]interface{}) (map[string]interface{}, error) { args := map[string]interface{}{} var arg0 *string @@ -1244,33 +1367,43 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Bug.Author(childComplexity), true - case "Bug.actors": - if e.complexity.Bug.Actors == nil { + case "Bug.createdAt": + if e.complexity.Bug.CreatedAt == nil { break } - return e.complexity.Bug.Actors(childComplexity), true + return e.complexity.Bug.CreatedAt(childComplexity), true - case "Bug.participants": - if e.complexity.Bug.Participants == nil { + case "Bug.lastEdit": + if e.complexity.Bug.LastEdit == nil { break } - return e.complexity.Bug.Participants(childComplexity), true + return e.complexity.Bug.LastEdit(childComplexity), true - case "Bug.createdAt": - if e.complexity.Bug.CreatedAt == nil { + case "Bug.actors": + if e.complexity.Bug.Actors == nil { break } - return e.complexity.Bug.CreatedAt(childComplexity), true + args, err := field_Bug_actors_args(rawArgs) + if err != nil { + return 0, false + } - case "Bug.lastEdit": - if e.complexity.Bug.LastEdit == nil { + return e.complexity.Bug.Actors(childComplexity, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)), true + + case "Bug.participants": + if e.complexity.Bug.Participants == nil { break } - return e.complexity.Bug.LastEdit(childComplexity), true + args, err := field_Bug_participants_args(rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Bug.Participants(childComplexity, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)), true case "Bug.comments": if e.complexity.Bug.Comments == nil { @@ -2798,33 +2931,33 @@ func (ec *executionContext) _Bug(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalid = true } - case "actors": + case "createdAt": + out.Values[i] = ec._Bug_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + case "lastEdit": wg.Add(1) go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Bug_actors(ctx, field, obj) + out.Values[i] = ec._Bug_lastEdit(ctx, field, obj) if out.Values[i] == graphql.Null { invalid = true } wg.Done() }(i, field) - case "participants": + case "actors": wg.Add(1) go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Bug_participants(ctx, field, obj) + out.Values[i] = ec._Bug_actors(ctx, field, obj) if out.Values[i] == graphql.Null { invalid = true } wg.Done() }(i, field) - case "createdAt": - out.Values[i] = ec._Bug_createdAt(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalid = true - } - case "lastEdit": + case "participants": wg.Add(1) go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Bug_lastEdit(ctx, field, obj) + out.Values[i] = ec._Bug_participants(ctx, field, obj) if out.Values[i] == graphql.Null { invalid = true } @@ -3041,7 +3174,7 @@ func (ec *executionContext) _Bug_author(ctx context.Context, field graphql.Colle } // nolint: vetshadow -func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { +func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -3053,7 +3186,7 @@ func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.Colle ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Actors(rctx, obj) + return obj.CreatedAt, nil }) if resTmp == nil { if !ec.HasError(rctx) { @@ -3061,51 +3194,14 @@ func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.([]*identity.Interface) + res := resTmp.(time.Time) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - - arr1 := make(graphql.Array, len(res)) - var wg sync.WaitGroup - - isLen1 := len(res) == 1 - if !isLen1 { - wg.Add(len(res)) - } - - for idx1 := range res { - idx1 := idx1 - rctx := &graphql.ResolverContext{ - Index: &idx1, - Result: res[idx1], - } - ctx := graphql.WithResolverContext(ctx, rctx) - f := func(idx1 int) { - if !isLen1 { - defer wg.Done() - } - arr1[idx1] = func() graphql.Marshaler { - - if res[idx1] == nil { - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res[idx1]) - }() - } - if isLen1 { - f(idx1) - } else { - go f(idx1) - } - - } - wg.Wait() - return arr1 + return graphql.MarshalTime(res) } // nolint: vetshadow -func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { +func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -3117,7 +3213,7 @@ func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Participants(rctx, obj) + return ec.resolvers.Bug().LastEdit(rctx, obj) }) if resTmp == nil { if !ec.HasError(rctx) { @@ -3125,63 +3221,32 @@ func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.([]*identity.Interface) + res := resTmp.(time.Time) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - - arr1 := make(graphql.Array, len(res)) - var wg sync.WaitGroup - - isLen1 := len(res) == 1 - if !isLen1 { - wg.Add(len(res)) - } - - for idx1 := range res { - idx1 := idx1 - rctx := &graphql.ResolverContext{ - Index: &idx1, - Result: res[idx1], - } - ctx := graphql.WithResolverContext(ctx, rctx) - f := func(idx1 int) { - if !isLen1 { - defer wg.Done() - } - arr1[idx1] = func() graphql.Marshaler { - - if res[idx1] == nil { - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res[idx1]) - }() - } - if isLen1 { - f(idx1) - } else { - go f(idx1) - } - - } - wg.Wait() - return arr1 + return graphql.MarshalTime(res) } // nolint: vetshadow -func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { +func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rawArgs := field.ArgumentMap(ec.Variables) + args, err := field_Bug_actors_args(rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } rctx := &graphql.ResolverContext{ Object: "Bug", - Args: nil, + Args: args, Field: field, } ctx = graphql.WithResolverContext(ctx, rctx) ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.CreatedAt, nil + return ec.resolvers.Bug().Actors(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if resTmp == nil { if !ec.HasError(rctx) { @@ -3189,26 +3254,33 @@ func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.(time.Time) + res := resTmp.(models.IdentityConnection) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - return graphql.MarshalTime(res) + + return ec._IdentityConnection(ctx, field.Selections, &res) } // nolint: vetshadow -func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { +func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rawArgs := field.ArgumentMap(ec.Variables) + args, err := field_Bug_participants_args(rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } rctx := &graphql.ResolverContext{ Object: "Bug", - Args: nil, + Args: args, Field: field, } ctx = graphql.WithResolverContext(ctx, rctx) ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().LastEdit(rctx, obj) + return ec.resolvers.Bug().Participants(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if resTmp == nil { if !ec.HasError(rctx) { @@ -3216,10 +3288,11 @@ func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(time.Time) + res := resTmp.(models.IdentityConnection) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - return graphql.MarshalTime(res) + + return ec._IdentityConnection(ctx, field.Selections, &res) } // nolint: vetshadow @@ -9802,11 +9875,34 @@ type Bug { title: String! labels: [Label!]! author: Identity! - actors: [Identity]! - participants: [Identity]! createdAt: Time! lastEdit: Time! + """The actors of the bug. Actors are Identity that have interacted with the bug.""" + actors( + """Returns the elements in the list that come after the specified cursor.""" + after: String + """Returns the elements in the list that come before the specified cursor.""" + before: String + """Returns the first _n_ elements from the list.""" + first: Int + """Returns the last _n_ elements from the list.""" + last: Int + ): IdentityConnection! + + """The participants of the bug. Participants are Identity that have created or + added a comment on the bug.""" + participants( + """Returns the elements in the list that come after the specified cursor.""" + after: String + """Returns the elements in the list that come before the specified cursor.""" + before: String + """Returns the first _n_ elements from the list.""" + first: Int + """Returns the last _n_ elements from the list.""" + last: Int + ): IdentityConnection! + comments( """Returns the elements in the list that come after the specified cursor.""" after: String diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go index 0b522b5e..eef8df3d 100644 --- a/graphql/graphql_test.go +++ b/graphql/graphql_test.go @@ -50,16 +50,6 @@ func TestQueries(t *testing.T) { email avatarUrl } - actors { - name - email - avatarUrl - } - participants { - name - email - avatarUrl - } createdAt humanId @@ -67,6 +57,36 @@ func TestQueries(t *testing.T) { lastEdit status title + + actors(first: 10) { + pageInfo { + endCursor + hasNextPage + startCursor + hasPreviousPage + } + nodes { + id + humanId + name + displayName + } + } + + participants(first: 10) { + pageInfo { + endCursor + hasNextPage + startCursor + hasPreviousPage + } + nodes { + id + humanId + name + displayName + } + } comments(first: 2) { pageInfo { @@ -123,9 +143,12 @@ func TestQueries(t *testing.T) { }` type Identity struct { - Name string `json:"name"` - Email string `json:"email"` - AvatarUrl string `json:"avatarUrl"` + Id string `json:"id"` + HumanId string `json:"humanId"` + Name string `json:"name"` + Email string `json:"email"` + AvatarUrl string `json:"avatarUrl"` + DisplayName string `json:"displayName"` } var resp struct { @@ -133,15 +156,23 @@ func TestQueries(t *testing.T) { AllBugs struct { PageInfo models.PageInfo Nodes []struct { - Author Identity - Actors []Identity - Participants []Identity - CreatedAt string `json:"createdAt"` - HumanId string `json:"humanId"` - Id string - LastEdit string `json:"lastEdit"` - Status string - Title string + Author Identity + CreatedAt string `json:"createdAt"` + HumanId string `json:"humanId"` + Id string + LastEdit string `json:"lastEdit"` + Status string + Title string + + Actors struct { + PageInfo models.PageInfo + Nodes []Identity + } + + Participants struct { + PageInfo models.PageInfo + Nodes []Identity + } Comments struct { PageInfo models.PageInfo diff --git a/graphql/resolvers/bug.go b/graphql/resolvers/bug.go index f48ff0a7..ef35853c 100644 --- a/graphql/resolvers/bug.go +++ b/graphql/resolvers/bug.go @@ -104,22 +104,56 @@ func (bugResolver) LastEdit(ctx context.Context, obj *bug.Snapshot) (time.Time, return obj.LastEditTime(), nil } -func (bugResolver) Actors(ctx context.Context, obj *bug.Snapshot) ([]*identity.Interface, error) { - actorsp := make([]*identity.Interface, len(obj.Actors)) +func (bugResolver) Actors(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.IdentityConnection, error) { + input := models.ConnectionInput{ + Before: before, + After: after, + First: first, + Last: last, + } - for i, actor := range obj.Actors { - actorsp[i] = &actor + edger := func(actor identity.Interface, offset int) connections.Edge { + return models.IdentityEdge{ + Node: actor, + Cursor: connections.OffsetToCursor(offset), + } + } + + conMaker := func(edges []models.IdentityEdge, nodes []identity.Interface, info models.PageInfo, totalCount int) (models.IdentityConnection, error) { + return models.IdentityConnection{ + Edges: edges, + Nodes: nodes, + PageInfo: info, + TotalCount: totalCount, + }, nil } - return actorsp, nil + return connections.IdentityCon(obj.Actors, edger, conMaker, input) } -func (bugResolver) Participants(ctx context.Context, obj *bug.Snapshot) ([]*identity.Interface, error) { - participantsp := make([]*identity.Interface, len(obj.Participants)) +func (bugResolver) Participants(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.IdentityConnection, error) { + input := models.ConnectionInput{ + Before: before, + After: after, + First: first, + Last: last, + } - for i, participant := range obj.Participants { - participantsp[i] = &participant + edger := func(participant identity.Interface, offset int) connections.Edge { + return models.IdentityEdge{ + Node: participant, + Cursor: connections.OffsetToCursor(offset), + } + } + + conMaker := func(edges []models.IdentityEdge, nodes []identity.Interface, info models.PageInfo, totalCount int) (models.IdentityConnection, error) { + return models.IdentityConnection{ + Edges: edges, + Nodes: nodes, + PageInfo: info, + TotalCount: totalCount, + }, nil } - return participantsp, nil + return connections.IdentityCon(obj.Participants, edger, conMaker, input) } diff --git a/graphql/schema/bug.graphql b/graphql/schema/bug.graphql index e294a363..8e058ed7 100644 --- a/graphql/schema/bug.graphql +++ b/graphql/schema/bug.graphql @@ -36,11 +36,34 @@ type Bug { title: String! labels: [Label!]! author: Identity! - actors: [Identity]! - participants: [Identity]! createdAt: Time! lastEdit: Time! + """The actors of the bug. Actors are Identity that have interacted with the bug.""" + actors( + """Returns the elements in the list that come after the specified cursor.""" + after: String + """Returns the elements in the list that come before the specified cursor.""" + before: String + """Returns the first _n_ elements from the list.""" + first: Int + """Returns the last _n_ elements from the list.""" + last: Int + ): IdentityConnection! + + """The participants of the bug. Participants are Identity that have created or + added a comment on the bug.""" + participants( + """Returns the elements in the list that come after the specified cursor.""" + after: String + """Returns the elements in the list that come before the specified cursor.""" + before: String + """Returns the first _n_ elements from the list.""" + first: Int + """Returns the last _n_ elements from the list.""" + last: Int + ): IdentityConnection! + comments( """Returns the elements in the list that come after the specified cursor.""" after: String |