OurBigBook logoOurBigBook Docs OurBigBook logoOurBigBook.comSite Source code
web/back/IndexPage.ts
import { getLoggedInUser } from 'back'
import { articleLimit } from 'front/config'
import { getOrderAndPage } from 'front/js'
import { IndexPageProps } from 'front/IndexPage'
import { MyGetServerSideProps } from 'front/types'

export const getServerSidePropsIndexHoc = ({
  followed=false,
  itemType=undefined,
}={}): MyGetServerSideProps => {
  return async ({ query, req, res }) => {
    const loggedInUser = await getLoggedInUser(req, res)
    let followedEff = followed
    if (!loggedInUser) {
      followedEff = false;
    }
    let itemTypeEff = itemType
    if (itemTypeEff === undefined) {
      if (loggedInUser) {
        itemTypeEff = 'article'
      } else {
        itemTypeEff = 'topic'
      }
    }
    const getOrderAndPageOpts: {
      defaultOrder?: string;
      allowedSortsExtra?: any;
    } = {}
    const sequelize = req.sequelize
    const { Article, Comment, Issue, Site, Topic, User } = sequelize.models
    switch (itemTypeEff) {
      case 'article':
        getOrderAndPageOpts.allowedSortsExtra = Article.ALLOWED_SORTS_EXTRA
        break
      case 'comment':
        break
      case 'discussion':
        getOrderAndPageOpts.allowedSortsExtra = Issue.ALLOWED_SORTS_EXTRA
        break
      case 'topic':
        getOrderAndPageOpts.defaultOrder = Topic.DEFAULT_SORT
        getOrderAndPageOpts.allowedSortsExtra = Topic.ALLOWED_SORTS_EXTRA
        break
    }
    const { ascDesc, err, order, page } = getOrderAndPage(req, query.page, getOrderAndPageOpts)
    if (err) { res.statusCode = 422 }
    const offset = page * articleLimit
    const limit = articleLimit
    const [
      [articles, articlesCount],
      commentsAndCount,
      pinnedArticle,
      totalArticles,
      totalComments,
      totalDiscussions,
      totalTopics,
      totalUsers,
    ] = await Promise.all([
      (async () => {
        let articles
        let articlesCount
        let articlesAndCounts
        switch (itemTypeEff) {
          case 'article':
            if (followedEff) {
              articlesAndCounts = await loggedInUser.findAndCountArticlesByFollowedToJson(
                offset, limit, order, ascDesc)
              articles = articlesAndCounts.articles
              articlesCount = articlesAndCounts.articlesCount
            } else {
              articlesAndCounts = await Article.getArticles({
                limit,
                list: true,
                offset,
                order,
                orderAscDesc: ascDesc,
                topicIdSearch: query.search,
                sequelize,
              })
              articles = await Promise.all(articlesAndCounts.rows.map(
                (article) => {return article.toJson(loggedInUser) }))
              articlesCount = articlesAndCounts.count
            }
            break
          case 'comment':
            articles = null
            articlesCount = null
          case 'discussion':
            articlesAndCounts = await Issue.getIssues({
              sequelize,
              includeArticle: true,
              offset,
              order,
              orderAscDesc: ascDesc,
              limit,
            })
            articles = await Promise.all(articlesAndCounts.rows.map(
              (article) => {
                return article.toJson(loggedInUser)
              }))
            articlesCount = articlesAndCounts.count
            break
          case 'topic':
            articlesAndCounts = await Topic.getTopics({
              limit,
              offset,
              order,
              orderAscDesc: ascDesc,
              topicIdSearch: query.search,
              sequelize,
            })
            articles = await Promise.all(articlesAndCounts.rows.map(
              (article) => {return article.toJson(loggedInUser) }))
            articlesCount = articlesAndCounts.count
            break
          default:
            throw new Error(`unknown itemType: ${itemTypeEff}`)
        }
        return [articles, articlesCount]
      })(),
      // commentsAndCount
      itemType === 'comment'
        ? Comment.getComments({ limit, offset })
        : {}
      ,
      // pinnedArticle
      Site.findOne({ include:
        [{
          model: Article,
          as: 'pinnedArticle',
        }]
      }).then(site => {
        const pinnedArticle = site.pinnedArticle
        if (pinnedArticle) {
          return pinnedArticle.toJson(loggedInUser)
        } else {
          return null
        }
      }),
      // totalArticles
      Article.count({ where: { list: true } }),
      // totalComments
      Comment.count(),
      // totalDiscussions
      Issue.count(),
      // totalTopics
      Topic.count(),
      // totalUsers
      User.count(),
    ])
    const props: IndexPageProps = {
      followed: followedEff,
      itemType: itemTypeEff,
      order,
      orderAscDesc: ascDesc,
      page,
      pinnedArticle,
      totalArticles,
      totalDiscussions,
      totalComments,
      totalTopics,
      totalUsers,
    }
    if (itemType === 'comment') {
      props.comments = await Promise.all(commentsAndCount.rows.map(comment => comment.toJson(loggedInUser)))
      props.commentsCount = commentsAndCount.count
    } else {
      if (articles) {
        props.articles = articles
        props.articlesCount = articlesCount
      }
    }
    if (loggedInUser) {
      props.loggedInUser = await loggedInUser.toJson()
    }
    return { props }
  }
}