main

mattermost/focalboard

Last updated at: 29/12/2023 09:39

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 and dstBlock 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 to newContentOrder, with the block ID either before or after the dstBlock ID based on the where 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 updated contentOrder.
  • Calls a.PatchBlock to update the card with the new BlockPatch.
  • 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
}