Changeset 0.29.0 (#195)
This commit is contained in:
@@ -2,61 +2,34 @@ package handlers
|
||||
|
||||
// folders.go — Chat folder CRUD (v0.23.1)
|
||||
//
|
||||
// Folders are user-scoped groupings for personal (direct) chats.
|
||||
// Routes:
|
||||
// GET /api/v1/folders
|
||||
// POST /api/v1/folders
|
||||
// PUT /api/v1/folders/:id
|
||||
// DELETE /api/v1/folders/:id
|
||||
// v0.29.0: Raw SQL replaced with FolderStore methods.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
)
|
||||
|
||||
type FolderHandler struct{}
|
||||
type FolderHandler struct {
|
||||
stores store.Stores
|
||||
}
|
||||
|
||||
func NewFolderHandler() *FolderHandler { return &FolderHandler{} }
|
||||
|
||||
type folderRow struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ParentID *string `json:"parent_id,omitempty"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
func NewFolderHandler(s store.Stores) *FolderHandler {
|
||||
return &FolderHandler{stores: s}
|
||||
}
|
||||
|
||||
func (h *FolderHandler) List(c *gin.Context) {
|
||||
userID := getUserID(c)
|
||||
rows, err := database.DB.QueryContext(c.Request.Context(), database.Q(`
|
||||
SELECT id, name, parent_id, sort_order, created_at, updated_at
|
||||
FROM folders
|
||||
WHERE user_id = $1
|
||||
ORDER BY sort_order, name
|
||||
`), userID)
|
||||
|
||||
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
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var folders []folderRow
|
||||
for rows.Next() {
|
||||
var f folderRow
|
||||
if err := rows.Scan(&f.ID, &f.Name, &f.ParentID, &f.SortOrder, &f.CreatedAt, &f.UpdatedAt); err != nil {
|
||||
continue
|
||||
}
|
||||
folders = append(folders, f)
|
||||
}
|
||||
if folders == nil {
|
||||
folders = []folderRow{}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"folders": folders})
|
||||
}
|
||||
|
||||
@@ -76,14 +49,12 @@ func (h *FolderHandler) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var f folderRow
|
||||
err := database.DB.QueryRowContext(c.Request.Context(), database.Q(`
|
||||
INSERT INTO folders (user_id, name, sort_order)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id, name, parent_id, sort_order, created_at, updated_at
|
||||
`), userID, req.Name, req.SortOrder).Scan(
|
||||
&f.ID, &f.Name, &f.ParentID, &f.SortOrder, &f.CreatedAt, &f.UpdatedAt)
|
||||
if err != nil {
|
||||
f := &models.Folder{
|
||||
UserID: userID,
|
||||
Name: req.Name,
|
||||
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
|
||||
}
|
||||
@@ -105,17 +76,12 @@ func (h *FolderHandler) Update(c *gin.Context) {
|
||||
req.Name = strings.TrimSpace(req.Name)
|
||||
}
|
||||
|
||||
res, err := database.DB.ExecContext(c.Request.Context(), database.Q(`
|
||||
UPDATE folders
|
||||
SET name = COALESCE(NULLIF($3, ''), name),
|
||||
sort_order = COALESCE($4, sort_order)
|
||||
WHERE id = $1 AND user_id = $2
|
||||
`), folderID, userID, req.Name, req.SortOrder)
|
||||
n, err := h.stores.Folders.Update(c.Request.Context(), folderID, userID, req.Name, req.SortOrder)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update folder"})
|
||||
return
|
||||
}
|
||||
if n, _ := res.RowsAffected(); n == 0 {
|
||||
if n == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
|
||||
return
|
||||
}
|
||||
@@ -127,18 +93,14 @@ func (h *FolderHandler) Delete(c *gin.Context) {
|
||||
folderID := c.Param("id")
|
||||
|
||||
// Unassign chats before deleting folder
|
||||
_, _ = database.DB.ExecContext(c.Request.Context(), database.Q(`
|
||||
UPDATE channels SET folder_id = NULL WHERE folder_id = $1 AND user_id = $2
|
||||
`), folderID, userID)
|
||||
_ = h.stores.Folders.UnassignChannels(c.Request.Context(), folderID, userID)
|
||||
|
||||
res, err := database.DB.ExecContext(c.Request.Context(), database.Q(`
|
||||
DELETE FROM folders WHERE id = $1 AND user_id = $2
|
||||
`), 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, _ := res.RowsAffected(); n == 0 {
|
||||
if n == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user