From 39b28cbc986089d37f9e561f2a05adb3e5756112 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 11 Jul 2023 22:11:15 +0800 Subject: [PATCH 1/5] :recycle: Refactor av data structure --- kernel/av/attribute_view.go | 58 ++++------------- kernel/model/attribute_view.go | 113 ++++++++++++++++++++++++++++++--- kernel/model/transaction.go | 11 +++- kernel/sql/queue.go | 38 +++-------- 4 files changed, 137 insertions(+), 83 deletions(-) diff --git a/kernel/av/attribute_view.go b/kernel/av/attribute_view.go index 6b84cc609..0438b73ea 100644 --- a/kernel/av/attribute_view.go +++ b/kernel/av/attribute_view.go @@ -18,11 +18,9 @@ package av import ( - "bytes" - "database/sql" + "errors" "os" "path/filepath" - "strings" "github.com/88250/gulu" "github.com/88250/lute/ast" @@ -167,6 +165,16 @@ func SaveAttributeView(av *AttributeView) (err error) { return } +func (av *AttributeView) GetView(viewID string) (ret *View) { + for _, v := range av.Views { + if v.ID == viewID { + ret = v + return + } + } + return +} + func getAttributeViewDataPath(avID string) (ret string) { av := filepath.Join(util.DataDir, "storage", "av") ret = filepath.Join(av, avID+".json") @@ -179,44 +187,6 @@ func getAttributeViewDataPath(avID string) (ret string) { return } -func RebuildAttributeViewTable(tx *sql.Tx, av *AttributeView) (err error) { - avID := av.ID - var columns []string - for _, c := range av.Columns { - columns = append(columns, "`"+c.ID+"`") - } - - _, err = tx.Exec("DROP TABLE IF EXISTS `av_" + avID + "`") - if nil != err { - logging.LogErrorf("drop table [%s] failed: %s", avID, err) - return - } - - _, err = tx.Exec("CREATE TABLE IF NOT EXISTS `av_" + avID + "` (" + strings.Join(columns, ", ") + ")") - if nil != err { - logging.LogErrorf("create table [%s] failed: %s", avID, err) - return - } - - for _, r := range av.Rows { - buf := bytes.Buffer{} - for i, _ := range r.Cells { - buf.WriteString("?") - if i < len(r.Cells)-1 { - buf.WriteString(", ") - } - } - - var values []interface{} - for _, c := range r.Cells { - values = append(values, c.Value) - } - - _, err = tx.Exec("INSERT INTO `av_"+avID+"` VALUES ("+buf.String()+")", values...) - if nil != err { - logging.LogErrorf("insert row [%s] failed: %s", r.ID, err) - return - } - } - return -} +var ( + ErrViewNotFound = errors.New("view not found") +) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 2d9e6ec36..3ccf1d8f8 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -42,7 +42,7 @@ func RenderAttributeView(avID string) (viewable av.Viewable, attrView *av.Attrib } if 1 > len(attrView.Views) { - err = errors.New("no view") + err = av.ErrViewNotFound return } @@ -69,6 +69,108 @@ func RenderAttributeView(avID string) (viewable av.Viewable, attrView *av.Attrib return } +func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) { + err := setAttributeViewName(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + +func (tx *Transaction) doSetAttrViewFilters(operation *Operation) (ret *TxErr) { + err := setAttributeViewFilters(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + +func (tx *Transaction) doSetAttrViewSorts(operation *Operation) (ret *TxErr) { + err := setAttributeViewSorts(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + +func setAttributeViewName(operation *Operation) (err error) { + avID := operation.ID + attrView, err := av.ParseAttributeView(avID) + if nil != err { + return + } + + attrView.Name = operation.Data.(string) + + data, err := gulu.JSON.MarshalJSON(attrView) + if nil != err { + return + } + + if err = gulu.JSON.UnmarshalJSON(data, attrView); nil != err { + return + } + + err = av.SaveAttributeView(attrView) + return +} + +func setAttributeViewFilters(operation *Operation) (err error) { + avID := operation.ID + attrView, err := av.ParseAttributeView(avID) + if nil != err { + return + } + + view := attrView.GetView(operation.ViewID) + if nil == view { + err = av.ErrViewNotFound + return + } + + operationData := operation.Data.([]interface{}) + data, err := gulu.JSON.MarshalJSON(operationData) + if nil != err { + return + } + + if err = gulu.JSON.UnmarshalJSON(data, &view.Filters); nil != err { + return + } + + err = av.SaveAttributeView(attrView) + return +} + +func setAttributeViewSorts(operation *Operation) (err error) { + avID := operation.ID + attrView, err := av.ParseAttributeView(avID) + if nil != err { + return + } + + view := attrView.GetView(operation.ViewID) + if nil == view { + err = av.ErrViewNotFound + return + } + + operationData := operation.Data.([]interface{}) + data, err := gulu.JSON.MarshalJSON(operationData) + if nil != err { + return + } + + if err = gulu.JSON.UnmarshalJSON(data, &view.Sorts); nil != err { + return + } + + err = av.SaveAttributeView(attrView) + return +} + +// TODO 下面的方法要重写 + func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) { ret = &av.Table{ Spec: attrView.Spec, @@ -144,7 +246,6 @@ func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { return } - sql.RebuildAttributeViewQueue(view) return } @@ -172,10 +273,6 @@ func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) avs = append(avs, av) } - - for _, av := range avs { - sql.RebuildAttributeViewQueue(av) - } return } @@ -195,10 +292,6 @@ func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) avs = append(avs, av) } - - for _, av := range avs { - sql.RebuildAttributeViewQueue(av) - } return } diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 7247cf88b..8bae615bd 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -19,7 +19,6 @@ package model import ( "bytes" "fmt" - "github.com/siyuan-note/siyuan/kernel/av" "path/filepath" "strings" "sync" @@ -34,6 +33,7 @@ import ( "github.com/emirpasic/gods/sets/hashset" "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/av" "github.com/siyuan-note/siyuan/kernel/cache" "github.com/siyuan-note/siyuan/kernel/filesys" "github.com/siyuan-note/siyuan/kernel/sql" @@ -217,6 +217,13 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doAddFlashcards(op) case "removeFlashcards": ret = tx.doRemoveFlashcards(op) + case "setAttrViewName": + ret = tx.doSetAttrViewName(op) + case "setAttrViewFilters": + ret = tx.doSetAttrViewFilters(op) + case "setAttrViewSorts": + ret = tx.doSetAttrViewSorts(op) + // TODO 下面的方法要重写 case "insertAttrViewBlock": ret = tx.doInsertAttrViewBlock(op) case "removeAttrViewBlock": @@ -1046,6 +1053,8 @@ type Operation struct { DeckID string `json:"deckID"` // 用于添加/删除闪卡 + AvID string `json:"avID"` // 属性视图 ID + ViewID string `json:"viewID"` // 属性视图的视图 ID SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中 Name string `json:"name"` // 用于属性视图列名 Typ string `json:"type"` // 用于属性视图列类型 diff --git a/kernel/sql/queue.go b/kernel/sql/queue.go index f3abc4602..e17fe596a 100644 --- a/kernel/sql/queue.go +++ b/kernel/sql/queue.go @@ -28,7 +28,6 @@ import ( "github.com/88250/lute/parse" "github.com/siyuan-note/eventbus" "github.com/siyuan-note/logging" - "github.com/siyuan-note/siyuan/kernel/av" "github.com/siyuan-note/siyuan/kernel/task" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -42,17 +41,16 @@ var ( type dbQueueOperation struct { inQueueTime time.Time - action string // upsert/delete/delete_id/rename/rename_sub_tree/delete_box/delete_box_refs/insert_refs/index/delete_ids/update_block_content/delete_assets/av_rebuild - indexPath string // index - upsertTree *parse.Tree // upsert/insert_refs/update_refs/delete_refs - removeTreeBox, removeTreePath string // delete - removeTreeIDBox, removeTreeID string // delete_id - removeTreeIDs []string // delete_ids - box string // delete_box/delete_box_refs/index - renameTree *parse.Tree // rename/rename_sub_tree - block *Block // update_block_content - removeAssetHashes []string // delete_assets - av *av.AttributeView // av_rebuild + action string // upsert/delete/delete_id/rename/rename_sub_tree/delete_box/delete_box_refs/insert_refs/index/delete_ids/update_block_content/delete_assets + indexPath string // index + upsertTree *parse.Tree // upsert/insert_refs/update_refs/delete_refs + removeTreeBox, removeTreePath string // delete + removeTreeIDBox, removeTreeID string // delete_id + removeTreeIDs []string // delete_ids + box string // delete_box/delete_box_refs/index + renameTree *parse.Tree // rename/rename_sub_tree + block *Block // update_block_content + removeAssetHashes []string // delete_assets } func FlushTxJob() { @@ -189,8 +187,6 @@ func execOp(op *dbQueueOperation, tx *sql.Tx, context map[string]interface{}) (e err = updateBlockContent(tx, op.block) case "delete_assets": err = deleteAssetsByHashes(tx, op.removeAssetHashes) - case "av_rebuild": - err = av.RebuildAttributeViewTable(tx, op.av) default: msg := fmt.Sprintf("unknown operation [%s]", op.action) logging.LogErrorf(msg) @@ -199,20 +195,6 @@ func execOp(op *dbQueueOperation, tx *sql.Tx, context map[string]interface{}) (e return } -func RebuildAttributeViewQueue(av *av.AttributeView) { - //dbQueueLock.Lock() - //defer dbQueueLock.Unlock() - // - //newOp := &dbQueueOperation{av: av, inQueueTime: time.Now(), action: "av_rebuild"} - //for i, op := range operationQueue { - // if "av_rebuild" == op.action && op.av.ID == av.ID { - // operationQueue[i] = newOp - // return - // } - //} - //operationQueue = append(operationQueue, newOp) -} - func BatchRemoveAssetsQueue(hashes []string) { if 1 > len(hashes) { return From 1ccdb4c57609e5e06bb8ae22d05930638dde2da8 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 11 Jul 2023 22:36:02 +0800 Subject: [PATCH 2/5] :recycle: Refactor av data structure --- kernel/model/attribute_view.go | 282 ++++++++++++++++----------------- kernel/model/transaction.go | 13 +- 2 files changed, 143 insertions(+), 152 deletions(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 3ccf1d8f8..a6f19a497 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -69,6 +69,19 @@ func RenderAttributeView(avID string) (viewable av.Viewable, attrView *av.Attrib return } +func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) { + ret = &av.Table{ + Spec: attrView.Spec, + ID: view.ID, + Name: view.Name, + Columns: attrView.Columns, + Rows: attrView.Rows, + Filters: view.Filters, + Sorts: view.Sorts, + } + return +} + func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) { err := setAttributeViewName(operation) if nil != err { @@ -77,22 +90,6 @@ func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) { return } -func (tx *Transaction) doSetAttrViewFilters(operation *Operation) (ret *TxErr) { - err := setAttributeViewFilters(operation) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} - } - return -} - -func (tx *Transaction) doSetAttrViewSorts(operation *Operation) (ret *TxErr) { - err := setAttributeViewSorts(operation) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} - } - return -} - func setAttributeViewName(operation *Operation) (err error) { avID := operation.ID attrView, err := av.ParseAttributeView(avID) @@ -115,6 +112,14 @@ func setAttributeViewName(operation *Operation) (err error) { return } +func (tx *Transaction) doSetAttrViewFilters(operation *Operation) (ret *TxErr) { + err := setAttributeViewFilters(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + func setAttributeViewFilters(operation *Operation) (err error) { avID := operation.ID attrView, err := av.ParseAttributeView(avID) @@ -142,6 +147,14 @@ func setAttributeViewFilters(operation *Operation) (err error) { return } +func (tx *Transaction) doSetAttrViewSorts(operation *Operation) (ret *TxErr) { + err := setAttributeViewSorts(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + func setAttributeViewSorts(operation *Operation) (err error) { avID := operation.ID attrView, err := av.ParseAttributeView(avID) @@ -169,21 +182,118 @@ func setAttributeViewSorts(operation *Operation) (err error) { return } -// TODO 下面的方法要重写 +func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) { + firstSrcID := operation.SrcIDs[0] + tree, err := tx.loadTree(firstSrcID) + if nil != err { + logging.LogErrorf("load tree [%s] failed: %s", firstSrcID, err) + return &TxErr{code: TxErrCodeBlockNotFound, id: firstSrcID, msg: err.Error()} + } -func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) { - ret = &av.Table{ - Spec: attrView.Spec, - ID: view.ID, - Name: view.Name, - Columns: attrView.Columns, - Rows: attrView.Rows, - Filters: view.Filters, - Sorts: view.Sorts, + for _, id := range operation.SrcIDs { + var avErr error + if avErr = addAttributeViewBlock(id, operation, tree, tx); nil != avErr { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: avErr.Error()} + } } return } +func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tree, tx *Transaction) (err error) { + node := treenode.GetNodeInTree(tree, blockID) + if nil == node { + err = ErrBlockNotFound + return + } + + if ast.NodeAttributeView == node.Type { + // 不能将一个属性视图拖拽到另一个属性视图中 + return + } + + block := sql.BuildBlockFromNode(node, tree) + if nil == block { + err = ErrBlockNotFound + return + } + + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + // 不允许重复添加相同的块到属性视图中 + for _, row := range attrView.Rows { + blockCell := row.GetBlockCell() + if nil == blockCell { + continue + } + + if blockCell.Value.Block.ID == blockID { + return + } + } + + row := av.NewRow() + attrs := parse.IAL2Map(node.KramdownIAL) + for _, col := range attrView.Columns { + if av.ColumnTypeBlock != col.Type { + attrs[NodeAttrNamePrefixAvCol+operation.AvID+"-"+col.ID] = "" // 将列作为属性添加到块中 + row.Cells = append(row.Cells, av.NewCell(col.Type)) + } else { + row.Cells = append(row.Cells, av.NewCellBlock(blockID, getNodeRefText(node))) + } + } + + if "" == attrs[NodeAttrNameAVs] { + attrs[NodeAttrNameAVs] = operation.AvID + } else { + avIDs := strings.Split(attrs[NodeAttrNameAVs], ",") + avIDs = append(avIDs, operation.AvID) + avIDs = gulu.Str.RemoveDuplicatedElem(avIDs) + attrs[NodeAttrNameAVs] = strings.Join(avIDs, ",") + } + + if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err { + return + } + + if "" == operation.PreviousRowID { + attrView.Rows = append([]*av.Row{row}, attrView.Rows...) + } else { + for i, r := range attrView.Rows { + if r.ID == operation.PreviousRowID { + attrView.Rows = append(attrView.Rows[:i+1], append([]*av.Row{row}, attrView.Rows[i+1:]...)...) + break + } + } + } + + err = av.SaveAttributeView(attrView) + return +} + +func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) { + var avs []*av.AttributeView + avID := operation.ParentID + for _, id := range operation.SrcIDs { + var av *av.AttributeView + var avErr error + if av, avErr = removeAttributeViewBlock(id, avID); nil != avErr { + return &TxErr{code: TxErrWriteAttributeView, id: avID} + } + + if nil == av { + continue + } + + avs = append(avs, av) + } + return +} + +// TODO 下面的方法要重写 + func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { avID := operation.ParentID view, err := av.ParseAttributeView(avID) @@ -249,52 +359,6 @@ func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { return } -func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) { - firstSrcID := operation.SrcIDs[0] - tree, err := tx.loadTree(firstSrcID) - if nil != err { - logging.LogErrorf("load tree [%s] failed: %s", firstSrcID, err) - return &TxErr{code: TxErrCodeBlockNotFound, id: firstSrcID, msg: err.Error()} - } - - avID := operation.ParentID - var avs []*av.AttributeView - previousID := operation.PreviousID - for _, id := range operation.SrcIDs { - var av *av.AttributeView - var avErr error - if av, avErr = addAttributeViewBlock(id, previousID, avID, tree, tx); nil != avErr { - return &TxErr{code: TxErrWriteAttributeView, id: avID, msg: avErr.Error()} - } - - if nil == av { - continue - } - - avs = append(avs, av) - } - return -} - -func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) { - var avs []*av.AttributeView - avID := operation.ParentID - for _, id := range operation.SrcIDs { - var av *av.AttributeView - var avErr error - if av, avErr = removeAttributeViewBlock(id, avID); nil != avErr { - return &TxErr{code: TxErrWriteAttributeView, id: avID} - } - - if nil == av { - continue - } - - avs = append(avs, av) - } - return -} - func (tx *Transaction) doUpdateAttrViewColOption(operation *Operation) (ret *TxErr) { err := updateAttributeViewColumnOption(operation) if nil != err { @@ -803,80 +867,6 @@ func removeAttributeViewBlock(blockID, avID string) (ret *av.AttributeView, err return } -func addAttributeViewBlock(blockID, previousRowID, avID string, tree *parse.Tree, tx *Transaction) (ret *av.AttributeView, err error) { - node := treenode.GetNodeInTree(tree, blockID) - if nil == node { - err = ErrBlockNotFound - return - } - - if ast.NodeAttributeView == node.Type { - // 不能将一个属性视图拖拽到另一个属性视图中 - return - } - - block := sql.BuildBlockFromNode(node, tree) - if nil == block { - err = ErrBlockNotFound - return - } - - ret, err = av.ParseAttributeView(avID) - if nil != err { - return - } - - // 不允许重复添加相同的块到属性视图中 - for _, row := range ret.Rows { - blockCell := row.GetBlockCell() - if nil == blockCell { - continue - } - - if blockCell.Value.Block.ID == blockID { - return - } - } - - row := av.NewRow() - attrs := parse.IAL2Map(node.KramdownIAL) - for _, col := range ret.Columns { - if av.ColumnTypeBlock != col.Type { - attrs[NodeAttrNamePrefixAvCol+avID+"-"+col.ID] = "" // 将列作为属性添加到块中 - row.Cells = append(row.Cells, av.NewCell(col.Type)) - } else { - row.Cells = append(row.Cells, av.NewCellBlock(blockID, getNodeRefText(node))) - } - } - - if "" == attrs[NodeAttrNameAVs] { - attrs[NodeAttrNameAVs] = avID - } else { - avIDs := strings.Split(attrs[NodeAttrNameAVs], ",") - avIDs = append(avIDs, avID) - avIDs = gulu.Str.RemoveDuplicatedElem(avIDs) - attrs[NodeAttrNameAVs] = strings.Join(avIDs, ",") - } - - if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err { - return - } - - if "" == previousRowID { - ret.Rows = append([]*av.Row{row}, ret.Rows...) - } else { - for i, r := range ret.Rows { - if r.ID == previousRowID { - ret.Rows = append(ret.Rows[:i+1], append([]*av.Row{row}, ret.Rows[i+1:]...)...) - break - } - } - } - - err = av.SaveAttributeView(ret) - return -} - const ( NodeAttrNameAVs = "custom-avs" NodeAttrNamePrefixAvCol = "custom-av-col-" diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 8bae615bd..26a41c366 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -1053,12 +1053,13 @@ type Operation struct { DeckID string `json:"deckID"` // 用于添加/删除闪卡 - AvID string `json:"avID"` // 属性视图 ID - ViewID string `json:"viewID"` // 属性视图的视图 ID - SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中 - Name string `json:"name"` // 用于属性视图列名 - Typ string `json:"type"` // 用于属性视图列类型 - RowID string `json:"rowID"` // 用于属性视图行 ID + AvID string `json:"avID"` // 属性视图 ID + ViewID string `json:"viewID"` // 属性视图的视图 ID + SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中 + Name string `json:"name"` // 属性视图列名 + Typ string `json:"type"` // 属性视图列类型 + PreviousRowID string `json:"previousRowID"` // 属性视图前一行 ID + RowID string `json:"rowID"` // 属性视图行 ID discard bool // 用于标识是否在事务合并中丢弃 } From 05e9133c7cbda93b5d8cde72e2f745bbc5989b78 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 11 Jul 2023 22:37:18 +0800 Subject: [PATCH 3/5] :recycle: Refactor av data structure --- kernel/model/attribute_view.go | 51 ++++++++++++++-------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index a6f19a497..18e5ba9dc 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -274,21 +274,35 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre } func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) { - var avs []*av.AttributeView - avID := operation.ParentID for _, id := range operation.SrcIDs { - var av *av.AttributeView var avErr error - if av, avErr = removeAttributeViewBlock(id, avID); nil != avErr { - return &TxErr{code: TxErrWriteAttributeView, id: avID} + if avErr = removeAttributeViewBlock(id, operation); nil != avErr { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID} } + } + return +} - if nil == av { +func removeAttributeViewBlock(blockID string, operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + for i, row := range attrView.Rows { + blockCell := row.GetBlockCell() + if nil == blockCell { continue } - avs = append(avs, av) + if blockCell.Value.Block.ID == blockID { + // 从行中移除,但是不移除属性 + attrView.Rows = append(attrView.Rows[:i], attrView.Rows[i+1:]...) + break + } } + + err = av.SaveAttributeView(attrView) return } @@ -844,29 +858,6 @@ func setAttributeView(operation *Operation) (err error) { return } -func removeAttributeViewBlock(blockID, avID string) (ret *av.AttributeView, err error) { - ret, err = av.ParseAttributeView(avID) - if nil != err { - return - } - - for i, row := range ret.Rows { - blockCell := row.GetBlockCell() - if nil == blockCell { - continue - } - - if blockCell.Value.Block.ID == blockID { - // 从行中移除,但是不移除属性 - ret.Rows = append(ret.Rows[:i], ret.Rows[i+1:]...) - break - } - } - - err = av.SaveAttributeView(ret) - return -} - const ( NodeAttrNameAVs = "custom-avs" NodeAttrNamePrefixAvCol = "custom-av-col-" From c605c496ee8aef819e3abfab99c36fc71c1f6c3e Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 11 Jul 2023 22:44:31 +0800 Subject: [PATCH 4/5] :recycle: Refactor av data structure --- kernel/model/attribute_view.go | 154 ++++++++++++++++----------------- kernel/model/transaction.go | 25 +++--- 2 files changed, 89 insertions(+), 90 deletions(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 18e5ba9dc..c31114270 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -258,11 +258,11 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre return } - if "" == operation.PreviousRowID { + if "" == operation.PreviousID { attrView.Rows = append([]*av.Row{row}, attrView.Rows...) } else { for i, r := range attrView.Rows { - if r.ID == operation.PreviousRowID { + if r.ID == operation.PreviousID { attrView.Rows = append(attrView.Rows[:i+1], append([]*av.Row{row}, attrView.Rows[i+1:]...)...) break } @@ -306,6 +306,81 @@ func removeAttributeViewBlock(blockID string, operation *Operation) (err error) return } +func (tx *Transaction) doSetAttrViewColumnWidth(operation *Operation) (ret *TxErr) { + err := setAttributeViewColWidth(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} + } + return +} + +func setAttributeViewColWidth(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + for _, column := range attrView.Columns { + if column.ID == operation.ID { + column.Width = operation.Data.(string) + break + } + } + + err = av.SaveAttributeView(attrView) + return +} + +func (tx *Transaction) doSetAttrViewColumnWrap(operation *Operation) (ret *TxErr) { + err := setAttributeViewColWrap(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} + } + return +} + +func setAttributeViewColWrap(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + for _, column := range attrView.Columns { + if column.ID == operation.ID { + column.Wrap = operation.Data.(bool) + break + } + } + + err = av.SaveAttributeView(attrView) + return +} + +func (tx *Transaction) doSetAttrViewColumnHidden(operation *Operation) (ret *TxErr) { + err := setAttributeViewColHidden(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} + } + return +} + +func setAttributeViewColHidden(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + for _, column := range attrView.Columns { + if column.ID == operation.ID { + column.Hidden = operation.Data.(bool) + break + } + } + + err = av.SaveAttributeView(attrView) + return +} + // TODO 下面的方法要重写 func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { @@ -437,30 +512,6 @@ func (tx *Transaction) doSortAttrViewRow(operation *Operation) (ret *TxErr) { return } -func (tx *Transaction) doSetAttrViewColumnHidden(operation *Operation) (ret *TxErr) { - err := setAttributeViewColHidden(operation.Data.(bool), operation.ID, operation.ParentID) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} - } - return -} - -func (tx *Transaction) doSetAttrViewColumnWrap(operation *Operation) (ret *TxErr) { - err := setAttributeViewColWrap(operation.Data.(bool), operation.ID, operation.ParentID) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} - } - return -} - -func (tx *Transaction) doSetAttrViewColumnWidth(operation *Operation) (ret *TxErr) { - err := setAttributeViewColWidth(operation.Data.(string), operation.ID, operation.ParentID) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} - } - return -} - func (tx *Transaction) doSetAttrView(operation *Operation) (ret *TxErr) { err := setAttributeView(operation) if nil != err { @@ -781,57 +832,6 @@ func sortAttributeViewRow(rowID, previousRowID, avID string) (err error) { return } -func setAttributeViewColHidden(hidden bool, columnID, avID string) (err error) { - attrView, err := av.ParseAttributeView(avID) - if nil != err { - return - } - - for _, column := range attrView.Columns { - if column.ID == columnID { - column.Hidden = hidden - break - } - } - - err = av.SaveAttributeView(attrView) - return -} - -func setAttributeViewColWrap(wrap bool, columnID, avID string) (err error) { - attrView, err := av.ParseAttributeView(avID) - if nil != err { - return - } - - for _, column := range attrView.Columns { - if column.ID == columnID { - column.Wrap = wrap - break - } - } - - err = av.SaveAttributeView(attrView) - return -} - -func setAttributeViewColWidth(width, columnID, avID string) (err error) { - attrView, err := av.ParseAttributeView(avID) - if nil != err { - return - } - - for _, column := range attrView.Columns { - if column.ID == columnID { - column.Width = width - break - } - } - - err = av.SaveAttributeView(attrView) - return -} - func setAttributeView(operation *Operation) (err error) { avID := operation.ID attrViewMap, err := av.ParseAttributeViewMap(avID) diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 26a41c366..9800db0a6 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -223,6 +223,12 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doSetAttrViewFilters(op) case "setAttrViewSorts": ret = tx.doSetAttrViewSorts(op) + case "setAttrViewColWidth": + ret = tx.doSetAttrViewColumnWidth(op) + case "setAttrViewColWrap": + ret = tx.doSetAttrViewColumnWrap(op) + case "setAttrViewColHidden": + ret = tx.doSetAttrViewColumnHidden(op) // TODO 下面的方法要重写 case "insertAttrViewBlock": ret = tx.doInsertAttrViewBlock(op) @@ -240,12 +246,6 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doUpdateAttrViewCell(op) case "sortAttrViewRow": ret = tx.doSortAttrViewRow(op) - case "setAttrViewColHidden": - ret = tx.doSetAttrViewColumnHidden(op) - case "setAttrViewColWrap": - ret = tx.doSetAttrViewColumnWrap(op) - case "setAttrViewColWidth": - ret = tx.doSetAttrViewColumnWidth(op) case "setAttrView": ret = tx.doSetAttrView(op) case "updateAttrViewColOptions": @@ -1053,13 +1053,12 @@ type Operation struct { DeckID string `json:"deckID"` // 用于添加/删除闪卡 - AvID string `json:"avID"` // 属性视图 ID - ViewID string `json:"viewID"` // 属性视图的视图 ID - SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中 - Name string `json:"name"` // 属性视图列名 - Typ string `json:"type"` // 属性视图列类型 - PreviousRowID string `json:"previousRowID"` // 属性视图前一行 ID - RowID string `json:"rowID"` // 属性视图行 ID + AvID string `json:"avID"` // 属性视图 ID + ViewID string `json:"viewID"` // 属性视图的视图 ID + SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中 + Name string `json:"name"` // 属性视图列名 + Typ string `json:"type"` // 属性视图列类型 + RowID string `json:"rowID"` // 属性视图行 ID discard bool // 用于标识是否在事务合并中丢弃 } From 3481e93463a14f50cf7f598bea6f0819d5deaf41 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 11 Jul 2023 22:47:19 +0800 Subject: [PATCH 5/5] :recycle: Refactor av data structure --- kernel/model/attribute_view.go | 172 ++++++++++++++++----------------- kernel/model/transaction.go | 11 ++- 2 files changed, 92 insertions(+), 91 deletions(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index c31114270..44c314885 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -381,6 +381,92 @@ func setAttributeViewColHidden(operation *Operation) (err error) { return } +func (tx *Transaction) doSortAttrViewRow(operation *Operation) (ret *TxErr) { + err := sortAttributeViewRow(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} + } + return +} + +func sortAttributeViewRow(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + var row *av.Row + var index, previousIndex int + for i, r := range attrView.Rows { + if r.ID == operation.ID { + row = r + index = i + break + } + } + if nil == row { + return + } + + attrView.Rows = append(attrView.Rows[:index], attrView.Rows[index+1:]...) + for i, r := range attrView.Rows { + if r.ID == operation.PreviousID { + previousIndex = i + 1 + break + } + } + attrView.Rows = util.InsertElem(attrView.Rows, previousIndex, row) + + err = av.SaveAttributeView(attrView) + return +} + +func (tx *Transaction) doSortAttrViewColumn(operation *Operation) (ret *TxErr) { + err := sortAttributeViewColumn(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} + } + return +} + +func sortAttributeViewColumn(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + var col *av.Column + var index, previousIndex int + for i, column := range attrView.Columns { + if column.ID == operation.ID { + col = column + index = i + break + } + } + if nil == col { + return + } + + attrView.Columns = append(attrView.Columns[:index], attrView.Columns[index+1:]...) + for i, column := range attrView.Columns { + if column.ID == operation.PreviousID { + previousIndex = i + 1 + break + } + } + attrView.Columns = util.InsertElem(attrView.Columns, previousIndex, col) + + for _, row := range attrView.Rows { + cel := row.Cells[index] + row.Cells = append(row.Cells[:index], row.Cells[index+1:]...) + row.Cells = util.InsertElem(row.Cells, previousIndex, cel) + } + + err = av.SaveAttributeView(attrView) + return +} + // TODO 下面的方法要重写 func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { @@ -496,22 +582,6 @@ func (tx *Transaction) doRemoveAttrViewColumn(operation *Operation) (ret *TxErr) return } -func (tx *Transaction) doSortAttrViewColumn(operation *Operation) (ret *TxErr) { - err := sortAttributeViewColumn(operation.ID, operation.PreviousID, operation.ParentID) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} - } - return -} - -func (tx *Transaction) doSortAttrViewRow(operation *Operation) (ret *TxErr) { - err := sortAttributeViewRow(operation.ID, operation.PreviousID, operation.ParentID) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} - } - return -} - func (tx *Transaction) doSetAttrView(operation *Operation) (ret *TxErr) { err := setAttributeView(operation) if nil != err { @@ -762,76 +832,6 @@ func removeAttributeViewColumn(columnID string, avID string) (err error) { return } -func sortAttributeViewColumn(columnID, previousColumnID, avID string) (err error) { - attrView, err := av.ParseAttributeView(avID) - if nil != err { - return - } - - var col *av.Column - var index, previousIndex int - for i, column := range attrView.Columns { - if column.ID == columnID { - col = column - index = i - break - } - } - if nil == col { - return - } - - attrView.Columns = append(attrView.Columns[:index], attrView.Columns[index+1:]...) - for i, column := range attrView.Columns { - if column.ID == previousColumnID { - previousIndex = i + 1 - break - } - } - attrView.Columns = util.InsertElem(attrView.Columns, previousIndex, col) - - for _, row := range attrView.Rows { - cel := row.Cells[index] - row.Cells = append(row.Cells[:index], row.Cells[index+1:]...) - row.Cells = util.InsertElem(row.Cells, previousIndex, cel) - } - - err = av.SaveAttributeView(attrView) - return -} - -func sortAttributeViewRow(rowID, previousRowID, avID string) (err error) { - attrView, err := av.ParseAttributeView(avID) - if nil != err { - return - } - - var row *av.Row - var index, previousIndex int - for i, r := range attrView.Rows { - if r.ID == rowID { - row = r - index = i - break - } - } - if nil == row { - return - } - - attrView.Rows = append(attrView.Rows[:index], attrView.Rows[index+1:]...) - for i, r := range attrView.Rows { - if r.ID == previousRowID { - previousIndex = i + 1 - break - } - } - attrView.Rows = util.InsertElem(attrView.Rows, previousIndex, row) - - err = av.SaveAttributeView(attrView) - return -} - func setAttributeView(operation *Operation) (err error) { avID := operation.ID attrViewMap, err := av.ParseAttributeViewMap(avID) diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 9800db0a6..25da3aade 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -229,23 +229,24 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doSetAttrViewColumnWrap(op) case "setAttrViewColHidden": ret = tx.doSetAttrViewColumnHidden(op) - // TODO 下面的方法要重写 + case "sortAttrViewRow": + ret = tx.doSortAttrViewRow(op) + case "sortAttrViewCol": + ret = tx.doSortAttrViewColumn(op) case "insertAttrViewBlock": ret = tx.doInsertAttrViewBlock(op) case "removeAttrViewBlock": ret = tx.doRemoveAttrViewBlock(op) + // TODO 下面的方法要重写 + case "addAttrViewCol": ret = tx.doAddAttrViewColumn(op) case "updateAttrViewCol": ret = tx.doUpdateAttrViewColumn(op) case "removeAttrViewCol": ret = tx.doRemoveAttrViewColumn(op) - case "sortAttrViewCol": - ret = tx.doSortAttrViewColumn(op) case "updateAttrViewCell": ret = tx.doUpdateAttrViewCell(op) - case "sortAttrViewRow": - ret = tx.doSortAttrViewRow(op) case "setAttrView": ret = tx.doSetAttrView(op) case "updateAttrViewColOptions":