From 3381f1f7d4cd2beafe7b050d482e7a9c03013bd4 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 15 Jul 2023 23:46:52 +0800 Subject: [PATCH 1/5] :art: Update av --- kernel/model/attribute_view.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index e5c295c73..d333d949e 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -104,6 +104,16 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *a } } + notFound := []string{} + for blockID, _ := range rows { + if treenode.GetBlockTree(blockID) == nil { + notFound = append(notFound, blockID) + } + } + for _, blockID := range notFound { + delete(rows, blockID) + } + for rowID, row := range rows { var tableRow av.TableRow for _, col := range ret.Columns { From 073a8bcdd7fc3c006431846aa820df42b4d8ae1d Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 16 Jul 2023 00:08:01 +0800 Subject: [PATCH 2/5] :art: Update av --- kernel/av/table.go | 114 ++++++++++++++++++++---------------- kernel/model/transaction.go | 35 +++++++++++ 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/kernel/av/table.go b/kernel/av/table.go index 0fe02408e..7217f9c41 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -379,7 +379,7 @@ func (table *Table) CalcCols() { 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))}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -387,7 +387,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countValues += len(row.Cells[colIndex].Value.MSelect) } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -401,7 +401,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -409,7 +409,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -417,7 +417,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -425,7 +425,9 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -433,14 +435,16 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } } } 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))}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -448,7 +452,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -458,7 +462,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countUniqueValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -466,7 +470,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -474,7 +478,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -482,7 +486,9 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: false}} + } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -490,14 +496,16 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } } } 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))}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -505,7 +513,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[int64]bool{} @@ -517,7 +525,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -525,7 +533,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -533,7 +541,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -541,7 +549,9 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -549,7 +559,9 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } case CalcOperatorEarliest: earliest := int64(0) for _, row := range table.Rows { @@ -596,7 +608,7 @@ func (table *Table) calcColDate(col *TableColumn, 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))}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -604,7 +616,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[float64]bool{} @@ -616,7 +628,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -624,7 +636,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -632,7 +644,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -640,7 +652,9 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -648,7 +662,9 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } case CalcOperatorSum: sum := 0.0 for _, row := range table.Rows { @@ -656,7 +672,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { sum += row.Cells[colIndex].Value.Number.Content } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: sum}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: sum, IsNotEmpty: true}} case CalcOperatorAverage: sum := 0.0 count := 0 @@ -667,9 +683,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if 0 != count { - col.Calc.Result = &Value{Number: &ValueNumber{Content: sum / float64(count)}} - } else { - col.Calc.Result = &Value{Number: &ValueNumber{Content: 0}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: sum / float64(count), IsNotEmpty: true}} } case CalcOperatorMedian: values := []float64{} @@ -681,12 +695,10 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { sort.Float64s(values) if len(values) > 0 { if len(values)%2 == 0 { - col.Calc.Result = &Value{Number: &ValueNumber{Content: (values[len(values)/2-1] + values[len(values)/2]) / 2}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: (values[len(values)/2-1] + values[len(values)/2]) / 2, IsNotEmpty: true}} } else { - col.Calc.Result = &Value{Number: &ValueNumber{Content: values[len(values)/2]}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: values[len(values)/2], IsNotEmpty: true}} } - } else { - col.Calc.Result = &Value{Number: &ValueNumber{IsNotEmpty: false}} } case CalcOperatorMin: min := math.MaxFloat64 @@ -698,9 +710,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if math.MaxFloat64 != min { - col.Calc.Result = &Value{Number: &ValueNumber{Content: min}} - } else { - col.Calc.Result = &Value{Number: &ValueNumber{IsNotEmpty: false}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: min, IsNotEmpty: true}} } case CalcOperatorMax: max := -math.MaxFloat64 @@ -712,9 +722,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if -math.MaxFloat64 != max { - col.Calc.Result = &Value{Number: &ValueNumber{Content: max}} - } else { - col.Calc.Result = &Value{Number: &ValueNumber{IsNotEmpty: false}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: max, IsNotEmpty: true}} } case CalcOperatorRange: min := math.MaxFloat64 @@ -730,9 +738,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if math.MaxFloat64 != min && -math.MaxFloat64 != max { - col.Calc.Result = &Value{Number: &ValueNumber{Content: max - min}} - } else { - col.Calc.Result = &Value{Number: &ValueNumber{IsNotEmpty: false}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: max - min, IsNotEmpty: true}} } } } @@ -740,7 +746,7 @@ func (table *Table) calcColNumber(col *TableColumn, 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))}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -748,7 +754,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -760,7 +766,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -768,7 +774,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -776,7 +782,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty)}} + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -784,7 +790,9 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -792,6 +800,8 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows))}} + if 0 < len(table.Rows) { + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + } } } diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index bca88c1ee..9512e20fa 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -722,9 +722,44 @@ func (tx *Transaction) doDelete(operation *Operation) (ret *TxErr) { if err = tx.writeTree(tree); nil != err { return } + + syncDelete2AttributeView(node) return } +func syncDelete2AttributeView(node *ast.Node) { + avs := node.IALAttr(NodeAttrNameAVs) + if "" == avs { + return + } + + avIDs := strings.Split(avs, ",") + for _, avID := range avIDs { + attrView, parseErr := av.ParseAttributeView(avID) + if nil != parseErr { + continue + } + + changedAv := false + blockValues := attrView.GetBlockKeyValues() + if nil == blockValues { + continue + } + + for i, blockValue := range blockValues.Values { + if blockValue.Block.ID == node.ID { + blockValues.Values = append(blockValues.Values[:i], blockValues.Values[i+1:]...) + changedAv = true + break + } + } + if changedAv { + av.SaveAttributeView(attrView) + util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": avID}) + } + } +} + func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) { var err error opParentID := operation.ParentID From 9354ba8bd64d0d8ac5a2f230cbcd73e0369d3cfd Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 16 Jul 2023 00:22:14 +0800 Subject: [PATCH 3/5] :art: Attribute View columns calculate https://github.com/siyuan-note/siyuan/issues/8699 --- kernel/av/table.go | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/kernel/av/table.go b/kernel/av/table.go index 7217f9c41..4df2fd091 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -426,7 +426,8 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -436,7 +437,8 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } } } @@ -487,7 +489,8 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: false}} + content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: false}} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -497,7 +500,8 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } } } @@ -550,7 +554,8 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -560,7 +565,8 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } case CalcOperatorEarliest: earliest := int64(0) @@ -653,7 +659,8 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -663,7 +670,8 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } case CalcOperatorSum: sum := 0.0 @@ -791,7 +799,8 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -801,7 +810,23 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty) / float64(len(table.Rows)), IsNotEmpty: true}} + content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} } } } + +// RoundUp rounds like 12.3416 -> 12.35 +func RoundUp(val float64, precision int) float64 { + return math.Ceil(val*(math.Pow10(precision))) / math.Pow10(precision) +} + +// RoundDown rounds like 12.3496 -> 12.34 +func RoundDown(val float64, precision int) float64 { + return math.Floor(val*(math.Pow10(precision))) / math.Pow10(precision) +} + +// Round rounds to nearest like 12.3456 -> 12.35 +func Round(val float64, precision int) float64 { + return math.Round(val*(math.Pow10(precision))) / math.Pow10(precision) +} From b785291aac6399b3c4db55378181ffc568d95779 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 16 Jul 2023 00:25:03 +0800 Subject: [PATCH 4/5] :art: Attribute View columns calculate https://github.com/siyuan-note/siyuan/issues/8699 --- kernel/av/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/av/table.go b/kernel/av/table.go index 4df2fd091..06887d3ed 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -362,7 +362,7 @@ func (table *Table) CalcCols() { } switch col.Type { - case KeyTypeText: + case KeyTypeText, KeyTypeBlock: table.calcColText(col, i) case KeyTypeNumber: table.calcColNumber(col, i) From d27e0f50ad52f6457f276449777daab2cb5468d5 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 16 Jul 2023 00:28:17 +0800 Subject: [PATCH 5/5] :art: Attribute View columns calculate https://github.com/siyuan-note/siyuan/issues/8699 --- kernel/av/table.go | 69 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/kernel/av/table.go b/kernel/av/table.go index 06887d3ed..4290add29 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -362,7 +362,9 @@ func (table *Table) CalcCols() { } switch col.Type { - case KeyTypeText, KeyTypeBlock: + case KeyTypeBlock: + table.calcColBlock(col, i) + case KeyTypeText: table.calcColText(col, i) case KeyTypeNumber: table.calcColNumber(col, i) @@ -816,6 +818,71 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } +func (table *Table) calcColBlock(col *TableColumn, colIndex int) { + switch col.Calc.Operator { + case CalcOperatorCountAll: + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + case CalcOperatorCountValues: + countValues := 0 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Block && "" != row.Cells[colIndex].Value.Block.Content { + countValues++ + } + } + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + case CalcOperatorCountUniqueValues: + countUniqueValues := 0 + uniqueValues := map[string]bool{} + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Block && "" != row.Cells[colIndex].Value.Block.Content { + if !uniqueValues[row.Cells[colIndex].Value.Block.Content] { + uniqueValues[row.Cells[colIndex].Value.Block.Content] = true + countUniqueValues++ + } + } + } + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + case CalcOperatorCountEmpty: + countEmpty := 0 + for _, row := range table.Rows { + if nil == row.Cells[colIndex] || nil == row.Cells[colIndex].Value || nil == row.Cells[colIndex].Value.Block || "" == row.Cells[colIndex].Value.Block.Content { + countEmpty++ + } + } + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + case CalcOperatorCountNotEmpty: + countNotEmpty := 0 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Block && "" != row.Cells[colIndex].Value.Block.Content { + countNotEmpty++ + } + } + col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + case CalcOperatorPercentEmpty: + countEmpty := 0 + for _, row := range table.Rows { + if nil == row.Cells[colIndex] || nil == row.Cells[colIndex].Value || nil == row.Cells[colIndex].Value.Block || "" == row.Cells[colIndex].Value.Block.Content { + countEmpty++ + } + } + if 0 < len(table.Rows) { + content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + } + case CalcOperatorPercentNotEmpty: + countNotEmpty := 0 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Block && "" != row.Cells[colIndex].Value.Block.Content { + countNotEmpty++ + } + } + if 0 < len(table.Rows) { + content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) + col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + } + } +} + // RoundUp rounds like 12.3416 -> 12.35 func RoundUp(val float64, precision int) float64 { return math.Ceil(val*(math.Pow10(precision))) / math.Pow10(precision)