mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-22 09:30:14 +01:00
🎨 Add some database related internal kernel APIs https://github.com/siyuan-note/siyuan/issues/10201
This commit is contained in:
parent
e51fb3cde7
commit
43042e8dc2
3 changed files with 131 additions and 31 deletions
|
|
@ -26,6 +26,61 @@ import (
|
||||||
"github.com/siyuan-note/siyuan/kernel/util"
|
"github.com/siyuan-note/siyuan/kernel/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func addAttributeViewValues(c *gin.Context) {
|
||||||
|
ret := gulu.Ret.NewResult()
|
||||||
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
||||||
|
arg, _ := util.JsonArg(c, ret)
|
||||||
|
if nil == arg {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
avID := arg["avID"].(string)
|
||||||
|
var srcIDs []string
|
||||||
|
for _, v := range arg["srcIDs"].([]interface{}) {
|
||||||
|
srcIDs = append(srcIDs, v.(string))
|
||||||
|
}
|
||||||
|
var previousID string
|
||||||
|
if nil != arg["previousID"] {
|
||||||
|
previousID = arg["previousID"].(string)
|
||||||
|
}
|
||||||
|
isDetached := arg["isDetached"].(bool)
|
||||||
|
|
||||||
|
err := model.AddAttributeViewBlock(nil, srcIDs, avID, previousID, isDetached)
|
||||||
|
if nil != err {
|
||||||
|
ret.Code = -1
|
||||||
|
ret.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pushRefreshAttrView(avID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAttributeViewValues(c *gin.Context) {
|
||||||
|
ret := gulu.Ret.NewResult()
|
||||||
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
||||||
|
arg, _ := util.JsonArg(c, ret)
|
||||||
|
if nil == arg {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
avID := arg["avID"].(string)
|
||||||
|
var srcIDs []string
|
||||||
|
for _, v := range arg["srcIDs"].([]interface{}) {
|
||||||
|
srcIDs = append(srcIDs, v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
err := model.RemoveAttributeViewBlock(srcIDs, avID)
|
||||||
|
if nil != err {
|
||||||
|
ret.Code = -1
|
||||||
|
ret.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pushRefreshAttrView(avID)
|
||||||
|
}
|
||||||
|
|
||||||
func addAttributeViewCol(c *gin.Context) {
|
func addAttributeViewCol(c *gin.Context) {
|
||||||
ret := gulu.Ret.NewResult()
|
ret := gulu.Ret.NewResult()
|
||||||
defer c.JSON(http.StatusOK, ret)
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
@ -48,6 +103,8 @@ func addAttributeViewCol(c *gin.Context) {
|
||||||
ret.Msg = err.Error()
|
ret.Msg = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushRefreshAttrView(avID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeAttributeViewCol(c *gin.Context) {
|
func removeAttributeViewCol(c *gin.Context) {
|
||||||
|
|
@ -68,6 +125,8 @@ func removeAttributeViewCol(c *gin.Context) {
|
||||||
ret.Msg = err.Error()
|
ret.Msg = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushRefreshAttrView(avID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortAttributeViewCol(c *gin.Context) {
|
func sortAttributeViewCol(c *gin.Context) {
|
||||||
|
|
@ -89,6 +148,8 @@ func sortAttributeViewCol(c *gin.Context) {
|
||||||
ret.Msg = err.Error()
|
ret.Msg = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushRefreshAttrView(avID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAttributeViewFilterSort(c *gin.Context) {
|
func getAttributeViewFilterSort(c *gin.Context) {
|
||||||
|
|
@ -357,6 +418,11 @@ func setAttributeViewBlockAttr(c *gin.Context) {
|
||||||
cellID := arg["cellID"].(string)
|
cellID := arg["cellID"].(string)
|
||||||
value := arg["value"].(interface{})
|
value := arg["value"].(interface{})
|
||||||
blockAttributeViewKeys := model.UpdateAttributeViewCell(nil, avID, keyID, rowID, cellID, value)
|
blockAttributeViewKeys := model.UpdateAttributeViewCell(nil, avID, keyID, rowID, cellID, value)
|
||||||
util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": avID})
|
|
||||||
ret.Data = blockAttributeViewKeys
|
ret.Data = blockAttributeViewKeys
|
||||||
|
|
||||||
|
pushRefreshAttrView(avID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushRefreshAttrView(avID string) {
|
||||||
|
util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": avID})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,8 @@ func ServeAPI(ginServer *gin.Engine) {
|
||||||
ginServer.Handle("POST", "/api/av/addAttributeViewKey", model.CheckAuth, model.CheckReadonly, addAttributeViewCol)
|
ginServer.Handle("POST", "/api/av/addAttributeViewKey", model.CheckAuth, model.CheckReadonly, addAttributeViewCol)
|
||||||
ginServer.Handle("POST", "/api/av/removeAttributeViewKey", model.CheckAuth, model.CheckReadonly, removeAttributeViewCol)
|
ginServer.Handle("POST", "/api/av/removeAttributeViewKey", model.CheckAuth, model.CheckReadonly, removeAttributeViewCol)
|
||||||
ginServer.Handle("POST", "/api/av/sortAttributeViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewCol)
|
ginServer.Handle("POST", "/api/av/sortAttributeViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewCol)
|
||||||
|
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/ai/chatGPT", model.CheckAuth, chatGPT)
|
ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
|
||||||
ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, chatGPTWithAction)
|
ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, chatGPTWithAction)
|
||||||
|
|
|
||||||
|
|
@ -1518,24 +1518,39 @@ func setAttributeViewColumnCalc(operation *Operation) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) {
|
func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) {
|
||||||
for _, id := range operation.SrcIDs {
|
err := AddAttributeViewBlock(tx, operation.SrcIDs, operation.AvID, operation.PreviousID, operation.IsDetached)
|
||||||
tree, err := tx.loadTree(id)
|
if nil != err {
|
||||||
if nil != err && !operation.IsDetached {
|
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
|
||||||
logging.LogErrorf("load tree [%s] failed: %s", id, err)
|
}
|
||||||
return &TxErr{code: TxErrCodeBlockNotFound, id: id, msg: err.Error()}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddAttributeViewBlock(tx *Transaction, srcIDs []string, avID, previousBlockID string, isDetached bool) (err error) {
|
||||||
|
for _, id := range srcIDs {
|
||||||
|
var tree *parse.Tree
|
||||||
|
if !isDetached {
|
||||||
|
var loadErr error
|
||||||
|
if nil != tx {
|
||||||
|
tree, loadErr = tx.loadTree(id)
|
||||||
|
} else {
|
||||||
|
tree, loadErr = loadTreeByBlockID(id)
|
||||||
|
}
|
||||||
|
if nil != loadErr {
|
||||||
|
logging.LogErrorf("load tree [%s] failed: %s", id, err)
|
||||||
|
return loadErr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var avErr error
|
if avErr := addAttributeViewBlock(avID, previousBlockID, id, isDetached, tree, tx); nil != avErr {
|
||||||
if avErr = addAttributeViewBlock(id, operation, tree, tx); nil != avErr {
|
return avErr
|
||||||
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: avErr.Error()}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tree, tx *Transaction) (err error) {
|
func addAttributeViewBlock(avID, previousBlockID, blockID string, isDetached bool, tree *parse.Tree, tx *Transaction) (err error) {
|
||||||
var node *ast.Node
|
var node *ast.Node
|
||||||
if !operation.IsDetached {
|
if !isDetached {
|
||||||
node = treenode.GetNodeInTree(tree, blockID)
|
node = treenode.GetNodeInTree(tree, blockID)
|
||||||
if nil == node {
|
if nil == node {
|
||||||
err = ErrBlockNotFound
|
err = ErrBlockNotFound
|
||||||
|
|
@ -1553,7 +1568,7 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrView, err := av.ParseAttributeView(operation.AvID)
|
attrView, err := av.ParseAttributeView(avID)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1567,11 +1582,11 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre
|
||||||
}
|
}
|
||||||
|
|
||||||
var content string
|
var content string
|
||||||
if !operation.IsDetached {
|
if !isDetached {
|
||||||
content = getNodeRefText(node)
|
content = getNodeRefText(node)
|
||||||
}
|
}
|
||||||
now := time.Now().UnixMilli()
|
now := time.Now().UnixMilli()
|
||||||
blockValue := &av.Value{ID: ast.NewNodeID(), KeyID: blockValues.Key.ID, BlockID: blockID, Type: av.KeyTypeBlock, IsDetached: operation.IsDetached, Block: &av.ValueBlock{ID: blockID, Content: content, Created: now, Updated: now}}
|
blockValue := &av.Value{ID: ast.NewNodeID(), KeyID: blockValues.Key.ID, BlockID: blockID, Type: av.KeyTypeBlock, IsDetached: isDetached, Block: &av.ValueBlock{ID: blockID, Content: content, Created: now, Updated: now}}
|
||||||
blockValues.Values = append(blockValues.Values, blockValue)
|
blockValues.Values = append(blockValues.Values, blockValue)
|
||||||
|
|
||||||
// 如果存在排序和过滤条件,则将排序和过滤条件应用到新添加的块上
|
// 如果存在排序和过滤条件,则将排序和过滤条件应用到新添加的块上
|
||||||
|
|
@ -1604,7 +1619,7 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre
|
||||||
newValue := cell.Value.Clone()
|
newValue := cell.Value.Clone()
|
||||||
newValue.ID = ast.NewNodeID()
|
newValue.ID = ast.NewNodeID()
|
||||||
newValue.BlockID = blockID
|
newValue.BlockID = blockID
|
||||||
newValue.IsDetached = operation.IsDetached
|
newValue.IsDetached = isDetached
|
||||||
values, _ := attrView.GetKeyValues(affectKeyID)
|
values, _ := attrView.GetKeyValues(affectKeyID)
|
||||||
values.Values = append(values.Values, newValue)
|
values.Values = append(values.Values, newValue)
|
||||||
addedValues[affectKeyID] = true
|
addedValues[affectKeyID] = true
|
||||||
|
|
@ -1635,7 +1650,7 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre
|
||||||
newValue.ID = ast.NewNodeID()
|
newValue.ID = ast.NewNodeID()
|
||||||
newValue.KeyID = keyValues.Key.ID
|
newValue.KeyID = keyValues.Key.ID
|
||||||
newValue.BlockID = blockID
|
newValue.BlockID = blockID
|
||||||
newValue.IsDetached = operation.IsDetached
|
newValue.IsDetached = isDetached
|
||||||
keyValues.Values = append(keyValues.Values, newValue)
|
keyValues.Values = append(keyValues.Values, newValue)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -1646,30 +1661,36 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !operation.IsDetached {
|
if !isDetached {
|
||||||
attrs := parse.IAL2Map(node.KramdownIAL)
|
attrs := parse.IAL2Map(node.KramdownIAL)
|
||||||
|
|
||||||
if "" == attrs[av.NodeAttrNameAvs] {
|
if "" == attrs[av.NodeAttrNameAvs] {
|
||||||
attrs[av.NodeAttrNameAvs] = operation.AvID
|
attrs[av.NodeAttrNameAvs] = avID
|
||||||
} else {
|
} else {
|
||||||
avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
|
avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
|
||||||
avIDs = append(avIDs, operation.AvID)
|
avIDs = append(avIDs, avID)
|
||||||
avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
|
avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
|
||||||
attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
|
attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
|
if nil != tx {
|
||||||
return
|
if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = setNodeAttrs(node, tree, attrs); nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, view := range attrView.Views {
|
for _, view := range attrView.Views {
|
||||||
switch view.LayoutType {
|
switch view.LayoutType {
|
||||||
case av.LayoutTypeTable:
|
case av.LayoutTypeTable:
|
||||||
if "" != operation.PreviousID {
|
if "" != previousBlockID {
|
||||||
changed := false
|
changed := false
|
||||||
for i, id := range view.Table.RowIDs {
|
for i, id := range view.Table.RowIDs {
|
||||||
if id == operation.PreviousID {
|
if id == previousBlockID {
|
||||||
view.Table.RowIDs = append(view.Table.RowIDs[:i+1], append([]string{blockID}, view.Table.RowIDs[i+1:]...)...)
|
view.Table.RowIDs = append(view.Table.RowIDs[:i+1], append([]string{blockID}, view.Table.RowIDs[i+1:]...)...)
|
||||||
changed = true
|
changed = true
|
||||||
break
|
break
|
||||||
|
|
@ -1704,15 +1725,20 @@ func GetLastSortRow(rows []*av.TableRow) *av.TableRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) {
|
func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) {
|
||||||
err := tx.removeAttributeViewBlock(operation)
|
err := removeAttributeViewBlock(operation.SrcIDs, operation.AvID, tx)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
|
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) removeAttributeViewBlock(operation *Operation) (err error) {
|
func RemoveAttributeViewBlock(srcIDs []string, avID string) (err error) {
|
||||||
attrView, err := av.ParseAttributeView(operation.AvID)
|
err = removeAttributeViewBlock(srcIDs, avID, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAttributeViewBlock(srcIDs []string, avID string, tx *Transaction) (err error) {
|
||||||
|
attrView, err := av.ParseAttributeView(avID)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1721,7 +1747,7 @@ func (tx *Transaction) removeAttributeViewBlock(operation *Operation) (err error
|
||||||
for _, keyValues := range attrView.KeyValues {
|
for _, keyValues := range attrView.KeyValues {
|
||||||
tmp := keyValues.Values[:0]
|
tmp := keyValues.Values[:0]
|
||||||
for i, values := range keyValues.Values {
|
for i, values := range keyValues.Values {
|
||||||
if !gulu.Str.Contains(values.BlockID, operation.SrcIDs) {
|
if !gulu.Str.Contains(values.BlockID, srcIDs) {
|
||||||
tmp = append(tmp, keyValues.Values[i])
|
tmp = append(tmp, keyValues.Values[i])
|
||||||
} else {
|
} else {
|
||||||
// Remove av block also remove node attr https://github.com/siyuan-note/siyuan/issues/9091#issuecomment-1709824006
|
// Remove av block also remove node attr https://github.com/siyuan-note/siyuan/issues/9091#issuecomment-1709824006
|
||||||
|
|
@ -1742,7 +1768,7 @@ func (tx *Transaction) removeAttributeViewBlock(operation *Operation) (err error
|
||||||
|
|
||||||
if avs := attrs[av.NodeAttrNameAvs]; "" != avs {
|
if avs := attrs[av.NodeAttrNameAvs]; "" != avs {
|
||||||
avIDs := strings.Split(avs, ",")
|
avIDs := strings.Split(avs, ",")
|
||||||
avIDs = gulu.Str.RemoveElem(avIDs, operation.AvID)
|
avIDs = gulu.Str.RemoveElem(avIDs, avID)
|
||||||
if 0 == len(avIDs) {
|
if 0 == len(avIDs) {
|
||||||
delete(attrs, av.NodeAttrNameAvs)
|
delete(attrs, av.NodeAttrNameAvs)
|
||||||
node.RemoveIALAttr(av.NodeAttrNameAvs)
|
node.RemoveIALAttr(av.NodeAttrNameAvs)
|
||||||
|
|
@ -1752,8 +1778,14 @@ func (tx *Transaction) removeAttributeViewBlock(operation *Operation) (err error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
|
if nil != tx {
|
||||||
return
|
if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = setNodeAttrs(node, tree, attrs); nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1764,7 +1796,7 @@ func (tx *Transaction) removeAttributeViewBlock(operation *Operation) (err error
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, view := range attrView.Views {
|
for _, view := range attrView.Views {
|
||||||
for _, blockID := range operation.SrcIDs {
|
for _, blockID := range srcIDs {
|
||||||
view.Table.RowIDs = gulu.Str.RemoveElem(view.Table.RowIDs, blockID)
|
view.Table.RowIDs = gulu.Str.RemoveElem(view.Table.RowIDs, blockID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue