diff --git a/kernel/av/attribute_view.go b/kernel/av/attribute_view.go index 0438b73ea..b7c2408dd 100644 --- a/kernel/av/attribute_view.go +++ b/kernel/av/attribute_view.go @@ -47,8 +47,8 @@ type View struct { Name string `json:"name"` // 视图名称 Type ViewType `json:"type"` // 视图类型 - Filters []*ViewFilter `json:"filters"` // 过滤规则 - Sorts []*ViewSort `json:"sorts"` // 排序规则 + Table *Table `json:"table,omitempty"` // 表格视图 + // TODO Kanban *Kanban `json:"kanban,omitempty"` // 看板视图 } // ViewType 描述了视图的类型。 @@ -59,6 +59,22 @@ const ( ViewTypeKanban ViewType = "kanban" // 属性视图类型 - 看板 ) +func NewView() *View { + id := ast.NewNodeID() + name := "Table" + return &View{ + ID: id, + Name: name, + Type: ViewTypeTable, + Table: &Table{ + Spec: 0, + ID: id, + Filters: []*ViewFilter{}, + Sorts: []*ViewSort{}, + }, + } +} + // Viewable 描述了视图的接口。 type Viewable interface { Filterable @@ -70,13 +86,7 @@ type Viewable interface { } func NewAttributeView(id string) *AttributeView { - view := &View{ - ID: ast.NewNodeID(), - Name: "Table", - Type: ViewTypeTable, - Filters: []*ViewFilter{}, - Sorts: []*ViewSort{}, - } + view := NewView() return &AttributeView{ Spec: 0, @@ -108,14 +118,7 @@ func ParseAttributeView(avID string) (ret *AttributeView, err error) { } if 1 > len(ret.Views) { - view := &View{ - ID: ast.NewNodeID(), - Name: "Table", - Type: ViewTypeTable, - Filters: []*ViewFilter{}, - Sorts: []*ViewSort{}, - } - + view := NewView() ret.CurrentViewID = view.ID ret.Views = []*View{view} } diff --git a/kernel/av/column.go b/kernel/av/column.go index 5ed989f2e..fbe40a0b4 100644 --- a/kernel/av/column.go +++ b/kernel/av/column.go @@ -23,32 +23,24 @@ import ( type ColumnType string const ( - ColumnTypeBlock ColumnType = "block" - ColumnTypeText ColumnType = "text" - ColumnTypeNumber ColumnType = "number" - ColumnTypeDate ColumnType = "date" - ColumnTypeSelect ColumnType = "select" - ColumnTypeMSelect ColumnType = "mSelect" - ColumnTypeRelation ColumnType = "relation" - ColumnTypeRollup ColumnType = "rollup" + ColumnTypeBlock ColumnType = "block" + ColumnTypeText ColumnType = "text" + ColumnTypeNumber ColumnType = "number" + ColumnTypeDate ColumnType = "date" + ColumnTypeSelect ColumnType = "select" + ColumnTypeMSelect ColumnType = "mSelect" ) // Column 描述了属性视图的基础结构。 type Column struct { - ID string `json:"id"` // 列 ID - Name string `json:"name"` // 列名 - Type ColumnType `json:"type"` // 列类型 - Icon string `json:"icon"` // 列图标 - Wrap bool `json:"wrap"` // 是否换行 - Hidden bool `json:"hidden"` // 是否隐藏 - Width string `json:"width"` // 列宽度 - Calc *ColumnCalc `json:"calc"` // 计算 + ID string `json:"id"` // 列 ID + Name string `json:"name"` // 列名 + Type ColumnType `json:"type"` // 列类型 + Icon string `json:"icon"` // 列图标 // 以下是某些列类型的特有属性 - AttributeViewID string `json:"attributeViewId"` // 关联的属性视图 ID - RelationColumnID string `json:"relationColumnId"` // 目标关联列 ID - Options []*ColumnSelectOption `json:"options"` // 选项列表 + Options []*ColumnSelectOption `json:"options"` // 选项列表 } type ColumnSelectOption struct { diff --git a/kernel/av/table.go b/kernel/av/table.go index 593706027..884b32eb7 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -23,14 +23,30 @@ import ( // Table 描述了表格视图的结构。 type Table struct { - Spec int `json:"spec"` // 视图格式版本 + Spec int `json:"spec"` // 视图格式版本 + ID string `json:"id"` // 视图 ID - ID string `json:"id"` // 表格 ID - Name string `json:"name"` // 表格名称 - Columns []*Column `json:"columns"` // 表格列 - Rows []*Row `json:"rows"` // 表格行 - Filters []*ViewFilter `json:"filters"` // 过滤规则 - Sorts []*ViewSort `json:"sorts"` // 排序规则 + Columns []*TableColumn `json:"columns"` // 表格列 + Rows []*TableRow `json:"rows"` // 表格行 + Filters []*ViewFilter `json:"filters"` // 过滤规则 + Sorts []*ViewSort `json:"sorts"` // 排序规则 +} + +type TableColumn struct { + ID string `json:"id"` // 列 ID + Name string `json:"name"` // 列名 + Type ColumnType `json:"type"` // 列类型 + Icon string `json:"icon"` // 列图标 + + Wrap bool `json:"wrap"` // 是否换行 + Hidden bool `json:"hidden"` // 是否隐藏 + Width string `json:"width"` // 列宽度 + Calc *ColumnCalc `json:"calc"` // 计算 +} + +type TableRow struct { + ID string `json:"id"` + Cells []*Cell `json:"cells"` } func (table *Table) GetType() ViewType { @@ -97,7 +113,7 @@ func (table *Table) FilterRows() { } } - rows := []*Row{} + rows := []*TableRow{} for _, row := range table.Rows { pass := true for j, index := range colIndexes { @@ -143,7 +159,7 @@ func (table *Table) CalcCols() { } } -func (table *Table) calcColMSelect(col *Column, colIndex int) { +func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows))}} @@ -204,7 +220,7 @@ func (table *Table) calcColMSelect(col *Column, colIndex int) { } } -func (table *Table) calcColSelect(col *Column, colIndex int) { +func (table *Table) calcColSelect(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows))}} @@ -261,7 +277,7 @@ func (table *Table) calcColSelect(col *Column, colIndex int) { } } -func (table *Table) calcColDate(col *Column, colIndex int) { +func (table *Table) calcColDate(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows))}} @@ -360,7 +376,7 @@ func (table *Table) calcColDate(col *Column, colIndex int) { } } -func (table *Table) calcColNumber(col *Column, colIndex int) { +func (table *Table) calcColNumber(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows))}} @@ -500,7 +516,7 @@ func (table *Table) calcColNumber(col *Column, colIndex int) { } } -func (table *Table) calcColText(col *Column, colIndex int) { +func (table *Table) calcColText(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows))}} diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 44c314885..7310861f0 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -70,14 +70,10 @@ func RenderAttributeView(avID string) (viewable av.Viewable, attrView *av.Attrib } 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, + ret = view.Table + for _, avRow := range attrView.Rows { + row := &av.TableRow{ID: avRow.ID, Cells: avRow.Cells} + ret.Rows = append(ret.Rows, row) } return } @@ -139,7 +135,7 @@ func setAttributeViewFilters(operation *Operation) (err error) { return } - if err = gulu.JSON.UnmarshalJSON(data, &view.Filters); nil != err { + if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Filters); nil != err { return } @@ -174,7 +170,7 @@ func setAttributeViewSorts(operation *Operation) (err error) { return } - if err = gulu.JSON.UnmarshalJSON(data, &view.Sorts); nil != err { + if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Sorts); nil != err { return } @@ -320,7 +316,13 @@ func setAttributeViewColWidth(operation *Operation) (err error) { return } - for _, column := range attrView.Columns { + view := attrView.GetView(operation.ViewID) + if nil == view { + err = av.ErrViewNotFound + return + } + + for _, column := range view.Table.Columns { if column.ID == operation.ID { column.Width = operation.Data.(string) break @@ -345,7 +347,13 @@ func setAttributeViewColWrap(operation *Operation) (err error) { return } - for _, column := range attrView.Columns { + view := attrView.GetView(operation.ViewID) + if nil == view { + err = av.ErrViewNotFound + return + } + + for _, column := range view.Table.Columns { if column.ID == operation.ID { column.Wrap = operation.Data.(bool) break @@ -370,7 +378,13 @@ func setAttributeViewColHidden(operation *Operation) (err error) { return } - for _, column := range attrView.Columns { + view := attrView.GetView(operation.ViewID) + if nil == view { + err = av.ErrViewNotFound + return + } + + for _, column := range view.Table.Columns { if column.ID == operation.ID { column.Hidden = operation.Data.(bool) break @@ -467,6 +481,47 @@ func sortAttributeViewColumn(operation *Operation) (err error) { return } +func (tx *Transaction) doAddAttrViewColumn(operation *Operation) (ret *TxErr) { + err := addAttributeViewColumn(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} + } + return +} + +func addAttributeViewColumn(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + view := attrView.GetView(operation.ViewID) + if nil == view { + err = av.ErrViewNotFound + return + } + + colType := av.ColumnType(operation.Typ) + switch colType { + case av.ColumnTypeText, av.ColumnTypeNumber, av.ColumnTypeDate, av.ColumnTypeSelect, av.ColumnTypeMSelect: + col := &av.Column{ID: ast.NewNodeID(), Name: operation.Name, Type: colType} + attrView.Columns = append(attrView.Columns, col) + view.Table.Columns = append(view.Table.Columns, &av.TableColumn{ID: col.ID, Name: col.Name, Type: col.Type}) + + for _, row := range attrView.Rows { + row.Cells = append(row.Cells, av.NewCell(colType)) + } + default: + msg := fmt.Sprintf("invalid column type [%s]", operation.Typ) + logging.LogErrorf(msg) + err = errors.New(msg) + return + } + + err = av.SaveAttributeView(attrView) + return +} + // TODO 下面的方法要重写 func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { @@ -558,14 +613,6 @@ func (tx *Transaction) doUpdateAttrViewColOptions(operation *Operation) (ret *Tx return } -func (tx *Transaction) doAddAttrViewColumn(operation *Operation) (ret *TxErr) { - err := addAttributeViewColumn(operation.Name, operation.Typ, operation.ParentID) - if nil != err { - return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()} - } - return -} - func (tx *Transaction) doUpdateAttrViewColumn(operation *Operation) (ret *TxErr) { err := updateAttributeViewColumn(operation.ID, operation.Name, operation.Typ, operation.ParentID) if nil != err { @@ -590,31 +637,6 @@ func (tx *Transaction) doSetAttrView(operation *Operation) (ret *TxErr) { return } -func addAttributeViewColumn(name string, typ string, avID string) (err error) { - attrView, err := av.ParseAttributeView(avID) - if nil != err { - return - } - - colType := av.ColumnType(typ) - switch colType { - case av.ColumnTypeText, av.ColumnTypeNumber, av.ColumnTypeDate, av.ColumnTypeSelect, av.ColumnTypeMSelect: - col := &av.Column{ID: ast.NewNodeID(), Name: name, Type: colType} - attrView.Columns = append(attrView.Columns, col) - for _, row := range attrView.Rows { - row.Cells = append(row.Cells, av.NewCell(colType)) - } - default: - msg := fmt.Sprintf("invalid column type [%s]", typ) - logging.LogErrorf(msg) - err = errors.New(msg) - return - } - - err = av.SaveAttributeView(attrView) - return -} - func updateAttributeViewColumn(id, name string, typ string, avID string) (err error) { attrView, err := av.ParseAttributeView(avID) if nil != err { diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 25da3aade..8afb19039 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -237,10 +237,9 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doInsertAttrViewBlock(op) case "removeAttrViewBlock": ret = tx.doRemoveAttrViewBlock(op) - // TODO 下面的方法要重写 - case "addAttrViewCol": ret = tx.doAddAttrViewColumn(op) + // TODO 下面的方法要重写 case "updateAttrViewCol": ret = tx.doUpdateAttrViewColumn(op) case "removeAttrViewCol":