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