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