Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
128 lines
3.2 KiB
Go
128 lines
3.2 KiB
Go
package handlers
|
|
|
|
// folders.go — Chat folder CRUD (v0.23.1)
|
|
//
|
|
// v0.29.0: Raw SQL replaced with FolderStore methods.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"chat-switchboard/models"
|
|
"chat-switchboard/store"
|
|
)
|
|
|
|
type FolderHandler struct {
|
|
stores store.Stores
|
|
}
|
|
|
|
func NewFolderHandler(s store.Stores) *FolderHandler {
|
|
return &FolderHandler{stores: s}
|
|
}
|
|
|
|
func (h *FolderHandler) List(c *gin.Context) {
|
|
userID := getUserID(c)
|
|
|
|
folders, err := h.stores.Folders.List(c.Request.Context(), userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list folders"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"data": folders})
|
|
}
|
|
|
|
func (h *FolderHandler) Create(c *gin.Context) {
|
|
userID := getUserID(c)
|
|
var req struct {
|
|
Name string `json:"name" binding:"required"`
|
|
ParentID *string `json:"parent_id"`
|
|
SortOrder int `json:"sort_order"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
req.Name = strings.TrimSpace(req.Name)
|
|
if req.Name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"})
|
|
return
|
|
}
|
|
|
|
f := &models.Folder{
|
|
UserID: userID,
|
|
Name: req.Name,
|
|
ParentID: req.ParentID,
|
|
SortOrder: req.SortOrder,
|
|
}
|
|
if err := h.stores.Folders.Create(c.Request.Context(), f); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create folder"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, gin.H{"folder": f})
|
|
}
|
|
|
|
func (h *FolderHandler) Update(c *gin.Context) {
|
|
userID := getUserID(c)
|
|
folderID := c.Param("id")
|
|
|
|
// Read raw body to detect which fields were explicitly sent
|
|
data, err := c.GetRawData()
|
|
if err != nil || len(data) == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
|
|
return
|
|
}
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
SortOrder *int `json:"sort_order"`
|
|
ParentID *string `json:"parent_id"`
|
|
}
|
|
if err := json.Unmarshal(data, &req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if req.Name != "" {
|
|
req.Name = strings.TrimSpace(req.Name)
|
|
}
|
|
|
|
// Only update parent_id if it was explicitly present in the JSON
|
|
var parentID **string
|
|
var raw map[string]json.RawMessage
|
|
_ = json.Unmarshal(data, &raw)
|
|
if _, ok := raw["parent_id"]; ok {
|
|
parentID = &req.ParentID
|
|
}
|
|
|
|
n, err := h.stores.Folders.Update(c.Request.Context(), folderID, userID, req.Name, req.SortOrder, parentID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update folder"})
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"ok": true})
|
|
}
|
|
|
|
func (h *FolderHandler) Delete(c *gin.Context) {
|
|
userID := getUserID(c)
|
|
folderID := c.Param("id")
|
|
|
|
// Unassign chats before deleting folder
|
|
_ = h.stores.Folders.UnassignChannels(c.Request.Context(), folderID, userID)
|
|
|
|
n, err := h.stores.Folders.Delete(c.Request.Context(), folderID, userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete folder"})
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"ok": true})
|
|
}
|