diff --git a/src/client/Blog.tsx b/src/client/Blog.tsx index 95ef975..c89d0b6 100644 --- a/src/client/Blog.tsx +++ b/src/client/Blog.tsx @@ -1,13 +1,66 @@ -import React from 'react'; +import React, {useState, useEffect, useCallback} from 'react'; import Display from './Display'; +import Loader from './Loader'; +import axios from 'axios'; /** * @return {jsx} The homepage component */ export default function Blog() { + const [articles, setArticles]: any = useState([]); + const [page, setPage] = useState(0); + + /** + * Check if you've reach the bottom of an HTMLElement + * @param {HTMLElement} element the element to check + * @return {boolean} true if reached else false + */ + function isBottom(element: HTMLElement) { + return element.getBoundingClientRect().bottom <= window.innerHeight; + } + + const trackScrolling = useCallback(() => { + const element = document.getElementById('root')!; + if (isBottom(element)) { + setPage(page + 1); + } + }, []); + + useEffect(() => { + const tmpArticles = articles; + tmpArticles.push(); + setArticles(tmpArticles); + axios.get('/api/articles/' + page).then((res) => { + tmpArticles.pop(); + for (let i = 0; i < res.data.length; i++) { + tmpArticles.push(

{res.data[i].title}

); + for (let j = 0; j < res.data[i].tags.length; j++) { + tmpArticles.push({res.data[i].tags[j].name}); + } + tmpArticles.push( + {new Date(res.data[i].createdAt).toLocaleDateString()} + ); + tmpArticles.push(
{res.data[i].sanitizedHtml}
); + } + console.log('test'); + setArticles([...tmpArticles]); + console.log(articles); + }); + }, [page]); + + useEffect(() => { + window.addEventListener('scroll', trackScrolling); + return () => { + window.removeEventListener('scroll', trackScrolling); + }; + }, [trackScrolling]); + return ( - + +
+ {articles} +
); } diff --git a/src/server/routes/api.ts b/src/server/routes/api.ts index dc7b6fd..ba30ac4 100644 --- a/src/server/routes/api.ts +++ b/src/server/routes/api.ts @@ -1,7 +1,6 @@ -import express, {RequestHandler} from 'express'; -import sequelize from './../dbobject'; +import express from 'express'; -import Article, {articleI} from './../models/article'; +import Article from './../models/article'; import Tag from './../models/tag'; import {authorize} from './../auth'; @@ -10,21 +9,34 @@ import {authorize} from './../auth'; const router = express.Router(); /* eslint-enable */ -/* eslint-disable */ -declare global { - namespace Express { - interface Request { - article: articleI; - } - } -} -/* eslint-enable */ - router.delete('/signout', async (_req, res) => { res.cookie('accessToken', '', {expires: new Date()}); res.sendStatus(204); }); +router.get('/articles/:page', async (req, res) => { + console.log(parseInt(req.params.page)); + const articles = await Article.findAll({ + attributes: [ + 'title', + 'createdAt', + 'sanitizedHtml', + ], + include: [{ + model: Tag, + attributes: [ + 'name', + ], + }], + order: [ + ['createdAt', 'DESC'], + ], + limit: 10, + offset: parseInt(req.params.page) * 10, + }); + res.send(articles); +}); + router.get('/articletable', authorize, async (_req, res) => { const articles = await Article.findAll({ attributes: [ @@ -36,70 +48,4 @@ router.get('/articletable', authorize, async (_req, res) => { res.send(articles); }); -router.get('/new', authorize, (_req, res) => { - res.render('admin/new', {article: Article.build(), tags: []}); -}); - -router.get('/edit/:id', authorize, async (req, res) => { - const article = await Article.findByPk(req.params.id, - {rejectOnEmpty: true}); - const tags = await Tag.findAll({ - where: {articleId: article.id}, - attributes: [ - 'name', - ], - }); - res.render('admin/edit', {article, tags}); -}); - -router.post('/', authorize, async (req, _res, next) => { - req.article = Article.build(); - next(); -}, saveArticleAndRedirect('new')); - -router.put('/:id', authorize, async (req, _res, next) => { - req.article = await Article.findByPk(req.params.id, {rejectOnEmpty: true}); - next(); -}, saveArticleAndRedirect('edit')); - -router.delete('/:id', authorize, async (req, _res) => { - await Article.destroy({where: {id: req.params.id}, cascade: true}); -}); - -/** - * @param {string} path Path of redirection - * @return {RequestHandler} middleware - */ -function saveArticleAndRedirect(path: string): RequestHandler { - return async (req, res) => { - let article: any = req.article; - article.title = req.body.title; - article.description = req.body.description; - article.markdown = req.body.markdown; - try { - await sequelize.transaction(async (t) => { - let tagCount = 0; - while (req.body.articletags[tagCount] != '') { - tagCount++; - } - Tag.destroy({where: {articleId: article.id}, - transaction: t}); - article = await article.save(); - for (let i = 0; i < tagCount; i++) { - await article.createTag({ - articleId: article.id, - main: (i == 0) ? true : false, - name: req.body.articletags[i], - }); - } - }); - res.redirect(`/blog/post/${article.slug}`); - } catch (e) { - console.log(e); - req.flash('error', 'The operation has failed, please try again'); - res.render(`admin/${path}`, {article: article}); - } - }; -} - export default router;