mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-17 15:10:12 +01:00
♻️ Refactor av data structure
This commit is contained in:
parent
39b28cbc98
commit
1ccdb4c576
2 changed files with 143 additions and 152 deletions
|
|
@ -69,6 +69,19 @@ func RenderAttributeView(avID string) (viewable av.Viewable, attrView *av.Attrib
|
||||||
return
|
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) {
|
func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) {
|
||||||
err := setAttributeViewName(operation)
|
err := setAttributeViewName(operation)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
|
@ -77,22 +90,6 @@ func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) {
|
||||||
return
|
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) {
|
func setAttributeViewName(operation *Operation) (err error) {
|
||||||
avID := operation.ID
|
avID := operation.ID
|
||||||
attrView, err := av.ParseAttributeView(avID)
|
attrView, err := av.ParseAttributeView(avID)
|
||||||
|
|
@ -115,6 +112,14 @@ func setAttributeViewName(operation *Operation) (err error) {
|
||||||
return
|
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) {
|
func setAttributeViewFilters(operation *Operation) (err error) {
|
||||||
avID := operation.ID
|
avID := operation.ID
|
||||||
attrView, err := av.ParseAttributeView(avID)
|
attrView, err := av.ParseAttributeView(avID)
|
||||||
|
|
@ -142,6 +147,14 @@ func setAttributeViewFilters(operation *Operation) (err error) {
|
||||||
return
|
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) {
|
func setAttributeViewSorts(operation *Operation) (err error) {
|
||||||
avID := operation.ID
|
avID := operation.ID
|
||||||
attrView, err := av.ParseAttributeView(avID)
|
attrView, err := av.ParseAttributeView(avID)
|
||||||
|
|
@ -169,21 +182,118 @@ func setAttributeViewSorts(operation *Operation) (err error) {
|
||||||
return
|
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) {
|
for _, id := range operation.SrcIDs {
|
||||||
ret = &av.Table{
|
var avErr error
|
||||||
Spec: attrView.Spec,
|
if avErr = addAttributeViewBlock(id, operation, tree, tx); nil != avErr {
|
||||||
ID: view.ID,
|
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: avErr.Error()}
|
||||||
Name: view.Name,
|
}
|
||||||
Columns: attrView.Columns,
|
|
||||||
Rows: attrView.Rows,
|
|
||||||
Filters: view.Filters,
|
|
||||||
Sorts: view.Sorts,
|
|
||||||
}
|
}
|
||||||
return
|
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) {
|
func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) {
|
||||||
avID := operation.ParentID
|
avID := operation.ParentID
|
||||||
view, err := av.ParseAttributeView(avID)
|
view, err := av.ParseAttributeView(avID)
|
||||||
|
|
@ -249,52 +359,6 @@ func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) {
|
||||||
return
|
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) {
|
func (tx *Transaction) doUpdateAttrViewColOption(operation *Operation) (ret *TxErr) {
|
||||||
err := updateAttributeViewColumnOption(operation)
|
err := updateAttributeViewColumnOption(operation)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
|
@ -803,80 +867,6 @@ func removeAttributeViewBlock(blockID, avID string) (ret *av.AttributeView, err
|
||||||
return
|
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 (
|
const (
|
||||||
NodeAttrNameAVs = "custom-avs"
|
NodeAttrNameAVs = "custom-avs"
|
||||||
NodeAttrNamePrefixAvCol = "custom-av-col-"
|
NodeAttrNamePrefixAvCol = "custom-av-col-"
|
||||||
|
|
|
||||||
|
|
@ -1053,12 +1053,13 @@ type Operation struct {
|
||||||
|
|
||||||
DeckID string `json:"deckID"` // 用于添加/删除闪卡
|
DeckID string `json:"deckID"` // 用于添加/删除闪卡
|
||||||
|
|
||||||
AvID string `json:"avID"` // 属性视图 ID
|
AvID string `json:"avID"` // 属性视图 ID
|
||||||
ViewID string `json:"viewID"` // 属性视图的视图 ID
|
ViewID string `json:"viewID"` // 属性视图的视图 ID
|
||||||
SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中
|
SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中
|
||||||
Name string `json:"name"` // 用于属性视图列名
|
Name string `json:"name"` // 属性视图列名
|
||||||
Typ string `json:"type"` // 用于属性视图列类型
|
Typ string `json:"type"` // 属性视图列类型
|
||||||
RowID string `json:"rowID"` // 用于属性视图行 ID
|
PreviousRowID string `json:"previousRowID"` // 属性视图前一行 ID
|
||||||
|
RowID string `json:"rowID"` // 属性视图行 ID
|
||||||
|
|
||||||
discard bool // 用于标识是否在事务合并中丢弃
|
discard bool // 用于标识是否在事务合并中丢弃
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue