Revision history: change sets + revisions + revert — the undo substrate (#48) (#61)
Build image / build-and-push (push) Successful in 5s
Build image / build-and-push (push) Successful in 5s
Co-authored-by: Steve Dudenhoeffer <[email protected]>
This commit was merged in pull request #61.
This commit is contained in:
@@ -122,7 +122,23 @@ func (s *Service) CreateObject(ctx context.Context, actorID, gardenID int64, in
|
||||
if err := finalizeObject(o, g); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.store.CreateObject(ctx, o)
|
||||
created, err := s.store.CreateObject(ctx, o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.record(ctx, gardenID, actorID, "Added "+objectLabel(created),
|
||||
changeCreate(domain.EntityObject, created.ID, created))
|
||||
return created, nil
|
||||
}
|
||||
|
||||
// objectLabel names an object for a change-set summary: its own name when it has
|
||||
// one, else its kind ("bed", "grow_bag"), so history reads as "Added bed" rather
|
||||
// than "Added ".
|
||||
func objectLabel(o *domain.GardenObject) string {
|
||||
if o.Name != "" {
|
||||
return o.Name
|
||||
}
|
||||
return o.Kind
|
||||
}
|
||||
|
||||
// objectForRole loads an object and enforces that the actor holds at least min
|
||||
@@ -148,21 +164,36 @@ func (s *Service) UpdateObject(ctx context.Context, actorID, objectID int64, pat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
before := *o // objectForRole returns the current row, and the patch mutates it
|
||||
applyObjectPatch(o, patch)
|
||||
if err := finalizeObject(o, g); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o.Version = version
|
||||
return s.store.UpdateObject(ctx, o)
|
||||
updated, err := s.store.UpdateObject(ctx, o)
|
||||
if err != nil {
|
||||
return updated, err // may carry the current row on a version conflict
|
||||
}
|
||||
s.record(ctx, g.ID, actorID, "Edited "+objectLabel(updated),
|
||||
changeUpdate(domain.EntityObject, updated.ID, &before, updated))
|
||||
return updated, nil
|
||||
}
|
||||
|
||||
// DeleteObject removes an object (its plantings cascade) from a garden the actor
|
||||
// can edit.
|
||||
func (s *Service) DeleteObject(ctx context.Context, actorID, objectID int64) error {
|
||||
if _, _, err := s.objectForRole(ctx, actorID, objectID, roleEditor); err != nil {
|
||||
o, g, err := s.objectForRole(ctx, actorID, objectID, roleEditor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.store.DeleteObject(ctx, objectID)
|
||||
// deleteObjectRecording snapshots the plantings the FK is about to cascade
|
||||
// away, so the delete is actually revertible rather than merely listed.
|
||||
changes, err := s.deleteObjectRecording(ctx, o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.record(ctx, g.ID, actorID, "Deleted "+objectLabel(o), changes...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GardenFull returns the whole editor payload for a garden the actor can view.
|
||||
|
||||
Reference in New Issue
Block a user