Simon Ser: 1 todo ticket edit: new command 4 files changed, 142 insertions(+), 0 deletions(-)
Thanks for the fixups!
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~emersion/hut-dev/patches/48744/mbox | git am -3Learn more about email & git
--- doc/hut.1.scd | 3 ++ srht/todosrht/gql.go | 35 ++++++++++++++++ srht/todosrht/operations.graphql | 34 ++++++++++++++++ todo.go | 70 ++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+) diff --git a/doc/hut.1.scd b/doc/hut.1.scd index 80a49a9fcbdf..0e909428411c 100644 --- a/doc/hut.1.scd +++ b/doc/hut.1.scd @@ -744,6 +744,9 @@ Options are: *-y*, *--yes* Confirm deletion without prompt. +*ticket edit* <ID> + Edit a ticket with _$EDITOR_. + *ticket label* <ID> [options...] Add a label to a ticket. diff --git a/srht/todosrht/gql.go b/srht/todosrht/gql.go index 8d2cf5dac345..d5b5a139e3b7 100644 --- a/srht/todosrht/gql.go +++ b/srht/todosrht/gql.go @@ -1218,6 +1218,29 @@ func TicketByUser(client *gqlclient.Client, ctx context.Context, username string return respData.User, err } +func TicketBodyByName(client *gqlclient.Client, ctx context.Context, name string, id int32) (me *User, err error) { + op := gqlclient.NewOperation("query ticketBodyByName ($name: String!, $id: Int!) {\n\tme {\n\t\ttracker(name: $name) {\n\t\t\tid\n\t\t\tticket(id: $id) {\n\t\t\t\t... ticketBody\n\t\t\t}\n\t\t}\n\t}\n}\nfragment ticketBody on Ticket {\n\tid\n\tsubject\n\tbody\n}\n") + op.Var("name", name) + op.Var("id", id) + var respData struct { + Me *User + } + err = client.Execute(ctx, op, &respData) + return respData.Me, err +} + +func TicketBodyByUser(client *gqlclient.Client, ctx context.Context, username string, tracker string, id int32) (user *User, err error) { + op := gqlclient.NewOperation("query ticketBodyByUser ($username: String!, $tracker: String!, $id: Int!) {\n\tuser(username: $username) {\n\t\ttracker(name: $tracker) {\n\t\t\tid\n\t\t\tticket(id: $id) {\n\t\t\t\t... ticketBody\n\t\t\t}\n\t\t}\n\t}\n}\nfragment ticketBody on Ticket {\n\tid\n\tsubject\n\tbody\n}\n") + op.Var("username", username) + op.Var("tracker", tracker) + op.Var("id", id) + var respData struct { + User *User + } + err = client.Execute(ctx, op, &respData) + return respData.User, err +} + func LabelIDByName(client *gqlclient.Client, ctx context.Context, trackerName string, labelName string) (me *User, err error) { op := gqlclient.NewOperation("query labelIDByName ($trackerName: String!, $labelName: String!) {\n\tme {\n\t\ttracker(name: $trackerName) {\n\t\t\tlabel(name: $labelName) {\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n}\n") op.Var("trackerName", trackerName) @@ -1528,3 +1551,15 @@ func UnlabelTicket(client *gqlclient.Client, ctx context.Context, trackerId int3 err = client.Execute(ctx, op, &respData) return respData.UnlabelTicket, err } + +func UpdateTicket(client *gqlclient.Client, ctx context.Context, trackerId int32, ticketId int32, input UpdateTicketInput) (updateTicket *Ticket, err error) { + op := gqlclient.NewOperation("mutation updateTicket ($trackerId: Int!, $ticketId: Int!, $input: UpdateTicketInput!) {\n\tupdateTicket(trackerId: $trackerId, ticketId: $ticketId, input: $input) {\n\t\tid\n\t}\n}\n") + op.Var("trackerId", trackerId) + op.Var("ticketId", ticketId) + op.Var("input", input) + var respData struct { + UpdateTicket *Ticket + } + err = client.Execute(ctx, op, &respData) + return respData.UpdateTicket, err +} diff --git a/srht/todosrht/operations.graphql b/srht/todosrht/operations.graphql index 5ef233ce7dd4..1765a9778fda 100644 --- a/srht/todosrht/operations.graphql +++ b/srht/todosrht/operations.graphql @@ -418,6 +418,34 @@ fragment ticket on Ticket { } } +query ticketBodyByName($name: String!, $id: Int!) { + me { + tracker(name: $name) { + id + ticket(id: $id) { + ...ticketBody + } + } + } +} + +query ticketBodyByUser($username: String!, $tracker: String!, $id: Int!) { + user(username: $username) { + tracker(name: $tracker) { + id + ticket(id: $id) { + ...ticketBody + } + } + } +} + +fragment ticketBody on Ticket { + id + subject + body +} + query labelIDByName($trackerName: String!, $labelName: String!) { me { tracker(name: $trackerName) { @@ -695,3 +723,9 @@ mutation unlabelTicket($trackerId: Int!, $ticketId: Int!, $labelId: Int!) { } } } + +mutation updateTicket($trackerId: Int!, $ticketId: Int!, $input: UpdateTicketInput!) { + updateTicket(trackerId: $trackerId, ticketId: $ticketId, input: $input) { + id + } +} diff --git a/todo.go b/todo.go index 0c1f56806930..0cb26dede3bc 100644 --- a/todo.go +++ b/todo.go @@ -274,6 +274,7 @@ func newTodoTicketCommand() *cobra.Command { cmd.AddCommand(newTodoTicketShowCommand()) cmd.AddCommand(newTodoTicketWebhookCommand()) cmd.AddCommand(newTodoTicketCreateCommand()) + cmd.AddCommand(newTodoTicketEditCommand()) cmd.AddCommand(newTodoTicketLabelCommand()) cmd.AddCommand(newTodoTicketUnlabelCommand()) return cmd @@ -1540,6 +1541,75 @@ func newTodoTicketCreateCommand() *cobra.Command { return cmd } +func newTodoTicketEditCommand() *cobra.Command { + run := func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + + ticketID, name, owner, instance, err := parseTicketResource(ctx, cmd, args[0]) + if err != nil { + log.Fatal(err) + } + + c := createClientWithInstance("todo", cmd, instance) + var ( + user *todosrht.User + username string + ) + + if owner != "" { + username = strings.TrimLeft(owner, ownerPrefixes) + user, err = todosrht.TicketBodyByUser(c.Client, ctx, username, name, ticketID) + } else { + user, err = todosrht.TicketBodyByName(c.Client, ctx, name, ticketID) + }
err was being ignored here, plus user and user.Tracker can be nil (in case a user/tracker does not exist).
+ tracker := user.Tracker + ticket := tracker.Ticket + + prefill := ticket.Subject + "\n\n" + if ticket.Body != nil { + prefill += *ticket.Body + } + text, err := getInputWithEditor("hut_ticket*.md", prefill) + if err != nil { + log.Fatalf("failed to read ticket subject and description: %v", err) + } + + parts := strings.SplitN(text, "\n", 2) + subject := strings.TrimSpace(parts[0]) + var body string + if len(parts) > 1 { + body = strings.TrimSpace(parts[1]) + } + + if subject == "" { + log.Println("Aborting due to empty subject.") + os.Exit(1) + } + + input := todosrht.UpdateTicketInput{ + Subject: &subject, + Body: &body, + } + ticket, err = todosrht.UpdateTicket(c.Client, ctx, tracker.Id, ticket.Id, input) + if err != nil { + log.Fatal(err) + } else if ticket == nil { + log.Fatal("failed to create ticket") + }
Changed this to "failed to edit ticket".
+ + log.Printf("Updated ticket %v\n", termfmt.DarkYellow.Sprintf("#%v", ticket.Id)) + } + + cmd := &cobra.Command{ + Use: "edit <ID>", + Short: "Edit a ticket", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completeTicketID, + Run: run, + } + return cmd +} + func newTodoTicketLabelCommand() *cobra.Command { var labelName string run := func(cmd *cobra.Command, args []string) { base-commit: 499ef88754326222b1567261ac6b39b9f2a586ed -- 2.43.0
I pushed this with slightly improved error handling, thanks!