diff --git a/kernel/api/av.go b/kernel/api/av.go new file mode 100644 index 000000000..59f51c965 --- /dev/null +++ b/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 . + +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) +} diff --git a/kernel/api/router.go b/kernel/api/router.go index 056daf79e..32a28127f 100644 --- a/kernel/api/router.go +++ b/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) } diff --git a/kernel/av/cell.go b/kernel/av/cell.go index ad1a6bea1..511978f35 100644 --- a/kernel/av/cell.go +++ b/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}} -} diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index e5eb439b6..10ddbcbbd 100644 --- a/kernel/model/attribute_view.go +++ b/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 } diff --git a/kernel/model/blockial.go b/kernel/model/blockial.go index 6a0599843..a5e322c3e 100644 --- a/kernel/model/blockial.go +++ b/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)) - newAttrs := parse.IAL2Map(node.KramdownIAL) - doOp := &Operation{Action: "updateAttrs", Data: map[string]interface{}{"old": oldAttrs, "new": newAttrs}, ID: node.ID} - trans := []*Transaction{{ - DoOperations: []*Operation{doOp}, - UndoOperations: []*Operation{}, - }} - pushBroadcastAttrTransactions(trans) + pushBroadcastAttrTransactions(oldAttrs, node) return } -func pushBroadcastAttrTransactions(transactions []*Transaction) { +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} evt := util.NewCmdResult("transactions", 0, util.PushModeBroadcast) - evt.Data = transactions + evt.Data = []*Transaction{{ + DoOperations: []*Operation{doOp}, + UndoOperations: []*Operation{}, + }} util.PushEvent(evt) } diff --git a/kernel/model/flashcard.go b/kernel/model/flashcard.go index 299ea654e..7ee0d8dd7 100644 --- a/kernel/model/flashcard.go +++ b/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]