♻️ Interactive v2 #1
@ -15,26 +15,26 @@ type Article struct {
|
|||||||
Comments []Comment `json:"comments" gorm:"foreignKey:ArticleID"`
|
Comments []Comment `json:"comments" gorm:"foreignKey:ArticleID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Article) GetReplyTo() PostInterface {
|
func (p *Article) GetReplyTo() PostInterface {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Article) GetRepostTo() PostInterface {
|
func (p *Article) GetRepostTo() PostInterface {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Article) GetHashtags() []Tag {
|
func (p *Article) GetHashtags() []Tag {
|
||||||
return p.Hashtags
|
return p.Hashtags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Article) GetCategories() []Category {
|
func (p *Article) GetCategories() []Category {
|
||||||
return p.Categories
|
return p.Categories
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Article) SetHashtags(tags []Tag) {
|
func (p *Article) SetHashtags(tags []Tag) {
|
||||||
p.Hashtags = tags
|
p.Hashtags = tags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Article) SetCategories(categories []Category) {
|
func (p *Article) SetCategories(categories []Category) {
|
||||||
p.Categories = categories
|
p.Categories = categories
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,22 @@ type Comment struct {
|
|||||||
Moment *Moment `json:"moment"`
|
Moment *Moment `json:"moment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Comment) GetReplyTo() PostInterface {
|
func (p *Comment) GetReplyTo() PostInterface {
|
||||||
return p.ReplyTo
|
return p.ReplyTo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Comment) GetHashtags() []Tag {
|
func (p *Comment) GetHashtags() []Tag {
|
||||||
return p.Hashtags
|
return p.Hashtags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Comment) GetCategories() []Category {
|
func (p *Comment) GetCategories() []Category {
|
||||||
return p.Categories
|
return p.Categories
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Comment) SetHashtags(tags []Tag) {
|
func (p *Comment) SetHashtags(tags []Tag) {
|
||||||
p.Hashtags = tags
|
p.Hashtags = tags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Comment) SetCategories(categories []Category) {
|
func (p *Comment) SetCategories(categories []Category) {
|
||||||
p.Categories = categories
|
p.Categories = categories
|
||||||
}
|
}
|
||||||
|
@ -15,26 +15,26 @@ type Moment struct {
|
|||||||
Comments []Comment `json:"comments" gorm:"foreignKey:MomentID"`
|
Comments []Comment `json:"comments" gorm:"foreignKey:MomentID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Moment) GetRepostTo() PostInterface {
|
func (p *Moment) GetRepostTo() PostInterface {
|
||||||
return p.RepostTo
|
return p.RepostTo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Moment) GetRealm() *Realm {
|
func (p *Moment) GetRealm() *Realm {
|
||||||
return p.Realm
|
return p.Realm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Moment) GetHashtags() []Tag {
|
func (p *Moment) GetHashtags() []Tag {
|
||||||
return p.Hashtags
|
return p.Hashtags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Moment) GetCategories() []Category {
|
func (p *Moment) GetCategories() []Category {
|
||||||
return p.Categories
|
return p.Categories
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Moment) SetHashtags(tags []Tag) {
|
func (p *Moment) SetHashtags(tags []Tag) {
|
||||||
p.Hashtags = tags
|
p.Hashtags = tags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Moment) SetCategories(categories []Category) {
|
func (p *Moment) SetCategories(categories []Category) {
|
||||||
p.Categories = categories
|
p.Categories = categories
|
||||||
}
|
}
|
||||||
|
@ -22,29 +22,34 @@ type PostBase struct {
|
|||||||
AuthorID uint `json:"author_id"`
|
AuthorID uint `json:"author_id"`
|
||||||
Author Account `json:"author"`
|
Author Account `json:"author"`
|
||||||
|
|
||||||
// TODO Give the reactions & replies & reposts info back
|
// Dynamic Calculated Values
|
||||||
|
ReactionList map[string]int64 `json:"reaction_list" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PostBase) GetID() uint {
|
func (p *PostBase) GetID() uint {
|
||||||
return p.ID
|
return p.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PostBase) GetReplyTo() PostInterface {
|
func (p *PostBase) GetReplyTo() PostInterface {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PostBase) GetRepostTo() PostInterface {
|
func (p *PostBase) GetRepostTo() PostInterface {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PostBase) GetAuthor() Account {
|
func (p *PostBase) GetAuthor() Account {
|
||||||
return p.Author
|
return p.Author
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PostBase) GetRealm() *Realm {
|
func (p *PostBase) GetRealm() *Realm {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PostBase) SetReactionList(list map[string]int64) {
|
||||||
|
p.ReactionList = list
|
||||||
|
}
|
||||||
|
|
||||||
type PostInterface interface {
|
type PostInterface interface {
|
||||||
GetID() uint
|
GetID() uint
|
||||||
GetHashtags() []Tag
|
GetHashtags() []Tag
|
||||||
@ -56,4 +61,5 @@ type PostInterface interface {
|
|||||||
|
|
||||||
SetHashtags([]Tag)
|
SetHashtags([]Tag)
|
||||||
SetCategories([]Category)
|
SetCategories([]Category)
|
||||||
|
SetReactionList(map[string]int64)
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func contextArticle() *services.PostTypeContext[models.Article] {
|
func contextArticle() *services.PostTypeContext[*models.Article] {
|
||||||
return &services.PostTypeContext[models.Article]{
|
return &services.PostTypeContext[*models.Article]{
|
||||||
Tx: database.C,
|
Tx: database.C,
|
||||||
TypeName: "Article",
|
TypeName: "Article",
|
||||||
CanReply: false,
|
CanReply: false,
|
||||||
@ -31,6 +31,11 @@ func getArticle(c *fiber.Ctx) error {
|
|||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.ReactionList, err = mx.CountReactions(item.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
return c.JSON(item)
|
return c.JSON(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +107,7 @@ func createArticle(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextArticle()
|
mx := contextArticle()
|
||||||
|
|
||||||
item := models.Article{
|
item := &models.Article{
|
||||||
PostBase: models.PostBase{
|
PostBase: models.PostBase{
|
||||||
Alias: data.Alias,
|
Alias: data.Alias,
|
||||||
Attachments: data.Attachments,
|
Attachments: data.Attachments,
|
||||||
@ -192,7 +197,7 @@ func reactArticle(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextArticle()
|
mx := contextArticle()
|
||||||
|
|
||||||
item, err := mx.Get(uint(id))
|
item, err := mx.Get(uint(id), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
@ -218,7 +223,7 @@ func deleteArticle(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextArticle().FilterAuthor(user.ID)
|
mx := contextArticle().FilterAuthor(user.ID)
|
||||||
|
|
||||||
item, err := mx.Get(uint(id))
|
item, err := mx.Get(uint(id), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func contextComment() *services.PostTypeContext[models.Comment] {
|
func contextComment() *services.PostTypeContext[*models.Comment] {
|
||||||
return &services.PostTypeContext[models.Comment]{
|
return &services.PostTypeContext[*models.Comment]{
|
||||||
Tx: database.C,
|
Tx: database.C,
|
||||||
TypeName: "Comment",
|
TypeName: "Comment",
|
||||||
CanReply: false,
|
CanReply: false,
|
||||||
@ -32,6 +32,11 @@ func getComment(c *fiber.Ctx) error {
|
|||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.ReactionList, err = mx.CountReactions(item.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
return c.JSON(item)
|
return c.JSON(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +108,7 @@ func createComment(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextComment()
|
mx := contextComment()
|
||||||
|
|
||||||
item := models.Comment{
|
item := &models.Comment{
|
||||||
PostBase: models.PostBase{
|
PostBase: models.PostBase{
|
||||||
Alias: data.Alias,
|
Alias: data.Alias,
|
||||||
Attachments: data.Attachments,
|
Attachments: data.Attachments,
|
||||||
@ -199,7 +204,7 @@ func reactComment(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextComment()
|
mx := contextComment()
|
||||||
|
|
||||||
item, err := mx.Get(uint(id))
|
item, err := mx.Get(uint(id), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
@ -225,7 +230,7 @@ func deleteComment(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextComment().FilterAuthor(user.ID)
|
mx := contextComment().FilterAuthor(user.ID)
|
||||||
|
|
||||||
item, err := mx.Get(uint(id))
|
item, err := mx.Get(uint(id), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"code.smartsheep.studio/hydrogen/interactive/pkg/models"
|
"code.smartsheep.studio/hydrogen/interactive/pkg/models"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/samber/lo"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ type FeedItem struct {
|
|||||||
RealmID *uint `json:"realm_id"`
|
RealmID *uint `json:"realm_id"`
|
||||||
|
|
||||||
Author models.Account `json:"author" gorm:"embedded"`
|
Author models.Account `json:"author" gorm:"embedded"`
|
||||||
|
ReactionList map[string]int64 `json:"reaction_list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -56,7 +58,7 @@ func listFeed(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result []FeedItem
|
var result []*FeedItem
|
||||||
|
|
||||||
userTable := viper.GetString("database.prefix") + "accounts"
|
userTable := viper.GetString("database.prefix") + "accounts"
|
||||||
commentTable := viper.GetString("database.prefix") + "comments"
|
commentTable := viper.GetString("database.prefix") + "comments"
|
||||||
@ -84,6 +86,59 @@ func listFeed(c *fiber.Ctx) error {
|
|||||||
offset,
|
offset,
|
||||||
).Scan(&result)
|
).Scan(&result)
|
||||||
|
|
||||||
|
if !c.QueryBool("noReact", false) {
|
||||||
|
var reactions []struct {
|
||||||
|
PostID uint
|
||||||
|
Symbol string
|
||||||
|
Count int64
|
||||||
|
}
|
||||||
|
|
||||||
|
revertReaction := func(dataset string) error {
|
||||||
|
itemMap := lo.SliceToMap(lo.FilterMap(result, func(item *FeedItem, index int) (*FeedItem, bool) {
|
||||||
|
return item, item.ModelType == dataset
|
||||||
|
}), func(item *FeedItem) (uint, *FeedItem) {
|
||||||
|
return item.ID, item
|
||||||
|
})
|
||||||
|
|
||||||
|
idx := lo.Map(lo.Filter(result, func(item *FeedItem, index int) bool {
|
||||||
|
return item.ModelType == dataset
|
||||||
|
}), func(item *FeedItem, index int) uint {
|
||||||
|
return item.ID
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := database.C.Model(&models.Reaction{}).
|
||||||
|
Select(dataset+"_id as post_id, symbol, COUNT(id) as count").
|
||||||
|
Where(dataset+"_id IN (?)", idx).
|
||||||
|
Group("post_id, symbol").
|
||||||
|
Scan(&reactions).Error; err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
list := map[uint]map[string]int64{}
|
||||||
|
for _, info := range reactions {
|
||||||
|
if _, ok := list[info.PostID]; !ok {
|
||||||
|
list[info.PostID] = make(map[string]int64)
|
||||||
|
}
|
||||||
|
list[info.PostID][info.Symbol] = info.Count
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range list {
|
||||||
|
if post, ok := itemMap[k]; ok {
|
||||||
|
post.ReactionList = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := revertReaction("article"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := revertReaction("moment"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var count int64
|
var count int64
|
||||||
database.C.Raw(`SELECT COUNT(*) FROM (? UNION ALL ?) as feed`,
|
database.C.Raw(`SELECT COUNT(*) FROM (? UNION ALL ?) as feed`,
|
||||||
database.C.Select(queryArticle).Model(&models.Article{}),
|
database.C.Select(queryArticle).Model(&models.Article{}),
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func contextMoment() *services.PostTypeContext[models.Moment] {
|
func contextMoment() *services.PostTypeContext[*models.Moment] {
|
||||||
return &services.PostTypeContext[models.Moment]{
|
return &services.PostTypeContext[*models.Moment]{
|
||||||
Tx: database.C,
|
Tx: database.C,
|
||||||
TypeName: "Moment",
|
TypeName: "Moment",
|
||||||
CanReply: false,
|
CanReply: false,
|
||||||
@ -31,6 +31,11 @@ func getMoment(c *fiber.Ctx) error {
|
|||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.ReactionList, err = mx.CountReactions(item.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
return c.JSON(item)
|
return c.JSON(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +106,7 @@ func createMoment(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextMoment()
|
mx := contextMoment()
|
||||||
|
|
||||||
item := models.Moment{
|
item := &models.Moment{
|
||||||
PostBase: models.PostBase{
|
PostBase: models.PostBase{
|
||||||
Alias: data.Alias,
|
Alias: data.Alias,
|
||||||
Attachments: data.Attachments,
|
Attachments: data.Attachments,
|
||||||
@ -197,7 +202,7 @@ func reactMoment(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextMoment()
|
mx := contextMoment()
|
||||||
|
|
||||||
item, err := mx.Get(uint(id))
|
item, err := mx.Get(uint(id), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
@ -223,7 +228,7 @@ func deleteMoment(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
mx := contextMoment().FilterAuthor(user.ID)
|
mx := contextMoment().FilterAuthor(user.ID)
|
||||||
|
|
||||||
item, err := mx.Get(uint(id))
|
item, err := mx.Get(uint(id), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
|
import "C"
|
||||||
import (
|
import (
|
||||||
"code.smartsheep.studio/hydrogen/identity/pkg/grpc/proto"
|
"code.smartsheep.studio/hydrogen/identity/pkg/grpc/proto"
|
||||||
"code.smartsheep.studio/hydrogen/interactive/pkg/database"
|
"code.smartsheep.studio/hydrogen/interactive/pkg/database"
|
||||||
@ -33,12 +34,16 @@ func (v *PostTypeContext[T]) GetTableName(plural ...bool) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PostTypeContext[T]) Preload() *PostTypeContext[T] {
|
func (v *PostTypeContext[T]) Preload(noComments ...bool) *PostTypeContext[T] {
|
||||||
v.Tx.Preload("Author").
|
v.Tx.Preload("Author").
|
||||||
Preload("Attachments").
|
Preload("Attachments").
|
||||||
Preload("Categories").
|
Preload("Categories").
|
||||||
Preload("Hashtags")
|
Preload("Hashtags")
|
||||||
|
|
||||||
|
if len(noComments) <= 0 || !noComments[0] {
|
||||||
|
v.Tx = v.Tx.Preload("Comments")
|
||||||
|
}
|
||||||
|
|
||||||
if v.CanReply {
|
if v.CanReply {
|
||||||
v.Tx.Preload("ReplyTo")
|
v.Tx.Preload("ReplyTo")
|
||||||
}
|
}
|
||||||
@ -98,18 +103,18 @@ func (v *PostTypeContext[T]) SortCreatedAt(order string) *PostTypeContext[T] {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PostTypeContext[T]) GetViaAlias(alias string) (T, error) {
|
func (v *PostTypeContext[T]) GetViaAlias(alias string, noComments ...bool) (T, error) {
|
||||||
var item T
|
var item T
|
||||||
if err := v.Preload().Tx.Where("alias = ?", alias).First(&item).Error; err != nil {
|
if err := v.Preload(noComments...).Tx.Where("alias = ?", alias).First(&item).Error; err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PostTypeContext[T]) Get(id uint) (T, error) {
|
func (v *PostTypeContext[T]) Get(id uint, noComments ...bool) (T, error) {
|
||||||
var item T
|
var item T
|
||||||
if err := v.Preload().Tx.Where("id = ?", id).First(&item).Error; err != nil {
|
if err := v.Preload(noComments...).Tx.Where("id = ?", id).First(&item).Error; err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +131,28 @@ func (v *PostTypeContext[T]) Count() (int64, error) {
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *PostTypeContext[T]) CountReactions(id uint) (map[string]int64, error) {
|
||||||
|
var reactions []struct {
|
||||||
|
Symbol string
|
||||||
|
Count int64
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.C.Model(&models.Reaction{}).
|
||||||
|
Select("symbol, COUNT(id) as count").
|
||||||
|
Where(strings.ToLower(v.TypeName)+"_id = ?", id).
|
||||||
|
Group("symbol").
|
||||||
|
Scan(&reactions).Error; err != nil {
|
||||||
|
return map[string]int64{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return lo.SliceToMap(reactions, func(item struct {
|
||||||
|
Symbol string
|
||||||
|
Count int64
|
||||||
|
}) (string, int64) {
|
||||||
|
return item.Symbol, item.Count
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (v *PostTypeContext[T]) List(take int, offset int, noReact ...bool) ([]T, error) {
|
func (v *PostTypeContext[T]) List(take int, offset int, noReact ...bool) ([]T, error) {
|
||||||
if take > 20 {
|
if take > 20 {
|
||||||
take = 20
|
take = 20
|
||||||
@ -136,6 +163,44 @@ func (v *PostTypeContext[T]) List(take int, offset int, noReact ...bool) ([]T, e
|
|||||||
return items, err
|
return items, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
idx := lo.Map(items, func(item T, index int) uint {
|
||||||
|
return item.GetID()
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(noReact) <= 0 || !noReact[0] {
|
||||||
|
var reactions []struct {
|
||||||
|
PostID uint
|
||||||
|
Symbol string
|
||||||
|
Count int64
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.C.Model(&models.Reaction{}).
|
||||||
|
Select(strings.ToLower(v.TypeName)+"_id as post_id, symbol, COUNT(id) as count").
|
||||||
|
Where(strings.ToLower(v.TypeName)+"_id IN (?)", idx).
|
||||||
|
Group("post_id, symbol").
|
||||||
|
Scan(&reactions).Error; err != nil {
|
||||||
|
return items, err
|
||||||
|
}
|
||||||
|
|
||||||
|
itemMap := lo.SliceToMap(items, func(item T) (uint, T) {
|
||||||
|
return item.GetID(), item
|
||||||
|
})
|
||||||
|
|
||||||
|
list := map[uint]map[string]int64{}
|
||||||
|
for _, info := range reactions {
|
||||||
|
if _, ok := list[info.PostID]; !ok {
|
||||||
|
list[info.PostID] = make(map[string]int64)
|
||||||
|
}
|
||||||
|
list[info.PostID][info.Symbol] = info.Count
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range list {
|
||||||
|
if post, ok := itemMap[k]; ok {
|
||||||
|
post.SetReactionList(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
open-on-hover
|
open-on-hover
|
||||||
open-on-click
|
open-on-click
|
||||||
:open-delay="0"
|
:open-delay="0"
|
||||||
:close-delay="1850"
|
:close-delay="0"
|
||||||
location="top"
|
location="top"
|
||||||
transition="scroll-y-reverse-transition"
|
transition="scroll-y-reverse-transition"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user