mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-10-15 01:12:06 +00:00
fix: pagination, adds total pages count and total rows count to results.
This commit is contained in:
@@ -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