package kb import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "github.com/yaoapp/yao/openapi/response" ) // Vote Management Handlers // ScrollVotes scrolls votes with iterator-style pagination for a specific segment func ScrollVotes(c *gin.Context) { // Extract docID from URL path docID := c.Param("docID") if docID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Document ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract segmentID from URL path segmentID := c.Param("segmentID") if segmentID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Segment ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Parse query parameters for scroll options options := map[string]interface{}{ "document_id": docID, "segment_id": segmentID, "limit": 100, // Default limit } // Parse limit (default: 100) if limitStr := c.Query("limit"); limitStr != "" { if limit, err := strconv.Atoi(limitStr); err == nil && limit > 0 { options["limit"] = limit } } // Parse scroll_id parameter for continuing pagination if scrollID := strings.TrimSpace(c.Query("scroll_id")); scrollID != "" { options["scroll_id"] = scrollID } // Parse order_by parameter if orderBy := strings.TrimSpace(c.Query("order_by")); orderBy != "" { orderByFields := strings.Split(orderBy, ",") // Trim spaces from each field for i, field := range orderByFields { orderByFields[i] = strings.TrimSpace(field) } options["order_by"] = orderByFields } // Parse filter parameters filter := make(map[string]interface{}) if voteType := c.Query("vote_type"); voteType != "" { filter["vote_type"] = voteType } if userID := c.Query("user_id"); userID != "" { filter["user_id"] = userID } if len(filter) > 0 { options["filter"] = filter } // TODO: Implement document permission validation for docID // TODO: Implement scroll votes logic with GraphRag or database // TODO: Call kb.Instance.ScrollVotes(c.Request.Context(), segmentID, options) // Return mock response for now result := gin.H{ "votes": []interface{}{}, "scroll_id": nil, "has_more": false, "total": 0, "options": options, } response.RespondWithSuccess(c, response.StatusOK, result) } // GetVotes gets votes for a specific segment (simple list, no pagination) func GetVotes(c *gin.Context) { // Extract docID from URL path docID := c.Param("docID") if docID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Document ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract segmentID from URL path segmentID := c.Param("segmentID") if segmentID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Segment ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Parse basic filter parameters filter := make(map[string]interface{}) if voteType := c.Query("vote_type"); voteType != "" { filter["vote_type"] = voteType } if userID := c.Query("user_id"); userID != "" { filter["user_id"] = userID } // Parse limit parameter (optional, for basic limiting without pagination) var limit int if limitStr := c.Query("limit"); limitStr != "" { if l, err := strconv.Atoi(limitStr); err == nil && l > 0 { limit = l } } // TODO: Implement document permission validation for docID // TODO: Implement get votes logic (simple query without pagination) // TODO: Call kb.Instance.GetVotes(c.Request.Context(), segmentID, filter, limit) // Return mock response for now result := gin.H{ "votes": []interface{}{}, "document_id": docID, "segment_id": segmentID, "total": 0, } if len(filter) > 0 { result["filter"] = filter } if limit > 0 { result["limit"] = limit } response.RespondWithSuccess(c, response.StatusOK, result) } // GetVote gets a specific vote by ID func GetVote(c *gin.Context) { // Extract docID from URL path docID := c.Param("docID") if docID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Document ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract segmentID from URL path segmentID := c.Param("segmentID") if segmentID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Segment ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract voteID from URL path voteID := c.Param("voteID") if voteID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Vote ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // TODO: Implement document permission validation for docID // TODO: Implement get vote detail logic c.JSON(http.StatusOK, gin.H{ "vote": nil, "document_id": docID, "segment_id": segmentID, "vote_id": voteID, }) } // AddVotes adds new votes to a segment func AddVotes(c *gin.Context) { // Extract docID from URL path docID := c.Param("docID") if docID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Document ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract segmentID from URL path segmentID := c.Param("segmentID") if segmentID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Segment ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // TODO: Implement document permission validation for docID // TODO: Implement add vote logic c.JSON(http.StatusOK, gin.H{ "message": "Vote added successfully", "document_id": docID, "segment_id": segmentID, "vote_id": "placeholder-vote-id", }) } // UpdateVotes updates votes in batch func UpdateVotes(c *gin.Context) { // Extract docID from URL path docID := c.Param("docID") if docID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Document ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract segmentID from URL path segmentID := c.Param("segmentID") if segmentID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Segment ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Parse vote_ids from query parameter or request body var voteIDs []string // Try query parameter first (comma-separated) if voteIDsParam := strings.TrimSpace(c.Query("vote_ids")); voteIDsParam != "" { voteIDs = strings.Split(voteIDsParam, ",") for i, id := range voteIDs { voteIDs[i] = strings.TrimSpace(id) } } // TODO: Also support request body with vote data for batch updates // TODO: Implement document permission validation for docID // TODO: Implement batch update vote logic result := gin.H{ "message": "Votes updated successfully", "document_id": docID, "segment_id": segmentID, "updated_count": len(voteIDs), } if len(voteIDs) > 0 { result["vote_ids"] = voteIDs } response.RespondWithSuccess(c, response.StatusOK, result) } // RemoveVotes removes votes from a segment in batch func RemoveVotes(c *gin.Context) { // Extract docID from URL path docID := c.Param("docID") if docID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Document ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Extract segmentID from URL path segmentID := c.Param("segmentID") if segmentID == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Segment ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Parse vote_ids from query parameter (comma-separated) voteIDsParam := strings.TrimSpace(c.Query("vote_ids")) if voteIDsParam == "" { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "vote_ids query parameter is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // Split comma-separated vote IDs voteIDs := strings.Split(voteIDsParam, ",") var validVoteIDs []string for _, id := range voteIDs { id = strings.TrimSpace(id) if id != "" { validVoteIDs = append(validVoteIDs, id) } } if len(validVoteIDs) == 0 { errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "At least one valid vote ID is required", } response.RespondWithError(c, response.StatusBadRequest, errorResp) return } // TODO: Implement document permission validation for docID // TODO: Implement batch remove vote logic result := gin.H{ "message": "Votes removed successfully", "document_id": docID, "segment_id": segmentID, "vote_ids": validVoteIDs, "removed_count": len(validVoteIDs), } response.RespondWithSuccess(c, response.StatusOK, result) }