Files
hudozka/src/routes/articles.js
T
2017-05-26 18:41:34 +03:00

156 lines
3.3 KiB
JavaScript

const React = require('react')
const {get} = require('koa-route')
const {c} = require('../core/db')
const Article = require('../components/Article')
const ArticleList = require('../components/ArticleList')
const Paginator = require('../components/Paginator')
const {render} = require('../lib/render')
const getPathWithNoTrailingSlash = require('../lib/url').getPathWithNoTrailingSlash
const timestamp = require('../lib/date').timestamp
const {sortBy} = require('../utils/sort')
const accepts = require('./index').accepts
const sortArticleByDate = sortBy(
i => timestamp(new Date(i.date))
)
const articleUrl = article => `/article/${article.id}`
async function findArticle(id) {
return c('articles').findOne({id: id})
}
async function findArticlesNin(nin, skip, limit, sort) {
return c('articles')
.find({
_id: {$nin: nin}
})
.sort(sort)
.skip(skip)
.limit(limit)
.toArray()
}
async function totalArticles() {
return c('articles')
.find({})
.count()
}
async function findPinned(page) {
const now = new Date()
return page !== 1
? []
: await c('articles')
.find({until: {$gte: now}})
.sort({date: -1})
.toArray()
}
async function getArticleListComponent(path, page, pageSize) {
path = getPathWithNoTrailingSlash(path)
const limit = pageSize
const skip = (page - 1) * pageSize
const pinnedArticles = await findPinned(page)
const total = await totalArticles()
const totalPages = total / pageSize
const id = i => i._id
const pinnedIds = pinnedArticles.map(id)
const articles = await findArticlesNin(pinnedIds, skip, limit, {date: -1})
const prevPage = page > 1
? page - 1
: null
const nextPage = page < totalPages
? page + 1
: null
const content = [
...pinnedArticles.sort(sortArticleByDate),
...articles
]
.map(article => ({
...article,
url: articleUrl(article),
}))
return (
<ArticleList
articles={content}
prevPage={prevPage}
nextPage={nextPage}
/>
)
}
function getMeta(article) {
return {
title: article.title,
}
}
function getArticles(pageSize) {
return get('/articles/:page?', async (ctx, page) => {
page = parseInt(page) || 1
if (page === 1) {
ctx.redirect('/')
} else {
const path = getPathWithNoTrailingSlash(ctx.path)
const articles = await getArticleListComponent(path, page, pageSize)
const Component = (
<div className="content content_thin">
{articles}
</div>
)
ctx.body = await render(path, Component, getMeta({title: `Статьи`}))
}
})
}
function getArticle() {
return get('/article/:id', accepts({
'text/html': async (ctx, id) => {
const path = getPathWithNoTrailingSlash(ctx.path)
const article = await findArticle(id)
if (article) {
const Component = (
<div className="content content_thin">
<Article
title={article.title}
date={article.date}
data={article.post}
shareable={true}
/>
</div>
)
ctx.type = 'text/html'
ctx.body = await render(path, Component, getMeta(article), {commentsEnabled: true})
} else {
ctx.status = 404
}
},
'application/json': async (ctx, id) => {
const article = await findArticle(id)
if (article) {
ctx.body = article
} else {
ctx.status = 404
}
}
}))
}
exports.getArticleListComponent = getArticleListComponent
exports.getArticles = getArticles
exports.getArticle = getArticle