diff --git a/.gitignore b/.gitignore
index 2d97410..efe5f74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,8 @@
.env
.overnodebundle
*.old
-node/node_modules
+backend/node_modules
+frontend/node_modules
nginx-react/node_modules
nginx-react/build
.vscode
diff --git a/backend/server.js b/backend/server.js
index 163ad2d..a54f67d 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -10,7 +10,7 @@ const mongoUri = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/default?rep
// Minio set-up variables
const minioURI = new URL(process.env.MINIO_URI || 'http://kspace-mugshot:2mSI6HdbJ8@127.0.0.1:9000/kspace-mugshot');
const minioBucket = minioURI.pathname.substring(1);
-const historyNumber = process.env.HISTORY_AMOUNT || 10;
+const historyNumber = parseInt(process.env.HISTORY_AMOUNT) || 1000;
// Stream set-up variables
let changeStream;
@@ -28,16 +28,15 @@ async function run() {
console.log('server.js has been launched');
const app = express();
- // Configuring mongoDB connection
await mongoClient.connect();
const collection = mongoClient.db().collection(mongoCollection);
let eventArray = [];
- // Opening event listener on the database
changeStream = collection.watch(pipeline, options);
console.log("Started watching changes in database");
+ // Triggers on GET at /event route
app.get('/events', async function (request, response) {
let minioClient = new minio.Client({
endPoint: minioURI.hostname,
@@ -47,19 +46,24 @@ async function run() {
secretKey: minioURI.password
});
- // Setting the header to event-stream for Server Sent Events (Eventsource)
+ // Notify SSE to React
const header = { 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive' };
response.writeHead(200, "OK", header);
response.write('Connection established \n\n');
- // Triggers callback on every change in collection set up
+ const historyCursor = collection.find({}).sort({$natural : -1}).limit(historyNumber);
+
+ historyCursor.forEach((document) => {
+ const stringFormat = JSON.stringify(document);
+ eventArray = [stringFormat, ...eventArray];
+ })
+ response.write(`event: events, data: [${[...eventArray]}]\n\n`)
+
changeStream.on("change", data => {
- // Retrieves modified document on the db and stores it
let document = JSON.stringify(data.fullDocument);
eventArray = [document];
- // Fetch screenshot if there is one
if (data.fullDocument.screenshot_count) {
for (let i = 1; i <= data.fullDocument.screenshot_count ; i++) {
@@ -72,8 +76,8 @@ async function run() {
};
- // sends updated array
response.write(`data: [${[...eventArray]}]\n\n`);
+
});
});
diff --git a/docker-compose.yml b/docker-compose.yml
index b04b5e1..9550284 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,6 +11,7 @@ x-common: &common
ME_CONFIG_MONGODB_AUTH_DATABASE: admin
MONGO_URI: mongodb://127.0.0.1:27017/default?replicaSet=rs0
MONGO_COLLECTION: eventlog
+ HISTORY_AMOUNT: 10
MINIO_ACCESS_KEY: kspace-mugshot
MINIO_SECRET_KEY: 2mSI6HdbJ8
MINIO_DEFAULT_BUCKETS: kspace-mugshot:download
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index c06e736..54466a6 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -13,6 +13,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
+ "react-hooks-sse": "^2.0.0",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.3"
}
@@ -12952,6 +12953,17 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
},
+ "node_modules/react-hooks-sse": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/react-hooks-sse/-/react-hooks-sse-2.0.0.tgz",
+ "integrity": "sha512-Bv/KYK+QUVS6UWwCyx6nyaOYIvaTMTCjmlXuBK9nATH2DOz+g4PGiIxi5q71ljUTmSPn/q9Cod7xwDA3/gqVQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.1.5"
+ },
+ "peerDependencies": {
+ "react": ">= 16.7.0"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -25025,6 +25037,14 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
},
+ "react-hooks-sse": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/react-hooks-sse/-/react-hooks-sse-2.0.0.tgz",
+ "integrity": "sha512-Bv/KYK+QUVS6UWwCyx6nyaOYIvaTMTCjmlXuBK9nATH2DOz+g4PGiIxi5q71ljUTmSPn/q9Cod7xwDA3/gqVQA==",
+ "requires": {
+ "@babel/runtime": "^7.1.5"
+ }
+ },
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 88949f2..47ccb39 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -8,6 +8,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
+ "react-hooks-sse": "^2.0.0",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.3"
},
diff --git a/frontend/src/components/app/App.js b/frontend/src/components/app/App.js
index 71df5d9..262b070 100644
--- a/frontend/src/components/app/App.js
+++ b/frontend/src/components/app/App.js
@@ -1,28 +1,29 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
+import { useSSE, SSEProvider, createCustomSource } from 'react-hooks-sse';
import './App.css';
import EventList from '../eventList/EventList.js';
-function App(props) {
- const [events, setEvents] = useState(['EventLog']); // initialises Event state
- const [sse, setSse] = useState(new EventSource('/events', { withCredentials: true })) // creates eventSource listener in state
+function SSE() {
+ const state = useSSE('events');
+ const [events, setEvents] = useState([]); // initialises Event state
- sse.onerror = (e) => {
- console.error();
- sse.close();
- }
+ useEffect(() => {
+ console.log('render');
+ if (state) {
+ setEvents([JSON.parse(state.data), ...events]);
+ }
+ }, [state])
- sse.onmessage = (e) => {
- // parses received data from string to JSON
- const message = JSON.parse(e.data);
+ return events;
+}
- // initialises a new array with updated server-side event array
- const newEvents = [...message, ...events];
+function App() {
- // sets the updated event array as state
- setEvents(newEvents);
- };
-
- return