feat(attachments): align list pagination
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/internal/search"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
"github.com/gochat/gochat/pkg/pagination"
|
||||
"github.com/gochat/gochat/pkg/response"
|
||||
)
|
||||
|
||||
@@ -847,8 +846,8 @@ func (h *ContactHandler) ListAttachments(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
p := pagination.Parse(c)
|
||||
attachments, total, svcErr := h.svc.ListAttachments(c.Request.Context(), accountID, contactID, p.Offset, p.PerPage)
|
||||
_, offset := fixedPageOffset(c, chatwootAttachmentResultsPerPage)
|
||||
attachments, total, svcErr := h.svc.ListAttachments(c.Request.Context(), accountID, contactID, offset, chatwootAttachmentResultsPerPage)
|
||||
if svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to list contact attachments"})
|
||||
return
|
||||
|
||||
@@ -644,6 +644,47 @@ func (s *ContactHandlerCRUDTestSuite) TestListAttachmentsReturnsChatwootPayload(
|
||||
s.Contains(item, "sender")
|
||||
}
|
||||
|
||||
func (s *ContactHandlerCRUDTestSuite) TestListAttachmentsUsesChatwootFixedPageSize() {
|
||||
contact := &model.Contact{AccountID: s.account.ID, Name: "Attachment Page Contact", Email: "attachment-page@example.com"}
|
||||
s.Require().NoError(s.db.Create(contact).Error)
|
||||
inbox := &model.Inbox{AccountID: s.account.ID, Name: "Shared Files Fixed Page", ChannelType: "web_widget"}
|
||||
s.Require().NoError(s.db.Create(inbox).Error)
|
||||
displayID := uint(77)
|
||||
conversation := &model.Conversation{AccountID: s.account.ID, InboxID: inbox.ID, ContactID: contact.ID, DisplayID: &displayID, Status: "open", ChannelType: "web_widget", Channel: "web_widget"}
|
||||
s.Require().NoError(s.db.Create(conversation).Error)
|
||||
message := &model.Message{AccountID: s.account.ID, InboxID: inbox.ID, ConversationID: conversation.ID, SenderID: &contact.ID, SenderType: "contact", Content: "files", MessageType: "incoming", ContentType: "text", Status: "sent"}
|
||||
s.Require().NoError(s.db.Create(message).Error)
|
||||
|
||||
baseTime := time.Now().Add(-time.Hour)
|
||||
var newestID uint
|
||||
for i := 0; i < 30; i++ {
|
||||
attachment := &model.Attachment{
|
||||
Base: model.Base{CreatedAt: baseTime.Add(time.Duration(i) * time.Minute), UpdatedAt: baseTime.Add(time.Duration(i) * time.Minute)},
|
||||
AccountID: s.account.ID,
|
||||
MessageID: message.ID,
|
||||
FileType: "file",
|
||||
FileURL: fmt.Sprintf("https://cdn.example.com/contact-file-%02d.txt", i),
|
||||
FileName: fmt.Sprintf("contact-file-%02d.txt", i),
|
||||
}
|
||||
s.Require().NoError(s.db.Create(attachment).Error)
|
||||
newestID = attachment.ID
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/attachments?per_page=5", s.account.ID, contact.ID), nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
s.Equal(http.StatusOK, w.Code, w.Body.String())
|
||||
var resp map[string]any
|
||||
s.NoError(json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
s.Equal(float64(30), resp["meta"].(map[string]any)["total_count"])
|
||||
payload := resp["payload"].([]any)
|
||||
s.Len(payload, 30)
|
||||
first := payload[0].(map[string]any)
|
||||
s.Equal(float64(newestID), first["id"])
|
||||
s.Equal(float64(displayID), first["conversation_id"])
|
||||
}
|
||||
|
||||
func (s *ContactHandlerCRUDTestSuite) TestMerge_ChatwootActionsPathReturnsRawContact() {
|
||||
base := &model.Contact{AccountID: s.account.ID, Name: "Base Contact", Email: "base@example.com"}
|
||||
mergee := &model.Contact{AccountID: s.account.ID, Name: "Mergee Contact", PhoneNumber: "+12212345"}
|
||||
|
||||
@@ -24,6 +24,8 @@ type ConversationHandler struct {
|
||||
auditSvc *service.AuditService
|
||||
}
|
||||
|
||||
const chatwootAttachmentResultsPerPage = 100
|
||||
|
||||
// NewConversationHandler creates a new ConversationHandler.
|
||||
func NewConversationHandler(conversationSvc *service.ConversationService, messageSvc *service.MessageService) *ConversationHandler {
|
||||
return &ConversationHandler{conversationSvc: conversationSvc, messageSvc: messageSvc}
|
||||
@@ -763,12 +765,12 @@ func (h *ConversationHandler) ListAttachments(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
p := pagination.Parse(c)
|
||||
_, offset := fixedPageOffset(c, chatwootAttachmentResultsPerPage)
|
||||
conversation, ok := h.resolveConversationRoute(c, accountID, conversationID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
attachments, total, svcErr := h.messageSvc.ListAttachments(c.Request.Context(), accountID, conversation.ID, p.Offset, p.PerPage)
|
||||
attachments, total, svcErr := h.messageSvc.ListAttachments(c.Request.Context(), accountID, conversation.ID, offset, chatwootAttachmentResultsPerPage)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -446,6 +447,41 @@ func (s *ConversationHandlerTestSuite) TestListAttachmentsReturnsChatwootPayload
|
||||
assert.Contains(s.T(), item, "created_at")
|
||||
}
|
||||
|
||||
func (s *ConversationHandlerTestSuite) TestListAttachmentsUsesChatwootFixedPageSize() {
|
||||
conversation := &model.Conversation{AccountID: s.testAccount.ID, InboxID: s.testConv.InboxID, ContactID: s.testConv.ContactID, Status: "open", ChannelType: "web_widget", Channel: "web_widget"}
|
||||
s.Require().NoError(s.db.Create(conversation).Error)
|
||||
message := &model.Message{AccountID: s.testAccount.ID, InboxID: conversation.InboxID, ConversationID: conversation.ID, Content: "files", MessageType: "incoming", ContentType: "text", Status: "sent"}
|
||||
s.Require().NoError(s.db.Create(message).Error)
|
||||
|
||||
baseTime := time.Now().Add(-time.Hour)
|
||||
var newestID uint
|
||||
for i := 0; i < 30; i++ {
|
||||
attachment := &model.Attachment{
|
||||
Base: model.Base{CreatedAt: baseTime.Add(time.Duration(i) * time.Minute), UpdatedAt: baseTime.Add(time.Duration(i) * time.Minute)},
|
||||
AccountID: s.testAccount.ID,
|
||||
MessageID: message.ID,
|
||||
FileType: "file",
|
||||
FileURL: fmt.Sprintf("https://cdn.example.com/file-%02d.txt", i),
|
||||
FileName: fmt.Sprintf("file-%02d.txt", i),
|
||||
}
|
||||
s.Require().NoError(s.db.Create(attachment).Error)
|
||||
newestID = attachment.ID
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", fmt.Sprintf("%s/conversations/%d/attachments?per_page=5", s.accountURL(), conversation.ID), nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code, w.Body.String())
|
||||
var resp map[string]any
|
||||
assert.NoError(s.T(), json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
assert.Equal(s.T(), float64(30), resp["meta"].(map[string]any)["total_count"])
|
||||
payload := resp["payload"].([]any)
|
||||
assert.Len(s.T(), payload, 30)
|
||||
first := payload[0].(map[string]any)
|
||||
assert.Equal(s.T(), float64(newestID), first["id"])
|
||||
}
|
||||
|
||||
func (s *ConversationHandlerTestSuite) TestToggleTyping_InvalidAccountID() {
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/accounts/abc/conversations/1/toggle_typing", bytes.NewBufferString(`{"typing_status":"on"}`))
|
||||
|
||||
@@ -66,6 +66,14 @@ func parseIntQueryDefault(c *gin.Context, param string, fallback int) (int, erro
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func fixedPageOffset(c *gin.Context, perPage int) (int, int) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
return page, (page - 1) * perPage
|
||||
}
|
||||
|
||||
func parseUintAnyParam(c *gin.Context, params ...string) (uint, error) {
|
||||
var lastErr error
|
||||
for _, param := range params {
|
||||
|
||||
Reference in New Issue
Block a user