1package bug
  2
  3import (
  4	"encoding/json"
  5
  6	"github.com/pkg/errors"
  7
  8	"github.com/MichaelMure/git-bug/entity"
  9	"github.com/MichaelMure/git-bug/identity"
 10	"github.com/MichaelMure/git-bug/util/timestamp"
 11)
 12
 13var _ Operation = &SetStatusOperation{}
 14
 15// SetStatusOperation will change the status of a bug
 16type SetStatusOperation struct {
 17	OpBase
 18	Status Status `json:"status"`
 19}
 20
 21func (op *SetStatusOperation) Id() entity.Id {
 22	return idOperation(op, &op.OpBase)
 23}
 24
 25func (op *SetStatusOperation) Apply(snapshot *Snapshot) {
 26	snapshot.Status = op.Status
 27	snapshot.addActor(op.Author_)
 28
 29	item := &SetStatusTimelineItem{
 30		id:       op.Id(),
 31		Author:   op.Author_,
 32		UnixTime: timestamp.Timestamp(op.UnixTime),
 33		Status:   op.Status,
 34	}
 35
 36	snapshot.Timeline = append(snapshot.Timeline, item)
 37}
 38
 39func (op *SetStatusOperation) Validate() error {
 40	if err := op.OpBase.Validate(op, SetStatusOp); err != nil {
 41		return err
 42	}
 43
 44	if err := op.Status.Validate(); err != nil {
 45		return errors.Wrap(err, "status")
 46	}
 47
 48	return nil
 49}
 50
 51// UnmarshalJSON is a two step JSON unmarshalling
 52// This workaround is necessary to avoid the inner OpBase.MarshalJSON
 53// overriding the outer op's MarshalJSON
 54func (op *SetStatusOperation) UnmarshalJSON(data []byte) error {
 55	// Unmarshal OpBase and the op separately
 56
 57	base := OpBase{}
 58	err := json.Unmarshal(data, &base)
 59	if err != nil {
 60		return err
 61	}
 62
 63	aux := struct {
 64		Status Status `json:"status"`
 65	}{}
 66
 67	err = json.Unmarshal(data, &aux)
 68	if err != nil {
 69		return err
 70	}
 71
 72	op.OpBase = base
 73	op.Status = aux.Status
 74
 75	return nil
 76}
 77
 78// Sign post method for gqlgen
 79func (op *SetStatusOperation) IsAuthored() {}
 80
 81func NewSetStatusOp(author identity.Interface, unixTime int64, status Status) *SetStatusOperation {
 82	return &SetStatusOperation{
 83		OpBase: newOpBase(SetStatusOp, author, unixTime),
 84		Status: status,
 85	}
 86}
 87
 88type SetStatusTimelineItem struct {
 89	id       entity.Id
 90	Author   identity.Interface
 91	UnixTime timestamp.Timestamp
 92	Status   Status
 93}
 94
 95func (s SetStatusTimelineItem) Id() entity.Id {
 96	return s.id
 97}
 98
 99// Sign post method for gqlgen
100func (s *SetStatusTimelineItem) IsAuthored() {}
101
102// Convenience function to apply the operation
103func Open(b Interface, author identity.Interface, unixTime int64) (*SetStatusOperation, error) {
104	op := NewSetStatusOp(author, unixTime, OpenStatus)
105	if err := op.Validate(); err != nil {
106		return nil, err
107	}
108	b.Append(op)
109	return op, nil
110}
111
112// Convenience function to apply the operation
113func Close(b Interface, author identity.Interface, unixTime int64) (*SetStatusOperation, error) {
114	op := NewSetStatusOp(author, unixTime, ClosedStatus)
115	if err := op.Validate(); err != nil {
116		return nil, err
117	}
118	b.Append(op)
119	return op, nil
120}