Skip to content

Commit

Permalink
Merge pull request #1090 from anyproto/go-2734-make-globalname-derived
Browse files Browse the repository at this point in the history
  • Loading branch information
KirillSto authored Apr 8, 2024
2 parents ed2c2f9 + 0174ea5 commit 3a78649
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 17 deletions.
12 changes: 2 additions & 10 deletions core/block/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,16 +615,8 @@ func (s *Service) GetRelations(ctx session.Context, objectId string) (relations

// ModifyDetails performs details get and update under the sb lock to make sure no modifications are done in the middle
func (s *Service) ModifyDetails(objectId string, modifier func(current *types.Struct) (*types.Struct, error)) (err error) {
if modifier == nil {
return fmt.Errorf("modifier is nil")
}
return Do(s, objectId, func(b smartblock.SmartBlock) error {
dets, err := modifier(b.CombinedDetails())
if err != nil {
return err
}

return b.Apply(b.NewState().SetDetails(dets))
return Do(s, objectId, func(du basic.DetailsUpdatable) error {
return du.UpdateDetails(modifier)
})
}

Expand Down
8 changes: 7 additions & 1 deletion core/block/editor/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/samber/lo"

"github.com/anyproto/anytype-heart/core/block/editor/converter"
Expand Down Expand Up @@ -40,6 +41,7 @@ type AllOperations interface {

type CommonOperations interface {
DetailsSettable
DetailsUpdatable

SetFields(ctx session.Context, fields ...*pb.RpcBlockListSetFieldsRequestBlockField) (err error)
SetDivStyle(ctx session.Context, style model.BlockContentDivStyle, ids ...string) (err error)
Expand All @@ -64,6 +66,10 @@ type DetailsSettable interface {
SetDetails(ctx session.Context, details []*pb.RpcObjectSetDetailsDetail, showEvent bool) (err error)
}

type DetailsUpdatable interface {
UpdateDetails(update func(current *types.Struct) (*types.Struct, error)) (err error)
}

type Restrictionable interface {
Restrictions() restriction.Restrictions
}
Expand Down Expand Up @@ -402,7 +408,7 @@ func (bs *basic) FeaturedRelationAdd(ctx session.Context, relations ...string) (
}
frc = append(frc, r)
if !bs.HasRelation(s, r) {
err = bs.addRelationLink(r, s)
err = bs.addRelationLink(s, r)
if err != nil {
return fmt.Errorf("failed to add relation link on adding featured relation '%s': %w", r, err)
}
Expand Down
36 changes: 34 additions & 2 deletions core/block/editor/basic/details.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/gogo/protobuf/types"
"golang.org/x/exp/maps"

"github.com/anyproto/anytype-heart/core/block/editor/objecttype"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
Expand Down Expand Up @@ -52,6 +53,25 @@ func (bs *basic) SetDetails(ctx session.Context, details []*pb.RpcObjectSetDetai
return nil
}

func (bs *basic) UpdateDetails(update func(current *types.Struct) (*types.Struct, error)) (err error) {
if update == nil {
return fmt.Errorf("update function is nil")
}
s := bs.NewState()

newDetails, err := update(s.CombinedDetails())
if err != nil {
return
}
s.SetDetails(newDetails)

if err = bs.addRelationLinks(s, maps.Keys(newDetails.Fields)...); err != nil {
return
}

return bs.Apply(s)
}

func (bs *basic) collectDetailUpdates(details []*pb.RpcObjectSetDetailsDetail, s *state.State) []*detailUpdate {
updates := make([]*detailUpdate, 0, len(details))
for _, detail := range details {
Expand Down Expand Up @@ -90,7 +110,7 @@ func (bs *basic) createDetailUpdate(st *state.State, detail *pb.RpcObjectSetDeta
if err := bs.setDetailSpecialCases(st, detail); err != nil {
return nil, fmt.Errorf("special case: %w", err)
}
if err := bs.addRelationLink(detail.Key, st); err != nil {
if err := bs.addRelationLink(st, detail.Key); err != nil {
return nil, err
}
if err := bs.validateDetailFormat(bs.SpaceID(), detail.Key, detail.Value); err != nil {
Expand Down Expand Up @@ -246,7 +266,7 @@ func (bs *basic) setDetailSpecialCases(st *state.State, detail *pb.RpcObjectSetD
return nil
}

func (bs *basic) addRelationLink(relationKey string, st *state.State) error {
func (bs *basic) addRelationLink(st *state.State, relationKey string) error {
relLink, err := bs.objectStore.GetRelationLink(bs.SpaceID(), relationKey)
if err != nil || relLink == nil {
return fmt.Errorf("failed to get relation: %w", err)
Expand All @@ -255,6 +275,18 @@ func (bs *basic) addRelationLink(relationKey string, st *state.State) error {
return nil
}

func (bs *basic) addRelationLinks(st *state.State, relationKeys ...string) error {
if len(relationKeys) == 0 {
return nil
}
relations, err := bs.objectStore.FetchRelationByKeys(bs.SpaceID(), relationKeys...)
if err != nil || relations == nil {
return fmt.Errorf("failed to get relations: %w", err)
}
st.AddRelationLinks(relations.RelationLinks()...)
return nil
}

func (bs *basic) discardOwnSetDetailsEvent(ctx session.Context, showEvent bool) {
if !showEvent && ctx != nil {
var filtered []*pb.EventMessage
Expand Down
138 changes: 138 additions & 0 deletions core/block/editor/basic/details_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package basic

import (
"testing"

"github.com/gogo/protobuf/types"
"github.com/stretchr/testify/assert"

"github.com/anyproto/anytype-heart/core/block/editor/converter"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock/smarttest"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
)

type duFixture struct {
sb *smarttest.SmartTest
store *objectstore.StoreFixture
basic DetailsUpdatable
}

var (
objectId = "objectId"
spaceId = "space1"
)

func newDUFixture(t *testing.T) *duFixture {
sb := smarttest.New(objectId)
sb.SetDetails(nil, nil, false)
sb.SetSpaceId(spaceId)

store := objectstore.NewStoreFixture(t)

b := NewBasic(sb, store, converter.NewLayoutConverter())

return &duFixture{
sb: sb,
store: store,
basic: b,
}
}

func TestBasic_UpdateDetails(t *testing.T) {
t.Run("add new details", func(t *testing.T) {
// given
f := newDUFixture(t)
f.store.AddObjects(t, []objectstore.TestObject{{
bundle.RelationKeyId: pbtypes.String("rel-aperture"),
bundle.RelationKeySpaceId: pbtypes.String(spaceId),
bundle.RelationKeyRelationKey: pbtypes.String("aperture"),
bundle.RelationKeyUniqueKey: pbtypes.String("rel-aperture"),
bundle.RelationKeyRelationFormat: pbtypes.Int64(int64(model.RelationFormat_longtext)),
}, {
bundle.RelationKeyId: pbtypes.String("rel-maxCount"),
bundle.RelationKeySpaceId: pbtypes.String(spaceId),
bundle.RelationKeyRelationKey: pbtypes.String("relationMaxCount"),
bundle.RelationKeyUniqueKey: pbtypes.String("rel-relationMaxCount"),
bundle.RelationKeyRelationFormat: pbtypes.Int64(int64(model.RelationFormat_number)),
}})

// when
err := f.basic.UpdateDetails(func(current *types.Struct) (*types.Struct, error) {
current.Fields[bundle.RelationKeyAperture.String()] = pbtypes.String("aperture")
current.Fields[bundle.RelationKeyRelationMaxCount.String()] = pbtypes.Int64(5)
return current, nil
})

// then
assert.NoError(t, err)

value, found := f.sb.Details().Fields[bundle.RelationKeyAperture.String()]
assert.True(t, found)
assert.Equal(t, pbtypes.String("aperture"), value)
assert.True(t, f.sb.HasRelation(f.sb.NewState(), bundle.RelationKeyAperture.String()))

value, found = f.sb.Details().Fields[bundle.RelationKeyRelationMaxCount.String()]
assert.True(t, found)
assert.Equal(t, pbtypes.Int64(5), value)
assert.True(t, f.sb.HasRelation(f.sb.NewState(), bundle.RelationKeyRelationMaxCount.String()))
})

t.Run("modify details", func(t *testing.T) {
// given
f := newDUFixture(t)
err := f.sb.SetDetails(nil, []*pb.RpcObjectSetDetailsDetail{{
Key: bundle.RelationKeySpaceDashboardId.String(),
Value: pbtypes.String("123"),
}}, false)
assert.NoError(t, err)
f.store.AddObjects(t, []objectstore.TestObject{{
bundle.RelationKeyId: pbtypes.String("rel-spaceDashboardId"),
bundle.RelationKeySpaceId: pbtypes.String(spaceId),
bundle.RelationKeyRelationKey: pbtypes.String("spaceDashboardId"),
bundle.RelationKeyUniqueKey: pbtypes.String("rel-spaceDashboardId"),
bundle.RelationKeyRelationFormat: pbtypes.Int64(int64(model.RelationFormat_object)),
}})

// when
err = f.basic.UpdateDetails(func(current *types.Struct) (*types.Struct, error) {
current.Fields[bundle.RelationKeySpaceDashboardId.String()] = pbtypes.String("new123")
return current, nil
})

// then
assert.NoError(t, err)

value, found := f.sb.Details().Fields[bundle.RelationKeySpaceDashboardId.String()]
assert.True(t, found)
assert.Equal(t, pbtypes.String("new123"), value)
assert.True(t, f.sb.HasRelation(f.sb.NewState(), bundle.RelationKeySpaceDashboardId.String()))
})

t.Run("delete details", func(t *testing.T) {
// given
f := newDUFixture(t)
err := f.sb.SetDetails(nil, []*pb.RpcObjectSetDetailsDetail{{
Key: bundle.RelationKeyTargetObjectType.String(),
Value: pbtypes.String("ot-note"),
}}, false)
assert.NoError(t, err)

// when
err = f.basic.UpdateDetails(func(current *types.Struct) (*types.Struct, error) {
delete(current.Fields, bundle.RelationKeyTargetObjectType.String())
return current, nil
})

// then
assert.NoError(t, err)

value, found := f.sb.Details().Fields[bundle.RelationKeyTargetObjectType.String()]
assert.False(t, found)
assert.Nil(t, value)
assert.False(t, f.sb.HasRelation(f.sb.NewState(), bundle.RelationKeyTargetObjectType.String()))
})
}
6 changes: 5 additions & 1 deletion core/block/editor/participant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package editor
import (
"time"

"github.com/anyproto/anytype-heart/core/block/editor/basic"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
"github.com/anyproto/anytype-heart/core/block/editor/template"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
Expand All @@ -12,11 +13,14 @@ import (

type participant struct {
smartblock.SmartBlock
basic.DetailsUpdatable
}

func (f *ObjectFactory) newParticipant(sb smartblock.SmartBlock) *participant {
basicComponent := basic.NewBasic(sb, f.objectStore, f.layoutConverter)
return &participant{
SmartBlock: sb,
SmartBlock: sb,
DetailsUpdatable: basicComponent,
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/lib/bundle/relation.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
)

const RelationChecksum = "d9166ff25c421f94e3fd6b640fa6ad8652b0d4a676e9963ffddb447d9a20e2ae"
const RelationChecksum = "d56fa782bf2d25bfc0e8e83717c349d63e49d1c3e96c6e83a342b1383942ffbf"
const (
RelationKeyTag domain.RelationKey = "tag"
RelationKeyCamera domain.RelationKey = "camera"
Expand Down Expand Up @@ -859,7 +859,7 @@ var (
},
RelationKeyGlobalName: {

DataSource: model.Relation_details,
DataSource: model.Relation_derived,
Description: "Name of profile that the user could be mentioned by",
Format: model.RelationFormat_shorttext,
Id: "_brglobalName",
Expand Down
2 changes: 1 addition & 1 deletion pkg/lib/bundle/relations.json
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,6 @@
"maxCount": 1,
"name": "Global name",
"readonly": true,
"source": "details"
"source": "derived"
}
]

0 comments on commit 3a78649

Please sign in to comment.