diff --git a/README.md b/README.md
index 622f93b2..e5707e5e 100644
--- a/README.md
+++ b/README.md
@@ -34,10 +34,13 @@ Start strapi:
git clone https://github.com/rocketchat/RC4Community
cd cms
npm i
-INITIALIZE_DATA=true npm run develop
+INITIALIZE_DATA=true DISCOURSE_DOMAIN=domain DISCOURSE_API_USERNAME=username DISCOURSE_API_KEY=api_key npm run develop
```
-Note the `INITIALIZE_DATA` environment variable is only needed the first time you startup the cms for development. It will seed the cms with a default set of components for you to start your own customization. (see [fetch data](https://github.com/RonLek/RC4Community/blob/master/cms/config/functions/fetchData.js) for the actual default initialization code)
+Note:
+1. `INITIALIZE_DATA` environment variable is only needed the first time you startup the cms for development. It will seed the cms with a default set of components for you to start your own customization. (see [fetch data](https://github.com/RonLek/RC4Community/blob/master/cms/config/functions/fetchData.js) for the actual default initialization code)
+2. `DISCOURSE_DOMAIN`, `DISCOURSE_API_USERNAME`, `DISCOURSE_API_KEY` environment variables are required for the cron job to fetch the latest top activity on discourse with the time interval of 5 mins.
+
The application is written on nextjs and deployable on all nextjs compatible CDN + microservices and scaled deployment platforms. For build and design, start it in a shell:
diff --git a/app/pages/index.js b/app/pages/index.js
index 9900968f..8bc66a6a 100644
--- a/app/pages/index.js
+++ b/app/pages/index.js
@@ -1,7 +1,6 @@
import React, { useState } from "react";
import { fetchAPI } from "../lib/api";
import {
- Button,
TextField,
Select,
MenuItem,
@@ -31,50 +30,50 @@ export default function Home({
guides,
releaseNotes,
topNavItems,
+ topPosts
}) {
const [searchCategory, setSearchCategory] = useState("");
const { t } = useTranslation();
let loginWindow = null;
- const activityItems = [
- {
- title:
- "I am setting up live chat and want to send an attachment ...how do I do that?",
- author: "LigayaFernandez",
- role: "LiveChat User",
- community: "Question Forum",
- time: "17 min ago",
- upvotes: 0,
- comments: 1,
- },
- {
- title: "Stranger Introduction",
- author: "Izzie ",
- role: "GSoC Student",
- community: "GSoC 2021",
- time: "1 hour ago",
- upvotes: 5,
- comments: 10,
- },
- {
- title: "Setting Up Rocket Chat",
- author: "arary",
- role: "Developer",
- community: "Developer Discussions",
- time: "2 hours ago",
- upvotes: 0,
- comments: 1,
- },
- {
- title: "RC4Community Improvements",
- author: "aumurad",
- role: "Admin",
- community: "Announcements",
- time: "4 hours ago",
- upvotes: 50,
- comments: 3,
- },
- ];
+
+ function timeSince(date) {
+ let seconds = Math.floor((new Date() - date) / 1000);
+ let interval = seconds / 31536000;
+ if (interval > 1) {
+ return Math.floor(interval) + " years";
+ }
+ interval = seconds / 2592000;
+ if (interval > 1) {
+ return Math.floor(interval) + " months ago";
+ }
+ interval = seconds / 86400;
+ if (interval > 1) {
+ return Math.floor(interval) + " days ago";
+ }
+ interval = seconds / 3600;
+ if (interval > 1) {
+ return Math.floor(interval) + " hours ago";
+ }
+ interval = seconds / 60;
+ if (interval > 1) {
+ return Math.floor(interval) + " minutes ago";
+ }
+ return Math.floor(seconds) + " seconds ago";
+ }
+ let activityItems = [];
+ topPosts[0]?.TopPost?.topic_list?.topics.map((topic) => {
+ let newTopic = {
+ title: topic.fancy_title,
+ time: timeSince(new Date(topic.created_at)),
+ upvotes: topic.like_count,
+ comments: topic.posts_count,
+ link: `https://forums.rocket.chat/t/${topic.slug}/${topic.id}`,
+ image_url: topic.image_url
+ }
+ activityItems.push(newTopic);
+ })
+
const Item = (props) => {
return (
@@ -283,20 +282,16 @@ export default function Home({
{t("unsigned-home-demo.community-activity-heading")}
{activityItems.map((item) => (
-
-
+
))}
@@ -334,9 +329,10 @@ export async function getStaticProps({ params }) {
const guides = await fetchAPI("/guides");
const releaseNotes = await fetchAPI("/release-notes");
const topNavItems = await fetchAPI("/top-nav-item");
+ const topPosts = await fetchAPI("/discourses");
return {
- props: { carousels, personas, guides, releaseNotes, topNavItems },
+ props: { carousels, personas, guides, releaseNotes, topNavItems, topPosts },
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 1 second
diff --git a/cms/api/discourse/config/routes.json b/cms/api/discourse/config/routes.json
new file mode 100644
index 00000000..c1828d63
--- /dev/null
+++ b/cms/api/discourse/config/routes.json
@@ -0,0 +1,52 @@
+{
+ "routes": [
+ {
+ "method": "GET",
+ "path": "/discourses",
+ "handler": "discourse.find",
+ "config": {
+ "policies": []
+ }
+ },
+ {
+ "method": "GET",
+ "path": "/discourses/count",
+ "handler": "discourse.count",
+ "config": {
+ "policies": []
+ }
+ },
+ {
+ "method": "GET",
+ "path": "/discourses/:id",
+ "handler": "discourse.findOne",
+ "config": {
+ "policies": []
+ }
+ },
+ {
+ "method": "POST",
+ "path": "/discourses",
+ "handler": "discourse.create",
+ "config": {
+ "policies": []
+ }
+ },
+ {
+ "method": "PUT",
+ "path": "/discourses/:id",
+ "handler": "discourse.update",
+ "config": {
+ "policies": []
+ }
+ },
+ {
+ "method": "DELETE",
+ "path": "/discourses/:id",
+ "handler": "discourse.delete",
+ "config": {
+ "policies": []
+ }
+ }
+ ]
+}
diff --git a/cms/api/discourse/controllers/discourse.js b/cms/api/discourse/controllers/discourse.js
new file mode 100644
index 00000000..e8608953
--- /dev/null
+++ b/cms/api/discourse/controllers/discourse.js
@@ -0,0 +1,8 @@
+'use strict';
+
+/**
+ * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers)
+ * to customize this controller
+ */
+
+module.exports = {};
diff --git a/cms/api/discourse/models/discourse.js b/cms/api/discourse/models/discourse.js
new file mode 100644
index 00000000..0054d33c
--- /dev/null
+++ b/cms/api/discourse/models/discourse.js
@@ -0,0 +1,8 @@
+'use strict';
+
+/**
+ * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#lifecycle-hooks)
+ * to customize this model
+ */
+
+module.exports = {};
diff --git a/cms/api/discourse/models/discourse.settings.json b/cms/api/discourse/models/discourse.settings.json
new file mode 100644
index 00000000..0ad4a21e
--- /dev/null
+++ b/cms/api/discourse/models/discourse.settings.json
@@ -0,0 +1,21 @@
+{
+ "kind": "collectionType",
+ "collectionName": "discourses",
+ "info": {
+ "name": "discourse",
+ "description": ""
+ },
+ "options": {
+ "increments": true,
+ "timestamps": true,
+ "draftAndPublish": true
+ },
+ "pluginOptions": {},
+ "attributes": {
+ "TopPost": {
+ "type": "json",
+ "required": true,
+ "unique": false
+ }
+ }
+}
diff --git a/cms/api/discourse/services/discourse.js b/cms/api/discourse/services/discourse.js
new file mode 100644
index 00000000..6538a8c8
--- /dev/null
+++ b/cms/api/discourse/services/discourse.js
@@ -0,0 +1,8 @@
+'use strict';
+
+/**
+ * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-services)
+ * to customize this service
+ */
+
+module.exports = {};
diff --git a/cms/config/functions/bootstrap.js b/cms/config/functions/bootstrap.js
index 51490ed4..47aaf4e1 100644
--- a/cms/config/functions/bootstrap.js
+++ b/cms/config/functions/bootstrap.js
@@ -1,5 +1,7 @@
"use strict";
+const { getLatestCommunityActivity } = require("./fetchTopPosts");
+
/**
* An asynchronous bootstrap function that runs before
* your application gets started.
@@ -32,5 +34,6 @@ module.exports = async () => {
// Fetches data and populates CMS from remote on server restart
if (process.env.INITIALIZE_DATA) {
await strapi.config.functions.fetchData();
+ await getLatestCommunityActivity();
}
};
diff --git a/cms/config/functions/cron.js b/cms/config/functions/cron.js
index fe26854c..0f90c276 100644
--- a/cms/config/functions/cron.js
+++ b/cms/config/functions/cron.js
@@ -1,5 +1,5 @@
'use strict';
-
+const { getLatestCommunityActivity } = require("./fetchTopPosts");
/**
* Cron config that gives you an opportunity
* to run scheduled jobs.
@@ -18,4 +18,7 @@ module.exports = {
// '0 1 * * 1': () => {
//
// }
+ '*/5 * * * *': () => {
+ getLatestCommunityActivity();
+ }
};
diff --git a/cms/config/functions/fetchTopPosts.js b/cms/config/functions/fetchTopPosts.js
new file mode 100644
index 00000000..f46f08dd
--- /dev/null
+++ b/cms/config/functions/fetchTopPosts.js
@@ -0,0 +1,25 @@
+const axios = require("axios");
+
+module.exports.getLatestCommunityActivity = async () => {
+ const TopPost = await axios({
+ url: `${process.env.DISCOURSE_DOMAIN}/top.json?period=all`,
+ method: "GET",
+ headers: {
+ "Api-Username": process.env.DISCOURSE_API_USERNAME,
+ "Api-Key": process.env.DISCOURSE_API_KEY,
+ },
+ });
+ let currentTopPost = await strapi.query("discourse").find();
+ if (currentTopPost.length !== 0) {
+ await strapi.query("discourse").update(
+ { id: currentTopPost[0].id },
+ {
+ TopPost: TopPost.data,
+ }
+ );
+ } else {
+ await strapi.query("discourse").create({
+ TopPost: TopPost.data,
+ });
+ }
+};
diff --git a/cms/config/server.js b/cms/config/server.js
index ce7f7bdb..59707ac2 100644
--- a/cms/config/server.js
+++ b/cms/config/server.js
@@ -6,4 +6,7 @@ module.exports = ({ env }) => ({
secret: env('ADMIN_JWT_SECRET', '9e07dfd3396d88a43609466615259199'),
},
},
+ cron: {
+ enabled: true,
+ },
});