Sfoglia il codice sorgente

:art: Add database table view checkbox column type https://github.com/siyuan-note/siyuan/issues/9667

Daniel 1 anno fa
parent
commit
0359f96c64
5 ha cambiato i file con 90 aggiunte e 2 eliminazioni
  1. 14 0
      kernel/av/av.go
  2. 2 0
      kernel/av/filter.go
  3. 68 0
      kernel/av/table.go
  4. 2 2
      kernel/model/attribute_view.go
  5. 4 0
      kernel/treenode/node.go

+ 14 - 0
kernel/av/av.go

@@ -107,6 +107,7 @@ const (
 	KeyTypeTemplate KeyType = "template"
 	KeyTypeCreated  KeyType = "created"
 	KeyTypeUpdated  KeyType = "updated"
+	KeyTypeCheckbox KeyType = "checkbox"
 )
 
 // Key 描述了属性视图属性列的基础结构。
@@ -157,6 +158,7 @@ type Value struct {
 	Template *ValueTemplate `json:"template,omitempty"`
 	Created  *ValueCreated  `json:"created,omitempty"`
 	Updated  *ValueUpdated  `json:"updated,omitempty"`
+	Checkbox *ValueCheckbox `json:"checkbox,omitempty"`
 }
 
 func (value *Value) String() string {
@@ -234,6 +236,14 @@ func (value *Value) String() string {
 			return ""
 		}
 		return value.Updated.FormattedContent
+	case KeyTypeCheckbox:
+		if nil == value.Checkbox {
+			return ""
+		}
+		if value.Checkbox.Checked {
+			return "√"
+		}
+		return ""
 	default:
 		return ""
 	}
@@ -529,6 +539,10 @@ func NewFormattedValueUpdated(content, content2 int64, format UpdatedFormat) (re
 	return
 }
 
+type ValueCheckbox struct {
+	Checked bool `json:"checked"`
+}
+
 // View 描述了视图的结构。
 type View struct {
 	ID   string `json:"id"`   // 视图 ID

+ 2 - 0
kernel/av/filter.go

@@ -43,4 +43,6 @@ const (
 	FilterOperatorEndsWith          FilterOperator = "Ends with"
 	FilterOperatorIsBetween         FilterOperator = "Is between"
 	FilterOperatorIsRelativeToToday FilterOperator = "Is relative to today"
+	FilterOperatorIsTrue            FilterOperator = "Is true"
+	FilterOperatorIsFalse           FilterOperator = "Is false"
 )

+ 68 - 0
kernel/av/table.go

@@ -72,6 +72,10 @@ const (
 	CalcOperatorRange             CalcOperator = "Range"
 	CalcOperatorEarliest          CalcOperator = "Earliest"
 	CalcOperatorLatest            CalcOperator = "Latest"
+	CalcOperatorChecked           CalcOperator = "Checked"
+	CalcOperatorUnchecked         CalcOperator = "Unchecked"
+	CalcOperatorPercentChecked    CalcOperator = "Percent checked"
+	CalcOperatorPercentUnchecked  CalcOperator = "Percent unchecked"
 )
 
 func (value *Value) Compare(other *Value) int {
@@ -171,6 +175,16 @@ func (value *Value) Compare(other *Value) int {
 		if nil != value.Template && nil != other.Template {
 			return strings.Compare(value.Template.Content, other.Template.Content)
 		}
+	case KeyTypeCheckbox:
+		if nil != value.Checkbox && nil != other.Checkbox {
+			if value.Checkbox.Checked && !other.Checkbox.Checked {
+				return 1
+			}
+			if !value.Checkbox.Checked && other.Checkbox.Checked {
+				return -1
+			}
+			return 0
+		}
 	}
 	return 0
 }
@@ -543,6 +557,15 @@ func (value *Value) CompareOperator(other *Value, operator FilterOperator) bool
 			return "" != strings.TrimSpace(value.Template.Content)
 		}
 	}
+
+	if nil != value.Checkbox {
+		switch operator {
+		case FilterOperatorIsTrue:
+			return value.Checkbox.Checked
+		case FilterOperatorIsFalse:
+			return !value.Checkbox.Checked
+		}
+	}
 	return true
 }
 
@@ -731,6 +754,8 @@ func (table *Table) CalcCols() {
 			table.calcColCreated(col, i)
 		case KeyTypeUpdated:
 			table.calcColUpdated(col, i)
+		case KeyTypeCheckbox:
+			table.calcColCheckbox(col, i)
 		}
 	}
 }
@@ -1840,3 +1865,46 @@ func (table *Table) calcColUpdated(col *TableColumn, colIndex int) {
 		}
 	}
 }
+
+func (table *Table) calcColCheckbox(col *TableColumn, colIndex int) {
+	switch col.Calc.Operator {
+	case CalcOperatorCountAll:
+		col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)}
+	case CalcOperatorChecked:
+		countChecked := 0
+		for _, row := range table.Rows {
+			if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Checkbox && row.Cells[colIndex].Value.Checkbox.Checked {
+				countChecked++
+			}
+		}
+		col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countChecked), NumberFormatNone)}
+	case CalcOperatorUnchecked:
+		countUnchecked := 0
+		for _, row := range table.Rows {
+			if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Checkbox && !row.Cells[colIndex].Value.Checkbox.Checked {
+				countUnchecked++
+			}
+		}
+		col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUnchecked), NumberFormatNone)}
+	case CalcOperatorPercentChecked:
+		countChecked := 0
+		for _, row := range table.Rows {
+			if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Checkbox && row.Cells[colIndex].Value.Checkbox.Checked {
+				countChecked++
+			}
+		}
+		if 0 < len(table.Rows) {
+			col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countChecked)/float64(len(table.Rows)), NumberFormatPercent)}
+		}
+	case CalcOperatorPercentUnchecked:
+		countUnchecked := 0
+		for _, row := range table.Rows {
+			if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Checkbox && !row.Cells[colIndex].Value.Checkbox.Checked {
+				countUnchecked++
+			}
+		}
+		if 0 < len(table.Rows) {
+			col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUnchecked)/float64(len(table.Rows)), NumberFormatPercent)}
+		}
+	}
+}

+ 2 - 2
kernel/model/attribute_view.go

@@ -1126,7 +1126,7 @@ func addAttributeViewColumn(operation *Operation) (err error) {
 
 	keyType := av.KeyType(operation.Typ)
 	switch keyType {
-	case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated:
+	case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox:
 		var icon string
 		if nil != operation.Data {
 			icon = operation.Data.(string)
@@ -1218,7 +1218,7 @@ func updateAttributeViewColumn(operation *Operation) (err error) {
 
 	colType := av.KeyType(operation.Typ)
 	switch colType {
-	case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated:
+	case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox:
 		for _, keyValues := range attrView.KeyValues {
 			if keyValues.Key.ID == operation.ID {
 				keyValues.Key.Name = operation.Name

+ 4 - 0
kernel/treenode/node.go

@@ -779,6 +779,10 @@ func FillAttributeViewTableCellNilValue(tableCell *av.TableCell, rowID, colID st
 		if nil == tableCell.Value.Updated {
 			tableCell.Value.Updated = &av.ValueUpdated{}
 		}
+	case av.KeyTypeCheckbox:
+		if nil == tableCell.Value.Checkbox {
+			tableCell.Value.Checkbox = &av.ValueCheckbox{}
+		}
 	}
 }