task.go

140 lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
//go:build cgo

package commands

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"

	"congo.gg/dev/models"
)

const taskUsage = `Manage tasks in the Congo Dev database

Usage:
  congo task <subcommand> [arguments]

Subcommands:
  list                     List tasks (JSON)
  create <title>           Create a task
  update <id> --status X   Update a task
  get <id>                 Get a single task (JSON)
`

func Task() {
	if len(os.Args) < 3 {
		fmt.Print(taskUsage)
		os.Exit(1)
	}

	switch os.Args[2] {
	case "list":
		taskList()
	case "create":
		taskCreate()
	case "update":
		taskUpdate()
	case "get":
		taskGet()
	default:
		fmt.Fprintf(os.Stderr, "unknown task subcommand %q\n", os.Args[2])
		os.Exit(1)
	}
}

func taskList() {
	f := flag.NewFlagSet("task list", flag.ExitOnError)
	status := f.String("status", "", "Filter by status (todo, in_progress, done, blocked)")
	assignee := f.String("assignee", "", "Filter by assignee")
	f.Parse(os.Args[3:])

	query := "ORDER BY CASE Priority WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END"
	var args []any

	if *status != "" {
		query = "WHERE Status = ? " + query
		args = append(args, *status)
	}
	if *assignee != "" {
		if len(args) > 0 {
			query = "WHERE Status = ? AND Assignee = ? ORDER BY CASE Priority WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END"
			args = append(args, *assignee)
		} else {
			query = "WHERE Assignee = ? " + query
			args = append(args, *assignee)
		}
	}

	tasks, _ := models.Tasks.Search(query, args...)
	json.NewEncoder(os.Stdout).Encode(tasks)
}

func taskCreate() {
	f := flag.NewFlagSet("task create", flag.ExitOnError)
	priority := f.String("priority", "medium", "Priority (high, medium, low)")
	assignee := f.String("assignee", "", "Assignee (twin, connor, etc)")
	category := f.String("category", "", "Category")
	description := f.String("description", "", "Description")
	f.Parse(os.Args[3:])

	title := f.Arg(0)
	if title == "" {
		fmt.Fprintln(os.Stderr, "usage: congo task create <title>")
		os.Exit(1)
	}

	task := &models.Task{
		Title:       title,
		Description: *description,
		Priority:    *priority,
		Status:      "todo",
		Assignee:    *assignee,
		Category:    *category,
	}
	id, _ := models.Tasks.Insert(task)
	fmt.Println(id)
}

func taskUpdate() {
	if len(os.Args) < 4 {
		fmt.Fprintln(os.Stderr, "usage: congo task update <id> --status done")
		os.Exit(1)
	}

	// ID is the first arg after "task update", flags follow
	id := os.Args[3]
	f := flag.NewFlagSet("task update", flag.ExitOnError)
	status := f.String("status", "", "New status")
	assignee := f.String("assignee", "", "New assignee")
	f.Parse(os.Args[4:]) // parse flags after the ID

	task, err := models.Tasks.Get(id)
	if err != nil || task == nil {
		fmt.Fprintf(os.Stderr, "task %s not found\n", id)
		os.Exit(1)
	}

	if *status != "" {
		task.Status = *status
	}
	if *assignee != "" {
		task.Assignee = *assignee
	}
	models.Tasks.Update(task)
	fmt.Println("updated")
}

func taskGet() {
	if len(os.Args) < 4 {
		fmt.Fprintln(os.Stderr, "usage: congo task get <id>")
		os.Exit(1)
	}
	task, err := models.Tasks.Get(os.Args[3])
	if err != nil || task == nil {
		fmt.Fprintf(os.Stderr, "task not found\n")
		os.Exit(1)
	}
	json.NewEncoder(os.Stdout).Encode(task)
}