Bladeren bron

:art: Add an internal kernel API `/api/av/appendAttributeViewDetachedBlocksWithValues` https://github.com/siyuan-note/siyuan/issues/11608

Daniel 1 jaar geleden
bovenliggende
commit
4e2de612d7
4 gewijzigde bestanden met toevoegingen van 121 en 15 verwijderingen
  1. 44 2
      kernel/api/av.go
  2. 3 2
      kernel/api/router.go
  3. 20 0
      kernel/av/av.go
  4. 54 11
      kernel/model/attribute_view.go

+ 44 - 2
kernel/api/av.go

@@ -135,7 +135,49 @@ func getAttributeViewPrimaryKeyValues(c *gin.Context) {
 	}
 }
 
-func addAttributeViewValues(c *gin.Context) {
+func appendAttributeViewDetachedBlocksWithValues(c *gin.Context) {
+	// Add an internal kernel API `/api/av/appendAttributeViewDetachedBlocksWithValues` https://github.com/siyuan-note/siyuan/issues/11608
+
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	arg, _ := util.JsonArg(c, ret)
+	if nil == arg {
+		return
+	}
+
+	avID := arg["avID"].(string)
+	var values [][]*av.Value
+	for _, blocksVals := range arg["blocksValues"].([]interface{}) {
+		vals := blocksVals.([]interface{})
+		var rowValues []*av.Value
+		for _, val := range vals {
+			data, marshalErr := gulu.JSON.MarshalJSON(val)
+			if nil != marshalErr {
+				ret.Code = -1
+				ret.Msg = marshalErr.Error()
+				return
+			}
+			value := av.Value{}
+			if unmarshalErr := gulu.JSON.UnmarshalJSON(data, &value); nil != unmarshalErr {
+				ret.Code = -1
+				ret.Msg = unmarshalErr.Error()
+				return
+			}
+			rowValues = append(rowValues, &value)
+		}
+		values = append(values, rowValues)
+	}
+
+	err := model.AppendAttributeViewDetachedBlocksWithValues(avID, values)
+	if nil != err {
+		ret.Code = -1
+		ret.Msg = err.Error()
+		return
+	}
+}
+
+func addAttributeViewBlocks(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)
 
@@ -173,7 +215,7 @@ func addAttributeViewValues(c *gin.Context) {
 	util.PushReloadAttrView(avID)
 }
 
-func removeAttributeViewValues(c *gin.Context) {
+func removeAttributeViewBlocks(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)
 

+ 3 - 2
kernel/api/router.go

@@ -419,13 +419,14 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/av/removeAttributeViewKey", model.CheckAuth, model.CheckReadonly, removeAttributeViewKey)
 	ginServer.Handle("POST", "/api/av/sortAttributeViewViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewViewKey)
 	ginServer.Handle("POST", "/api/av/sortAttributeViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewKey)
-	ginServer.Handle("POST", "/api/av/addAttributeViewValues", model.CheckAuth, model.CheckReadonly, addAttributeViewValues)
-	ginServer.Handle("POST", "/api/av/removeAttributeViewValues", model.CheckAuth, model.CheckReadonly, removeAttributeViewValues)
+	ginServer.Handle("POST", "/api/av/addAttributeViewBlocks", model.CheckAuth, model.CheckReadonly, addAttributeViewBlocks)
+	ginServer.Handle("POST", "/api/av/removeAttributeViewBlocks", model.CheckAuth, model.CheckReadonly, removeAttributeViewBlocks)
 	ginServer.Handle("POST", "/api/av/getAttributeViewPrimaryKeyValues", model.CheckAuth, model.CheckReadonly, getAttributeViewPrimaryKeyValues)
 	ginServer.Handle("POST", "/api/av/setDatabaseBlockView", model.CheckAuth, model.CheckReadonly, setDatabaseBlockView)
 	ginServer.Handle("POST", "/api/av/getMirrorDatabaseBlocks", model.CheckAuth, model.CheckReadonly, getMirrorDatabaseBlocks)
 	ginServer.Handle("POST", "/api/av/getAttributeViewKeysByAvID", model.CheckAuth, model.CheckReadonly, getAttributeViewKeysByAvID)
 	ginServer.Handle("POST", "/api/av/duplicateAttributeViewBlock", model.CheckAuth, model.CheckReadonly, duplicateAttributeViewBlock)
+	ginServer.Handle("POST", "/api/av/appendAttributeViewDetachedBlocksWithValues", model.CheckAuth, model.CheckReadonly, appendAttributeViewDetachedBlocksWithValues)
 
 	ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
 	ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, chatGPTWithAction)

+ 20 - 0
kernel/av/av.go

@@ -62,6 +62,26 @@ func (kValues *KeyValues) GetValue(blockID string) (ret *Value) {
 	return
 }
 
+func (kValues *KeyValues) GetBlockValue() (ret *Value) {
+	for _, v := range kValues.Values {
+		if KeyTypeBlock != v.Type {
+			ret = v
+			return
+		}
+	}
+	return
+}
+
+func GetKeyBlockValue(blockKeyValues []*KeyValues) (ret *Value) {
+	for _, kv := range blockKeyValues {
+		if KeyTypeBlock == kv.Key.Type && 0 < len(kv.Values) {
+			ret = kv.Values[0]
+			break
+		}
+	}
+	return
+}
+
 type KeyType string
 
 const (

+ 54 - 11
kernel/model/attribute_view.go

@@ -42,6 +42,59 @@ import (
 	"github.com/xrash/smetrics"
 )
 
+func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*av.Value) (err error) {
+	attrView, err := av.ParseAttributeView(avID)
+	if nil != err {
+		logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
+		return
+	}
+
+	now := util.CurrentTimeMillis()
+	var blockIDs []string
+	for _, blockValues := range blocksValues {
+		blockID := ast.NewNodeID()
+		blockIDs = append(blockIDs, blockID)
+		for _, v := range blockValues {
+			keyValues, _ := attrView.GetKeyValues(v.KeyID)
+			if nil == keyValues {
+				err = fmt.Errorf("key [%s] not found", v.KeyID)
+				return
+			}
+
+			v.ID = ast.NewNodeID()
+			v.BlockID = blockID
+			v.Type = keyValues.Key.Type
+			if av.KeyTypeBlock == v.Type {
+				v.Block.ID = blockID
+				v.Block.Created = now
+				v.Block.Updated = now
+			}
+			v.IsDetached = true
+			v.CreatedAt = now
+			v.UpdatedAt = now
+
+			keyValues.Values = append(keyValues.Values, v)
+		}
+	}
+
+	for _, v := range attrView.Views {
+		switch v.LayoutType {
+		case av.LayoutTypeTable:
+			for _, addingBlockID := range blockIDs {
+				v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
+			}
+		}
+	}
+
+	if err = av.SaveAttributeView(attrView); nil != err {
+		logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
+		return
+	}
+
+	util.PushReloadAttrView(avID)
+	return
+}
+
 func DuplicateDatabaseBlock(avID string) (newAvID, newBlockID string, err error) {
 	storageAvDir := filepath.Join(util.DataDir, "storage", "av")
 	oldAvPath := filepath.Join(storageAvDir, avID+".json")
@@ -574,7 +627,7 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) {
 			case av.KeyTypeTemplate:
 				if 0 < len(kv.Values) {
 					ial := map[string]string{}
-					block := getRowBlockValue(keyValues)
+					block := av.GetKeyBlockValue(keyValues)
 					if nil != block && !block.IsDetached {
 						ial = GetBlockAttrsWithoutWaitWriting(block.BlockID)
 					}
@@ -915,16 +968,6 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page,
 	return
 }
 
-func getRowBlockValue(keyValues []*av.KeyValues) (ret *av.Value) {
-	for _, kv := range keyValues {
-		if av.KeyTypeBlock == kv.Key.Type && 0 < len(kv.Values) {
-			ret = kv.Values[0]
-			break
-		}
-	}
-	return
-}
-
 func (tx *Transaction) doUnbindAttrViewBlock(operation *Operation) (ret *TxErr) {
 	err := unbindAttributeViewBlock(operation, tx)
 	if nil != err {