From f9edbe0041548bf8b22f0bc4cb4ad12e8332f298 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 1 Dec 2023 09:00:14 +0800 Subject: [PATCH 1/4] :art: Supports multiple views for the database https://github.com/siyuan-note/siyuan/issues/9751 --- kernel/model/attribute_view.go | 24 ++++++++++++++++++++++++ kernel/model/transaction.go | 2 ++ 2 files changed, 26 insertions(+) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index fb973766a..91a1d40a3 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -683,6 +683,30 @@ func (tx *Transaction) doAddAttrViewView(operation *Operation) (ret *TxErr) { return } +func (tx *Transaction) doSetAttrViewViewName(operation *Operation) (ret *TxErr) { + var err error + avID := operation.AvID + attrView, err := av.ParseAttributeView(avID) + if nil != err { + logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err) + return &TxErr{code: TxErrWriteAttributeView, id: avID} + } + + viewID := operation.ID + view := attrView.GetView(viewID) + if nil == view { + logging.LogErrorf("get view [%s] failed: %s", viewID, err) + return &TxErr{code: TxErrWriteAttributeView, id: viewID} + } + + view.Name = operation.Data.(string) + if err = av.SaveAttributeView(attrView); nil != err { + logging.LogErrorf("save attribute view [%s] failed: %s", avID, err) + return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID} + } + return +} + func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) { err := setAttributeViewName(operation) if nil != err { diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 3405146d9..f94f01a09 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -246,6 +246,8 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doAddAttrViewView(op) case "removeAttrViewView": ret = tx.doRemoveAttrViewView(op) + case "setAttrViewViewName": + ret = tx.doSetAttrViewViewName(op) } if nil != ret { From 46e566cbfdf4cbc7a9c96669ffe0a091d0d73957 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 1 Dec 2023 09:05:28 +0800 Subject: [PATCH 2/4] :art: Supports multiple views for the database https://github.com/siyuan-note/siyuan/issues/9751 --- kernel/treenode/node.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/treenode/node.go b/kernel/treenode/node.go index 8c041e877..1a33cf9a4 100644 --- a/kernel/treenode/node.go +++ b/kernel/treenode/node.go @@ -508,6 +508,8 @@ func getAttributeViewContent(avID string) (content string) { } buf := bytes.Buffer{} + buf.WriteString(attrView.Name) + buf.WriteByte(' ') for _, v := range attrView.Views { buf.WriteString(v.Name) buf.WriteByte(' ') @@ -526,7 +528,7 @@ func getAttributeViewContent(avID string) (content string) { } } if nil == view { - content = buf.String() + content = strings.TrimSpace(buf.String()) return } From 5f04af1afe6976240ac696c7b536dd73cabcaa94 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 1 Dec 2023 09:17:44 +0800 Subject: [PATCH 3/4] :art: Supports multiple views for the database https://github.com/siyuan-note/siyuan/issues/9751 --- kernel/av/av.go | 21 ++++++++++++++++++--- kernel/model/attribute_view.go | 15 ++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/kernel/av/av.go b/kernel/av/av.go index 74dc595ac..2e34ddff0 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -64,7 +64,7 @@ func ShallowCloneAttributeView(av *AttributeView) (ret *AttributeView) { view.ID = ast.NewNodeID() ret.ViewID = view.ID } else { - view, _ = NewView(ast.NewNodeID()) + view, _ = NewTableViewWithBlockKey(ast.NewNodeID()) ret.ViewID = view.ID ret.Views = append(ret.Views, view) } @@ -559,7 +559,22 @@ const ( LayoutTypeTable LayoutType = "table" // 属性视图类型 - 表格 ) -func NewView(blockKeyID string) (view *View, blockKey *Key) { +func NewTableView() (ret *View) { + ret = &View{ + ID: ast.NewNodeID(), + Name: "Table", + LayoutType: LayoutTypeTable, + Table: &LayoutTable{ + Spec: 0, + ID: ast.NewNodeID(), + Filters: []*ViewFilter{}, + Sorts: []*ViewSort{}, + }, + } + return +} + +func NewTableViewWithBlockKey(blockKeyID string) (view *View, blockKey *Key) { name := "Table" view = &View{ ID: ast.NewNodeID(), @@ -588,7 +603,7 @@ type Viewable interface { } func NewAttributeView(id string) (ret *AttributeView) { - view, blockKey := NewView(ast.NewNodeID()) + view, blockKey := NewTableViewWithBlockKey(ast.NewNodeID()) ret = &AttributeView{ Spec: 0, ID: id, diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 91a1d40a3..b397e0615 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -294,7 +294,7 @@ func RenderAttributeView(avID, viewID string) (viewable av.Viewable, attrView *a func renderAttributeView(attrView *av.AttributeView, viewID string) (viewable av.Viewable, err error) { if 1 > len(attrView.Views) { - view, _ := av.NewView(ast.NewNodeID()) + view, _ := av.NewTableViewWithBlockKey(ast.NewNodeID()) attrView.Views = append(attrView.Views, view) attrView.ViewID = view.ID if err = av.SaveAttributeView(attrView); nil != err { @@ -666,16 +666,21 @@ func (tx *Transaction) doAddAttrViewView(operation *Operation) (ret *TxErr) { return &TxErr{code: TxErrWriteAttributeView, id: avID} } - bKey := attrView.GetBlockKey() - if nil == bKey { - logging.LogErrorf("get block key failed: %s", avID) + firstView := attrView.Views[0] + if nil == firstView { + logging.LogErrorf("get first view failed: %s", avID) return &TxErr{code: TxErrWriteAttributeView, id: avID} } - view, _ := av.NewView(bKey.ID) + view := av.NewTableView() view.ID = operation.ID attrView.Views = append(attrView.Views, view) attrView.ViewID = view.ID + + for _, col := range firstView.Table.Columns { + view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: col.ID}) + } + if err = av.SaveAttributeView(attrView); nil != err { logging.LogErrorf("save attribute view [%s] failed: %s", avID, err) return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID} From 3f5e49cec6799e5d24291b71f2e54b2f1b726b98 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 1 Dec 2023 09:48:20 +0800 Subject: [PATCH 4/4] :art: Supports multiple views for the database https://github.com/siyuan-note/siyuan/issues/9751 --- kernel/av/av.go | 1 + kernel/av/table.go | 1 + kernel/model/attribute_view.go | 82 ++++++++++++++++++++++++++++++++++ kernel/model/transaction.go | 4 ++ kernel/treenode/node.go | 1 + 5 files changed, 89 insertions(+) diff --git a/kernel/av/av.go b/kernel/av/av.go index 2e34ddff0..20a9a05b0 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -546,6 +546,7 @@ type ValueCheckbox struct { // View 描述了视图的结构。 type View struct { ID string `json:"id"` // 视图 ID + Icon string `json:"icon"` // 视图图标 Name string `json:"name"` // 视图名称 LayoutType LayoutType `json:"type"` // 当前布局类型 diff --git a/kernel/av/table.go b/kernel/av/table.go index 89621bfda..840ab1aa8 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -572,6 +572,7 @@ func (value *Value) CompareOperator(other *Value, operator FilterOperator) bool // Table 描述了表格实例的结构。 type Table struct { ID string `json:"id"` // 表格布局 ID + Icon string `json:icon` // 表格图标 Name string `json:"name"` // 表格名称 Filters []*ViewFilter `json:"filters"` // 过滤规则 Sorts []*ViewSort `json:"sorts"` // 排序规则 diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index b397e0615..17de6f582 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -443,6 +443,7 @@ func renderTemplateCol(ial map[string]string, tplContent string, rowValues []*av func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) { ret = &av.Table{ ID: view.ID, + Icon: view.Icon, Name: view.Name, Columns: []*av.TableColumn{}, Rows: []*av.TableRow{}, @@ -657,6 +658,63 @@ func (tx *Transaction) doRemoveAttrViewView(operation *Operation) (ret *TxErr) { return } +func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr) { + var err error + avID := operation.AvID + attrView, err := av.ParseAttributeView(avID) + if nil != err { + logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err) + return &TxErr{code: TxErrWriteAttributeView, id: avID} + } + + masterView := attrView.GetView(operation.PreviousID) + if nil == masterView { + logging.LogErrorf("get master view failed: %s", avID) + return &TxErr{code: TxErrWriteAttributeView, id: avID} + } + + view := av.NewTableView() + view.ID = operation.ID + attrView.Views = append(attrView.Views, view) + attrView.ViewID = view.ID + + view.Icon = masterView.Icon + view.Name = masterView.Name + view.LayoutType = masterView.LayoutType + + for _, col := range masterView.Table.Columns { + view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ + ID: col.ID, + Wrap: col.Wrap, + Hidden: col.Hidden, + Pin: col.Pin, + Width: col.Width, + Calc: col.Calc, + }) + } + + for _, filter := range masterView.Table.Filters { + view.Table.Filters = append(view.Table.Filters, &av.ViewFilter{ + Column: filter.Column, + Operator: filter.Operator, + Value: filter.Value, + }) + } + + for _, s := range masterView.Table.Sorts { + view.Table.Sorts = append(view.Table.Sorts, &av.ViewSort{ + Column: s.Column, + Order: s.Order, + }) + } + + if err = av.SaveAttributeView(attrView); nil != err { + logging.LogErrorf("save attribute view [%s] failed: %s", avID, err) + return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID} + } + return +} + func (tx *Transaction) doAddAttrViewView(operation *Operation) (ret *TxErr) { var err error avID := operation.AvID @@ -712,6 +770,30 @@ func (tx *Transaction) doSetAttrViewViewName(operation *Operation) (ret *TxErr) return } +func (tx *Transaction) doSetAttrViewViewIcon(operation *Operation) (ret *TxErr) { + var err error + avID := operation.AvID + attrView, err := av.ParseAttributeView(avID) + if nil != err { + logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err) + return &TxErr{code: TxErrWriteAttributeView, id: avID} + } + + viewID := operation.ID + view := attrView.GetView(viewID) + if nil == view { + logging.LogErrorf("get view [%s] failed: %s", viewID, err) + return &TxErr{code: TxErrWriteAttributeView, id: viewID} + } + + view.Icon = operation.Data.(string) + if err = av.SaveAttributeView(attrView); nil != err { + logging.LogErrorf("save attribute view [%s] failed: %s", avID, err) + return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID} + } + return +} + func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) { err := setAttributeViewName(operation) if nil != err { diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index f94f01a09..a6f0e083a 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -248,6 +248,10 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doRemoveAttrViewView(op) case "setAttrViewViewName": ret = tx.doSetAttrViewViewName(op) + case "setAttrViewViewIcon": + ret = tx.doSetAttrViewViewIcon(op) + case "duplicateAttrViewView": + ret = tx.doDuplicateAttrViewView(op) } if nil != ret { diff --git a/kernel/treenode/node.go b/kernel/treenode/node.go index 1a33cf9a4..b230912af 100644 --- a/kernel/treenode/node.go +++ b/kernel/treenode/node.go @@ -560,6 +560,7 @@ func getAttributeViewContent(avID string) (content string) { func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) { ret = &av.Table{ ID: view.ID, + Icon: view.Icon, Name: view.Name, Columns: []*av.TableColumn{}, Rows: []*av.TableRow{},