diff options
-rw-r--r-- | api/graphql/graph/gen_graph.go | 383 | ||||
-rw-r--r-- | api/graphql/models/gen_models.go | 24 | ||||
-rw-r--r-- | api/graphql/resolvers/mutation.go | 38 | ||||
-rw-r--r-- | api/graphql/schema/mutations.graphql | 24 | ||||
-rw-r--r-- | api/graphql/schema/root.graphql | 2 | ||||
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 3 | ||||
-rw-r--r-- | webui/src/components/CloseBugButton/index.tsx (renamed from webui/src/components/CloseBugButton/CloseBugButton.tsx) | 3 | ||||
-rw-r--r-- | webui/src/components/CloseBugWithCommentButton/index.tsx (renamed from webui/src/components/CloseBugWithCommentButton/CloseBugWithCommentButton.tsx) | 10 | ||||
-rw-r--r-- | webui/src/components/ReopenBugButton/index.tsx (renamed from webui/src/components/ReopenBugButton/ReopenBugButton.tsx) | 5 | ||||
-rw-r--r-- | webui/src/components/ReopenBugWithCommentButton/ReopenBugWithComment.graphql | 11 | ||||
-rw-r--r-- | webui/src/components/ReopenBugWithCommentButton/index.tsx | 65 | ||||
-rw-r--r-- | webui/src/pages/bug/CommentForm.tsx | 26 | ||||
-rw-r--r-- | webui/src/pages/list/BugRow.tsx | 2 |
14 files changed, 578 insertions, 20 deletions
diff --git a/api/graphql/graph/gen_graph.go b/api/graphql/graph/gen_graph.go index 9db21303..b94effed 100644 --- a/api/graphql/graph/gen_graph.go +++ b/api/graphql/graph/gen_graph.go @@ -74,6 +74,13 @@ type ComplexityRoot struct { StatusOperation func(childComplexity int) int } + AddCommentAndReopenBugPayload struct { + Bug func(childComplexity int) int + ClientMutationID func(childComplexity int) int + CommentOperation func(childComplexity int) int + StatusOperation func(childComplexity int) int + } + AddCommentOperation struct { Author func(childComplexity int) int Date func(childComplexity int) int @@ -268,14 +275,15 @@ type ComplexityRoot struct { } Mutation struct { - AddComment func(childComplexity int, input models.AddCommentInput) int - AddCommentAndClose func(childComplexity int, input models.AddCommentAndCloseBugInput) int - ChangeLabels func(childComplexity int, input *models.ChangeLabelInput) int - CloseBug func(childComplexity int, input models.CloseBugInput) int - EditComment func(childComplexity int, input models.EditCommentInput) int - NewBug func(childComplexity int, input models.NewBugInput) int - OpenBug func(childComplexity int, input models.OpenBugInput) int - SetTitle func(childComplexity int, input models.SetTitleInput) int + AddComment func(childComplexity int, input models.AddCommentInput) int + AddCommentAndClose func(childComplexity int, input models.AddCommentAndCloseBugInput) int + AddCommentAndReopen func(childComplexity int, input models.AddCommentAndReopenBugInput) int + ChangeLabels func(childComplexity int, input *models.ChangeLabelInput) int + CloseBug func(childComplexity int, input models.CloseBugInput) int + EditComment func(childComplexity int, input models.EditCommentInput) int + NewBug func(childComplexity int, input models.NewBugInput) int + OpenBug func(childComplexity int, input models.OpenBugInput) int + SetTitle func(childComplexity int, input models.SetTitleInput) int } NewBugPayload struct { @@ -449,6 +457,7 @@ type MutationResolver interface { NewBug(ctx context.Context, input models.NewBugInput) (*models.NewBugPayload, error) AddComment(ctx context.Context, input models.AddCommentInput) (*models.AddCommentPayload, error) AddCommentAndClose(ctx context.Context, input models.AddCommentAndCloseBugInput) (*models.AddCommentAndCloseBugPayload, error) + AddCommentAndReopen(ctx context.Context, input models.AddCommentAndReopenBugInput) (*models.AddCommentAndReopenBugPayload, error) EditComment(ctx context.Context, input models.EditCommentInput) (*models.EditCommentPayload, error) ChangeLabels(ctx context.Context, input *models.ChangeLabelInput) (*models.ChangeLabelPayload, error) OpenBug(ctx context.Context, input models.OpenBugInput) (*models.OpenBugPayload, error) @@ -533,6 +542,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AddCommentAndCloseBugPayload.StatusOperation(childComplexity), true + case "AddCommentAndReopenBugPayload.bug": + if e.complexity.AddCommentAndReopenBugPayload.Bug == nil { + break + } + + return e.complexity.AddCommentAndReopenBugPayload.Bug(childComplexity), true + + case "AddCommentAndReopenBugPayload.clientMutationId": + if e.complexity.AddCommentAndReopenBugPayload.ClientMutationID == nil { + break + } + + return e.complexity.AddCommentAndReopenBugPayload.ClientMutationID(childComplexity), true + + case "AddCommentAndReopenBugPayload.commentOperation": + if e.complexity.AddCommentAndReopenBugPayload.CommentOperation == nil { + break + } + + return e.complexity.AddCommentAndReopenBugPayload.CommentOperation(childComplexity), true + + case "AddCommentAndReopenBugPayload.statusOperation": + if e.complexity.AddCommentAndReopenBugPayload.StatusOperation == nil { + break + } + + return e.complexity.AddCommentAndReopenBugPayload.StatusOperation(childComplexity), true + case "AddCommentOperation.author": if e.complexity.AddCommentOperation.Author == nil { break @@ -1387,6 +1424,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.AddCommentAndClose(childComplexity, args["input"].(models.AddCommentAndCloseBugInput)), true + case "Mutation.addCommentAndReopen": + if e.complexity.Mutation.AddCommentAndReopen == nil { + break + } + + args, err := ec.field_Mutation_addCommentAndReopen_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.AddCommentAndReopen(childComplexity, args["input"].(models.AddCommentAndReopenBugInput)), true + case "Mutation.changeLabels": if e.complexity.Mutation.ChangeLabels == nil { break @@ -2148,6 +2197,30 @@ type AddCommentAndCloseBugPayload { statusOperation: SetStatusOperation! } +input AddCommentAndReopenBugInput { + """A unique identifier for the client performing the mutation.""" + clientMutationId: String + """The name of the repository. If not set, the default repository is used.""" + repoRef: String + """The bug ID's prefix.""" + prefix: String! + """The message to be added to the bug.""" + message: String! + """The collection of file's hash required for the first message.""" + files: [Hash!] +} + +type AddCommentAndReopenBugPayload { + """A unique identifier for the client performing the mutation.""" + clientMutationId: String + """The affected bug.""" + bug: Bug! + """The resulting AddComment operation.""" + commentOperation: AddCommentOperation! + """The resulting SetStatusOperation.""" + statusOperation: SetStatusOperation! +} + input EditCommentInput { """A unique identifier for the client performing the mutation.""" clientMutationId: String @@ -2431,6 +2504,8 @@ type Mutation { addComment(input: AddCommentInput!): AddCommentPayload! """Add a new comment to a bug and close it""" addCommentAndClose(input: AddCommentAndCloseBugInput!): AddCommentAndCloseBugPayload! + """Add a new comment to a bug and reopen it""" + addCommentAndReopen(input: AddCommentAndReopenBugInput!): AddCommentAndReopenBugPayload! """Change a comment of a bug""" editComment(input: EditCommentInput!): EditCommentPayload! """Add or remove a set of label on a bug""" @@ -2772,6 +2847,20 @@ func (ec *executionContext) field_Mutation_addCommentAndClose_args(ctx context.C return args, nil } +func (ec *executionContext) field_Mutation_addCommentAndReopen_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 models.AddCommentAndReopenBugInput + if tmp, ok := rawArgs["input"]; ok { + arg0, err = ec.unmarshalNAddCommentAndReopenBugInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentAndReopenBugInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_addComment_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -3217,6 +3306,139 @@ func (ec *executionContext) _AddCommentAndCloseBugPayload_statusOperation(ctx co return ec.marshalNSetStatusOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐSetStatusOperation(ctx, field.Selections, res) } +func (ec *executionContext) _AddCommentAndReopenBugPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.AddCommentAndReopenBugPayload) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AddCommentAndReopenBugPayload", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ClientMutationID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _AddCommentAndReopenBugPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.AddCommentAndReopenBugPayload) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AddCommentAndReopenBugPayload", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Bug, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(models.BugWrapper) + fc.Result = res + return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res) +} + +func (ec *executionContext) _AddCommentAndReopenBugPayload_commentOperation(ctx context.Context, field graphql.CollectedField, obj *models.AddCommentAndReopenBugPayload) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AddCommentAndReopenBugPayload", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CommentOperation, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*bug.AddCommentOperation) + fc.Result = res + return ec.marshalNAddCommentOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐAddCommentOperation(ctx, field.Selections, res) +} + +func (ec *executionContext) _AddCommentAndReopenBugPayload_statusOperation(ctx context.Context, field graphql.CollectedField, obj *models.AddCommentAndReopenBugPayload) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AddCommentAndReopenBugPayload", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StatusOperation, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*bug.SetStatusOperation) + fc.Result = res + return ec.marshalNSetStatusOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐSetStatusOperation(ctx, field.Selections, res) +} + func (ec *executionContext) _AddCommentOperation_id(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -7261,6 +7483,47 @@ func (ec *executionContext) _Mutation_addCommentAndClose(ctx context.Context, fi return ec.marshalNAddCommentAndCloseBugPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentAndCloseBugPayload(ctx, field.Selections, res) } +func (ec *executionContext) _Mutation_addCommentAndReopen(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_addCommentAndReopen_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().AddCommentAndReopen(rctx, args["input"].(models.AddCommentAndReopenBugInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*models.AddCommentAndReopenBugPayload) + fc.Result = res + return ec.marshalNAddCommentAndReopenBugPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentAndReopenBugPayload(ctx, field.Selections, res) +} + func (ec *executionContext) _Mutation_editComment(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -10384,6 +10647,48 @@ func (ec *executionContext) unmarshalInputAddCommentAndCloseBugInput(ctx context return it, nil } +func (ec *executionContext) unmarshalInputAddCommentAndReopenBugInput(ctx context.Context, obj interface{}) (models.AddCommentAndReopenBugInput, error) { + var it models.AddCommentAndReopenBugInput + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "clientMutationId": + var err error + it.ClientMutationID, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "repoRef": + var err error + it.RepoRef, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "prefix": + var err error + it.Prefix, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "message": + var err error + it.Message, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "files": + var err error + it.Files, err = ec.unmarshalOHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputAddCommentInput(ctx context.Context, obj interface{}) (models.AddCommentInput, error) { var it models.AddCommentInput var asMap = obj.(map[string]interface{}) @@ -10856,6 +11161,45 @@ func (ec *executionContext) _AddCommentAndCloseBugPayload(ctx context.Context, s return out } +var addCommentAndReopenBugPayloadImplementors = []string{"AddCommentAndReopenBugPayload"} + +func (ec *executionContext) _AddCommentAndReopenBugPayload(ctx context.Context, sel ast.SelectionSet, obj *models.AddCommentAndReopenBugPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, addCommentAndReopenBugPayloadImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("AddCommentAndReopenBugPayload") + case "clientMutationId": + out.Values[i] = ec._AddCommentAndReopenBugPayload_clientMutationId(ctx, field, obj) + case "bug": + out.Values[i] = ec._AddCommentAndReopenBugPayload_bug(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "commentOperation": + out.Values[i] = ec._AddCommentAndReopenBugPayload_commentOperation(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "statusOperation": + out.Values[i] = ec._AddCommentAndReopenBugPayload_statusOperation(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var addCommentOperationImplementors = []string{"AddCommentOperation", "Operation", "Authored"} func (ec *executionContext) _AddCommentOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.AddCommentOperation) graphql.Marshaler { @@ -12387,6 +12731,11 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { invalids++ } + case "addCommentAndReopen": + out.Values[i] = ec._Mutation_addCommentAndReopen(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } case "editComment": out.Values[i] = ec._Mutation_editComment(ctx, field) if out.Values[i] == graphql.Null { @@ -13431,6 +13780,24 @@ func (ec *executionContext) marshalNAddCommentAndCloseBugPayload2ᚖgithubᚗcom return ec._AddCommentAndCloseBugPayload(ctx, sel, v) } +func (ec *executionContext) unmarshalNAddCommentAndReopenBugInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentAndReopenBugInput(ctx context.Context, v interface{}) (models.AddCommentAndReopenBugInput, error) { + return ec.unmarshalInputAddCommentAndReopenBugInput(ctx, v) +} + +func (ec *executionContext) marshalNAddCommentAndReopenBugPayload2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentAndReopenBugPayload(ctx context.Context, sel ast.SelectionSet, v models.AddCommentAndReopenBugPayload) graphql.Marshaler { + return ec._AddCommentAndReopenBugPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAddCommentAndReopenBugPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentAndReopenBugPayload(ctx context.Context, sel ast.SelectionSet, v *models.AddCommentAndReopenBugPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._AddCommentAndReopenBugPayload(ctx, sel, v) +} + func (ec *executionContext) unmarshalNAddCommentInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐAddCommentInput(ctx context.Context, v interface{}) (models.AddCommentInput, error) { return ec.unmarshalInputAddCommentInput(ctx, v) } diff --git a/api/graphql/models/gen_models.go b/api/graphql/models/gen_models.go index 708fa409..203d6451 100644 --- a/api/graphql/models/gen_models.go +++ b/api/graphql/models/gen_models.go @@ -40,6 +40,30 @@ type AddCommentAndCloseBugPayload struct { StatusOperation *bug.SetStatusOperation `json:"statusOperation"` } +type AddCommentAndReopenBugInput struct { + // A unique identifier for the client performing the mutation. + ClientMutationID *string `json:"clientMutationId"` + // The name of the repository. If not set, the default repository is used. + RepoRef *string `json:"repoRef"` + // The bug ID's prefix. + Prefix string `json:"prefix"` + // The message to be added to the bug. + Message string `json:"message"` + // The collection of file's hash required for the first message. + Files []repository.Hash `json:"files"` +} + +type AddCommentAndReopenBugPayload struct { + // A unique identifier for the client performing the mutation. + ClientMutationID *string `json:"clientMutationId"` + // The affected bug. + Bug BugWrapper `json:"bug"` + // The resulting AddComment operation. + CommentOperation *bug.AddCommentOperation `json:"commentOperation"` + // The resulting SetStatusOperation. + StatusOperation *bug.SetStatusOperation `json:"statusOperation"` +} + type AddCommentInput struct { // A unique identifier for the client performing the mutation. ClientMutationID *string `json:"clientMutationId"` diff --git a/api/graphql/resolvers/mutation.go b/api/graphql/resolvers/mutation.go index b55270c2..aa99e93d 100644 --- a/api/graphql/resolvers/mutation.go +++ b/api/graphql/resolvers/mutation.go @@ -138,6 +138,44 @@ func (r mutationResolver) AddCommentAndClose(ctx context.Context, input models.A }, nil } +func (r mutationResolver) AddCommentAndReopen(ctx context.Context, input models.AddCommentAndReopenBugInput) (*models.AddCommentAndReopenBugPayload, error) { + repo, b, err := r.getBug(input.RepoRef, input.Prefix) + if err != nil { + return nil, err + } + + author, err := auth.UserFromCtx(ctx, repo) + if err != nil { + return nil, err + } + + opAddComment, err := b.AddCommentRaw(author, + time.Now().Unix(), + text.Cleanup(input.Message), + input.Files, + nil) + if err != nil { + return nil, err + } + + opReopen, err := b.OpenRaw(author, time.Now().Unix(), nil) + if err != nil { + return nil, err + } + + err = b.Commit() + if err != nil { + return nil, err + } + + return &models.AddCommentAndReopenBugPayload{ + ClientMutationID: input.ClientMutationID, + Bug: models.NewLoadedBug(b.Snapshot()), + CommentOperation: opAddComment, + StatusOperation: opReopen, + }, nil +} + func (r mutationResolver) EditComment(ctx context.Context, input models.EditCommentInput) (*models.EditCommentPayload, error) { repo, b, err := r.getBug(input.RepoRef, input.Prefix) if err != nil { diff --git a/api/graphql/schema/mutations.graphql b/api/graphql/schema/mutations.graphql index 36222e6b..cd5cba4e 100644 --- a/api/graphql/schema/mutations.graphql +++ b/api/graphql/schema/mutations.graphql @@ -66,6 +66,30 @@ type AddCommentAndCloseBugPayload { statusOperation: SetStatusOperation! } +input AddCommentAndReopenBugInput { + """A unique identifier for the client performing the mutation.""" + clientMutationId: String + """The name of the repository. If not set, the default repository is used.""" + repoRef: String + """The bug ID's prefix.""" + prefix: String! + """The message to be added to the bug.""" + message: String! + """The collection of file's hash required for the first message.""" + files: [Hash!] +} + +type AddCommentAndReopenBugPayload { + """A unique identifier for the client performing the mutation.""" + clientMutationId: String + """The affected bug.""" + bug: Bug! + """The resulting AddComment operation.""" + commentOperation: AddCommentOperation! + """The resulting SetStatusOperation.""" + statusOperation: SetStatusOperation! +} + input EditCommentInput { """A unique identifier for the client performing the mutation.""" clientMutationId: String diff --git a/api/graphql/schema/root.graphql b/api/graphql/schema/root.graphql index 4b4e0e2f..e3c76c03 100644 --- a/api/graphql/schema/root.graphql +++ b/api/graphql/schema/root.graphql @@ -10,6 +10,8 @@ type Mutation { addComment(input: AddCommentInput!): AddCommentPayload! """Add a new comment to a bug and close it""" addCommentAndClose(input: AddCommentAndCloseBugInput!): AddCommentAndCloseBugPayload! + """Add a new comment to a bug and reopen it""" + addCommentAndReopen(input: AddCommentAndReopenBugInput!): AddCommentAndReopenBugPayload! """Change a comment of a bug""" editComment(input: EditCommentInput!): EditCommentPayload! """Add or remove a set of label on a bug""" @@ -19,7 +19,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/hashicorp/golang-lru v0.5.4 github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 - github.com/mattn/go-isatty v0.0.12 + github.com/mattn/go-isatty v0.0.13 github.com/phayes/freeport v0.0.0-20171002181615-b8543db493a5 github.com/pkg/errors v0.9.1 github.com/shurcooL/githubv4 v0.0.0-20190601194912-068505affed7 @@ -350,8 +350,9 @@ github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= diff --git a/webui/src/components/CloseBugButton/CloseBugButton.tsx b/webui/src/components/CloseBugButton/index.tsx index 5ec78bb2..bb154ea7 100644 --- a/webui/src/components/CloseBugButton/CloseBugButton.tsx +++ b/webui/src/components/CloseBugButton/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import Button from '@material-ui/core/Button'; +import CircularProgress from '@material-ui/core/CircularProgress'; import { makeStyles, Theme } from '@material-ui/core/styles'; import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline'; @@ -46,7 +47,7 @@ function CloseBugButton({ bug, disabled }: Props) { }); } - if (loading) return <div>Loading...</div>; + if (loading) return <CircularProgress />; if (error) return <div>Error</div>; return ( diff --git a/webui/src/components/CloseBugWithCommentButton/CloseBugWithCommentButton.tsx b/webui/src/components/CloseBugWithCommentButton/index.tsx index 1d713f88..a0fefa4a 100644 --- a/webui/src/components/CloseBugWithCommentButton/CloseBugWithCommentButton.tsx +++ b/webui/src/components/CloseBugWithCommentButton/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import Button from '@material-ui/core/Button'; +import CircularProgress from '@material-ui/core/CircularProgress'; import { makeStyles, Theme } from '@material-ui/core/styles'; import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline'; @@ -19,9 +20,10 @@ const useStyles = makeStyles((theme: Theme) => ({ interface Props { bug: BugFragment; comment: string; + postClick?: () => void; } -function CloseBugWithCommentButton({ bug, comment }: Props) { +function CloseBugWithCommentButton({ bug, comment, postClick }: Props) { const [ addCommentAndCloseBug, { loading, error }, @@ -47,10 +49,14 @@ function CloseBugWithCommentButton({ bug, comment }: Props) { }, ], awaitRefetchQueries: true, + }).then(() => { + if (postClick) { + postClick(); + } }); } - if (loading) return <div>Loading...</div>; + if (loading) return <CircularProgress />; if (error) return <div>Error</div>; return ( diff --git a/webui/src/components/ReopenBugButton/ReopenBugButton.tsx b/webui/src/components/ReopenBugButton/index.tsx index e3e792fc..e62c58df 100644 --- a/webui/src/components/ReopenBugButton/ReopenBugButton.tsx +++ b/webui/src/components/ReopenBugButton/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import Button from '@material-ui/core/Button'; +import CircularProgress from '@material-ui/core/CircularProgress'; import { BugFragment } from 'src/pages/bug/Bug.generated'; import { TimelineDocument } from 'src/pages/bug/TimelineQuery.generated'; @@ -9,7 +10,7 @@ import { useOpenBugMutation } from './OpenBug.generated'; interface Props { bug: BugFragment; - disabled: boolean; + disabled?: boolean; } function ReopenBugButton({ bug, disabled }: Props) { @@ -36,7 +37,7 @@ function ReopenBugButton({ bug, disabled }: Props) { }); } - if (loading) return <div>Loading...</div>; + if (loading) return <CircularProgress />; if (error) return <div>Error</div>; return ( diff --git a/webui/src/components/ReopenBugWithCommentButton/ReopenBugWithComment.graphql b/webui/src/components/ReopenBugWithCommentButton/ReopenBugWithComment.graphql new file mode 100644 index 00000000..4c220208 --- /dev/null +++ b/webui/src/components/ReopenBugWithCommentButton/ReopenBugWithComment.graphql @@ -0,0 +1,11 @@ +mutation AddCommentAndReopenBug($input: AddCommentAndReopenBugInput!) { + addCommentAndReopen(input: $input) { + statusOperation { + status + } + commentOperation { + message + } + } +} + diff --git a/webui/src/components/ReopenBugWithCommentButton/index.tsx b/webui/src/components/ReopenBugWithCommentButton/index.tsx new file mode 100644 index 00000000..0a534f27 --- /dev/null +++ b/webui/src/components/ReopenBugWithCommentButton/index.tsx @@ -0,0 +1,65 @@ +import React from 'react'; + +import Button from '@material-ui/core/Button'; +import CircularProgress from '@material-ui/core/CircularProgress'; + +import { BugFragment } from 'src/pages/bug/Bug.generated'; +import { TimelineDocument } from 'src/pages/bug/TimelineQuery.generated'; + +import { useAddCommentAndReopenBugMutation } from './ReopenBugWithComment.generated'; + +interface Props { + bug: BugFragment; + comment: string; + postClick?: () => void; +} + +function ReopenBugWithCommentButton({ bug, comment, postClick }: Props) { + const [ + addCommentAndReopenBug, + { loading, error }, + ] = useAddCommentAndReopenBugMutation(); + + function addCommentAndReopenBugAction() { + addCommentAndReopenBug({ + variables: { + input: { + prefix: bug.id, + message: comment, + }, + }, + refetchQueries: [ + // TODO: update the cache instead of refetching + { + query: TimelineDocument, + variables: { + id: bug.id, + first: 100, + }, + }, + ], + awaitRefetchQueries: true, + }).then(() => { + if (postClick) { + postClick(); + } + }); + } + + if (loading) return <CircularProgress />; + if (error) return <div>Error</div>; + + return ( + <div> + <Button + variant="contained" + type="submit" + onClick={() => addCommentAndReopenBugAction()} + > + Reopen bug with comment + </Button> + </div> + ); +} + +export default ReopenBugWithCommentButton; diff --git a/webui/src/pages/bug/CommentForm.tsx b/webui/src/pages/bug/CommentForm.tsx index 1a7ebc29..6d917889 100644 --- a/webui/src/pages/bug/CommentForm.tsx +++ b/webui/src/pages/bug/CommentForm.tsx @@ -5,9 +5,10 @@ import Paper from '@material-ui/core/Paper'; import { makeStyles, Theme } from '@material-ui/core/styles'; import CommentInput from '../../components/CommentInput/CommentInput'; -import CloseBugButton from 'src/components/CloseBugButton/CloseBugButton'; -import CloseBugWithCommentButton from 'src/components/CloseBugWithCommentButton/CloseBugWithCommentButton'; -import ReopenBugButton from 'src/components/ReopenBugButton/ReopenBugButton'; +import CloseBugButton from 'src/components/CloseBugButton'; +import CloseBugWithCommentButton from 'src/components/CloseBugWithCommentButton'; +import ReopenBugButton from 'src/components/ReopenBugButton'; +import ReopenBugWithCommentButton from 'src/components/ReopenBugWithCommentButton'; import { BugFragment } from './Bug.generated'; import { useAddCommentMutation } from './CommentForm.generated'; @@ -80,12 +81,27 @@ function CommentForm({ bug }: Props) { function getBugStatusButton() { if (bug.status === 'OPEN' && issueComment.length > 0) { - return <CloseBugWithCommentButton bug={bug} comment={issueComment} />; + return ( + <CloseBugWithCommentButton + bug={bug} + comment={issueComment} + postClick={resetForm} + /> + ); } if (bug.status === 'OPEN') { return <CloseBugButton bug={bug} />; } - return <ReopenBugButton bug={bug} disabled={issueComment.length > 0} />; + if (bug.status === 'CLOSED' && issueComment.length > 0) { + return ( + <ReopenBugWithCommentButton + bug={bug} + comment={issueComment} + postClick={resetForm} + /> + ); + } + return <ReopenBugButton bug={bug} />; } return ( diff --git a/webui/src/pages/list/BugRow.tsx b/webui/src/pages/list/BugRow.tsx index 562149f3..68a3b299 100644 --- a/webui/src/pages/list/BugRow.tsx +++ b/webui/src/pages/list/BugRow.tsx @@ -84,7 +84,9 @@ const useStyles = makeStyles((theme) => ({ }, commentCount: { fontSize: '1rem', + minWidth: '2rem', marginLeft: theme.spacing(0.5), + marginRight: theme.spacing(1), }, commentCountCell: { display: 'inline-flex', |