diff --git a/kernel/av/filter.go b/kernel/av/filter.go index 30f23d611..24a1c7f65 100644 --- a/kernel/av/filter.go +++ b/kernel/av/filter.go @@ -16,6 +16,11 @@ package av +import ( + "github.com/siyuan-note/siyuan/kernel/util" + "strings" +) + type Filterable interface { FilterRows() } @@ -46,3 +51,195 @@ const ( FilterOperatorIsTrue FilterOperator = "Is true" FilterOperatorIsFalse FilterOperator = "Is false" ) + +func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { + ret = filter.Value.Clone() + switch filter.Value.Type { + case KeyTypeBlock: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: filter.Value.Block.Content} + case FilterOperatorIsNotEqual: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: strings.TrimSpace(filter.Value.Block.Content + " Untitled")} + case FilterOperatorContains: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: filter.Value.Block.Content} + case FilterOperatorDoesNotContain: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: strings.TrimSpace(filter.Value.Block.Content + " Untitled")} + case FilterOperatorStartsWith: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: filter.Value.Block.Content} + case FilterOperatorEndsWith: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: filter.Value.Block.Content} + case FilterOperatorIsEmpty: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: ""} + case FilterOperatorIsNotEmpty: + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: "Untitled"} + } + case KeyTypeText: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.Text = &ValueText{Content: filter.Value.Text.Content} + case FilterOperatorIsNotEqual: + ret.Text = &ValueText{Content: strings.TrimSpace(filter.Value.Text.Content + " Untitled")} + case FilterOperatorContains: + ret.Text = &ValueText{Content: filter.Value.Text.Content} + case FilterOperatorDoesNotContain: + ret.Text = &ValueText{Content: strings.TrimSpace(filter.Value.Text.Content + " Untitled")} + case FilterOperatorStartsWith: + ret.Text = &ValueText{Content: filter.Value.Text.Content} + case FilterOperatorEndsWith: + ret.Text = &ValueText{Content: filter.Value.Text.Content} + case FilterOperatorIsEmpty: + ret.Text = &ValueText{Content: ""} + case FilterOperatorIsNotEmpty: + ret.Text = &ValueText{Content: "Untitled"} + } + case KeyTypeNumber: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.Number = &ValueNumber{Content: filter.Value.Number.Content, IsNotEmpty: false} + case FilterOperatorIsNotEqual: + if 0 == filter.Value.Number.Content { + ret.Number = &ValueNumber{Content: 1, IsNotEmpty: true} + } else { + ret.Number = &ValueNumber{Content: 0, IsNotEmpty: true} + } + case FilterOperatorIsGreater: + ret.Number = &ValueNumber{Content: filter.Value.Number.Content + 1, IsNotEmpty: true} + case FilterOperatorIsGreaterOrEqual: + ret.Number = &ValueNumber{Content: filter.Value.Number.Content, IsNotEmpty: true} + case FilterOperatorIsLess: + ret.Number = &ValueNumber{Content: filter.Value.Number.Content - 1, IsNotEmpty: true} + case FilterOperatorIsLessOrEqual: + ret.Number = &ValueNumber{Content: filter.Value.Number.Content, IsNotEmpty: true} + case FilterOperatorIsEmpty: + ret.Number = &ValueNumber{Content: 0, IsNotEmpty: false} + case FilterOperatorIsNotEmpty: + ret.Number = &ValueNumber{Content: 0, IsNotEmpty: true} + } + case KeyTypeDate: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.Date = &ValueDate{Content: filter.Value.Date.Content, IsNotEmpty: true} + case FilterOperatorIsNotEqual: + ret.Date = &ValueDate{Content: util.CurrentTimeMillis(), IsNotEmpty: true} + case FilterOperatorIsGreater: + ret.Date = &ValueDate{Content: filter.Value.Date.Content + 1000*60, IsNotEmpty: true} + case FilterOperatorIsGreaterOrEqual: + ret.Date = &ValueDate{Content: filter.Value.Date.Content, IsNotEmpty: true} + case FilterOperatorIsLess: + ret.Date = &ValueDate{Content: filter.Value.Date.Content - 1000*60, IsNotEmpty: true} + case FilterOperatorIsLessOrEqual: + ret.Date = &ValueDate{Content: filter.Value.Date.Content, IsNotEmpty: true} + case FilterOperatorIsBetween: + ret.Date = &ValueDate{Content: filter.Value.Date.Content - 1000*60, IsNotEmpty: true} + case FilterOperatorIsEmpty: + ret.Date = &ValueDate{Content: 0, IsNotEmpty: false} + case FilterOperatorIsNotEmpty: + ret.Date = &ValueDate{Content: util.CurrentTimeMillis(), IsNotEmpty: true} + } + case KeyTypeMSelect: + switch filter.Operator { + case FilterOperatorIsEqual, FilterOperatorContains: + if 0 < len(filter.Value.MSelect) { + ret.MSelect = []*ValueSelect{{Content: filter.Value.MSelect[0].Content}} + } + case FilterOperatorIsNotEqual, FilterOperatorDoesNotContain: + if 0 < len(filter.Value.MSelect) { + ret.MSelect = []*ValueSelect{{Content: filter.Value.MSelect[0].Content + " Untitled"}} + } + case FilterOperatorIsEmpty: + ret.MSelect = []*ValueSelect{} + case FilterOperatorIsNotEmpty: + if 0 < len(key.Options) { + ret.MSelect = []*ValueSelect{{Content: key.Options[0].Name, Color: key.Options[0].Color}} + } + } + case KeyTypeURL: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.URL = &ValueURL{Content: filter.Value.URL.Content} + case FilterOperatorIsNotEqual: + ret.URL = &ValueURL{Content: filter.Value.URL.Content + " Untitled"} + case FilterOperatorContains: + ret.URL = &ValueURL{Content: filter.Value.URL.Content} + case FilterOperatorDoesNotContain: + ret.URL = &ValueURL{Content: filter.Value.URL.Content + " Untitled"} + case FilterOperatorStartsWith: + ret.URL = &ValueURL{Content: filter.Value.URL.Content} + case FilterOperatorEndsWith: + ret.URL = &ValueURL{Content: filter.Value.URL.Content} + case FilterOperatorIsEmpty: + ret.URL = &ValueURL{Content: ""} + case FilterOperatorIsNotEmpty: + ret.URL = &ValueURL{Content: "Untitled"} + } + case KeyTypeEmail: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.Email = &ValueEmail{Content: filter.Value.Email.Content} + case FilterOperatorIsNotEqual: + ret.Email = &ValueEmail{Content: filter.Value.Email.Content + " Untitled"} + case FilterOperatorContains: + ret.Email = &ValueEmail{Content: filter.Value.Email.Content} + case FilterOperatorDoesNotContain: + ret.Email = &ValueEmail{Content: filter.Value.Email.Content + " Untitled"} + case FilterOperatorStartsWith: + ret.Email = &ValueEmail{Content: filter.Value.Email.Content} + case FilterOperatorEndsWith: + ret.Email = &ValueEmail{Content: filter.Value.Email.Content} + case FilterOperatorIsEmpty: + ret.Email = &ValueEmail{Content: ""} + case FilterOperatorIsNotEmpty: + ret.Email = &ValueEmail{Content: "Untitled"} + } + case KeyTypePhone: + switch filter.Operator { + case FilterOperatorIsEqual: + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content} + case FilterOperatorIsNotEqual: + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content + " Untitled"} + case FilterOperatorContains: + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content} + case FilterOperatorDoesNotContain: + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content + " Untitled"} + case FilterOperatorStartsWith: + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content} + case FilterOperatorEndsWith: + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content} + case FilterOperatorIsEmpty: + ret.Phone = &ValuePhone{Content: ""} + case FilterOperatorIsNotEmpty: + ret.Phone = &ValuePhone{Content: "Untitled"} + } + case KeyTypeMAsset: + switch filter.Operator { + case FilterOperatorIsEqual, FilterOperatorContains: + if 0 < len(filter.Value.MAsset) { + ret.MAsset = []*ValueAsset{{Type: filter.Value.MAsset[0].Type, Name: filter.Value.MAsset[0].Name, Content: filter.Value.MAsset[0].Content}} + } + case FilterOperatorIsNotEqual, FilterOperatorDoesNotContain: + case FilterOperatorIsEmpty: + ret.MAsset = []*ValueAsset{} + case FilterOperatorIsNotEmpty: + } + case KeyTypeCheckbox: + switch filter.Operator { + case FilterOperatorIsTrue: + ret.Checkbox = &ValueCheckbox{Checked: true} + case FilterOperatorIsFalse: + ret.Checkbox = &ValueCheckbox{Checked: false} + } + case KeyTypeRelation: + switch filter.Operator { + case FilterOperatorContains: + if 0 < len(filter.Value.Relation.Contents) { + ret.Relation = &ValueRelation{Contents: filter.Value.Relation.Contents} + } + case FilterOperatorDoesNotContain: + case FilterOperatorIsEmpty: + ret.Relation = &ValueRelation{Contents: []string{}} + case FilterOperatorIsNotEmpty: + } + } + return +} diff --git a/kernel/av/table.go b/kernel/av/table.go index 830d4e740..57ea9a2a4 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -762,12 +762,6 @@ func (table *Table) FilterRows() { rows := []*TableRow{} for _, row := range table.Rows { - block := row.GetBlockValue() - if nil != block && block.NotAffectFilter() { - rows = append(rows, row) - continue - } - pass := true for j, index := range colIndexes { operator := table.Filters[j].Operator diff --git a/kernel/av/value.go b/kernel/av/value.go index 73015cbda..4c0c6bddd 100644 --- a/kernel/av/value.go +++ b/kernel/av/value.go @@ -30,12 +30,11 @@ import ( ) type Value struct { - ID string `json:"id,omitempty"` - KeyID string `json:"keyID,omitempty"` - BlockID string `json:"blockID,omitempty"` - Type KeyType `json:"type,omitempty"` - IsDetached bool `json:"isDetached,omitempty"` - IsInitialized bool `json:"isInitialized,omitempty"` + ID string `json:"id,omitempty"` + KeyID string `json:"keyID,omitempty"` + BlockID string `json:"blockID,omitempty"` + Type KeyType `json:"type,omitempty"` + IsDetached bool `json:"isDetached,omitempty"` Block *ValueBlock `json:"block,omitempty"` Text *ValueText `json:"text,omitempty"` @@ -54,10 +53,6 @@ type Value struct { Rollup *ValueRollup `json:"rollup,omitempty"` } -func (value *Value) NotAffectFilter() bool { - return !value.IsInitialized && nil != value.Block && "" == value.Block.Content && value.IsDetached -} - func (value *Value) String() string { switch value.Type { case KeyTypeBlock: diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 269064286..b8a23b5bb 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -901,10 +901,13 @@ func updateAttributeViewColRollup(operation *Operation) (err error) { KeyID: operation.KeyID, } - if "" != operation.Data { - if err = gulu.JSON.UnmarshalJSON([]byte(operation.Data.(string)), &rollUpKey.Rollup.Calc); nil != err { - return - } + data := operation.Data.(map[string]interface{}) + calcData, err := gulu.JSON.MarshalJSON(data["calc"]) + if nil != err { + return + } + if err = gulu.JSON.UnmarshalJSON(calcData, &rollUpKey.Rollup.Calc); nil != err { + return } err = av.SaveAttributeView(attrView) @@ -1489,7 +1492,7 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre content = getNodeRefText(node) } now := time.Now().UnixMilli() - blockValue := &av.Value{ID: ast.NewNodeID(), KeyID: blockValues.Key.ID, BlockID: blockID, Type: av.KeyTypeBlock, IsDetached: operation.IsDetached, IsInitialized: false, Block: &av.ValueBlock{ID: blockID, Content: content, Created: now, Updated: now}} + blockValue := &av.Value{ID: ast.NewNodeID(), KeyID: blockValues.Key.ID, BlockID: blockID, Type: av.KeyTypeBlock, IsDetached: operation.IsDetached, Block: &av.ValueBlock{ID: blockID, Content: content, Created: now, Updated: now}} blockValues.Values = append(blockValues.Values, blockValue) // 如果存在过滤条件,则将过滤条件应用到新添加的块上 @@ -1499,6 +1502,7 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre viewable.FilterRows() viewable.SortRows() + addedVal := false if 0 < len(viewable.Rows) { row := GetLastSortRow(viewable.Rows) if nil != row { @@ -1514,12 +1518,27 @@ func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tre newValue.ID = ast.NewNodeID() newValue.BlockID = blockID newValue.IsDetached = operation.IsDetached - newValue.IsInitialized = false values, _ := attrView.GetKeyValues(filter.Column) values.Values = append(values.Values, newValue) } } } + addedVal = true + } + } + + if !addedVal { + for _, filter := range view.Table.Filters { + for _, keyValues := range attrView.KeyValues { + if keyValues.Key.ID == filter.Column { + newValue := filter.GetAffectValue(keyValues.Key) + newValue.ID = ast.NewNodeID() + newValue.BlockID = blockID + newValue.IsDetached = operation.IsDetached + values, _ := attrView.GetKeyValues(filter.Column) + values.Values = append(values.Values, newValue) + } + } } } } @@ -1570,7 +1589,7 @@ func GetLastSortRow(rows []*av.TableRow) *av.TableRow { for i := len(rows) - 1; i >= 0; i-- { row := rows[i] block := row.GetBlockValue() - if nil != block && !block.NotAffectFilter() { + if nil != block { return row } } @@ -2295,7 +2314,6 @@ func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string, if nil != blockVal { blockVal.Block.Updated = time.Now().UnixMilli() - blockVal.IsInitialized = true if isUpdatingBlockKey { blockVal.IsDetached = val.IsDetached }