aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/graphql/graph/gen_graph.go383
-rw-r--r--api/graphql/models/gen_models.go24
-rw-r--r--api/graphql/resolvers/mutation.go38
-rw-r--r--api/graphql/schema/mutations.graphql24
-rw-r--r--api/graphql/schema/root.graphql2
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-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.graphql11
-rw-r--r--webui/src/components/ReopenBugWithCommentButton/index.tsx65
-rw-r--r--webui/src/pages/bug/CommentForm.tsx26
-rw-r--r--webui/src/pages/list/BugRow.tsx2
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"""
diff --git a/go.mod b/go.mod
index 8bb69287..fb9882a7 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
index b07e19e8..b880a86e 100644
--- a/go.sum
+++ b/go.sum
@@ -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',