mirror of
https://github.com/get-drexa/drive.git
synced 2026-02-02 16:11:17 +00:00
feat: support bulk file move in same dir
This commit is contained in:
@@ -2,6 +2,8 @@ package catalog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/get-drexa/drexa/internal/account"
|
||||
@@ -30,6 +32,10 @@ type createDirectoryRequest struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type postDirectoryContentRequest struct {
|
||||
Items []string `json:"items"`
|
||||
}
|
||||
|
||||
func (h *HTTPHandler) currentDirectoryMiddleware(c *fiber.Ctx) error {
|
||||
account := account.CurrentAccount(c)
|
||||
if account == nil {
|
||||
@@ -54,6 +60,10 @@ func mustCurrentDirectoryNode(c *fiber.Ctx) *virtualfs.Node {
|
||||
return c.Locals("directory").(*virtualfs.Node)
|
||||
}
|
||||
|
||||
func includeParam(c *fiber.Ctx) []string {
|
||||
return strings.Split(c.Query("include"), ",")
|
||||
}
|
||||
|
||||
func (h *HTTPHandler) createDirectory(c *fiber.Ctx) error {
|
||||
account := account.CurrentAccount(c)
|
||||
if account == nil {
|
||||
@@ -91,19 +101,30 @@ func (h *HTTPHandler) createDirectory(c *fiber.Ctx) error {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
|
||||
return c.JSON(DirectoryInfo{
|
||||
i := DirectoryInfo{
|
||||
Kind: DirItemKindDirectory,
|
||||
ID: node.PublicID,
|
||||
Name: node.Name,
|
||||
CreatedAt: node.CreatedAt,
|
||||
UpdatedAt: node.UpdatedAt,
|
||||
DeletedAt: node.DeletedAt,
|
||||
})
|
||||
}
|
||||
|
||||
include := includeParam(c)
|
||||
if slices.Contains(include, "path") {
|
||||
p, err := h.vfs.RealPath(c.Context(), tx, node)
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
i.Path = p
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
|
||||
return c.JSON(i)
|
||||
}
|
||||
|
||||
func (h *HTTPHandler) fetchDirectory(c *fiber.Ctx) error {
|
||||
@@ -118,8 +139,8 @@ func (h *HTTPHandler) fetchDirectory(c *fiber.Ctx) error {
|
||||
DeletedAt: node.DeletedAt,
|
||||
}
|
||||
|
||||
include := c.Query("include")
|
||||
if include == "path" {
|
||||
include := includeParam(c)
|
||||
if slices.Contains(include, "path") {
|
||||
p, err := h.vfs.RealPath(c.Context(), h.db, node)
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
@@ -237,3 +258,54 @@ func (h *HTTPHandler) deleteDirectory(c *fiber.Ctx) error {
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *HTTPHandler) moveItemsToDirectory(c *fiber.Ctx) error {
|
||||
acc := account.CurrentAccount(c)
|
||||
if acc == nil {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
targetDir := mustCurrentDirectoryNode(c)
|
||||
|
||||
req := new(postDirectoryContentRequest)
|
||||
if err := c.BodyParser(req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
|
||||
}
|
||||
|
||||
if len(req.Items) == 0 {
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
tx, err := h.db.BeginTx(c.Context(), nil)
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
nodes, err := h.vfs.FindNodesByPublicID(c.Context(), tx, acc.ID, req.Items)
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
if len(nodes) != len(req.Items) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "One or more items not found"})
|
||||
}
|
||||
|
||||
// Move all nodes to the target directory
|
||||
err = h.vfs.MoveNodesInSameDirectory(c.Context(), tx, nodes, targetDir.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, virtualfs.ErrUnsupportedOperation) {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "All items must be in the same directory"})
|
||||
}
|
||||
if errors.Is(err, virtualfs.ErrNodeConflict) {
|
||||
return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": "Name conflict in target directory"})
|
||||
}
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return httperr.Internal(err)
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ func (h *HTTPHandler) RegisterRoutes(api fiber.Router) {
|
||||
dg := api.Group("/directories/:directoryID")
|
||||
dg.Use(h.currentDirectoryMiddleware)
|
||||
dg.Get("/", h.fetchDirectory)
|
||||
dg.Post("/content", h.moveItemsToDirectory)
|
||||
dg.Get("/content", h.listDirectory)
|
||||
dg.Patch("/", h.patchDirectory)
|
||||
dg.Delete("/", h.deleteDirectory)
|
||||
|
||||
Reference in New Issue
Block a user