mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-30 13:28:48 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
8752ee69e5
8 changed files with 130 additions and 11 deletions
29
API.md
29
API.md
|
|
@ -38,6 +38,7 @@
|
|||
* [File](#File)
|
||||
* [Get file](#Get-file)
|
||||
* [Put file](#Put-file)
|
||||
* [Remove file](#Remove-file)
|
||||
* [Export](#Export)
|
||||
* [Export Markdown](#Export-Markdown)
|
||||
* [Notification](#Notification)
|
||||
|
|
@ -439,7 +440,7 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||
}
|
||||
```
|
||||
|
||||
* `id`:Block ID
|
||||
* `id`: Block ID
|
||||
* Return value
|
||||
|
||||
```json
|
||||
|
|
@ -854,7 +855,7 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||
* `isDir`: whether to create a folder, when `true` only create a folder, ignore `file`
|
||||
* `modTime`: last access and modification time, Unix time
|
||||
* `file`: the uploaded file
|
||||
* return value
|
||||
* Return value
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -864,6 +865,28 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||
}
|
||||
```
|
||||
|
||||
### Remove file
|
||||
|
||||
* `/api/file/removeFile`
|
||||
* Parameters
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "/data/20210808180117-6v0mkxr/20200923234011-ieuun1p.sy"
|
||||
}
|
||||
```
|
||||
* `path`: the file path under the workspace path
|
||||
* Return value
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Export
|
||||
|
||||
### Export Markdown
|
||||
|
|
@ -946,7 +969,7 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||
}
|
||||
}
|
||||
```
|
||||
* `id`:Message ID
|
||||
* `id`: Message ID
|
||||
|
||||
## System
|
||||
|
||||
|
|
|
|||
22
API_zh_CN.md
22
API_zh_CN.md
|
|
@ -38,6 +38,7 @@
|
|||
* [文件](#文件)
|
||||
* [获取文件](#获取文件)
|
||||
* [写入文件](#写入文件)
|
||||
* [删除文件](#删除文件)
|
||||
* [导出](#导出)
|
||||
* [导出 Markdown 文本](#导出-markdown-文本)
|
||||
* [通知](#通知)
|
||||
|
|
@ -858,6 +859,27 @@
|
|||
}
|
||||
```
|
||||
|
||||
### 删除文件
|
||||
|
||||
* `/api/file/removeFile`
|
||||
* 参数
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "/data/20210808180117-6v0mkxr/20200923234011-ieuun1p.sy"
|
||||
}
|
||||
```
|
||||
* `path`:工作空间路径下的文件路径
|
||||
* 返回值
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
## 导出
|
||||
|
||||
### 导出 Markdown 文本
|
||||
|
|
|
|||
|
|
@ -110,6 +110,33 @@ func getFile(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func removeFile(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
c.JSON(http.StatusOK, ret)
|
||||
return
|
||||
}
|
||||
|
||||
filePath := arg["path"].(string)
|
||||
filePath = filepath.Join(util.WorkspaceDir, filePath)
|
||||
_, err := os.Stat(filePath)
|
||||
if os.IsNotExist(err) {
|
||||
c.Status(404)
|
||||
return
|
||||
}
|
||||
if nil != err {
|
||||
logging.LogErrorf("stat [%s] failed: %s", filePath, err)
|
||||
c.Status(500)
|
||||
return
|
||||
}
|
||||
|
||||
if err = os.RemoveAll(filePath); nil != err {
|
||||
c.Status(500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func putFile(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||
ginServer.Handle("POST", "/api/file/getFile", model.CheckAuth, getFile)
|
||||
ginServer.Handle("POST", "/api/file/putFile", model.CheckAuth, model.CheckReadonly, putFile)
|
||||
ginServer.Handle("POST", "/api/file/copyFile", model.CheckAuth, model.CheckReadonly, copyFile)
|
||||
ginServer.Handle("POST", "/api/file/removeFile", model.CheckAuth, model.CheckReadonly, removeFile)
|
||||
|
||||
ginServer.Handle("POST", "/api/ref/refreshBacklink", model.CheckAuth, refreshBacklink)
|
||||
ginServer.Handle("POST", "/api/ref/getBacklink", model.CheckAuth, getBacklink)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ func NewAttributeView(id string) *AttributeView {
|
|||
return &AttributeView{
|
||||
Spec: 0,
|
||||
ID: id,
|
||||
Columns: []*Column{&Column{ID: ast.NewNodeID(), Name: "Block", Type: ColumnTypeBlock}},
|
||||
Columns: []*Column{{ID: ast.NewNodeID(), Name: "Block", Type: ColumnTypeBlock}},
|
||||
Rows: []*Row{},
|
||||
Type: AttributeViewTypeTable,
|
||||
Projections: []string{},
|
||||
|
|
|
|||
|
|
@ -73,7 +73,23 @@ func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr)
|
|||
return
|
||||
}
|
||||
|
||||
func AddAttributeViewColumn(name string, typ string, columnIndex int, avID string) (err error) {
|
||||
func (tx *Transaction) doAddAttrViewColumn(operation *Operation) (ret *TxErr) {
|
||||
err := addAttributeViewColumn(operation.Name, operation.Typ, 1024, operation.ParentID)
|
||||
if nil != err {
|
||||
return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (tx *Transaction) doRemoveAttrViewColumn(operation *Operation) (ret *TxErr) {
|
||||
err := removeAttributeViewColumn(operation.ID, operation.ParentID)
|
||||
if nil != err {
|
||||
return &TxErr{code: TxErrWriteAttributeView, id: operation.ParentID, msg: err.Error()}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func addAttributeViewColumn(name string, typ string, columnIndex int, avID string) (err error) {
|
||||
attrView, err := av.ParseAttributeView(avID)
|
||||
if nil != err {
|
||||
return
|
||||
|
|
@ -81,7 +97,7 @@ func AddAttributeViewColumn(name string, typ string, columnIndex int, avID strin
|
|||
|
||||
switch av.ColumnType(typ) {
|
||||
case av.ColumnTypeText:
|
||||
attrView.InsertColumn(columnIndex, &av.Column{ID: ast.NewNodeID(), Name: name, Type: av.ColumnTypeText})
|
||||
attrView.InsertColumn(columnIndex, &av.Column{ID: "av" + ast.NewNodeID(), Name: name, Type: av.ColumnTypeText})
|
||||
default:
|
||||
msg := fmt.Sprintf("invalid column type [%s]", typ)
|
||||
logging.LogErrorf(msg)
|
||||
|
|
@ -93,6 +109,23 @@ func AddAttributeViewColumn(name string, typ string, columnIndex int, avID strin
|
|||
return
|
||||
}
|
||||
|
||||
func removeAttributeViewColumn(columnID string, avID string) (err error) {
|
||||
attrView, err := av.ParseAttributeView(avID)
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
for i, column := range attrView.Columns[1:] {
|
||||
if column.ID == columnID {
|
||||
attrView.Columns = append(attrView.Columns[:i], attrView.Columns[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
err = av.SaveAttributeView(attrView)
|
||||
return
|
||||
}
|
||||
|
||||
func removeAttributeViewBlock(blockID, avID string, tree *parse.Tree, tx *Transaction) (err error) {
|
||||
node := treenode.GetNodeInTree(tree, blockID)
|
||||
if nil == node {
|
||||
|
|
@ -107,6 +140,7 @@ func removeAttributeViewBlock(blockID, avID string, tree *parse.Tree, tx *Transa
|
|||
|
||||
for i, row := range attrView.Rows {
|
||||
if row.Cells[0].Value == blockID {
|
||||
// 从行中移除,但是不移除属性
|
||||
attrView.Rows = append(attrView.Rows[:i], attrView.Rows[i+1:]...)
|
||||
break
|
||||
}
|
||||
|
|
@ -150,11 +184,9 @@ func addAttributeViewBlock(blockID, avID string, tree *parse.Tree, tx *Transacti
|
|||
row.Cells = append(row.Cells, &av.Cell{ID: ast.NewNodeID(), Value: blockID})
|
||||
if 1 < len(attrView.Columns) {
|
||||
// 将列作为属性添加到块中
|
||||
|
||||
attrs := parse.IAL2Map(node.KramdownIAL)
|
||||
for _, col := range attrView.Columns[1:] {
|
||||
colName := col.Name
|
||||
attrs[colName] = ""
|
||||
attrs["av"+col.ID] = ""
|
||||
}
|
||||
|
||||
if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ package model
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/88250/lute/parse"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/88250/gulu"
|
||||
"github.com/88250/lute/ast"
|
||||
"github.com/88250/lute/html"
|
||||
"github.com/88250/lute/lex"
|
||||
"github.com/88250/lute/parse"
|
||||
"github.com/araddon/dateparse"
|
||||
"github.com/siyuan-note/siyuan/kernel/cache"
|
||||
"github.com/siyuan-note/siyuan/kernel/treenode"
|
||||
|
|
@ -166,6 +167,12 @@ func setNodeAttrs0(node *ast.Node, nameValues map[string]string) (oldAttrs map[s
|
|||
}
|
||||
|
||||
for name, value := range nameValues {
|
||||
if strings.HasPrefix(name, "av") {
|
||||
// 属性视图设置的属性值可以为空
|
||||
node.SetIALAttr(name, value)
|
||||
continue
|
||||
}
|
||||
|
||||
if "" == value {
|
||||
node.RemoveIALAttr(name)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -218,6 +218,10 @@ func performTx(tx *Transaction) (ret *TxErr) {
|
|||
ret = tx.doInsertAttrViewBlock(op)
|
||||
case "removeAttrViewBlock":
|
||||
ret = tx.doRemoveAttrViewBlock(op)
|
||||
case "addAttrViewCol":
|
||||
ret = tx.doAddAttrViewColumn(op)
|
||||
case "removeAttrViewCol":
|
||||
ret = tx.doRemoveAttrViewColumn(op)
|
||||
}
|
||||
|
||||
if nil != ret {
|
||||
|
|
@ -1026,9 +1030,12 @@ type Operation struct {
|
|||
ParentID string `json:"parentID"`
|
||||
PreviousID string `json:"previousID"`
|
||||
NextID string `json:"nextID"`
|
||||
SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中
|
||||
RetData interface{} `json:"retData"`
|
||||
|
||||
SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中
|
||||
Name string `json:"name"` // 用于属性视图列名
|
||||
Typ string `json:"type"` // 用于属性视图列类型
|
||||
|
||||
discard bool // 用于标识是否在事务合并中丢弃
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue