| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 1 | package loop |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "strings" |
| 6 | "sync" |
| 7 | |
| 8 | "github.com/invopop/jsonschema" |
| 9 | ) |
| 10 | |
| 11 | type Comment struct { |
| Sketch🕴️ | 0020265 | 2026-02-28 21:10:00 +0400 | [diff] [blame] | 12 | Author string `json:"author" jsonschema:"title=author,description=author of the comment,required"` |
| 13 | Comment string `json:"comment" jsonschema:"title=comment,description=actual comment text,required"` |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 14 | } |
| 15 | |
| 16 | func (c Comment) String() string { |
| 17 | return fmt.Sprintf("%s: %s", c.Author, c.Comment) |
| 18 | } |
| 19 | |
| 20 | type ToDo struct { |
| Sketch🕴️ | 0020265 | 2026-02-28 21:10:00 +0400 | [diff] [blame] | 21 | ID string `json:"id" jsonschema:"title=id,description=unique id of the TODO item,required"` |
| 22 | Title string `json:"title" jsonschema:"title=title,description=high level title of the TODO item,required"` |
| 23 | Description string `json:"description" jsonschema:"title=description,description=detailed description what this TODO item is about"` |
| 24 | Items []*ToDo `json:"items" jsonschema:"title=sub items,description=array of sub items current item consists of"` |
| 25 | Parallel bool `json:"parallel" jsonschema:"title=parallel,description=if true sub-items may be worked on in parallel and there is no depencency between them, otherwise they shall be worked on sequentially"` |
| 26 | Done bool `json:"done" jsonschema:"title=done,description=if true item shall be considered as done"` |
| 27 | AssignedTo string `json:"assignedTo" jsonschema:"title=assigned to,description=name of the person who shall work on this item"` |
| 28 | Discussion []Comment `json:"discussion" jsonschema:"title=discussion,description=comments related to current item"` |
| 29 | Summary string `json:"summary" jsonschem:"title=summary,description=detailed summary of current item and all of it's sub-item trees."` |
| 30 | lock sync.RWMutex |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 31 | } |
| 32 | |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 33 | func (t ToDo) String() string { |
| Sketch🕴️ | 0020265 | 2026-02-28 21:10:00 +0400 | [diff] [blame] | 34 | var ret []string |
| 35 | status := "IN PROGRESS" |
| 36 | if t.Done { |
| 37 | status = "DONE" |
| 38 | } |
| 39 | ret = append(ret, fmt.Sprintf("%s: %s - %s %s %t", t.ID, t.Title, status, t.AssignedTo, t.Parallel)) |
| 40 | if t.Description != "" { |
| 41 | ret = append(ret, t.Description) |
| 42 | } |
| 43 | if t.Summary != "" { |
| 44 | ret = append(ret, fmt.Sprintf("SUMMARY: %s", t.Summary)) |
| 45 | } |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 46 | for _, c := range t.Discussion { |
| Sketch🕴️ | 0020265 | 2026-02-28 21:10:00 +0400 | [diff] [blame] | 47 | ret = append(ret, fmt.Sprintf("\t - %s", c.String())) |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 48 | } |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 49 | for _, i := range t.Items { |
| Sketch🕴️ | 0020265 | 2026-02-28 21:10:00 +0400 | [diff] [blame] | 50 | for _, k := range strings.Split(i.String(), "\n") { |
| 51 | ret = append(ret, fmt.Sprintf("\t%s", k)) |
| 52 | } |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 53 | } |
| Sketch🕴️ | 0020265 | 2026-02-28 21:10:00 +0400 | [diff] [blame] | 54 | return strings.Join(ret, "\n") |
| 55 | } |
| 56 | |
| 57 | func (t *ToDo) LockRead() { |
| 58 | t.lock.RLock() |
| 59 | } |
| 60 | |
| 61 | func (t *ToDo) UnlockRead() { |
| 62 | t.lock.RUnlock() |
| 63 | } |
| 64 | |
| 65 | func (t *ToDo) Lock() { |
| 66 | t.lock.Lock() |
| 67 | } |
| 68 | |
| 69 | func (t *ToDo) Unlock() { |
| 70 | t.lock.Unlock() |
| Sketch🕴️ | 305f817 | 2026-02-27 13:58:43 +0400 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | func ToDoJSONSchema() string { |
| 74 | reflector := jsonschema.Reflector{ |
| 75 | AllowAdditionalProperties: false, |
| 76 | RequiredFromJSONSchemaTags: true, |
| 77 | DoNotReference: false, |
| 78 | } |
| 79 | var v ToDo |
| 80 | s := reflector.Reflect(v) |
| 81 | b, err := s.MarshalJSON() |
| 82 | if err != nil { |
| 83 | panic(err) |
| 84 | } |
| 85 | return string(b) |
| 86 | } |