1package board
2
3import (
4 "fmt"
5
6 "github.com/git-bug/git-bug/entities/identity"
7 "github.com/git-bug/git-bug/entity"
8 "github.com/git-bug/git-bug/entity/dag"
9 "github.com/git-bug/git-bug/repository"
10 "github.com/git-bug/git-bug/util/text"
11 "github.com/git-bug/git-bug/util/timestamp"
12)
13
14var _ Operation = &AddItemDraftOperation{}
15
16type AddItemDraftOperation struct {
17 dag.OpBase
18 ColumnId entity.Id `json:"column"`
19 Title string `json:"title"`
20 Message string `json:"message"`
21 Files []repository.Hash `json:"files"`
22}
23
24func (op *AddItemDraftOperation) Id() entity.Id {
25 return dag.IdOperation(op, &op.OpBase)
26}
27
28func (op *AddItemDraftOperation) GetFiles() []repository.Hash {
29 return op.Files
30}
31
32func (op *AddItemDraftOperation) Validate() error {
33 if err := op.OpBase.Validate(op, AddItemDraftOp); err != nil {
34 return err
35 }
36
37 if err := op.ColumnId.Validate(); err != nil {
38 return err
39 }
40
41 if text.Empty(op.Title) {
42 return fmt.Errorf("title is empty")
43 }
44 if !text.SafeOneLine(op.Title) {
45 return fmt.Errorf("title has unsafe characters")
46 }
47
48 if !text.Safe(op.Message) {
49 return fmt.Errorf("message is not fully printable")
50 }
51
52 for _, file := range op.Files {
53 if !file.IsValid() {
54 return fmt.Errorf("invalid file hash")
55 }
56 }
57
58 return nil
59}
60
61func (op *AddItemDraftOperation) Apply(snapshot *Snapshot) {
62 // Recreate the combined Id to match on
63 combinedId := entity.CombineIds(snapshot.Id(), op.ColumnId)
64
65 // search the column
66 for _, column := range snapshot.Columns {
67 if column.CombinedId == combinedId {
68 column.Items = append(column.Items, &Draft{
69 combinedId: entity.CombineIds(snapshot.id, op.Id()),
70 author: op.Author(),
71 title: op.Title,
72 Message: op.Message,
73 unixTime: timestamp.Timestamp(op.UnixTime),
74 })
75
76 snapshot.addParticipant(op.Author())
77 return
78 }
79 }
80}
81
82func NewAddItemDraftOp(author identity.Interface, unixTime int64, columnId entity.Id, title, message string, files []repository.Hash) *AddItemDraftOperation {
83 return &AddItemDraftOperation{
84 OpBase: dag.NewOpBase(AddItemDraftOp, author, unixTime),
85 ColumnId: columnId,
86 Title: title,
87 Message: message,
88 Files: files,
89 }
90}
91
92// AddItemDraft is a convenience function to add a draft item to a Board
93func AddItemDraft(b ReadWrite, author identity.Interface, unixTime int64, columnId entity.Id, title, message string, files []repository.Hash, metadata map[string]string) (entity.CombinedId, *AddItemDraftOperation, error) {
94 op := NewAddItemDraftOp(author, unixTime, columnId, title, message, files)
95 for key, val := range metadata {
96 op.SetMetadata(key, val)
97 }
98 if err := op.Validate(); err != nil {
99 return entity.UnsetCombinedId, nil, err
100 }
101 b.Append(op)
102 return entity.CombineIds(b.Id(), op.Id()), op, nil
103}