mirror of
				https://github.com/abhinavxd/libredesk.git
				synced 2025-11-04 05:53:30 +00:00 
			
		
		
		
	fix: pagination, adds total pages count and total rows count to results.
This commit is contained in:
		@@ -11,7 +11,7 @@ import (
 | 
			
		||||
	"github.com/zerodha/fastglue"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// handleGetAllConversations retrieves all conversations with pagination, sorting, and filtering.
 | 
			
		||||
// handleGetAllConversations retrieves all conversations.
 | 
			
		||||
func handleGetAllConversations(r *fastglue.Request) error {
 | 
			
		||||
	var (
 | 
			
		||||
		app         = r.Context.(*App)
 | 
			
		||||
@@ -20,12 +20,22 @@ func handleGetAllConversations(r *fastglue.Request) error {
 | 
			
		||||
		page, _     = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page")))
 | 
			
		||||
		pageSize, _ = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page_size")))
 | 
			
		||||
		filters     = string(r.RequestCtx.QueryArgs().Peek("filters"))
 | 
			
		||||
		total       = 0
 | 
			
		||||
	)
 | 
			
		||||
	c, err := app.conversation.GetAllConversationsList(order, orderBy, filters, page, pageSize)
 | 
			
		||||
	conversations, pageSize, err := app.conversation.GetAllConversationsList(order, orderBy, filters, page, pageSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return sendErrorEnvelope(r, err)
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(c)
 | 
			
		||||
	if len(conversations) > 0 {
 | 
			
		||||
		total = conversations[0].Total
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(envelope.PageResults{
 | 
			
		||||
		Results:    conversations,
 | 
			
		||||
		Total:      total,
 | 
			
		||||
		PerPage:    pageSize,
 | 
			
		||||
		TotalPages: total / pageSize,
 | 
			
		||||
		Page:       page,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleGetAssignedConversations retrieves conversations assigned to the current user.
 | 
			
		||||
@@ -38,12 +48,22 @@ func handleGetAssignedConversations(r *fastglue.Request) error {
 | 
			
		||||
		page, _     = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page")))
 | 
			
		||||
		pageSize, _ = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page_size")))
 | 
			
		||||
		filters     = string(r.RequestCtx.QueryArgs().Peek("filters"))
 | 
			
		||||
		total       = 0
 | 
			
		||||
	)
 | 
			
		||||
	c, err := app.conversation.GetAssignedConversationsList(user.ID, order, orderBy, filters, page, pageSize)
 | 
			
		||||
	conversations, pageSize, err := app.conversation.GetAssignedConversationsList(user.ID, order, orderBy, filters, page, pageSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return r.SendErrorEnvelope(fasthttp.StatusInternalServerError, err.Error(), nil, "")
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(c)
 | 
			
		||||
	if len(conversations) > 0 {
 | 
			
		||||
		total = conversations[0].Total
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(envelope.PageResults{
 | 
			
		||||
		Results:    conversations,
 | 
			
		||||
		Total:      total,
 | 
			
		||||
		PerPage:    pageSize,
 | 
			
		||||
		TotalPages: total / pageSize,
 | 
			
		||||
		Page:       page,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleGetUnassignedConversations retrieves unassigned conversations.
 | 
			
		||||
@@ -56,12 +76,22 @@ func handleGetUnassignedConversations(r *fastglue.Request) error {
 | 
			
		||||
		page, _     = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page")))
 | 
			
		||||
		pageSize, _ = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page_size")))
 | 
			
		||||
		filters     = string(r.RequestCtx.QueryArgs().Peek("filters"))
 | 
			
		||||
		total       = 0
 | 
			
		||||
	)
 | 
			
		||||
	c, err := app.conversation.GetUnassignedConversationsList(user.ID, order, orderBy, filters, page, pageSize)
 | 
			
		||||
	conversations, pageSize, err := app.conversation.GetUnassignedConversationsList(user.ID, order, orderBy, filters, page, pageSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return r.SendErrorEnvelope(fasthttp.StatusInternalServerError, err.Error(), nil, "")
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(c)
 | 
			
		||||
	if len(conversations) > 0 {
 | 
			
		||||
		total = conversations[0].Total
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(envelope.PageResults{
 | 
			
		||||
		Results:    conversations,
 | 
			
		||||
		Total:      total,
 | 
			
		||||
		PerPage:    pageSize,
 | 
			
		||||
		TotalPages: total / pageSize,
 | 
			
		||||
		Page:       page,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleGetConversation retrieves a single conversation by UUID with permission checks.
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/abhinavxd/artemis/internal/conversation"
 | 
			
		||||
	cmodels "github.com/abhinavxd/artemis/internal/conversation/models"
 | 
			
		||||
	"github.com/abhinavxd/artemis/internal/envelope"
 | 
			
		||||
	medModels "github.com/abhinavxd/artemis/internal/media/models"
 | 
			
		||||
	umodels "github.com/abhinavxd/artemis/internal/user/models"
 | 
			
		||||
	"github.com/valyala/fasthttp"
 | 
			
		||||
@@ -24,6 +25,7 @@ func handleGetMessages(r *fastglue.Request) error {
 | 
			
		||||
		user        = r.RequestCtx.UserValue("user").(umodels.User)
 | 
			
		||||
		page, _     = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page")))
 | 
			
		||||
		pageSize, _ = strconv.Atoi(string(r.RequestCtx.QueryArgs().Peek("page_size")))
 | 
			
		||||
		total       = 0
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Check permission
 | 
			
		||||
@@ -32,17 +34,24 @@ func handleGetMessages(r *fastglue.Request) error {
 | 
			
		||||
		return sendErrorEnvelope(r, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	messages, err := app.conversation.GetConversationMessages(uuid, page, pageSize)
 | 
			
		||||
	messages, pageSize, err := app.conversation.GetConversationMessages(uuid, page, pageSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return sendErrorEnvelope(r, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range messages {
 | 
			
		||||
		total = messages[i].Total
 | 
			
		||||
		for j := range messages[i].Attachments {
 | 
			
		||||
			messages[i].Attachments[j].URL = app.media.GetURL(messages[i].Attachments[j].UUID)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return r.SendEnvelope(messages)
 | 
			
		||||
	return r.SendEnvelope(envelope.PageResults{
 | 
			
		||||
		Total:      total,
 | 
			
		||||
		Results:    messages,
 | 
			
		||||
		Page:       page,
 | 
			
		||||
		PerPage:    pageSize,
 | 
			
		||||
		TotalPages: total / pageSize,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func handleGetMessage(r *fastglue.Request) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ const nonInlineAttachments = computed(() =>
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const getFullName = computed(() => {
 | 
			
		||||
  return convStore.current.contact.first_name + ' ' + convStore.current.last_name
 | 
			
		||||
  return convStore.current.contact.first_name + ' ' + convStore.current.contact.last_name
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const avatarFallback = computed(() => {
 | 
			
		||||
 
 | 
			
		||||
@@ -146,29 +146,19 @@ export const useConversationStore = defineStore('conversation', () => {
 | 
			
		||||
    messages.loading = true
 | 
			
		||||
    try {
 | 
			
		||||
      const response = await api.getConversationMessages(uuid, messages.page)
 | 
			
		||||
      const fetchedMessages = response.data?.data || []
 | 
			
		||||
 | 
			
		||||
      const result = response.data?.data || {}
 | 
			
		||||
      const results = result.results || []
 | 
			
		||||
      // Filter out messages already seen.
 | 
			
		||||
      const newMessages = fetchedMessages.filter((message) => {
 | 
			
		||||
      const newMessages = results.filter((message) => {
 | 
			
		||||
        if (!seenMessageUUIDs.has(message.uuid)) {
 | 
			
		||||
          seenMessageUUIDs.add(message.uuid)
 | 
			
		||||
          return true
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (newMessages.length === 0 && messages.page === 1) {
 | 
			
		||||
        messages.data = []
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (newMessages.length === 0 && messages.page > 1) {
 | 
			
		||||
        messages.hasMore = false
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Add new messages to the messages state.
 | 
			
		||||
      if (newMessages.length === 0 && messages.page === 1) messages.data = []
 | 
			
		||||
      if (result.total_pages <= messages.page) messages.hasMore = false
 | 
			
		||||
      messages.data.unshift(...newMessages)
 | 
			
		||||
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
 | 
			
		||||
        title: 'Something went wrong',
 | 
			
		||||
@@ -250,22 +240,17 @@ export const useConversationStore = defineStore('conversation', () => {
 | 
			
		||||
        default:
 | 
			
		||||
          return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (response?.data?.data) {
 | 
			
		||||
        const newConversations = response.data.data.filter((conversation) => {
 | 
			
		||||
          if (!seenConversationUUIDs.has(conversation.uuid)) {
 | 
			
		||||
            seenConversationUUIDs.set(conversation.uuid, true)
 | 
			
		||||
            return true
 | 
			
		||||
          }
 | 
			
		||||
          return false
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if (!conversations.data) conversations.data = []
 | 
			
		||||
        if (newConversations.length === 0) conversations.hasMore = false
 | 
			
		||||
        conversations.data.push(...newConversations)
 | 
			
		||||
      } else {
 | 
			
		||||
        conversations.hasMore = false
 | 
			
		||||
      }
 | 
			
		||||
      const apiResponse = response.data.data
 | 
			
		||||
      const newConversations = apiResponse.results.filter((conversation) => {
 | 
			
		||||
        if (!seenConversationUUIDs.has(conversation.uuid)) {
 | 
			
		||||
          seenConversationUUIDs.set(conversation.uuid, true)
 | 
			
		||||
          return true
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
      })
 | 
			
		||||
      if (apiResponse.total_pages <= conversations.page) conversations.hasMore = false
 | 
			
		||||
      if (!conversations.data) conversations.data = []
 | 
			
		||||
      conversations.data.push(...newConversations)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      conversations.errorMessage = handleHTTPError(error).message
 | 
			
		||||
      emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
 | 
			
		||||
 
 | 
			
		||||
@@ -289,59 +289,48 @@ func (c *Manager) GetConversationUUID(id int) (string, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllConversationsList retrieves all conversations with optional filtering, ordering, and pagination.
 | 
			
		||||
func (c *Manager) GetAllConversationsList(order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
 | 
			
		||||
func (c *Manager) GetAllConversationsList(order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
 | 
			
		||||
	return c.GetConversations(0, models.AllConversations, order, orderBy, filters, page, pageSize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAssignedConversationsList retrieves conversations assigned to a specific user with optional filtering, ordering, and pagination.
 | 
			
		||||
func (c *Manager) GetAssignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
 | 
			
		||||
func (c *Manager) GetAssignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
 | 
			
		||||
	return c.GetConversations(userID, models.AssignedConversations, order, orderBy, filters, page, pageSize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetUnassignedConversationsList retrieves conversations assigned to a team the user is part of with optional filtering, ordering, and pagination.
 | 
			
		||||
func (c *Manager) GetUnassignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
 | 
			
		||||
func (c *Manager) GetUnassignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
 | 
			
		||||
	return c.GetConversations(userID, models.UnassignedConversations, order, orderBy, filters, page, pageSize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetConversations retrieves conversations list based on user ID, type, and optional filtering, ordering, and pagination.
 | 
			
		||||
func (c *Manager) GetConversations(userID int, listType, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
 | 
			
		||||
func (c *Manager) GetConversations(userID int, listType, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
 | 
			
		||||
	var conversations = make([]models.Conversation, 0)
 | 
			
		||||
 | 
			
		||||
	if orderBy == "" {
 | 
			
		||||
		orderBy = "last_message_at"
 | 
			
		||||
	}
 | 
			
		||||
	if order == "" {
 | 
			
		||||
		order = "DESC"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if filters == "" {
 | 
			
		||||
		filters = "[]"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	query, qArgs, err := c.makeConversationsListQuery(userID, c.q.GetConversations, listType, order, orderBy, page, pageSize, filters)
 | 
			
		||||
	query, pageSize, qArgs, err := c.makeConversationsListQuery(userID, c.q.GetConversations, listType, order, orderBy, page, pageSize, filters)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return conversations, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
 | 
			
		||||
		return conversations, pageSize, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tx, err := c.db.BeginTxx(context.Background(), nil)
 | 
			
		||||
	defer tx.Rollback()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.lo.Error("error preparing get conversations query", "error", err)
 | 
			
		||||
		return conversations, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
 | 
			
		||||
		return conversations, pageSize, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := tx.Select(&conversations, query, qArgs...); err != nil {
 | 
			
		||||
		c.lo.Error("error fetching conversations", "error", err)
 | 
			
		||||
		return conversations, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
 | 
			
		||||
		return conversations, pageSize, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
 | 
			
		||||
	}
 | 
			
		||||
	return conversations, nil
 | 
			
		||||
	return conversations, pageSize, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetConversationsListUUIDs retrieves the UUIDs of conversations list.
 | 
			
		||||
func (c *Manager) GetConversationsListUUIDs(userID, page, pageSize int, typ string) ([]string, error) {
 | 
			
		||||
	var ids = make([]string, 0)
 | 
			
		||||
 | 
			
		||||
	query, qArgs, err := c.makeConversationsListQuery(userID, c.q.GetConversationsListUUIDs, typ, "", "", page, pageSize, "")
 | 
			
		||||
	query, _, qArgs, err := c.makeConversationsListQuery(userID, c.q.GetConversationsListUUIDs, typ, "", "", page, pageSize, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.lo.Error("error generating conversations query", "error", err)
 | 
			
		||||
		return ids, err
 | 
			
		||||
@@ -560,12 +549,27 @@ func (t *Manager) UpsertConversationTags(uuid string, tagIDs []int) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// makeConversationsListQuery prepares a SQL query string for conversations list
 | 
			
		||||
func (c *Manager) makeConversationsListQuery(userID int, baseQuery, listType, order, orderBy string, page, pageSize int, filtersJSON string) (string, []interface{}, error) {
 | 
			
		||||
func (c *Manager) makeConversationsListQuery(userID int, baseQuery, listType, order, orderBy string, page, pageSize int, filtersJSON string) (string, int, []interface{}, error) {
 | 
			
		||||
	var qArgs []interface{}
 | 
			
		||||
 | 
			
		||||
	if orderBy == "" {
 | 
			
		||||
		orderBy = "last_message_at"
 | 
			
		||||
	}
 | 
			
		||||
	if order == "" {
 | 
			
		||||
		order = "DESC"
 | 
			
		||||
	}
 | 
			
		||||
	if filtersJSON == "" {
 | 
			
		||||
		filtersJSON = "[]"
 | 
			
		||||
	}
 | 
			
		||||
	if pageSize > conversationsListMaxPageSize {
 | 
			
		||||
		pageSize = conversationsListMaxPageSize
 | 
			
		||||
	}
 | 
			
		||||
	if pageSize < 1 {
 | 
			
		||||
		pageSize = 10
 | 
			
		||||
	}
 | 
			
		||||
	if page < 1 {
 | 
			
		||||
		page = 1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set condition based on the list type.
 | 
			
		||||
	switch listType {
 | 
			
		||||
@@ -578,7 +582,7 @@ func (c *Manager) makeConversationsListQuery(userID int, baseQuery, listType, or
 | 
			
		||||
	case models.AllConversations:
 | 
			
		||||
		baseQuery = fmt.Sprintf(baseQuery, "")
 | 
			
		||||
	default:
 | 
			
		||||
		return "", nil, fmt.Errorf("invalid conversation type %s", listType)
 | 
			
		||||
		return "", pageSize, nil, fmt.Errorf("invalid conversation type %s", listType)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	query, qArgs, err := dbutil.PaginateAndFilterQuery(baseQuery, qArgs, dbutil.PaginationOptions{
 | 
			
		||||
@@ -591,10 +595,10 @@ func (c *Manager) makeConversationsListQuery(userID int, baseQuery, listType, or
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.lo.Error("error preparing query", "error", err)
 | 
			
		||||
		return "", nil, err
 | 
			
		||||
		return "", pageSize, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return query, qArgs, err
 | 
			
		||||
	return query, pageSize, qArgs, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetToAddress retrieves the recipient addresses for a conversation.
 | 
			
		||||
 
 | 
			
		||||
@@ -212,32 +212,32 @@ func (m *Manager) RenderContentInTemplate(channel string, message *models.Messag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetConversationMessages retrieves messages for a specific conversation.
 | 
			
		||||
func (m *Manager) GetConversationMessages(conversationUUID string, page, pageSize int) ([]models.Message, error) {
 | 
			
		||||
func (m *Manager) GetConversationMessages(conversationUUID string, page, pageSize int) ([]models.Message, int, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		messages = make([]models.Message, 0)
 | 
			
		||||
		qArgs    []interface{}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	qArgs = append(qArgs, conversationUUID)
 | 
			
		||||
	query, qArgs, err := m.generateMessagesQuery(m.q.GetMessages, qArgs, page, pageSize)
 | 
			
		||||
	query, pageSize, qArgs, err := m.generateMessagesQuery(m.q.GetMessages, qArgs, page, pageSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		m.lo.Error("error generating messages query", "error", err)
 | 
			
		||||
		return messages, envelope.NewError(envelope.GeneralError, "Error fetching messages", nil)
 | 
			
		||||
		return messages, pageSize, envelope.NewError(envelope.GeneralError, "Error fetching messages", nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tx, err := m.db.BeginTxx(context.Background(), nil)
 | 
			
		||||
	defer tx.Rollback()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		m.lo.Error("error preparing get messages query", "error", err)
 | 
			
		||||
		return messages, envelope.NewError(envelope.GeneralError, "Error fetching messages", nil)
 | 
			
		||||
		return messages, pageSize, envelope.NewError(envelope.GeneralError, "Error fetching messages", nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := tx.Select(&messages, query, qArgs...); err != nil {
 | 
			
		||||
		m.lo.Error("error fetching conversations", "error", err)
 | 
			
		||||
		return messages, envelope.NewError(envelope.GeneralError, "Error fetching messages", nil)
 | 
			
		||||
		return messages, pageSize, envelope.NewError(envelope.GeneralError, "Error fetching messages", nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return messages, nil
 | 
			
		||||
	return messages, pageSize, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMessage retrieves a message by UUID.
 | 
			
		||||
@@ -489,14 +489,16 @@ func (m *Manager) GetConversationByMessageID(id int) (models.Conversation, error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// generateMessagesQuery generates the SQL query for fetching messages in a conversation.
 | 
			
		||||
func (c *Manager) generateMessagesQuery(baseQuery string, qArgs []interface{}, page, pageSize int) (string, []interface{}, error) {
 | 
			
		||||
	// Set default values for page and page size if they are invalid
 | 
			
		||||
func (c *Manager) generateMessagesQuery(baseQuery string, qArgs []interface{}, page, pageSize int) (string, int, []interface{}, error) {
 | 
			
		||||
	if page <= 0 {
 | 
			
		||||
		page = 1
 | 
			
		||||
	}
 | 
			
		||||
	if pageSize <= 0 || pageSize > maxMessagesPerPage {
 | 
			
		||||
	if pageSize > maxMessagesPerPage {
 | 
			
		||||
		pageSize = maxMessagesPerPage
 | 
			
		||||
	}
 | 
			
		||||
	if pageSize <= 0 {
 | 
			
		||||
		pageSize = 10
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Calculate the offset
 | 
			
		||||
	offset := (page - 1) * pageSize
 | 
			
		||||
@@ -506,7 +508,7 @@ func (c *Manager) generateMessagesQuery(baseQuery string, qArgs []interface{}, p
 | 
			
		||||
 | 
			
		||||
	// Include LIMIT and OFFSET in the SQL query
 | 
			
		||||
	sqlQuery := fmt.Sprintf(baseQuery, fmt.Sprintf("LIMIT $%d OFFSET $%d", len(qArgs)-1, len(qArgs)))
 | 
			
		||||
	return sqlQuery, qArgs, nil
 | 
			
		||||
	return sqlQuery, pageSize, qArgs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// uploadMessageAttachments uploads attachments for a message.
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@ type Conversation struct {
 | 
			
		||||
	LastMessageAt      null.Time       `db:"last_message_at" json:"last_message_at"`
 | 
			
		||||
	LastMessage        string          `db:"last_message" json:"last_message"`
 | 
			
		||||
	Contact            cmodels.Contact `db:"contact" json:"contact"`
 | 
			
		||||
	Total              int             `db:"total" json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ConversationParticipant struct {
 | 
			
		||||
@@ -93,6 +94,7 @@ type Message struct {
 | 
			
		||||
	InReplyTo        string                 `json:"-"`
 | 
			
		||||
	Headers          textproto.MIMEHeader   `json:"-"`
 | 
			
		||||
	Media            []mmodels.Media        `db:"-" json:"-"`
 | 
			
		||||
	Total            int                    `db:"total" json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IncomingMessage links a message with the contact information and inbox id.
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ RETURNING id, uuid;
 | 
			
		||||
 | 
			
		||||
-- name: get-conversations
 | 
			
		||||
SELECT
 | 
			
		||||
    COUNT(*) OVER() AS total,
 | 
			
		||||
    conversations.updated_at,
 | 
			
		||||
    conversations.uuid,
 | 
			
		||||
    conversations.assignee_last_seen_at,
 | 
			
		||||
@@ -368,6 +369,7 @@ attachments AS (
 | 
			
		||||
    GROUP BY message_id
 | 
			
		||||
)
 | 
			
		||||
SELECT
 | 
			
		||||
    COUNT(*) OVER() AS total,
 | 
			
		||||
    m.created_at,
 | 
			
		||||
    m.updated_at,
 | 
			
		||||
    m.status,
 | 
			
		||||
 
 | 
			
		||||
@@ -47,14 +47,6 @@ func PaginateAndFilterQuery(baseQuery string, existingArgs []interface{}, opts P
 | 
			
		||||
		return "", nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate and set default values for pagination
 | 
			
		||||
	if opts.Page <= 0 {
 | 
			
		||||
		opts.Page = 1
 | 
			
		||||
	}
 | 
			
		||||
	if opts.PageSize <= 0 {
 | 
			
		||||
		opts.PageSize = 10 // Default page size
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Calculate offset
 | 
			
		||||
	offset := (opts.Page - 1) * opts.PageSize
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,15 @@ func (e Error) Error() string {
 | 
			
		||||
	return e.Message
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PageResults is a generic struct for paginated results.
 | 
			
		||||
type PageResults struct {
 | 
			
		||||
	Results    interface{} `json:"results"`
 | 
			
		||||
	Total      int         `json:"total"`
 | 
			
		||||
	PerPage    int         `json:"per_page"`
 | 
			
		||||
	TotalPages int         `json:"total_pages"`
 | 
			
		||||
	Page       int         `json:"page"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewError creates and returns a new instance of Error with custom error metadata.
 | 
			
		||||
func NewError(etype string, message string, data interface{}) error {
 | 
			
		||||
	err := Error{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user