feat: articles pagination
This commit is contained in:
1 parent
a2d224240c
commit
73f4b539fe
45 files changed
+3528
-317
No files matched your search
@@ -7,6 +7,11 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
type mockArticleRepo struct {
|
||||
@@ -47,6 +52,85 @@ func (m *mockArticleRepo) FindByFilters(filters article.Filters) ([]article.Arti
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (m *mockArticleRepo) FindPage(filters article.Filters) (article.PageResult, error) {
|
||||
if err := m.fail.trigger("FindPage"); err != nil {
|
||||
return article.PageResult{}, err
|
||||
}
|
||||
matching := make([]article.Article, 0)
|
||||
for _, a := range m.articles {
|
||||
if filters.IsOnline != nil && a.IsOnline != *filters.IsOnline {
|
||||
continue
|
||||
}
|
||||
if filters.Status == article.StatusOnline && !a.IsOnline {
|
||||
continue
|
||||
}
|
||||
if filters.Status == article.StatusDraft && a.IsOnline {
|
||||
continue
|
||||
}
|
||||
if filters.Q != "" && !strings.Contains(foldArticleSearch(a.Title), foldArticleSearch(filters.Q)) {
|
||||
continue
|
||||
}
|
||||
matching = append(matching, a)
|
||||
}
|
||||
sort.Slice(matching, func(i, j int) bool { return articleSortsBefore(matching[i], matching[j], filters.Sort) })
|
||||
start := min((filters.Page-1)*filters.Size, len(matching))
|
||||
end := min(start+filters.Size, len(matching))
|
||||
return article.PageResult{Items: matching[start:end], Total: len(matching)}, nil
|
||||
}
|
||||
|
||||
func (m *mockArticleRepo) CountByVisibility(onlineOnly bool) (article.Counts, error) {
|
||||
if err := m.fail.trigger("CountByVisibility"); err != nil {
|
||||
return article.Counts{}, err
|
||||
}
|
||||
counts := article.Counts{}
|
||||
for _, a := range m.articles {
|
||||
if a.IsOnline {
|
||||
counts.Online++
|
||||
} else if !onlineOnly {
|
||||
counts.Draft++
|
||||
}
|
||||
}
|
||||
counts.All = counts.Online + counts.Draft
|
||||
return counts, nil
|
||||
}
|
||||
|
||||
func articleSortsBefore(left, right article.Article, order article.Sort) bool {
|
||||
if order.Field == "" {
|
||||
order = article.DefaultSort()
|
||||
}
|
||||
var comparison int
|
||||
switch order.Field {
|
||||
case article.SortByTitle:
|
||||
comparison = strings.Compare(strings.ToLower(left.Title), strings.ToLower(right.Title))
|
||||
case article.SortByStatus:
|
||||
if left.IsOnline != right.IsOnline {
|
||||
comparison = 1
|
||||
if !left.IsOnline {
|
||||
comparison = -1
|
||||
}
|
||||
}
|
||||
case article.SortByCreatedAt:
|
||||
comparison = left.CreatedAt.Compare(right.CreatedAt)
|
||||
default:
|
||||
comparison = left.UpdatedAt.Compare(right.UpdatedAt)
|
||||
}
|
||||
if order.Direction == article.SortDesc {
|
||||
comparison = -comparison
|
||||
}
|
||||
if comparison != 0 {
|
||||
return comparison < 0
|
||||
}
|
||||
return left.ID > right.ID
|
||||
}
|
||||
|
||||
func foldArticleSearch(value string) string {
|
||||
folded, _, err := transform.String(transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC), value)
|
||||
if err != nil {
|
||||
return strings.ToLower(value)
|
||||
}
|
||||
return strings.ToLower(folded)
|
||||
}
|
||||
|
||||
func (m *mockArticleRepo) Get(id uint32) (article.Article, error) {
|
||||
if err := m.fail.trigger("Get"); err != nil {
|
||||
return article.Article{}, err
|
||||
|
||||
Reference in new issue
Block a user