diff --git a/src/core/Page.js b/src/core/Page.js new file mode 100644 index 00000000..388800a9 --- /dev/null +++ b/src/core/Page.js @@ -0,0 +1,93 @@ +const Data = require('./Data') +const Image = require('./Image') +const Config = require('./Config') +const {find, findOne, total} = require('../lib/store') + +const store = () => Data.getStore(Page) + +class Page { + static async find(query, options = {}) { + const items = await find(store(), query, options) + + return Promise.all(items.map(processPage)) + } + + static async findById(id) { + const item = await findOne(store(), {id}) + + return !item + ? null + : processPage(item) + } + + static async findByUrl(url) { + const item = await findOne(store(), {url}) + + return !item + ? null + : processPage(item) + } + + static async total(query = {}) { + return total(store(), query) + } + + constructor(data) { + this.id = data.id + this.hash = data.hash + this.file = data.file + this.url = data.url + this.content = data.content + this.title = data.title + this.data = data.data + this.images = data.images + this.documents = data.documents + this.preview = data.preview + } + + plain() { + return { + id: this.id, + images: this.images, + documents: this.documents, + data: this.data, + title: this.title, + content: this.content, + hash: this.hash, + file: this.file, + preview: this.preview, + url: this.url, + } + } +} + +const previewFromImage = (imgs = []) => imgs.length + ? imgs[0] + : null + +async function resolveDefaultPreview() { + const config = await Config.findConfig() + if (!config) return null + + return Image.findByFile(config.articleCardDefaultPreview) +} + +async function processPage(article) { + let preview = null + const previewId = article.preview + ? article.preview + : previewFromImage(article.images) + + if (previewId) { + preview = await Image.findById(previewId) + } else { + preview = await resolveDefaultPreview() + } + + return new Page({ + ...article, + preview, + }) +} + +module.exports = Page diff --git a/src/core/db.js b/src/core/db.js index 9528a1de..b3a6e123 100644 --- a/src/core/db.js +++ b/src/core/db.js @@ -1,4 +1,5 @@ const Data = require('./Data') +const Page = require('./Page') const Article = require('./Article') const Album = require('./Album') const Teacher = require('./Teacher') @@ -30,6 +31,7 @@ export function id(i) { } function init(db) { + Data.setStore(Page, db.collection('pages')) Data.setStore(Article, db.collection('articles')) Data.setStore(Album, db.collection('albums')) Data.setStore(Image, db.collection('images')) diff --git a/src/render/page.js b/src/render/page.js new file mode 100644 index 00000000..0b118e71 --- /dev/null +++ b/src/render/page.js @@ -0,0 +1,54 @@ +const React = require('react') +const Page = require('../core/Page') +const ImageArtifactType = require('../core/ImageArtifactType') + +const {render} = require('../lib/render') + +const metaImageTypesPriority = [ + ImageArtifactType.FACEBOOK, + ImageArtifactType.MEDIUM, + ImageArtifactType.BIG, + ImageArtifactType.ORIGIN, +] + +function getMeta(page) { + const meta = { + title: page.title, + description: page.title, + } + + if (page.preview) { + try { + const artifact = page.preview.findArtifact(metaImageTypesPriority) + meta.image = artifact.url + meta.imageWidth = artifact.width + meta.imageHeight = artifact.height + } catch (error) { + } + } + return meta +} + +function getComponent(page) { + const Page = require('../components/Page') + + return ( +
+ {page.data} +
+ ) +} + +async function renderPage(path) { + const page = await Page.findByUrl(path) + if (!page) return null + + return render( + path, + getComponent(page), + getMeta(page), + {menuPadding: true}, + ) +} + +exports.renderPage = renderPage diff --git a/src/routes/pages.js b/src/routes/pages.js index ca5a5fea..c06afb30 100644 --- a/src/routes/pages.js +++ b/src/routes/pages.js @@ -1,43 +1,14 @@ -const React = require('react') -const Page = require('../components/Page') - +const {renderPage} = require('../render/page') const {get} = require('koa-route') -const {c} = require('../core/db') - const getPathWithNoTrailingSlash = require('../lib/url').getPathWithNoTrailingSlash -const {render} = require('../lib/render') - -async function getPage(path) { - return await c('pages').findOne({url: path}) -} - -function getPageMeta(page) { - return { - title: page.title, - description: page.title, - } -} - -function getComponent(page) { - return ( -
- {page.data} -
- ) -} module.exports = function () { return get('*', async ctx => { const path = getPathWithNoTrailingSlash(ctx.path) - const page = await getPage(path) - if (page) { + const body = await renderPage(path) + if (body) { ctx.type = 'text/html' - ctx.body = await render( - path, - getComponent(page), - getPageMeta(page), - {menuPadding: true}, - ) + ctx.body = body } else { ctx.status = 404 }