Browse Source

:art: 编辑器支持属性视图 - 表格 https://github.com/siyuan-note/siyuan/issues/7536

Liang Ding 2 years ago
parent
commit
832f31cbb3
6 changed files with 110 additions and 55 deletions
  1. 39 0
      kernel/api/av.go
  2. 2 0
      kernel/api/router.go
  3. 1 8
      kernel/av/cell.go
  4. 18 7
      kernel/model/attribute_view.go
  5. 48 24
      kernel/model/blockial.go
  6. 2 16
      kernel/model/flashcard.go

+ 39 - 0
kernel/api/av.go

@@ -0,0 +1,39 @@
+// SiYuan - Build Your Eternal Digital Garden
+// Copyright (c) 2020-present, b3log.org
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+package api
+
+import (
+	"net/http"
+
+	"github.com/88250/gulu"
+	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/siyuan/kernel/model"
+	"github.com/siyuan-note/siyuan/kernel/util"
+)
+
+func renderAttributeView(c *gin.Context) {
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	arg, ok := util.JsonArg(c, ret)
+	if !ok {
+		return
+	}
+
+	id := arg["id"].(string)
+	ret.Data = model.RenderAttributeView(id)
+}

+ 2 - 0
kernel/api/router.go

@@ -325,4 +325,6 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/snippet/setSnippet", model.CheckAuth, setSnippet)
 	ginServer.Handle("POST", "/api/snippet/removeSnippet", model.CheckAuth, removeSnippet)
 	ginServer.Handle("GET", "/snippets/*filepath", serveSnippets)
+
+	ginServer.Handle("POST", "/api/av/renderAttributeView", model.CheckAuth, renderAttributeView)
 }

+ 1 - 8
kernel/av/cell.go

@@ -17,13 +17,6 @@
 package av
 
 type Cell struct {
+	ID    string `json:"id"`
 	Value string `json:"value"`
 }
-
-type CellBlock struct {
-	*Cell
-}
-
-func NewCellBlock(blockID string) *CellBlock {
-	return &CellBlock{&Cell{Value: blockID}}
-}

+ 18 - 7
kernel/model/attribute_view.go

@@ -28,6 +28,17 @@ import (
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 )
 
