perf(web): add pagination

and remove getting total quotes count
This commit is contained in:
Masahiko AMANO 2025-01-07 04:04:06 +03:00
parent 65152526b7
commit 8b417dc623
5 changed files with 51 additions and 60 deletions

View File

@ -162,17 +162,6 @@ func quotesGet(c *gin.Context) {
c.JSON(http.StatusOK, quotes)
}
func quotesCount(c *gin.Context) {
user_id := c.GetString("user_id")
count, err := db.QuotesCount(context.Background(), user_id)
if err != nil {
status, message := handleDBError(err)
c.JSON(status, gin.H{"error": message})
return
}
c.JSON(http.StatusOK, gin.H{"count": count})
}
func quoteGet(c *gin.Context) {
user_id := c.GetString("user_id")
quote_id := c.Param("id")

View File

@ -26,7 +26,6 @@ func RegisterRoutes(r *gin.Engine) {
api.DELETE("/auth", userLogout)
api.GET("/quotes", MiddlewareAuth, quotesGet)
api.GET("/quotes/count", MiddlewareAuth, quotesCount)
api.POST("/quotes", MiddlewareAuth, quoteAdd)
api.GET("/quotes/:id", MiddlewareAuth, quoteGet)
api.PATCH("/quotes/:id", MiddlewareAuth, quoteUpdate)

View File

@ -72,13 +72,13 @@ func UserUpdatePassword(ctx context.Context, user_id string, new_password string
//#region Quotes
func QuotesGet(ctx context.Context, user_id string, filter string, sort string, limit int, offset int) (quotes []models.Quote, err error) {
query := "SELECT * FROM quotes_get($1) WHERE position($2 in lower(text))>0 OR position($2 in lower(author))>0"
func QuotesGet(ctx context.Context, user_id string, filter string, sort string, limit int, offset int) (quotes models.Quotes, err error) {
queryGet := "SELECT * FROM quotes_get($1) WHERE position($2 in lower(text))>0 OR position($2 in lower(author))>0"
if sort == "random" {
query += " ORDER BY random()"
queryGet += " ORDER BY random()"
} else if sort != "" {
sort_options := strings.Split(sort, ",")
query += " ORDER BY "
queryGet += " ORDER BY "
for i, sort_option := range sort_options {
sort_order := sort_option[:1]
sort_field := sort_option[1:]
@ -105,23 +105,26 @@ func QuotesGet(ctx context.Context, user_id string, filter string, sort string,
return
}
if i > 0 {
query += ", "
queryGet += ", "
}
query += fmt.Sprintf("%s %s", sort_field, sort_order)
queryGet += fmt.Sprintf("%s %s", sort_field, sort_order)
}
}
queryCount := queryGet
if limit >= 0 {
query += fmt.Sprintf(" LIMIT %d", limit)
queryGet += fmt.Sprintf(" LIMIT %d", limit)
}
if offset > 0 {
query += fmt.Sprintf(" OFFSET %d", offset)
queryGet += fmt.Sprintf(" OFFSET %d", offset)
}
rows, err := ConnPool.Query(ctx, query, user_id, strings.ToLower(filter))
filter = strings.ToLower(filter)
rows, err := ConnPool.Query(ctx, queryGet, user_id, filter)
if err != nil {
err = fmt.Errorf("error while getting quotes: %w", err)
return
}
quotes = []models.Quote{}
quotes.Quotes = []models.Quote{}
count := 0
for rows.Next() {
var quote models.Quote
err = rows.Scan(&quote.ID, &quote.Text, &quote.Author, &quote.Datetime, &quote.Creator.ID, &quote.Creator.Name, &quote.Creator.Login, &quote.Creator.Role, &quote.Creator.TelegramID)
@ -129,15 +132,19 @@ func QuotesGet(ctx context.Context, user_id string, filter string, sort string,
err = fmt.Errorf("error while fetching quotes: %w", err)
return
}
quotes = append(quotes, quote)
quotes.Quotes = append(quotes.Quotes, quote)
count++
}
err = rows.Err()
return
}
func QuotesCount(ctx context.Context, user_id string) (count int, err error) {
row := ConnPool.QueryRow(ctx, "SELECT count(*) FROM quotes_get($1)", user_id)
err = row.Scan(&count)
if err != nil {
return
}
quotes.Pagination.Limit = limit
quotes.Pagination.Offset = offset
quotes.Pagination.Count = count
queryCount = fmt.Sprintf("SELECT count(*) FROM (%s) q", queryCount)
row := ConnPool.QueryRow(ctx, queryCount, user_id, filter)
err = row.Scan(&quotes.Pagination.TotalCount)
return
}

View File

@ -27,3 +27,15 @@ type Quote struct {
Datetime time.Time `json:"datetime"`
Creator User `json:"creator"`
}
type Pagination struct {
TotalCount int `json:"totalCount"`
Offset int `json:"offset"`
Limit int `json:"limit"`
Count int `json:"count"`
}
type Quotes struct {
Pagination Pagination `json:"pagination"`
Quotes []Quote `json:"quotes"`
}

View File

@ -45,28 +45,33 @@ function renderBlockQuote(quote) {
function load() {
var quotesCount;
failed = false;
$("#input-search").val(search);
$("#input-sorting").val(sorting);
container = $("#block-quotes");
$.ajax({
async: false,
url: "/api/quotes/count",
url: `/api/quotes?filter=${encodeURIComponent(search)}&sort=${encodeURIComponent(sorting)}&limit=${PAGE_SIZE}&offset=${(currPage - 1)*PAGE_SIZE}`,
type: "GET",
dataType: "json",
success: function (resp) {
quotesCount = resp.count;
quotesCount = resp.pagination.totalCount
if (resp.pagination.count == 0) {
container.html("<p style='text-align: center;'><i>Чёт нету ничего...</i></p>");
return;
}
resp.quotes.forEach((quote) => {
container.append(renderBlockQuote(quote));
});
},
error: function (err) {
$("#error-message").text(err.responseJSON.error);
$("#error").removeClass("hidden");
failed = true;
},
complete: function () {
$("#block-quotes-loader").addClass("hidden");
},
});
if (failed) {
return;
}
totalPages = Math.ceil(quotesCount / PAGE_SIZE);
$("#input-search").val(search);
$("#input-sorting").val(sorting);
$("#btn-page-curr").text(currPage);
if (currPage > 1) {
$("#btn-page-first").removeClass("hidden");
@ -89,28 +94,6 @@ function load() {
}
}
}
container = $("#block-quotes");
$.ajax({
url: `/api/quotes?filter=${encodeURIComponent(search)}&sort=${encodeURIComponent(sorting)}&limit=${PAGE_SIZE}&offset=${(currPage - 1)*PAGE_SIZE}`,
type: "GET",
dataType: "json",
success: function (resp) {
if (resp.length == 0) {
container.html("<p style='text-align: center;'><i>Чёт нету ничего...</i></p>");
return;
}
resp.forEach((quote) => {
container.append(renderBlockQuote(quote));
});
},
error: function (err) {
$("#error-message").text(err.responseJSON.error);
$("#error").removeClass("hidden");
},
complete: function () {
$("#block-quotes-loader").addClass("hidden");
},
});
}
function reload() {
@ -122,6 +105,7 @@ function reload() {
$("#btn-page-first").addClass("hidden");
$("#pages-prev").addClass("hidden");
$("#btn-page-prev").addClass("hidden");
$("#btn-page-curr").text(1);
$("#btn-page-next").addClass("hidden");
$("#pages-next").addClass("hidden");
$("#btn-page-last").addClass("hidden");