Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2023-07-03 19:07:55 +08:00
commit 9f17d9bd7d
3 changed files with 194 additions and 13 deletions

View file

@ -75,27 +75,27 @@ func (av *AttributeView) GetColumnNames() (ret []string) {
type AttributeViewFilter struct {
Column string `json:"column"`
Operator FilterOperator `json:"operator"`
Value string `json:"value"`
Value *Value `json:"value"`
}
type FilterOperator string
const (
FilterOperatorEq FilterOperator = "="
FilterOperatorNe FilterOperator = "!="
FilterOperatorGt FilterOperator = ">"
FilterOperatorGe FilterOperator = ">="
FilterOperatorLt FilterOperator = "<"
FilterOperatorLe FilterOperator = "<="
FilterOperatorIn FilterOperator = "IN"
FilterOperatorNotIn FilterOperator = "NOT IN"
FilterOperatorLike FilterOperator = "LIKE"
FilterOperatorNotLike FilterOperator = "NOT LIKE"
FilterOperatorEq FilterOperator = "="
FilterOperatorNe FilterOperator = "!="
FilterOperatorGt FilterOperator = ">"
FilterOperatorGe FilterOperator = ">="
FilterOperatorLt FilterOperator = "<"
FilterOperatorLe FilterOperator = "<="
FilterOperatorContains FilterOperator = "CONTAINS"
FilterOperatorNotContains FilterOperator = "NOT CONTAINS"
FilterOperatorIsEmpty FilterOperator = "IS EMPTY"
FilterOperatorIsNotEmpty FilterOperator = "IS NOT EMPTY"
)
type AttributeViewSort struct {
Column string `json:"column"`
Order SortOrder `json:"order"`
Column string `json:"column"` // 列 ID
Order SortOrder `json:"order"` // 排序顺序
}
type SortOrder string

View file

@ -19,6 +19,7 @@ package av
import (
"github.com/88250/gulu"
"github.com/88250/lute/ast"
"strings"
)
type Cell struct {
@ -46,6 +47,116 @@ func (value *Value) ToJSONString() string {
return string(data)
}
func (value *Value) Compare(other *Value) int {
if nil == value {
return -1
}
if nil == other {
return 1
}
if nil != value.Block && nil != other.Block {
return strings.Compare(value.Block.Content, other.Block.Content)
}
if nil != value.Text && nil != other.Text {
return strings.Compare(value.Text.Content, other.Text.Content)
}
if nil != value.Number && nil != other.Number {
if value.Number.Content > other.Number.Content {
return 1
} else if value.Number.Content < other.Number.Content {
return -1
} else {
return 0
}
}
if nil != value.Date && nil != other.Date {
if value.Date.Content > other.Date.Content {
return 1
} else if value.Date.Content < other.Date.Content {
return -1
} else {
return 0
}
}
if nil != value.Select && nil != other.Select {
return strings.Compare(value.Select.Content, other.Select.Content)
}
if nil != value.MSelect && nil != other.MSelect {
var v1 string
for _, v := range value.MSelect {
v1 += v.Content
}
var v2 string
for _, v := range other.MSelect {
v2 += v.Content
}
return strings.Compare(v1, v2)
}
return 0
}
func (value *Value) CompareOperator(other *Value, operator FilterOperator) bool {
if nil == value {
return false
}
if nil == other {
return false
}
if nil != value.Block && nil != other.Block {
return strings.Contains(value.Block.Content, other.Block.Content)
}
if nil != value.Text && nil != other.Text {
return strings.Contains(value.Text.Content, other.Text.Content)
}
if nil != value.Number && nil != other.Number {
switch operator {
case FilterOperatorEq:
return value.Number.Content == other.Number.Content
case FilterOperatorNe:
return value.Number.Content != other.Number.Content
case FilterOperatorGt:
return value.Number.Content > other.Number.Content
case FilterOperatorGe:
return value.Number.Content >= other.Number.Content
case FilterOperatorLt:
return value.Number.Content < other.Number.Content
case FilterOperatorLe:
return value.Number.Content <= other.Number.Content
}
}
if nil != value.Date && nil != other.Date {
switch operator {
case FilterOperatorEq:
return value.Date.Content == other.Date.Content
case FilterOperatorNe:
return value.Date.Content != other.Date.Content
case FilterOperatorGt:
return value.Date.Content > other.Date.Content
case FilterOperatorGe:
return value.Date.Content >= other.Date.Content
case FilterOperatorLt:
return value.Date.Content < other.Date.Content
case FilterOperatorLe:
return value.Date.Content <= other.Date.Content
}
}
if nil != value.Select && nil != other.Select {
return strings.Contains(value.Select.Content, other.Select.Content)
}
if nil != value.MSelect && nil != other.MSelect {
var v1 string
for _, v := range value.MSelect {
v1 += v.Content
}
var v2 string
for _, v := range other.MSelect {
v2 += v.Content
}
return strings.Contains(v1, v2)
}
return false
}
func NewCellBlock(blockID, blockContent string) *Cell {
return &Cell{
ID: ast.NewNodeID(),

View file

@ -19,6 +19,7 @@ package model
import (
"errors"
"fmt"
"sort"
"strings"
"github.com/88250/gulu"
@ -40,9 +41,78 @@ func RenderAttributeView(avID string) (ret *av.AttributeView, err error) {
logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
return
}
filterRows(ret)
sortRows(ret)
return
}
func filterRows(ret *av.AttributeView) {
if 0 < len(ret.Filters) {
var colIndexes []int
for _, f := range ret.Filters {
for i, c := range ret.Columns {
if c.ID == f.Column {
colIndexes = append(colIndexes, i)
break
}
}
}
var rows []*av.Row
for _, row := range ret.Rows {
pass := true
for j, index := range colIndexes {
c := ret.Columns[index]
if c.Type == av.ColumnTypeBlock {
continue
}
if !row.Cells[index].Value.CompareOperator(ret.Filters[j].Value, ret.Filters[j].Operator) {
pass = false
break
}
}
if pass {
rows = append(rows, row)
}
}
ret.Rows = rows
}
}
func sortRows(ret *av.AttributeView) {
if 0 < len(ret.Sorts) {
var colIndexes []int
for _, s := range ret.Sorts {
for i, c := range ret.Columns {
if c.ID == s.Column {
colIndexes = append(colIndexes, i)
break
}
}
}
sort.Slice(ret.Rows, func(i, j int) bool {
less := false
for _, index := range colIndexes {
c := ret.Columns[index]
if c.Type == av.ColumnTypeBlock {
continue
}
result := ret.Rows[i].Cells[index].Value.Compare(ret.Rows[j].Cells[index].Value)
if 0 == result {
continue
} else if 0 > result {
less = true
}
}
return less
})
}
}
func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) {
avID := operation.ParentID
view, err := av.ParseAttributeView(avID)