diff --git a/kernel/av/av.go b/kernel/av/av.go index 74dc595ac..20a9a05b0 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) } @@ -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"` // 当前布局类型 @@ -559,7 +560,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 +604,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/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 fb973766a..17de6f582 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 { @@ -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 @@ -666,16 +724,69 @@ 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} + } + 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) 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} diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 3405146d9..a6f0e083a 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -246,6 +246,12 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doAddAttrViewView(op) case "removeAttrViewView": 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 8c041e877..b230912af 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 } @@ -558,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{},