Skip to content

Commit

Permalink
Add topics list page (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmalahie committed Dec 5, 2021
1 parent 166e4b4 commit c186578
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 28 deletions.
67 changes: 57 additions & 10 deletions v2/app/pages/forum/category/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,78 @@ import ClassicPage, { commonStyles } from "../../../components/ClassicPage/Class
import styles from "../../../styles/Forum.module.scss";
import Link from "next/link"
import useLanguage, { plural } from "../../../hooks/useLanguage";
import useUser from "../../../hooks/useUser";
import cx from "classnames";
import WithAppContext from "../../../components/WithAppContext/WithAppContext";
import ForumAccount from "../../../components/Forum/Account/Account";
import Ad from "../../../components/Ad/Ad";
import { formatDate } from "../../../helpers/dates";
import useFetch from "../../../hooks/useFetch";
import { useRouter } from "next/dist/client/router";

const ForumCategory: NextPage = () => {
const language = useLanguage();
const router = useRouter();
const categoryID = +router.query.id;

const category = {
id: 1,
name: "Topics officiels",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
const { data: categoryPayload } = useFetch(`/api/forum/categories/${categoryID}`);

// TODO make right API call
const { data: topicsPayload } = useFetch(`/api/forum/topics`);

const categoryID = category.id;

return (
<ClassicPage title="Forum Mario Kart PC" className={styles.Forum} page="forum">
<h1>{category.name}</h1>
<h1>{categoryPayload?.name}</h1>
<ForumAccount />
<Ad width={728} height={90} bannerId="4919860724" />
<p><a href="forum.php">{language ? 'Back to the forum' : 'Retour au forum'}</a></p>
<p id="category-description">{category.description}</p>
<p id={styles["category-description"]}>{categoryPayload?.description}</p>
{/* TODO handle rights */}
{categoryID && <p className="forumButtons"><a href={"newtopic.php?category=" + categoryID} className={commonStyles.action_button}>{language ? 'New topic' : 'Nouveau topic'}</a></p>}
{!!categoryID && <p className={styles.forumButtons}>
<a href={"newtopic.php?category=" + categoryID} className={commonStyles.action_button}>{language ? 'New topic' : 'Nouveau topic'}</a>
</p>}
<table id={styles.listeTopics}>
<col />
<col id={styles.authors} />
<col id={styles.nbmsgs} />
<col id={styles.lastmsgs} />
<tr id={styles.titres}>
<td>{language ? 'Subjects' : 'Sujets'}</td>
<td>{language ? 'Author' : 'Auteur'}</td>
<td className={styles["topic-nbmsgs"]}>{language ? 'Msgs nb' : 'Nb msgs'}</td>
<td>{language ? 'Last message' : 'Dernier message'}</td>
</tr>
{topicsPayload?.data.map((topic, i) => (<tr className={(i % 2) ? styles.fonce : styles.clair}>
<td className={styles.subjects}>
<a href={"topic.php?topic=" + topic.id} className={styles.fulllink}>{topic.title}</a>
</td>
<td className={styles.authors}>
{
topic.firstMessage.author
? <a className={styles["forum-auteur"]} href={"profil.php?id=" + topic.firstMessage.author.id}>{topic.firstMessage.author.name}</a>
: <em>{language ? "Deleted account" : "Compte supprimé"}</em>
}
</td>
<td className={styles["topic-nbmsgs"]}>{topic.nbMessages}</td>
<td className={styles.lastmsgs}>
{formatDate(topic.lastMessage.date, {
language,
mode: "datetime",
prefix: true,
case: "capitalize",
includeYear: "always",
includeSeconds: true
})}
</td>
</tr>))}
</table>
{/* TODO add pagination */}
<p className={styles.forumButtons}>
{/* TODO handle rights */}
{!!categoryID && <a href={"newtopic.php?category=" + categoryID} className={cx(commonStyles.action_button, styles.action_button)}>{language ? 'New topic' : 'Nouveau topic'}</a>}
<a href="forum.php">{language ? 'Back to the forum' : 'Retour au forum'}</a><br />
<a href="index.php">{language ? 'Back to home' : 'Retour à l\'accueil'}</a>
</p>
</ClassicPage>
);
}
Expand Down
2 changes: 2 additions & 0 deletions v2/node-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@nestjs/platform-express": "^8.0.0",
"@nestjs/typeorm": "^8.0.2",
"cookie-parser": "^1.4.5",
"lodash": "^4.17.21",
"luxon": "^2.1.1",
"mysql2": "^2.3.3-rc.0",
"nestjs-i18n": "^8.1.9",
Expand All @@ -42,6 +43,7 @@
"@types/cookie-parser": "^1.4.2",
"@types/express": "^4.17.13",
"@types/jest": "^27.0.1",
"@types/lodash": "^4.14.177",
"@types/luxon": "^2.0.7",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
Expand Down
66 changes: 48 additions & 18 deletions v2/node-api/src/forum/forum.controller.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Controller, Get, Req } from '@nestjs/common';
import { Controller, Get, NotFoundException, Param, Req } from '@nestjs/common';
import { Auth } from '../auth/auth.decorator';
import { I18n, I18nContext } from 'nestjs-i18n';
import { AuthUser, GetUser } from 'src/user/user.decorator';
import { EntityManager, MoreThan } from 'typeorm';
import { EntityManager, In, MoreThan } from 'typeorm';
import { Message } from './message.entity';
import { Topic } from './topic.entity';
import { Category } from './category.entity';
import { Profile } from 'src/user/profile.entity';
import { DateTime } from 'luxon';
import { keyBy, pick } from 'lodash'
@Controller("/forum")
export class ForumController {
constructor(private em: EntityManager) {}
constructor(private em: EntityManager) { }

@Auth({loadRoles: true})
@Auth({ loadRoles: true })
@Get("/topics")
async getTopics(@GetUser() user: AuthUser, @I18n() i18n: I18nContext) {
let topics = await this.em.find(Topic, {
Expand All @@ -31,26 +32,38 @@ export class ForumController {
...topics.filter(t => t.getLanguage() === "fr")
];
}
const firstMessages = await this.em.find(Message, {
where: {
id: 1,
topic: In(topics.map(topic => topic.id))
},
relations: ["author"]
});
const firstMessagesByTopic = keyBy(firstMessages, "topic");
const lastMessages = await Promise.all(topics.map(topic => this.em.findOne(Message, {
where: {
topic: topic.id
},
relations: ["author"],
order: {
id: "DESC"
}
})));
const data = topics.map((topic,i) => ({
where: {
topic: topic.id
},
relations: ["author"],
order: {
id: "DESC"
}
})));
const data = topics.map((topic, i) => ({
id: topic.id,
title: topic.title,
nbMessages: topic.nbMessages,
category: {
id: topic.category.id,
name: topic.category.getName(i18n.detectedLanguage)
},
firstMessage: {
author: firstMessagesByTopic[topic.id]?.author && pick(firstMessagesByTopic[topic.id].author, "id", "name"),
date: firstMessagesByTopic[topic.id]?.date
},
lastMessage: {
author: lastMessages[i].author,
date: lastMessages[i].date
author: lastMessages[i]?.author && pick(lastMessages[i].author, "id", "name"),
date: lastMessages[i]?.date
}
}))
return {
Expand All @@ -62,7 +75,7 @@ export class ForumController {
async getCategories(@I18n() i18n: I18nContext) {
const lang = i18n.detectedLanguage;
const categories = await this.em.find(Category);
const sortedCategories = categories.sort((c1,c2) => c1.getOrder(lang) - c2.getOrder(lang))
const sortedCategories = categories.sort((c1, c2) => c1.getOrder(lang) - c2.getOrder(lang))
const categoriesWithData = await Promise.all(sortedCategories.map(async category => {
const nbTopics = await this.em.count(Topic, {
where: {
Expand All @@ -77,13 +90,13 @@ export class ForumController {
lastMessageDate: "DESC"
}
});
return {
return {
category,
nbTopics,
lastTopic
};
}))
const data = categoriesWithData.map(({category,nbTopics,lastTopic}) => ({
const data = categoriesWithData.map(({ category, nbTopics, lastTopic }) => ({
id: category.id,
name: category.getName(lang),
description: category.getDescription(lang),
Expand All @@ -102,6 +115,23 @@ export class ForumController {
}
}

@Get("/categories/:id")
async getCategory(@I18n() i18n: I18nContext, @Param("id") id: number) {
const lang = i18n.detectedLanguage;
const category = await this.em.findOne(Category, {
where: {
id
}
});
if (!category)
throw new NotFoundException(`Category with id ${id} does not exist`);
return {
id: category.id,
name: category.getName(lang),
description: category.getDescription(lang)
};
}

@Get("/stats")
async getStats() {
const messagesStats = await this.em.getRepository(Topic).createQueryBuilder("t")
Expand Down
5 changes: 5 additions & 0 deletions v2/node-api/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=

"@types/lodash@^4.14.177":
version "4.14.177"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.177.tgz#f70c0d19c30fab101cad46b52be60363c43c4578"
integrity sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==

"@types/luxon@^2.0.7":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-2.0.7.tgz#6189930542400e2c48b4d5ed06c4f136ee38bb1a"
Expand Down

0 comments on commit c186578

Please sign in to comment.