focalboard/server/app/templates.go

103 lines
2.6 KiB
Go
Raw Normal View History

package app
import (
"bytes"
"fmt"
"strings"
_ "embed"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
const (
defaultTemplateVersion = 2
)
//go:embed templates.boardarchive
var defTemplates []byte
// initializeTemplates imports default templates if the blocks table is empty.
func (a *App) initializeTemplates() error {
blocks, err := a.store.GetDefaultTemplateBlocks()
if err != nil {
return fmt.Errorf("cannot initialize templates: %w", err)
}
a.logger.Debug("Fetched template blocks", mlog.Int("count", len(blocks)))
isNeeded, reason := a.isInitializationNeeded(blocks)
if !isNeeded {
a.logger.Debug("Template import not needed, skipping")
return nil
}
a.logger.Debug("Importing new default templates", mlog.String("reason", reason))
if err := a.store.RemoveDefaultTemplates(blocks); err != nil {
return fmt.Errorf("cannot remove old templates: %w", err)
}
r := bytes.NewReader(defTemplates)
opt := model.ImportArchiveOptions{
WorkspaceID: "0",
ModifiedBy: "system",
BlockModifier: fixTemplateBlock,
}
return a.ImportArchive(r, opt)
}
// isInitializationNeeded returns true if the blocks table contains no default templates,
// or contains at least one default template with an old version number.
func (a *App) isInitializationNeeded(blocks []model.Block) (bool, string) {
if len(blocks) == 0 {
return true, "no default templates found"
}
// look for any template blocks with the wrong version number (or no version #).
for _, block := range blocks {
v, ok := block.Fields["templateVer"]
if !ok {
return true, "block missing templateVer"
}
version, ok := v.(float64)
if !ok {
return true, "templateVer NaN"
}
if version < defaultTemplateVersion {
return true, "templateVer too old"
}
}
return false, ""
}
// fixTemplateBlock fixes a block to be inserted as part of a template.
func fixTemplateBlock(block *model.Block, cache map[string]interface{}) bool {
// cache contains ids of skipped blocks. Ensure their children are skipped as well.
if _, ok := cache[block.ParentID]; ok {
cache[block.ID] = struct{}{}
return false
}
// filter out template blocks; we only want the non-template
// blocks which we will turn into default template blocks.
if b, ok := block.Fields["isTemplate"]; ok {
if val, ok := b.(bool); ok && val {
cache[block.ID] = struct{}{}
return false
}
}
// remove '(NEW)' from title & force template flag
if block.Type == model.TypeBoard {
block.Title = strings.ReplaceAll(block.Title, "(NEW)", "")
block.Fields["isTemplate"] = true
block.Fields["templateVer"] = defaultTemplateVersion
}
return true
}