+func RenderAttributeView(avID string) (dom string) {
+	attrView, err := av.ParseAttributeView(avID)
+	if nil != err {
+		logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
+		return
+	}
+
+	_ = attrView
+	return
+}
+
 func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) {
 	firstSrcID := operation.SrcIDs[0]
 	tree, err := tx.loadTree(firstSrcID)
@@ -38,7 +49,7 @@ func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr)
 
 	avID := operation.ParentID
 	for _, id := range operation.SrcIDs {
-		if err = addAttributeViewBlock(id, avID, tree); nil != err {
+		if err = addAttributeViewBlock(id, avID, tree, tx); nil != err {
 			return &TxErr{code: TxErrWriteAttributeView, id: avID, msg: err.Error()}
 		}
 	}
@@ -55,7 +66,7 @@ func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr)
 
 	avID := operation.ParentID
 	for _, id := range operation.SrcIDs {
-		if err = removeAttributeViewBlock(id, avID, tree); nil != err {
+		if err = removeAttributeViewBlock(id, avID, tree, tx); nil != err {
 			return &TxErr{code: TxErrWriteAttributeView, id: avID}
 		}
 	}
@@ -82,7 +93,7 @@ func AddAttributeViewColumn(name string, typ string, columnIndex int, avID strin
 	return
 }
 
-func removeAttributeViewBlock(blockID, avID string, tree *parse.Tree) (err error) {
+func removeAttributeViewBlock(blockID, avID string, tree *parse.Tree, tx *Transaction) (err error) {
 	node := treenode.GetNodeInTree(tree, blockID)
 	if nil == node {
 		err = ErrBlockNotFound
@@ -105,7 +116,7 @@ func removeAttributeViewBlock(blockID, avID string, tree *parse.Tree) (err error
 	return
 }
 
-func addAttributeViewBlock(blockID, avID string, tree *parse.Tree) (err error) {
+func addAttributeViewBlock(blockID, avID string, tree *parse.Tree, tx *Transaction) (err error) {
 	node := treenode.GetNodeInTree(tree, blockID)
 	if nil == node {
 		err = ErrBlockNotFound
@@ -138,20 +149,20 @@ func addAttributeViewBlock(blockID, avID string, tree *parse.Tree) (err error) {
 	row := av.NewRow()
 	row.Cells = append(row.Cells, &av.Cell{Value: blockID})
 	if 1 < len(attrView.Columns) {
-		attrs := parse.IAL2Map(node.KramdownIAL)
+		// 将列作为属性添加到块中
 
+		attrs := parse.IAL2Map(node.KramdownIAL)
 		for _, col := range attrView.Columns[1:] {
 			colName := col.Name
 			attrs[colName] = ""
 		}
 
-		if err = setNodeAttrs(node, tree, attrs); nil != err {
+		if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
 			return
 		}
 	}
 
 	attrView.Rows = append(attrView.Rows, row)
-
 	err = av.SaveAttributeView(attrView)
 	return
 }

+ 48 - 24
kernel/model/blockial.go

@@ -110,22 +110,9 @@ func SetBlockAttrs(id string, nameValues map[string]string) (err error) {
 }
 
 func setNodeAttrs(node *ast.Node, tree *parse.Tree, nameValues map[string]string) (err error) {
-	oldAttrs := parse.IAL2Map(node.KramdownIAL)
-
-	for name := range nameValues {
-		for i := 0; i < len(name); i++ {
-			if !lex.IsASCIILetterNumHyphen(name[i]) {
-				return errors.New(fmt.Sprintf(Conf.Language(25), node.ID))
-			}
-		}
-	}
-
-	for name, value := range nameValues {
-		if "" == value {
-			node.RemoveIALAttr(name)
-		} else {
-			node.SetIALAttr(name, value)
-		}
+	oldAttrs, err := setNodeAttrs0(node, nameValues)
+	if nil != err {
+		return
 	}
 
 	if 1 == len(nameValues) && "" != nameValues["scroll"] {
@@ -142,19 +129,56 @@ func setNodeAttrs(node *ast.Node, tree *parse.Tree, nameValues map[string]string
 	IncSync()
 	cache.PutBlockIAL(node.ID, parse.IAL2Map(node.KramdownIAL))
 
+	pushBroadcastAttrTransactions(oldAttrs, node)
+	return
+}
+
+func setNodeAttrsWithTx(tx *Transaction, node *ast.Node, tree *parse.Tree, nameValues map[string]string) (err error) {
+	oldAttrs, err := setNodeAttrs0(node, nameValues)
+	if nil != err {
+		return
+	}
+
+	if err = tx.writeTree(tree); nil != err {
+		return
+	}
+
+	IncSync()
+	cache.PutBlockIAL(node.ID, parse.IAL2Map(node.KramdownIAL))
+	pushBroadcastAttrTransactions(oldAttrs, node)
+	return
+}
+
+func setNodeAttrs0(node *ast.Node, nameValues map[string]string) (oldAttrs map[string]string, err error) {
+	oldAttrs = parse.IAL2Map(node.KramdownIAL)
+
+	for name := range nameValues {
+		for i := 0; i < len(name); i++ {
+			if !lex.IsASCIILetterNumHyphen(name[i]) {
+				err = errors.New(fmt.Sprintf(Conf.Language(25), node.ID))
+				return
+			}
+		}
+	}
+
+	for name, value := range nameValues {
+		if "" == value {
+			node.RemoveIALAttr(name)
+		} else {
+			node.SetIALAttr(name, value)
+		}
+	}
+	return
+}
+
+func pushBroadcastAttrTransactions(oldAttrs map[string]string, node *ast.Node) {
 	newAttrs := parse.IAL2Map(node.KramdownIAL)
 	doOp := &Operation{Action: "updateAttrs", Data: map[string]interface{}{"old": oldAttrs, "new": newAttrs}, ID: node.ID}
-	trans := []*Transaction{{
+	evt := util.NewCmdResult("transactions", 0, util.PushModeBroadcast)
+	evt.Data = []*Transaction{{
 		DoOperations:   []*Operation{doOp},
 		UndoOperations: []*Operation{},
 	}}
-	pushBroadcastAttrTransactions(trans)
-	return
-}
-
-func pushBroadcastAttrTransactions(transactions []*Transaction) {
-	evt := util.NewCmdResult("transactions", 0, util.PushModeBroadcast)
-	evt.Data = transactions
 	util.PushEvent(evt)
 }
 

+ 2 - 16
kernel/model/flashcard.go

@@ -592,14 +592,7 @@ func removeBlocksDeckAttr(blockIDs []string, deckID string) (err error) {
 		}
 
 		cache.PutBlockIAL(blockID, parse.IAL2Map(node.KramdownIAL))
-
-		newAttrs := parse.IAL2Map(node.KramdownIAL)
-		doOp := &Operation{Action: "updateAttrs", Data: map[string]interface{}{"old": oldAttrs, "new": newAttrs}, ID: blockID}
-		trans := []*Transaction{{
-			DoOperations:   []*Operation{doOp},
-			UndoOperations: []*Operation{},
-		}}
-		pushBroadcastAttrTransactions(trans)
+		pushBroadcastAttrTransactions(oldAttrs, node)
 	}
 
 	return
@@ -674,14 +667,7 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
 		}
 
 		cache.PutBlockIAL(blockID, parse.IAL2Map(node.KramdownIAL))
-
-		newAttrs := parse.IAL2Map(node.KramdownIAL)
-		doOp := &Operation{Action: "updateAttrs", Data: map[string]interface{}{"old": oldAttrs, "new": newAttrs}, ID: blockID}
-		trans := []*Transaction{{
-			DoOperations:   []*Operation{doOp},
-			UndoOperations: []*Operation{},
-		}}
-		pushBroadcastAttrTransactions(trans)
+		pushBroadcastAttrTransactions(oldAttrs, node)
 	}
 
 	deck := Decks[deckID]