content_blocks.go
TLDR
This file contains a function MoveContentBlock
that is part of the App
struct in the app
package. It is responsible for moving a content block within a card to a specific position.
Methods
MoveContentBlock
This method is used to move a content block within a card to a specific position. It takes the following parameters:
-
block
: The content block to be moved -
dstBlock
: The destination block -
where
: The position where the block should be moved ("after" or "before") -
userID
: The ID of the user making the move
The method performs the following steps:
- Checks if the parent IDs of
block
anddstBlock
match. If not, it returns a bad request error. - Retrieves the card containing the blocks by their parent ID.
- Extracts the
contentOrder
field from the card, if it exists. - Creates a new empty
newContentOrder
slice to store the updated block order. - Loops through each block ID in the
contentOrder
and appends it tonewContentOrder
, with theblock
ID either before or after thedstBlock
ID based on thewhere
parameter. - Checks if both the source and destination blocks were found in the
contentOrder
. If not, it returns a bad request error. - Creates a
BlockPatch
with the updatedcontentOrder
. - Calls
a.PatchBlock
to update the card with the newBlockPatch
. - Returns any error that occurred during the process or
nil
if successful.
package app
import (
"fmt"
"github.com/mattermost/focalboard/server/model"
"github.com/pkg/errors"
)
func (a *App) MoveContentBlock(block *model.Block, dstBlock *model.Block, where string, userID string) error {
if block.ParentID != dstBlock.ParentID {
message := fmt.Sprintf("not matching parent %s and %s", block.ParentID, dstBlock.ParentID)
return model.NewErrBadRequest(message)
}
card, err := a.GetBlockByID(block.ParentID)
if err != nil {
return err
}
contentOrderData, ok := card.Fields["contentOrder"]
var contentOrder []interface{}
if ok {
contentOrder = contentOrderData.([]interface{})
}
newContentOrder := []interface{}{}
foundDst := false
foundSrc := false
for _, id := range contentOrder {
stringID, ok := id.(string)
if !ok {
newContentOrder = append(newContentOrder, id)
continue
}
if dstBlock.ID == stringID {
foundDst = true
if where == "after" {
newContentOrder = append(newContentOrder, id)
newContentOrder = append(newContentOrder, block.ID)
} else {
newContentOrder = append(newContentOrder, block.ID)
newContentOrder = append(newContentOrder, id)
}
continue
}
if block.ID == stringID {
foundSrc = true
continue
}
newContentOrder = append(newContentOrder, id)
}
if !foundSrc {
message := fmt.Sprintf("source block %s not found", block.ID)
return model.NewErrBadRequest(message)
}
if !foundDst {
message := fmt.Sprintf("destination block %s not found", dstBlock.ID)
return model.NewErrBadRequest(message)
}
patch := &model.BlockPatch{
UpdatedFields: map[string]interface{}{
"contentOrder": newContentOrder,
},
}
_, err = a.PatchBlock(block.ParentID, patch, userID)
if errors.Is(err, model.ErrPatchUpdatesLimitedCards) {
return err
}
if err != nil {
return err
}
return nil
}