From b134313b1658e8480e843b03fe6d7be997114b82 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Wed, 6 Mar 2024 11:20:20 +0800 Subject: [PATCH] :art: Improve adding row prompt when database filter exists https://github.com/siyuan-note/siyuan/issues/10517 Improve adding row prompt when database sort exists https://github.com/siyuan-note/siyuan/issues/10525 --- kernel/av/filter.go | 79 +++++++++++++++++----------------- kernel/av/table.go | 10 +++++ kernel/av/value.go | 76 +++++++++++++++++++++++++++++++- kernel/model/attribute_view.go | 57 ++++++++++++++++++------ 4 files changed, 169 insertions(+), 53 deletions(-) diff --git a/kernel/av/filter.go b/kernel/av/filter.go index a999fab54..7848290c1 100644 --- a/kernel/av/filter.go +++ b/kernel/av/filter.go @@ -17,8 +17,6 @@ package av import ( - "strings" - "github.com/siyuan-note/siyuan/kernel/util" ) @@ -77,7 +75,7 @@ const ( FilterOperatorIsFalse FilterOperator = "Is false" ) -func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { +func (filter *ViewFilter) GetAffectValue(key *Key, defaultVal *Value) (ret *Value) { if nil != filter.Value { if filter.Value.IsGenerated() { // 自动生成类型的过滤条件不设置默认值 @@ -99,17 +97,29 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { } ret = filter.Value.Clone() + + if nil != defaultVal { + // 如果有默认值则优先使用默认值 + clonedDefaultVal := defaultVal.Clone() + defaultRawVal := clonedDefaultVal.GetValByType(filter.Value.Type) + if nil != defaultRawVal { + ret.SetValByType(filter.Value.Type, defaultRawVal) + return + } + } + // 没有默认值则使用过滤条件的值 + 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")} + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: ""} 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.ReplaceAll("Untitled", filter.Value.Block.Content, "")} + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: ""} case FilterOperatorStartsWith: ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: filter.Value.Block.Content} case FilterOperatorEndsWith: @@ -117,18 +127,18 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { case FilterOperatorIsEmpty: ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: ""} case FilterOperatorIsNotEmpty: - ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: "Untitled"} + ret.Block = &ValueBlock{ID: filter.Value.Block.ID, Content: ""} } 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")} + ret.Text = &ValueText{Content: ""} case FilterOperatorContains: ret.Text = &ValueText{Content: filter.Value.Text.Content} case FilterOperatorDoesNotContain: - ret.Text = &ValueText{Content: strings.ReplaceAll("Untitled", filter.Value.Text.Content, "")} + ret.Text = &ValueText{Content: ""} case FilterOperatorStartsWith: ret.Text = &ValueText{Content: filter.Value.Text.Content} case FilterOperatorEndsWith: @@ -136,7 +146,7 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { case FilterOperatorIsEmpty: ret.Text = &ValueText{Content: ""} case FilterOperatorIsNotEmpty: - ret.Text = &ValueText{Content: "Untitled"} + ret.Text = &ValueText{Content: ""} } case KeyTypeNumber: switch filter.Operator { @@ -182,32 +192,21 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { case FilterOperatorIsNotEmpty: ret.Date = &ValueDate{Content: util.CurrentTimeMillis(), IsNotEmpty: true} } - case KeyTypeSelect: + case KeyTypeSelect, KeyTypeMSelect: switch filter.Operator { case FilterOperatorIsEqual: - if 0 < len(filter.Value.MSelect) { - ret.MSelect = []*ValueSelect{{Content: filter.Value.MSelect[0].Content, Color: filter.Value.MSelect[0].Color}} + valueSelect := &ValueSelect{Content: "", Color: "1"} + if 0 < len(key.Options) { + valueSelect.Color = key.Options[0].Color } + if 0 < len(filter.Value.MSelect) { + valueSelect.Content = filter.Value.MSelect[0].Content + valueSelect.Color = filter.Value.MSelect[0].Color + } + ret.MSelect = []*ValueSelect{valueSelect} case FilterOperatorIsNotEqual: if 0 < len(filter.Value.MSelect) { - ret.MSelect = []*ValueSelect{{Content: filter.Value.MSelect[0].Content + " Untitled", Color: "1"}} - } - 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 KeyTypeMSelect: - switch filter.Operator { - case FilterOperatorIsEqual, FilterOperatorContains: - if 0 < len(filter.Value.MSelect) { - ret.MSelect = []*ValueSelect{{Content: filter.Value.MSelect[0].Content, Color: filter.Value.MSelect[0].Color}} - } - case FilterOperatorIsNotEqual, FilterOperatorDoesNotContain: - if 0 < len(filter.Value.MSelect) { - ret.MSelect = []*ValueSelect{{Content: filter.Value.MSelect[0].Content + " Untitled", Color: "1"}} + ret.MSelect = []*ValueSelect{} } case FilterOperatorIsEmpty: ret.MSelect = []*ValueSelect{} @@ -221,30 +220,30 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { case FilterOperatorIsEqual: ret.URL = &ValueURL{Content: filter.Value.URL.Content} case FilterOperatorIsNotEqual: - ret.URL = &ValueURL{Content: filter.Value.URL.Content + " Untitled"} + ret.URL = &ValueURL{Content: filter.Value.URL.Content} case FilterOperatorContains: ret.URL = &ValueURL{Content: filter.Value.URL.Content} case FilterOperatorDoesNotContain: - ret.URL = &ValueURL{Content: strings.ReplaceAll("Untitled", filter.Value.URL.Content, "")} + ret.URL = &ValueURL{Content: ""} 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: ""} + ret.URL = &ValueURL{} case FilterOperatorIsNotEmpty: - ret.URL = &ValueURL{Content: "Untitled"} + ret.URL = &ValueURL{} } 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"} + ret.Email = &ValueEmail{Content: filter.Value.Email.Content} case FilterOperatorContains: ret.Email = &ValueEmail{Content: filter.Value.Email.Content} case FilterOperatorDoesNotContain: - ret.Email = &ValueEmail{Content: strings.ReplaceAll("Untitled", filter.Value.Email.Content, "")} + ret.Email = &ValueEmail{Content: ""} case FilterOperatorStartsWith: ret.Email = &ValueEmail{Content: filter.Value.Email.Content} case FilterOperatorEndsWith: @@ -252,18 +251,18 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { case FilterOperatorIsEmpty: ret.Email = &ValueEmail{Content: ""} case FilterOperatorIsNotEmpty: - ret.Email = &ValueEmail{Content: "Untitled"} + ret.Email = &ValueEmail{Content: ""} } 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"} + ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content + ""} case FilterOperatorContains: ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content} case FilterOperatorDoesNotContain: - ret.Phone = &ValuePhone{Content: strings.ReplaceAll("Untitled", filter.Value.Phone.Content, "")} + ret.Phone = &ValuePhone{Content: ""} case FilterOperatorStartsWith: ret.Phone = &ValuePhone{Content: filter.Value.Phone.Content} case FilterOperatorEndsWith: @@ -271,7 +270,7 @@ func (filter *ViewFilter) GetAffectValue(key *Key) (ret *Value) { case FilterOperatorIsEmpty: ret.Phone = &ValuePhone{Content: ""} case FilterOperatorIsNotEmpty: - ret.Phone = &ValuePhone{Content: "Untitled"} + ret.Phone = &ValuePhone{Content: ""} } case KeyTypeMAsset: switch filter.Operator { diff --git a/kernel/av/table.go b/kernel/av/table.go index 63ede4391..7e2f126d3 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -921,6 +921,16 @@ func (row *TableRow) GetBlockValue() (ret *Value) { return } +func (row *TableRow) GetValue(keyID string) (ret *Value) { + for _, cell := range row.Cells { + if nil != cell.Value && keyID == cell.Value.KeyID { + ret = cell.Value + break + } + } + return +} + func (table *Table) GetType() LayoutType { return LayoutTypeTable } diff --git a/kernel/av/value.go b/kernel/av/value.go index 57aaa8e67..120fe1453 100644 --- a/kernel/av/value.go +++ b/kernel/av/value.go @@ -276,10 +276,84 @@ func (value *Value) IsEmpty() bool { case KeyTypeRollup: return 1 > len(value.Rollup.Contents) } - return false } +func (value *Value) SetValByType(typ KeyType, val interface{}) { + switch typ { + case KeyTypeBlock: + value.Block = val.(*ValueBlock) + case KeyTypeText: + value.Text = val.(*ValueText) + case KeyTypeNumber: + value.Number = val.(*ValueNumber) + case KeyTypeDate: + value.Date = val.(*ValueDate) + case KeyTypeSelect: + value.MSelect = val.([]*ValueSelect) + case KeyTypeMSelect: + value.MSelect = val.([]*ValueSelect) + case KeyTypeURL: + value.URL = val.(*ValueURL) + case KeyTypeEmail: + value.Email = val.(*ValueEmail) + case KeyTypePhone: + value.Phone = val.(*ValuePhone) + case KeyTypeMAsset: + value.MAsset = val.([]*ValueAsset) + case KeyTypeTemplate: + value.Template = val.(*ValueTemplate) + case KeyTypeCreated: + value.Created = val.(*ValueCreated) + case KeyTypeUpdated: + value.Updated = val.(*ValueUpdated) + case KeyTypeCheckbox: + value.Checkbox = val.(*ValueCheckbox) + case KeyTypeRelation: + value.Relation = val.(*ValueRelation) + case KeyTypeRollup: + value.Rollup = val.(*ValueRollup) + } +} + +func (value *Value) GetValByType(typ KeyType) (ret interface{}) { + switch typ { + case KeyTypeBlock: + return value.Block + case KeyTypeText: + return value.Text + case KeyTypeNumber: + return value.Number + case KeyTypeDate: + return value.Date + case KeyTypeSelect: + return value.MSelect + case KeyTypeMSelect: + return value.MSelect + case KeyTypeURL: + return value.URL + case KeyTypeEmail: + return value.Email + case KeyTypePhone: + return value.Phone + case KeyTypeMAsset: + return value.MAsset + case KeyTypeTemplate: + return value.Template + case KeyTypeCreated: + return value.Created + case KeyTypeUpdated: + return value.Updated + case KeyTypeCheckbox: + return value.Checkbox + case KeyTypeRelation: + return value.Relation + case KeyTypeRollup: + return value.Rollup + } + return +} + type ValueBlock struct { ID string `json:"id"` Content string `json:"content"` diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 83ffa4142..d0406514c 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -1854,22 +1854,55 @@ func addAttributeViewBlock(avID, blockID, previousBlockID, addingBlockID string, viewable, _ := renderAttributeViewTable(attrView, view) viewable.FilterRows(attrView) - for _, filter := range view.Table.Filters { - for _, keyValues := range attrView.KeyValues { - if keyValues.Key.ID == filter.Column { - newValue := filter.GetAffectValue(keyValues.Key) - if nil == newValue { - continue - } - newValue.ID = ast.NewNodeID() - newValue.KeyID = keyValues.Key.ID - newValue.BlockID = addingBlockID - newValue.IsDetached = isDetached - keyValues.Values = append(keyValues.Values, newValue) + sameKeyFilterSort := false // 是否在同一个字段上同时存在过滤和排序 + var lastRow *av.TableRow + if 0 < len(viewable.Sorts) { + viewable.SortRows() + if 0 < len(viewable.Rows) { + lastRow = viewable.Rows[len(viewable.Rows)-1] + } + + filterKeys, sortKeys := map[string]bool{}, map[string]bool{} + for _, filter := range view.Table.Filters { + filterKeys[filter.Column] = true + } + for _, sort := range view.Table.Sorts { + sortKeys[sort.Column] = true + } + + for key := range filterKeys { + if sortKeys[key] { + sameKeyFilterSort = true break } } } + + if !sameKeyFilterSort { + // 如果在同一个字段上仅存在过滤条件,则将过滤条件应用到新添加的块上 + for _, filter := range view.Table.Filters { + for _, keyValues := range attrView.KeyValues { + if keyValues.Key.ID == filter.Column { + var defaultVal *av.Value + if nil != lastRow { + defaultVal = lastRow.GetValue(filter.Column) + } + + newValue := filter.GetAffectValue(keyValues.Key, defaultVal) + if nil == newValue { + continue + } + + newValue.ID = ast.NewNodeID() + newValue.KeyID = keyValues.Key.ID + newValue.BlockID = addingBlockID + newValue.IsDetached = isDetached + keyValues.Values = append(keyValues.Values, newValue) + break + } + } + } + } } if !isDetached {