graphql: make Bug's actors and participants a connection

This commit is contained in:
Michael Muré 2019-04-05 01:13:17 +02:00
parent b9e413c5f9
commit e027d5ee65
No known key found for this signature in database
GPG Key ID: A4457C029293126F
9 changed files with 514 additions and 217 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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,20 +1367,6 @@ 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 {
break
}
return e.complexity.Bug.Actors(childComplexity), true
case "Bug.participants":
if e.complexity.Bug.Participants == nil {
break
}
return e.complexity.Bug.Participants(childComplexity), true
case "Bug.createdAt":
if e.complexity.Bug.CreatedAt == nil {
break
@ -1272,6 +1381,30 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Bug.LastEdit(childComplexity), true
case "Bug.actors":
if e.complexity.Bug.Actors == nil {
break
}
args, err := field_Bug_actors_args(rawArgs)
if err != nil {
return 0, false
}
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
}
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 {
break
@ -2798,6 +2931,20 @@ func (ec *executionContext) _Bug(ctx context.Context, sel ast.SelectionSet, obj
if out.Values[i] == graphql.Null {
invalid = true
}
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_lastEdit(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalid = true
}
wg.Done()
}(i, field)
case "actors":
wg.Add(1)
go func(i int, field graphql.CollectedField) {
@ -2816,20 +2963,6 @@ func (ec *executionContext) _Bug(ctx context.Context, sel ast.SelectionSet, obj
}
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":
wg.Add(1)
go func(i int, field graphql.CollectedField) {
out.Values[i] = ec._Bug_lastEdit(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalid = true
}
wg.Done()
}(i, field)
case "comments":
wg.Add(1)
go func(i int, field graphql.CollectedField) {
@ -3040,134 +3173,6 @@ func (ec *executionContext) _Bug_author(ctx context.Context, field graphql.Colle
return ec._Identity(ctx, field.Selections, &res)
}
// nolint: vetshadow
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) }()
rctx := &graphql.ResolverContext{
Object: "Bug",
Args: nil,
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().Actors(rctx, obj)
})
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.([]*identity.Interface)
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
}
// nolint: vetshadow
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) }()
rctx := &graphql.ResolverContext{
Object: "Bug",
Args: nil,
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().Participants(rctx, obj)
})
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.([]*identity.Interface)
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
}
// nolint: vetshadow
func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
@ -3222,6 +3227,74 @@ func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.Col
return graphql.MarshalTime(res)
}
// nolint: vetshadow
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: 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().Actors(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int))
})
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(models.IdentityConnection)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec._IdentityConnection(ctx, field.Selections, &res)
}
// nolint: vetshadow
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: 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().Participants(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int))
})
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(models.IdentityConnection)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec._IdentityConnection(ctx, field.Selections, &res)
}
// nolint: vetshadow
func (ec *executionContext) _Bug_comments(ctx context.Context, field graphql.CollectedField, obj *bug.Snapshot) graphql.Marshaler {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
@ -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

View File

@ -50,16 +50,6 @@ func TestQueries(t *testing.T) {
email
avatarUrl
}
actors {
name
email
avatarUrl
}
participants {
name
email
avatarUrl
}
createdAt
humanId
@ -68,6 +58,36 @@ func TestQueries(t *testing.T) {
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 {
endCursor
@ -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

View File

@ -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))
for i, actor := range obj.Actors {
actorsp[i] = &actor
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,
}
return actorsp, nil
}
func (bugResolver) Participants(ctx context.Context, obj *bug.Snapshot) ([]*identity.Interface, error) {
participantsp := make([]*identity.Interface, len(obj.Participants))
for i, participant := range obj.Participants {
participantsp[i] = &participant
edger := func(actor identity.Interface, offset int) connections.Edge {
return models.IdentityEdge{
Node: actor,
Cursor: connections.OffsetToCursor(offset),
}
}
return participantsp, nil
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 connections.IdentityCon(obj.Actors, edger, conMaker, input)
}
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,
}
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 connections.IdentityCon(obj.Participants, edger, conMaker, input)
}

View File

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