mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-05-13 07:30:50 +08:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
a7e232b4c8
@ -267,6 +267,31 @@ func moveDoc(c *gin.Context) {
|
|||||||
util.PushEvent(evt)
|
util.PushEvent(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func moveDocs(c *gin.Context) {
|
||||||
|
ret := gulu.Ret.NewResult()
|
||||||
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
||||||
|
arg, ok := util.JsonArg(c, ret)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var fromPaths []string
|
||||||
|
fromPathsArg := arg["fromPaths"].([]interface{})
|
||||||
|
for _, fromPath := range fromPathsArg {
|
||||||
|
fromPaths = append(fromPaths, fromPath.(string))
|
||||||
|
}
|
||||||
|
toPath := arg["toPath"].(string)
|
||||||
|
|
||||||
|
err := model.MoveDocs(fromPaths, toPath)
|
||||||
|
if nil != err {
|
||||||
|
ret.Code = -1
|
||||||
|
ret.Msg = err.Error()
|
||||||
|
ret.Data = map[string]interface{}{"closeTimeout": 7000}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func removeDoc(c *gin.Context) {
|
func removeDoc(c *gin.Context) {
|
||||||
ret := gulu.Ret.NewResult()
|
ret := gulu.Ret.NewResult()
|
||||||
defer c.JSON(http.StatusOK, ret)
|
defer c.JSON(http.StatusOK, ret)
|
||||||
@ -294,6 +319,28 @@ func removeDoc(c *gin.Context) {
|
|||||||
util.PushEvent(evt)
|
util.PushEvent(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeDocs(c *gin.Context) {
|
||||||
|
ret := gulu.Ret.NewResult()
|
||||||
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
||||||
|
arg, ok := util.JsonArg(c, ret)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pathsArg := arg["paths"].([]interface{})
|
||||||
|
var paths []string
|
||||||
|
for _, path := range pathsArg {
|
||||||
|
paths = append(paths, path.(string))
|
||||||
|
}
|
||||||
|
err := model.RemoveDocs(paths)
|
||||||
|
if nil != err {
|
||||||
|
ret.Code = -1
|
||||||
|
ret.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func renameDoc(c *gin.Context) {
|
func renameDoc(c *gin.Context) {
|
||||||
ret := gulu.Ret.NewResult()
|
ret := gulu.Ret.NewResult()
|
||||||
defer c.JSON(http.StatusOK, ret)
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
@ -87,7 +87,9 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||||||
ginServer.Handle("POST", "/api/filetree/createDoc", model.CheckAuth, model.CheckReadonly, createDoc)
|
ginServer.Handle("POST", "/api/filetree/createDoc", model.CheckAuth, model.CheckReadonly, createDoc)
|
||||||
ginServer.Handle("POST", "/api/filetree/renameDoc", model.CheckAuth, model.CheckReadonly, renameDoc)
|
ginServer.Handle("POST", "/api/filetree/renameDoc", model.CheckAuth, model.CheckReadonly, renameDoc)
|
||||||
ginServer.Handle("POST", "/api/filetree/removeDoc", model.CheckAuth, model.CheckReadonly, removeDoc)
|
ginServer.Handle("POST", "/api/filetree/removeDoc", model.CheckAuth, model.CheckReadonly, removeDoc)
|
||||||
|
ginServer.Handle("POST", "/api/filetree/removeDocs", model.CheckAuth, model.CheckReadonly, removeDocs)
|
||||||
ginServer.Handle("POST", "/api/filetree/moveDoc", model.CheckAuth, model.CheckReadonly, moveDoc)
|
ginServer.Handle("POST", "/api/filetree/moveDoc", model.CheckAuth, model.CheckReadonly, moveDoc)
|
||||||
|
ginServer.Handle("POST", "/api/filetree/moveDocs", model.CheckAuth, model.CheckReadonly, moveDocs)
|
||||||
ginServer.Handle("POST", "/api/filetree/duplicateDoc", model.CheckAuth, model.CheckReadonly, duplicateDoc)
|
ginServer.Handle("POST", "/api/filetree/duplicateDoc", model.CheckAuth, model.CheckReadonly, duplicateDoc)
|
||||||
ginServer.Handle("POST", "/api/filetree/getHPathByPath", model.CheckAuth, getHPathByPath)
|
ginServer.Handle("POST", "/api/filetree/getHPathByPath", model.CheckAuth, getHPathByPath)
|
||||||
ginServer.Handle("POST", "/api/filetree/getHPathByID", model.CheckAuth, getHPathByID)
|
ginServer.Handle("POST", "/api/filetree/getHPathByID", model.CheckAuth, getHPathByID)
|
||||||
|
@ -545,3 +545,14 @@ func TryAccessFileByBlockID(id string) (ok bool) {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBoxesByPaths(paths []string) (ret map[string]*Box) {
|
||||||
|
for _, p := range paths {
|
||||||
|
id := strings.TrimSuffix(path.Base(p), ".sy")
|
||||||
|
bt := treenode.GetBlockTree(id)
|
||||||
|
if nil != bt {
|
||||||
|
ret[p] = Conf.Box(bt.BoxID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -988,6 +988,8 @@ func GetFullHPathByID(id string) (hPath string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err error) {
|
func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err error) {
|
||||||
|
WaitForWritingFiles()
|
||||||
|
|
||||||
if fromBoxID == toBoxID && fromPath == toPath {
|
if fromBoxID == toBoxID && fromPath == toPath {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1004,13 +1006,6 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForWritingFiles()
|
|
||||||
tree, err := LoadTree(fromBoxID, fromPath)
|
|
||||||
if nil != err {
|
|
||||||
err = ErrBlockNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
childDepth := util.GetChildDocDepth(filepath.Join(util.DataDir, fromBoxID, fromPath))
|
childDepth := util.GetChildDocDepth(filepath.Join(util.DataDir, fromBoxID, fromPath))
|
||||||
if depth := strings.Count(toPath, "/") + childDepth; 6 < depth && !Conf.FileTree.AllowCreateDeeper {
|
if depth := strings.Count(toPath, "/") + childDepth; 6 < depth && !Conf.FileTree.AllowCreateDeeper {
|
||||||
err = errors.New(Conf.Language(118))
|
err = errors.New(Conf.Language(118))
|
||||||
@ -1022,7 +1017,81 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
|
|||||||
err = errors.New(Conf.Language(0))
|
err = errors.New(Conf.Language(0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isSameBox := fromBoxID == toBoxID
|
|
||||||
|
newPath, err = moveDoc(fromBox, fromPath, toBox, toPath)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.ClearDocsIAL()
|
||||||
|
IncSync()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func MoveDocs(fromPaths []string, toPath string) (err error) {
|
||||||
|
util.PushEndlessProgress(Conf.Language(116))
|
||||||
|
|
||||||
|
fromPaths = filterFromPaths(fromPaths, toPath)
|
||||||
|
pathsBoxes := getBoxesByPaths(fromPaths)
|
||||||
|
|
||||||
|
toID := strings.TrimSuffix(path.Base(toPath), ".sy")
|
||||||
|
toBlock := treenode.GetBlockTree(toID)
|
||||||
|
if nil == toBlock {
|
||||||
|
err = ErrBlockNotFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
toBox := Conf.Box(toBlock.BoxID)
|
||||||
|
if nil == toBox {
|
||||||
|
err = errors.New(Conf.Language(0))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for fromPath, fromBox := range pathsBoxes {
|
||||||
|
_, err = moveDoc(fromBox, fromPath, toBox, toPath)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache.ClearDocsIAL()
|
||||||
|
IncSync()
|
||||||
|
|
||||||
|
util.PushEndlessProgress(Conf.Language(113))
|
||||||
|
sql.WaitForWritingDatabase()
|
||||||
|
util.ReloadUI()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterFromPaths(fromPaths []string, toPath string) (retFromPaths []string) {
|
||||||
|
fromPaths = append(fromPaths, toPath)
|
||||||
|
retFromPaths = filterSelfChildDocs(fromPaths)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterSelfChildDocs(paths []string) (ret []string) {
|
||||||
|
sort.Slice(paths, func(i, j int) bool { return len(paths[i]) < len(paths[j]) })
|
||||||
|
|
||||||
|
dirs := map[string]string{}
|
||||||
|
for _, fromPath := range paths {
|
||||||
|
dir := strings.TrimSuffix(fromPath, ".sy")
|
||||||
|
existParent := false
|
||||||
|
for _, d := range dirs {
|
||||||
|
if strings.HasPrefix(d, fromPath) {
|
||||||
|
existParent = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existParent {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dirs[dir] = fromPath
|
||||||
|
ret = append(ret, fromPath)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string) (newPath string, err error) {
|
||||||
|
isSameBox := fromBox.ID == toBox.ID
|
||||||
|
|
||||||
if isSameBox {
|
if isSameBox {
|
||||||
if !fromBox.Exist(toPath) {
|
if !fromBox.Exist(toPath) {
|
||||||
@ -1036,6 +1105,12 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tree, err := LoadTree(fromBox.ID, fromPath)
|
||||||
|
if nil != err {
|
||||||
|
err = ErrBlockNotFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
moveToRoot := "/" == toPath
|
moveToRoot := "/" == toPath
|
||||||
toBlockID := tree.ID
|
toBlockID := tree.ID
|
||||||
fromFolder := path.Join(path.Dir(fromPath), tree.ID)
|
fromFolder := path.Join(path.Dir(fromPath), tree.ID)
|
||||||
@ -1043,9 +1118,9 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
|
|||||||
if !moveToRoot {
|
if !moveToRoot {
|
||||||
var toTree *parse.Tree
|
var toTree *parse.Tree
|
||||||
if isSameBox {
|
if isSameBox {
|
||||||
toTree, err = LoadTree(fromBoxID, toPath)
|
toTree, err = LoadTree(fromBox.ID, toPath)
|
||||||
} else {
|
} else {
|
||||||
toTree, err = LoadTree(toBoxID, toPath)
|
toTree, err = LoadTree(toBox.ID, toPath)
|
||||||
}
|
}
|
||||||
if nil != err {
|
if nil != err {
|
||||||
err = ErrBlockNotFound
|
err = ErrBlockNotFound
|
||||||
@ -1075,14 +1150,14 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
absFromPath := filepath.Join(util.DataDir, fromBoxID, fromFolder)
|
absFromPath := filepath.Join(util.DataDir, fromBox.ID, fromFolder)
|
||||||
absToPath := filepath.Join(util.DataDir, toBoxID, newFolder)
|
absToPath := filepath.Join(util.DataDir, toBox.ID, newFolder)
|
||||||
if gulu.File.IsExist(absToPath) {
|
if gulu.File.IsExist(absToPath) {
|
||||||
filelock.Remove(absToPath)
|
filelock.Remove(absToPath)
|
||||||
}
|
}
|
||||||
if err = filelock.Move(absFromPath, absToPath); nil != err {
|
if err = filelock.Move(absFromPath, absToPath); nil != err {
|
||||||
msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
|
msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
|
||||||
logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBoxID, err)
|
logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBox.ID, err)
|
||||||
err = errors.New(msg)
|
err = errors.New(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1096,32 +1171,30 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tree, err = LoadTree(fromBoxID, newPath)
|
tree, err = LoadTree(fromBox.ID, newPath)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTree(tree)
|
moveTree(tree)
|
||||||
} else {
|
} else {
|
||||||
absFromPath := filepath.Join(util.DataDir, fromBoxID, fromPath)
|
absFromPath := filepath.Join(util.DataDir, fromBox.ID, fromPath)
|
||||||
absToPath := filepath.Join(util.DataDir, toBoxID, newPath)
|
absToPath := filepath.Join(util.DataDir, toBox.ID, newPath)
|
||||||
if err = filelock.Move(absFromPath, absToPath); nil != err {
|
if err = filelock.Move(absFromPath, absToPath); nil != err {
|
||||||
msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
|
msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
|
||||||
logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBoxID, err)
|
logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBox.ID, err)
|
||||||
err = errors.New(msg)
|
err = errors.New(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tree, err = LoadTree(toBoxID, newPath)
|
tree, err = LoadTree(toBox.ID, newPath)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTree(tree)
|
moveTree(tree)
|
||||||
moveSorts(tree.ID, fromBoxID, toBoxID)
|
moveSorts(tree.ID, fromBox.ID, toBox.ID)
|
||||||
}
|
}
|
||||||
cache.ClearDocsIAL()
|
|
||||||
IncSync()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,7 +1206,40 @@ func RemoveDoc(boxID, p string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WaitForWritingFiles()
|
WaitForWritingFiles()
|
||||||
tree, err := LoadTree(boxID, p)
|
err = removeDoc(box, p)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
IncSync()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveDocs(paths []string) (err error) {
|
||||||
|
util.PushEndlessProgress(Conf.Language(116))
|
||||||
|
|
||||||
|
paths = filterSelfChildDocs(paths)
|
||||||
|
var ids []string
|
||||||
|
for _, p := range paths {
|
||||||
|
ids = append(ids, strings.TrimSuffix(path.Base(p), ".sy"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pathsBoxes := getBoxesByPaths(ids)
|
||||||
|
WaitForWritingFiles()
|
||||||
|
for p, box := range pathsBoxes {
|
||||||
|
err = removeDoc(box, p)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
util.PushEndlessProgress(Conf.Language(113))
|
||||||
|
sql.WaitForWritingDatabase()
|
||||||
|
util.ReloadUI()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeDoc(box *Box, p string) (err error) {
|
||||||
|
tree, err := LoadTree(box.ID, p)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1144,13 +1250,13 @@ func RemoveDoc(boxID, p string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
historyPath := filepath.Join(historyDir, boxID, p)
|
historyPath := filepath.Join(historyDir, box.ID, p)
|
||||||
absPath := filepath.Join(util.DataDir, boxID, p)
|
absPath := filepath.Join(util.DataDir, box.ID, p)
|
||||||
if err = filelock.Copy(absPath, historyPath); nil != err {
|
if err = filelock.Copy(absPath, historyPath); nil != err {
|
||||||
return errors.New(fmt.Sprintf(Conf.Language(70), box.Name, absPath, err))
|
return errors.New(fmt.Sprintf(Conf.Language(70), box.Name, absPath, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
copyDocAssetsToDataAssets(boxID, p)
|
copyDocAssetsToDataAssets(box.ID, p)
|
||||||
|
|
||||||
rootID := tree.ID
|
rootID := tree.ID
|
||||||
dir := path.Dir(p)
|
dir := path.Dir(p)
|
||||||
@ -1178,7 +1284,7 @@ func RemoveDoc(boxID, p string) (err error) {
|
|||||||
sql.RemoveTreePathQueue(box.ID, childrenDir)
|
sql.RemoveTreePathQueue(box.ID, childrenDir)
|
||||||
|
|
||||||
if "/" != dir {
|
if "/" != dir {
|
||||||
others, err := os.ReadDir(filepath.Join(util.DataDir, boxID, dir))
|
others, err := os.ReadDir(filepath.Join(util.DataDir, box.ID, dir))
|
||||||
if nil == err && 1 > len(others) {
|
if nil == err && 1 > len(others) {
|
||||||
box.Remove(dir)
|
box.Remove(dir)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user