mirror of
https://github.com/mattermost/focalboard.git
synced 2025-02-07 19:30:18 +02:00
fix cardOrder when modifying block ids (#2345)
This commit is contained in:
parent
5ba81b4c27
commit
d4133ec9d9
@ -2,12 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
)
|
||||
|
||||
// Block is the basic data unit
|
||||
@ -182,110 +177,3 @@ type QueryBlockHistoryOptions struct {
|
||||
Limit uint64 // if non-zero then limit the number of returned records
|
||||
Descending bool // if true then the records are sorted by insert_at in descending order
|
||||
}
|
||||
|
||||
// GenerateBlockIDs generates new IDs for all the blocks of the list,
|
||||
// keeping consistent any references that other blocks would made to
|
||||
// the original IDs, so a tree of blocks can get new IDs and maintain
|
||||
// its shape.
|
||||
func GenerateBlockIDs(blocks []Block, logger *mlog.Logger) []Block {
|
||||
blockIDs := map[string]BlockType{}
|
||||
referenceIDs := map[string]bool{}
|
||||
for _, block := range blocks {
|
||||
if _, ok := blockIDs[block.ID]; !ok {
|
||||
blockIDs[block.ID] = block.Type
|
||||
}
|
||||
|
||||
if _, ok := referenceIDs[block.RootID]; !ok {
|
||||
referenceIDs[block.RootID] = true
|
||||
}
|
||||
if _, ok := referenceIDs[block.ParentID]; !ok {
|
||||
referenceIDs[block.ParentID] = true
|
||||
}
|
||||
|
||||
if _, ok := block.Fields["contentOrder"]; ok {
|
||||
contentOrder, typeOk := block.Fields["contentOrder"].([]interface{})
|
||||
if !typeOk {
|
||||
logger.Warn(
|
||||
"type assertion failed for content order when saving reference block IDs",
|
||||
mlog.String("blockID", block.ID),
|
||||
mlog.String("actionType", fmt.Sprintf("%T", block.Fields["contentOrder"])),
|
||||
mlog.String("expectedType", "[]interface{}"),
|
||||
mlog.String("contentOrder", fmt.Sprintf("%v", block.Fields["contentOrder"])),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, blockID := range contentOrder {
|
||||
switch v := blockID.(type) {
|
||||
case []interface{}:
|
||||
for _, columnBlockID := range v {
|
||||
referenceIDs[columnBlockID.(string)] = true
|
||||
}
|
||||
case string:
|
||||
referenceIDs[v] = true
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newIDs := map[string]string{}
|
||||
for id, blockType := range blockIDs {
|
||||
for referenceID := range referenceIDs {
|
||||
if id == referenceID {
|
||||
newIDs[id] = utils.NewID(BlockType2IDType(blockType))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getExistingOrOldID := func(id string) string {
|
||||
if existingID, ok := newIDs[id]; ok {
|
||||
return existingID
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
getExistingOrNewID := func(id string) string {
|
||||
if existingID, ok := newIDs[id]; ok {
|
||||
return existingID
|
||||
}
|
||||
return utils.NewID(BlockType2IDType(blockIDs[id]))
|
||||
}
|
||||
|
||||
newBlocks := make([]Block, len(blocks))
|
||||
for i, block := range blocks {
|
||||
block.ID = getExistingOrNewID(block.ID)
|
||||
block.RootID = getExistingOrOldID(block.RootID)
|
||||
block.ParentID = getExistingOrOldID(block.ParentID)
|
||||
|
||||
if _, ok := block.Fields["contentOrder"]; ok {
|
||||
contentOrder, typeOk := block.Fields["contentOrder"].([]interface{})
|
||||
if !typeOk {
|
||||
logger.Warn(
|
||||
"type assertion failed for content order when setting new block IDs",
|
||||
mlog.String("blockID", block.ID),
|
||||
mlog.String("actionType", fmt.Sprintf("%T", block.Fields["contentOrder"])),
|
||||
mlog.String("expectedType", "[]interface{}"),
|
||||
mlog.String("contentOrder", fmt.Sprintf("%v", block.Fields["contentOrder"])),
|
||||
)
|
||||
} else {
|
||||
for j := range contentOrder {
|
||||
switch v := contentOrder[j].(type) {
|
||||
case string:
|
||||
contentOrder[j] = getExistingOrOldID(v)
|
||||
case []interface{}:
|
||||
subOrder := contentOrder[j].([]interface{})
|
||||
for k := range v {
|
||||
subOrder[k] = getExistingOrOldID(v[k].(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newBlocks[i] = block
|
||||
}
|
||||
|
||||
return newBlocks
|
||||
}
|
||||
|
126
server/model/blockid.go
Normal file
126
server/model/blockid.go
Normal file
@ -0,0 +1,126 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
// GenerateBlockIDs generates new IDs for all the blocks of the list,
|
||||
// keeping consistent any references that other blocks would made to
|
||||
// the original IDs, so a tree of blocks can get new IDs and maintain
|
||||
// its shape.
|
||||
func GenerateBlockIDs(blocks []Block, logger *mlog.Logger) []Block {
|
||||
blockIDs := map[string]BlockType{}
|
||||
referenceIDs := map[string]bool{}
|
||||
for _, block := range blocks {
|
||||
if _, ok := blockIDs[block.ID]; !ok {
|
||||
blockIDs[block.ID] = block.Type
|
||||
}
|
||||
|
||||
if _, ok := referenceIDs[block.RootID]; !ok {
|
||||
referenceIDs[block.RootID] = true
|
||||
}
|
||||
if _, ok := referenceIDs[block.ParentID]; !ok {
|
||||
referenceIDs[block.ParentID] = true
|
||||
}
|
||||
|
||||
if _, ok := block.Fields["contentOrder"]; ok {
|
||||
contentOrder, typeOk := block.Fields["contentOrder"].([]interface{})
|
||||
if !typeOk {
|
||||
logger.Warn(
|
||||
"type assertion failed for content order when saving reference block IDs",
|
||||
mlog.String("blockID", block.ID),
|
||||
mlog.String("actionType", fmt.Sprintf("%T", block.Fields["contentOrder"])),
|
||||
mlog.String("expectedType", "[]interface{}"),
|
||||
mlog.String("contentOrder", fmt.Sprintf("%v", block.Fields["contentOrder"])),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, blockID := range contentOrder {
|
||||
switch v := blockID.(type) {
|
||||
case []interface{}:
|
||||
for _, columnBlockID := range v {
|
||||
referenceIDs[columnBlockID.(string)] = true
|
||||
}
|
||||
case string:
|
||||
referenceIDs[v] = true
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newIDs := map[string]string{}
|
||||
for id, blockType := range blockIDs {
|
||||
for referenceID := range referenceIDs {
|
||||
if id == referenceID {
|
||||
newIDs[id] = utils.NewID(BlockType2IDType(blockType))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getExistingOrOldID := func(id string) string {
|
||||
if existingID, ok := newIDs[id]; ok {
|
||||
return existingID
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
getExistingOrNewID := func(id string) string {
|
||||
if existingID, ok := newIDs[id]; ok {
|
||||
return existingID
|
||||
}
|
||||
return utils.NewID(BlockType2IDType(blockIDs[id]))
|
||||
}
|
||||
|
||||
newBlocks := make([]Block, len(blocks))
|
||||
for i, block := range blocks {
|
||||
block.ID = getExistingOrNewID(block.ID)
|
||||
block.RootID = getExistingOrOldID(block.RootID)
|
||||
block.ParentID = getExistingOrOldID(block.ParentID)
|
||||
|
||||
blockMod := block
|
||||
if _, ok := blockMod.Fields["contentOrder"]; ok {
|
||||
fixFieldIDs(&blockMod, "contentOrder", getExistingOrOldID, logger)
|
||||
}
|
||||
|
||||
if _, ok := blockMod.Fields["cardOrder"]; ok {
|
||||
fixFieldIDs(&blockMod, "cardOrder", getExistingOrOldID, logger)
|
||||
}
|
||||
|
||||
newBlocks[i] = blockMod
|
||||
}
|
||||
|
||||
return newBlocks
|
||||
}
|
||||
|
||||
func fixFieldIDs(block *Block, fieldName string, getExistingOrOldID func(string) string, logger *mlog.Logger) {
|
||||
field, typeOk := block.Fields[fieldName].([]interface{})
|
||||
if !typeOk {
|
||||
logger.Warn(
|
||||
"type assertion failed for JSON field when setting new block IDs",
|
||||
mlog.String("blockID", block.ID),
|
||||
mlog.String("fieldName", fieldName),
|
||||
mlog.String("actionType", fmt.Sprintf("%T", block.Fields[fieldName])),
|
||||
mlog.String("expectedType", "[]interface{}"),
|
||||
mlog.String("value", fmt.Sprintf("%v", block.Fields[fieldName])),
|
||||
)
|
||||
} else {
|
||||
for j := range field {
|
||||
switch v := field[j].(type) {
|
||||
case string:
|
||||
field[j] = getExistingOrOldID(v)
|
||||
case []interface{}:
|
||||
subOrder := field[j].([]interface{})
|
||||
for k := range v {
|
||||
subOrder[k] = getExistingOrOldID(v[k].(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user