Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GO-3942: add layouts for tag as an object #1511

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions core/block/editor/converter/layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ func (c *layoutConverter) Convert(space smartblock.Space, st *state.State, fromL

// TODO We need more granular cases (not catch-all)

if toLayout == model.ObjectType_tag {
return c.fromAnyToTag(st)
}

return c.fromAnyToAny(st)
}

Expand Down Expand Up @@ -322,3 +326,12 @@ func (c *layoutConverter) appendTypesFilter(types []string, filters []*model.Blo
}
return filters
}

func (c *layoutConverter) fromAnyToTag(st *state.State) error {
template.InitTemplate(st,
template.WithTitle,
template.WithNoDescription,
template.WithRelations([]domain.RelationKey{bundle.RelationKeyRelationOptionColor}),
)
return nil
}
5 changes: 5 additions & 0 deletions core/block/editor/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ func (p *Page) CreationStateMigration(ctx *smartblock.InitContext) migration.Mig
template.WithAddedFeaturedRelation(bundle.RelationKeyType),
)
// TODO case for relationOption?
case model.ObjectType_tag:
templates = append(templates,
template.WithTitle,
template.WithNoDescription,
template.WithRelations([]domain.RelationKey{bundle.RelationKeyRelationOptionColor}))
default:
templates = append(templates,
template.WithTitle,
Expand Down
2 changes: 1 addition & 1 deletion core/block/import/common/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (r *ImportCollection) addRelations(st *state.State) error {
for _, relation := range []*model.RelationLink{
{
Key: bundle.RelationKeyTag.String(),
Format: model.RelationFormat_tag,
Format: model.RelationFormat_object,
},
{
Key: bundle.RelationKeyCreatedDate.String(),
Expand Down
124 changes: 79 additions & 45 deletions core/block/import/pb/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,70 +315,104 @@ func (p *Pb) normalizeSnapshot(snapshot *pb.SnapshotWithType,
id, profileID, path string,
isMigration bool,
pbFiles source.Source) (string, error) {
p.normalizeRelationLinks(snapshot)
if snapshot.SbType == model.SmartBlockType_STRelationOption {
p.normalizeRelationOption(snapshot)
}
if _, ok := model.SmartBlockType_name[int32(snapshot.SbType)]; !ok {
newSbType := model.SmartBlockType_Page
if int32(snapshot.SbType) == 96 { // fallback for objectType smartblocktype
newSbType = model.SmartBlockType_SubObject
}
snapshot.SbType = newSbType
p.normalizeNormalizeOldType(snapshot)
}

if snapshot.SbType == model.SmartBlockType_SubObject {
details := snapshot.Snapshot.Data.Details
originalId := pbtypes.GetString(snapshot.Snapshot.Data.Details, bundle.RelationKeyId.String())
var sourceObjectId string
// migrate old sub objects into real objects
if snapshot.Snapshot.Data.ObjectTypes[0] == bundle.TypeKeyObjectType.URL() {
snapshot.SbType = model.SmartBlockType_STType
typeKey, err := bundle.TypeKeyFromUrl(originalId)
if err == nil {
sourceObjectId = typeKey.BundledURL()
}
} else if snapshot.Snapshot.Data.ObjectTypes[0] == bundle.TypeKeyRelation.URL() {
snapshot.SbType = model.SmartBlockType_STRelation
relationKey, err := bundle.RelationKeyFromID(originalId)
if err == nil {
sourceObjectId = relationKey.BundledURL()
}
} else if snapshot.Snapshot.Data.ObjectTypes[0] == bundle.TypeKeyRelationOption.URL() {
snapshot.SbType = model.SmartBlockType_STRelationOption
} else {
return "", fmt.Errorf("unknown sub object type %s", snapshot.Snapshot.Data.ObjectTypes[0])
}
if sourceObjectId != "" {
if pbtypes.GetString(details, bundle.RelationKeySourceObject.String()) == "" {
details.Fields[bundle.RelationKeySourceObject.String()] = pbtypes.String(sourceObjectId)
}
}
id = originalId
return p.normalizeSubObject(snapshot, id)
}

if snapshot.SbType == model.SmartBlockType_ProfilePage {
var err error
id, err = p.getIDForUserProfile(snapshot, profileID, id, isMigration)
if err != nil {
return "", fmt.Errorf("get user profile id: %w", err)
}
p.setProfileIconOption(snapshot, profileID)
return p.normalizeProfile(snapshot, id, profileID, isMigration)
}
if snapshot.SbType == model.SmartBlockType_Page {
p.cleanupEmptyBlock(snapshot)
}
if snapshot.SbType == model.SmartBlockType_File {
if snapshot.SbType == model.SmartBlockType_File || snapshot.SbType == model.SmartBlockType_FileObject {
err := p.normalizeFilePath(snapshot, pbFiles, path)
if err != nil {
return "", fmt.Errorf("failed to update file path in file snapshot %w", err)
}
}
if snapshot.SbType == model.SmartBlockType_FileObject {
err := p.normalizeFilePath(snapshot, pbFiles, path)
if err != nil {
return "", fmt.Errorf("failed to update file path in file snapshot %w", err)
return id, nil
}

func (p *Pb) normalizeRelationLinks(snapshot *pb.SnapshotWithType) {
for _, link := range snapshot.Snapshot.Data.RelationLinks {
if link.Key == bundle.RelationKeyTag.String() {
link.Format = model.RelationFormat_object
break
}
}
}

func (p *Pb) normalizeRelationOption(snapshot *pb.SnapshotWithType) {
key := pbtypes.GetString(snapshot.Snapshot.Data.Details, bundle.RelationKeyRelationKey.String())
if key != bundle.RelationKeyTag.String() {
return
}
snapshot.SbType = model.SmartBlockType_Page
snapshot.Snapshot.Data.Key = ""
snapshot.Snapshot.Data.ObjectTypes = []string{bundle.TypeKeyTag.URL()}
if snapshot.Snapshot.Data.Details == nil || snapshot.Snapshot.Data.Details.Fields == nil {
snapshot.Snapshot.Data.Details.Fields = map[string]*types.Value{}
}
snapshot.Snapshot.Data.Details.Fields[bundle.RelationKeyLayout.String()] = pbtypes.Int64(int64(model.ObjectType_tag))
delete(snapshot.Snapshot.Data.Details.Fields, bundle.RelationKeyRelationKey.String())
delete(snapshot.Snapshot.Data.Details.Fields, bundle.RelationKeyUniqueKey.String())
}

func (p *Pb) normalizeProfile(snapshot *pb.SnapshotWithType, id string, profileID string, isMigration bool) (string, error) {
id, err := p.getIDForUserProfile(snapshot, profileID, id, isMigration)
if err != nil {
return "", fmt.Errorf("get user profile id: %w", err)
}
p.setProfileIconOption(snapshot, profileID)
return id, nil
}

func (p *Pb) normalizeSubObject(snapshot *pb.SnapshotWithType, id string) (string, error) {
details := snapshot.Snapshot.Data.Details
originalId := pbtypes.GetString(snapshot.Snapshot.Data.Details, bundle.RelationKeyId.String())
var sourceObjectId string
// migrate old sub objects into real objects
if snapshot.Snapshot.Data.ObjectTypes[0] == bundle.TypeKeyObjectType.URL() {
snapshot.SbType = model.SmartBlockType_STType
typeKey, err := bundle.TypeKeyFromUrl(originalId)
if err == nil {
sourceObjectId = typeKey.BundledURL()
}
} else if snapshot.Snapshot.Data.ObjectTypes[0] == bundle.TypeKeyRelation.URL() {
snapshot.SbType = model.SmartBlockType_STRelation
relationKey, err := bundle.RelationKeyFromID(originalId)
if err == nil {
sourceObjectId = relationKey.BundledURL()
}
} else if snapshot.Snapshot.Data.ObjectTypes[0] == bundle.TypeKeyRelationOption.URL() {
snapshot.SbType = model.SmartBlockType_STRelationOption
} else {
return "", fmt.Errorf("unknown sub object type %s", snapshot.Snapshot.Data.ObjectTypes[0])
}
if sourceObjectId != "" {
if pbtypes.GetString(details, bundle.RelationKeySourceObject.String()) == "" {
details.Fields[bundle.RelationKeySourceObject.String()] = pbtypes.String(sourceObjectId)
}
}
id = originalId
return id, nil
}

func (p *Pb) normalizeNormalizeOldType(snapshot *pb.SnapshotWithType) {
newSbType := model.SmartBlockType_Page
if int32(snapshot.SbType) == 96 { // fallback for objectType smartblocktype
newSbType = model.SmartBlockType_SubObject
}
snapshot.SbType = newSbType
}

func (p *Pb) normalizeFilePath(snapshot *pb.SnapshotWithType, pbFiles source.Source, path string) error {
filePath := pbtypes.GetString(snapshot.Snapshot.Data.Details, bundle.RelationKeySource.String())
fileName, _, err := common.ProvideFileName(filePath, pbFiles, path, p.tempDirProvider)
Expand Down
74 changes: 74 additions & 0 deletions core/block/import/pb/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ import (
"sync"
"testing"

"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"

"github.com/anyproto/anytype-heart/core/block/process"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
)

func Test_GetSnapshotsSuccess(t *testing.T) {
Expand Down Expand Up @@ -187,6 +194,73 @@ func Test_GetSnapshotsSkipFileWithoutExtension(t *testing.T) {
assert.Contains(t, res.Snapshots[1].FileName, rootCollectionName)
}

func Test_normalizeSnapshot(t *testing.T) {
t.Run("normalize relation option", func(t *testing.T) {
// given
p := &Pb{}

key := bson.NewObjectId().Hex()
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelationOption, key)
assert.NoError(t, err)

snapshot := &pb.SnapshotWithType{
SbType: model.SmartBlockType_STRelationOption,
Snapshot: &pb.ChangeSnapshot{
Data: &model.SmartBlockSnapshotBase{
Details: &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyUniqueKey.String(): pbtypes.String(uniqueKey.Marshal()),
bundle.RelationKeyRelationKey.String(): pbtypes.String(bundle.RelationKeyTag.String()),
}},
ObjectTypes: []string{bundle.TypeKeyRelationOption.URL()},
Key: "key",
},
},
}
// when
_, err = p.normalizeSnapshot(snapshot, uuid.New().String(), "", "path", false, nil)

// then
assert.NoError(t, err)
assert.Equal(t, model.SmartBlockType_Page, snapshot.SbType)
assert.Empty(t, snapshot.Snapshot.Data.Details.Fields[bundle.RelationKeyUniqueKey.String()])
assert.Empty(t, snapshot.Snapshot.Data.Details.Fields[bundle.RelationKeyRelationKey.String()])
assert.Equal(t, []string{bundle.TypeKeyTag.URL()}, snapshot.Snapshot.Data.ObjectTypes)
assert.Empty(t, snapshot.Snapshot.Data.Key)
})
t.Run("normalize relation option, but it's not tag relation option", func(t *testing.T) {
// given
p := &Pb{}

key := bson.NewObjectId().Hex()
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelationOption, key)
assert.NoError(t, err)

snapshot := &pb.SnapshotWithType{
SbType: model.SmartBlockType_STRelationOption,
Snapshot: &pb.ChangeSnapshot{
Data: &model.SmartBlockSnapshotBase{
Details: &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyUniqueKey.String(): pbtypes.String(uniqueKey.Marshal()),
bundle.RelationKeyRelationKey.String(): pbtypes.String("test"),
}},
ObjectTypes: []string{bundle.TypeKeyRelationOption.URL()},
Key: "key",
},
},
}
// when
_, err = p.normalizeSnapshot(snapshot, uuid.New().String(), "", "path", false, nil)

// then
assert.NoError(t, err)
assert.Equal(t, model.SmartBlockType_STRelationOption, snapshot.SbType)
assert.Equal(t, pbtypes.String(uniqueKey.Marshal()), snapshot.Snapshot.Data.Details.Fields[bundle.RelationKeyUniqueKey.String()])
assert.Equal(t, pbtypes.String("test"), snapshot.Snapshot.Data.Details.Fields[bundle.RelationKeyRelationKey.String()])
assert.Equal(t, []string{bundle.TypeKeyRelationOption.URL()}, snapshot.Snapshot.Data.ObjectTypes)
assert.Equal(t, "key", snapshot.Snapshot.Data.Key)
})
}

func newZipWriter(path string) (*zipWriter, error) {
filename := filepath.Join(path, "Anytype"+strconv.FormatInt(rand.Int63(), 10)+".zip")
f, err := os.Create(filename)
Expand Down
37 changes: 17 additions & 20 deletions core/kanban/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"github.com/anyproto/any-sync/app"
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
sb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
"github.com/anyproto/anytype-heart/pkg/lib/database"
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
Expand All @@ -30,40 +33,34 @@ func Test_GrouperTags(t *testing.T) {

objectStore := objectstore.NewStoreFixture(t)

key := "key"
uniqueKey, err := domain.NewUniqueKey(sb.SmartBlockTypeRelation, key)
assert.NoError(t, err)

objectStore.AddObjects(t, []objectstore.TestObject{
{
bundle.RelationKeyId: pbtypes.String("tag1"),
bundle.RelationKeyUniqueKey: pbtypes.String("rel-tag"),
bundle.RelationKeyId: pbtypes.String("relationId"),
bundle.RelationKeyUniqueKey: pbtypes.String(uniqueKey.Marshal()),
bundle.RelationKeyRelationFormat: pbtypes.Int64(int64(model.RelationFormat_tag)),
bundle.RelationKeySpaceId: pbtypes.String(""),
},
})

kanbanSrv := New()
err := a.Register(objectStore).
err = a.Register(objectStore).
Register(kanbanSrv).
Register(tp).
Start(context.Background())
require.NoError(t, err)

require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), "rel-tag", &types.Struct{
Fields: map[string]*types.Value{
"id": pbtypes.String("rel-tag"),
"relationKey": pbtypes.String("tag"),
"relationFormat": pbtypes.Int64(int64(model.RelationFormat_tag)),
"type": pbtypes.String(bundle.TypeKeyRelation.URL()),
"layout": pbtypes.Int64(int64(model.ObjectType_relation)),
},
}))

idTag1 := bson.NewObjectId().Hex()
idTag2 := bson.NewObjectId().Hex()
idTag3 := bson.NewObjectId().Hex()

require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), idTag1, &types.Struct{
Fields: map[string]*types.Value{
"id": pbtypes.String(idTag1),
"relationKey": pbtypes.String("tag"),
"relationKey": pbtypes.String(key),
"type": pbtypes.String(bundle.TypeKeyRelationOption.URL()),
"layout": pbtypes.Int64(int64(model.ObjectType_relationOption)),
},
Expand All @@ -72,15 +69,15 @@ func Test_GrouperTags(t *testing.T) {
require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), idTag2, &types.Struct{
Fields: map[string]*types.Value{
"id": pbtypes.String(idTag2),
"relationKey": pbtypes.String("tag"),
"relationKey": pbtypes.String(key),
"type": pbtypes.String(bundle.TypeKeyRelationOption.URL()),
"layout": pbtypes.Int64(int64(model.ObjectType_relationOption)),
},
}))
require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), idTag3, &types.Struct{
Fields: map[string]*types.Value{
"id": pbtypes.String(idTag3),
"relationKey": pbtypes.String("tag"),
"relationKey": pbtypes.String(key),
"type": pbtypes.String(bundle.TypeKeyRelationOption.URL()),
"layout": pbtypes.Int64(int64(model.ObjectType_relationOption)),
},
Expand All @@ -97,20 +94,20 @@ func Test_GrouperTags(t *testing.T) {

require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), id2, &types.Struct{Fields: map[string]*types.Value{
"name": pbtypes.String("two"),
"tag": pbtypes.StringList([]string{idTag1}),
key: pbtypes.StringList([]string{idTag1}),
}}))

require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), id3, &types.Struct{Fields: map[string]*types.Value{
"name": pbtypes.String("three"),
"tag": pbtypes.StringList([]string{idTag1, idTag2, idTag3}),
key: pbtypes.StringList([]string{idTag1, idTag2, idTag3}),
}}))

require.NoError(t, objectStore.UpdateObjectDetails(context.Background(), id4, &types.Struct{Fields: map[string]*types.Value{
"name": pbtypes.String("four"),
"tag": pbtypes.StringList([]string{idTag1, idTag3}),
key: pbtypes.StringList([]string{idTag1, idTag3}),
}}))

grouper, err := kanbanSrv.Grouper("", "tag")
grouper, err := kanbanSrv.Grouper("", key)
require.NoError(t, err)
err = grouper.InitGroups("", nil)
require.NoError(t, err)
Expand Down
Loading
Loading