op_create.go

  1package board
  2
  3import (
  4	"fmt"
  5
  6	"github.com/MichaelMure/git-bug/entities/identity"
  7
  8	"github.com/MichaelMure/git-bug/entity"
  9	"github.com/MichaelMure/git-bug/entity/dag"
 10	"github.com/MichaelMure/git-bug/util/text"
 11)
 12
 13var DefaultColumns = []string{"To Do", "In Progress", "Done"}
 14
 15var _ dag.Operation = &CreateOperation{}
 16
 17type CreateOperation struct {
 18	dag.OpBase
 19	Title       string   `json:"title"`
 20	Description string   `json:"description"`
 21	Columns     []string `json:"columns"`
 22}
 23
 24func NewCreateOp(author identity.Interface, unixTime int64, title string, description string, columns []string) *CreateOperation {
 25	return &CreateOperation{
 26		OpBase:      dag.NewOpBase(CreateOp, author, unixTime),
 27		Title:       title,
 28		Description: description,
 29		Columns:     columns,
 30	}
 31}
 32
 33func (op *CreateOperation) Id() entity.Id {
 34	return dag.IdOperation(op, &op.OpBase)
 35}
 36
 37func (op *CreateOperation) Validate() error {
 38	if err := op.OpBase.Validate(op, CreateOp); err != nil {
 39		return err
 40	}
 41
 42	if text.Empty(op.Title) {
 43		return fmt.Errorf("title is empty")
 44	}
 45	if !text.SafeOneLine(op.Title) {
 46		return fmt.Errorf("title has unsafe characters")
 47	}
 48
 49	if !text.SafeOneLine(op.Description) {
 50		return fmt.Errorf("description has unsafe characters")
 51	}
 52
 53	if len(op.Columns) <= 0 {
 54		return fmt.Errorf("no columns")
 55	}
 56	for _, column := range op.Columns {
 57		if !text.SafeOneLine(column) {
 58			return fmt.Errorf("a columns has unsafe characters")
 59		}
 60		if len(column) > 100 {
 61			return fmt.Errorf("a columns is too long")
 62		}
 63	}
 64
 65	set := make(map[string]struct{})
 66	for _, column := range op.Columns {
 67		set[column] = struct{}{}
 68	}
 69	if len(set) != len(op.Columns) {
 70		return fmt.Errorf("non unique column name")
 71	}
 72
 73	return nil
 74}
 75
 76func (op *CreateOperation) Apply(snap *Snapshot) {
 77	// sanity check: will fail when adding a second Create
 78	if snap.id != "" && snap.id != entity.UnsetId && snap.id != op.Id() {
 79		return
 80	}
 81
 82	snap.id = op.Id()
 83
 84	snap.Title = op.Title
 85	snap.Description = op.Description
 86	snap.CreateTime = op.Time()
 87
 88	for _, name := range op.Columns {
 89		// we derive a unique Id from the original column name
 90		id := entity.DeriveId([]byte(name))
 91
 92		snap.Columns = append(snap.Columns, &Column{
 93			Id:    id,
 94			Name:  name,
 95			Items: nil,
 96		})
 97	}
 98
 99	snap.addActor(op.Author())
100}
101
102// CreateDefaultColumns is a convenience function to create a board with the default columns
103func CreateDefaultColumns(author identity.Interface, unixTime int64, title, description string) (*Board, *CreateOperation, error) {
104	return Create(author, unixTime, title, description, DefaultColumns)
105}
106
107// Create is a convenience function to create a board
108func Create(author identity.Interface, unixTime int64, title, description string, columns []string) (*Board, *CreateOperation, error) {
109	b := NewBoard()
110	op := NewCreateOp(author, unixTime, title, description, columns)
111	if err := op.Validate(); err != nil {
112		return nil, op, err
113	}
114	b.Append(op)
115	return b, op, nil
116}