siyuan/kernel/av/attribute_view.go

193 lines
4.9 KiB
Go
Raw Normal View History

// SiYuan - Refactor your thinking
// Copyright (c) 2020-present, b3log.org
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// Package av 包含了属性视图Attribute View相关的实现。
package av
import (
2023-07-11 22:11:15 +08:00
"errors"
"os"
"path/filepath"
"github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/util"
)
// AttributeView 描述了属性视图的结构。
type AttributeView struct {
2023-07-11 19:45:27 +08:00
Spec int `json:"spec"` // 格式版本
ID string `json:"id"` // 属性视图 ID
2023-06-10 16:52:54 +08:00
Name string `json:"name"` // 属性视图名称
2023-07-11 19:45:27 +08:00
Columns []*Column `json:"columns"` // 列
Rows []*Row `json:"rows"` // 行
2023-07-11 19:45:27 +08:00
CurrentViewID string `json:"currentViewId"` // 当前视图 ID
Views []*View `json:"views"` // 视图
}
2023-07-11 19:45:27 +08:00
// View 描述了视图的结构。
type View struct {
ID string `json:"id"` // 视图 ID
Name string `json:"name"` // 视图名称
Type ViewType `json:"type"` // 视图类型
Filters []*ViewFilter `json:"filters"` // 过滤规则
Sorts []*ViewSort `json:"sorts"` // 排序规则
}
// ViewType 描述了视图的类型。
type ViewType string
const (
2023-07-11 19:45:27 +08:00
ViewTypeTable ViewType = "table" // 属性视图类型 - 表格
ViewTypeKanban ViewType = "kanban" // 属性视图类型 - 看板
)
2023-07-11 19:45:27 +08:00
// Viewable 描述了视图的接口。
type Viewable interface {
Filterable
Sortable
Calculable
GetType() ViewType
GetID() string
2023-07-11 19:45:27 +08:00
}
func NewAttributeView(id string) *AttributeView {
2023-07-11 19:45:27 +08:00
view := &View{
ID: ast.NewNodeID(),
2023-07-03 15:39:13 +08:00
Name: "Table",
2023-07-11 19:45:27 +08:00
Type: ViewTypeTable,
Filters: []*ViewFilter{},
Sorts: []*ViewSort{},
}
2023-07-11 19:45:27 +08:00
return &AttributeView{
Spec: 0,
ID: id,
Columns: []*Column{{ID: ast.NewNodeID(), Name: "Block", Type: ColumnTypeBlock}},
Rows: []*Row{},
CurrentViewID: view.ID,
Views: []*View{view},
}
}
func ParseAttributeView(avID string) (ret *AttributeView, err error) {
avJSONPath := getAttributeViewDataPath(avID)
if !gulu.File.IsExist(avJSONPath) {
ret = NewAttributeView(avID)
return
}
data, err := filelock.ReadFile(avJSONPath)
if nil != err {
logging.LogErrorf("read attribute view [%s] failed: %s", avID, err)
return
}
ret = &AttributeView{}
if err = gulu.JSON.UnmarshalJSON(data, ret); nil != err {
logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
return
}
2023-07-11 19:45:27 +08:00
if 1 > len(ret.Views) {
view := &View{
ID: ast.NewNodeID(),
Name: "Table",
Type: ViewTypeTable,
Filters: []*ViewFilter{},
Sorts: []*ViewSort{},
}
ret.CurrentViewID = view.ID
ret.Views = []*View{view}
}
return
}
2023-07-03 19:39:00 +08:00
func ParseAttributeViewMap(avID string) (ret map[string]interface{}, err error) {
ret = map[string]interface{}{}
avJSONPath := getAttributeViewDataPath(avID)
if !gulu.File.IsExist(avJSONPath) {
av := NewAttributeView(avID)
var data []byte
data, err = gulu.JSON.MarshalJSON(av)
if nil == err {
return
}
err = gulu.JSON.UnmarshalJSON(data, &ret)
return
}
data, err := filelock.ReadFile(avJSONPath)
if nil != err {
logging.LogErrorf("read attribute view [%s] failed: %s", avID, err)
return
}
if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
return
}
return
}
func SaveAttributeView(av *AttributeView) (err error) {
data, err := gulu.JSON.MarshalIndentJSON(av, "", "\t")
if nil != err {
logging.LogErrorf("marshal attribute view [%s] failed: %s", av.ID, err)
return
}
avJSONPath := getAttributeViewDataPath(av.ID)
if err = filelock.WriteFile(avJSONPath, data); nil != err {
logging.LogErrorf("save attribute view [%s] failed: %s", av.ID, err)
return
}
return
}
2023-07-11 22:11:15 +08:00
func (av *AttributeView) GetView(viewID string) (ret *View) {
for _, v := range av.Views {
if v.ID == viewID {
ret = v
return
}
}
return
}
func getAttributeViewDataPath(avID string) (ret string) {
av := filepath.Join(util.DataDir, "storage", "av")
ret = filepath.Join(av, avID+".json")
if !gulu.File.IsDir(av) {
if err := os.MkdirAll(av, 0755); nil != err {
logging.LogErrorf("create attribute view dir failed: %s", err)
return
}
}
return
}
2023-07-11 22:11:15 +08:00
var (
ErrViewNotFound = errors.New("view not found")
)