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;