diff --git a/package-lock.json b/package-lock.json index 3087c35..25759d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2689,6 +2689,11 @@ } } }, + "firstline": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/firstline/-/firstline-2.0.2.tgz", + "integrity": "sha512-8KcmfI0jgSECnzdhucm0i7vrwef3BWwgjimW2YkRC5eSFwjb5DibVoA0YvgkYwwxuJi9c+7M7X3b3lX8o9B6wg==" + }, "flatiron": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/flatiron/-/flatiron-0.4.3.tgz", @@ -3024,8 +3029,7 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", @@ -3033,8 +3037,7 @@ }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -3137,8 +3140,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -3148,7 +3150,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3260,8 +3261,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -3376,7 +3376,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/package.json b/package.json index e0be3ec..da8b7b6 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "cron": "^1.7.1", "dotenv": "^8.0.0", "express": "^4.17.1", + "firstline": "^2.0.2", "forever": "^1.0.0", "formidable": "^1.2.1", "mysql": "^2.17.1", diff --git a/public/content/task_list.md b/public/content/task_list.md index 7f8df42..b600008 100644 --- a/public/content/task_list.md +++ b/public/content/task_list.md @@ -6,6 +6,7 @@ Major * Implement admin panel (write posts without having to commit). * Implement bug tracker. * Ads / monetisation research. +* github pages hosting? Minor --- diff --git a/server/index.js b/server/index.js index d235026..d5f85c5 100644 --- a/server/index.js +++ b/server/index.js @@ -17,6 +17,8 @@ app.use(bodyParser.json()); let news = require('./news.js'); app.get('/newsrequest', news.newsRequest()); app.post('/newsrequest', news.newsRequest()); +app.get('/newsheadersrequest', news.newsHeadersRequest()); +app.post('/newsheadersrequest', news.newsHeadersRequest()); //database let { connectToDatabase } = require('./database.js'); diff --git a/server/news.js b/server/news.js index 79f7d8e..e08649f 100644 --- a/server/news.js +++ b/server/news.js @@ -4,6 +4,7 @@ require('dotenv').config(); //libraries let fs = require('fs'); let path = require('path'); +let firstline = require('firstline'); let { log } = require('../common/utilities.js'); @@ -49,6 +50,28 @@ const newsRequest = () => (req, res) => { log('News sent', max, fileNames, JSON.stringify(json)); }; +const newsHeadersRequest = () => (req, res) => { + let fpath = path.join(__dirname, '..', 'public', 'news'); + let fileNames = fs.readdirSync(fpath); + + let json = {}; + + let promises = []; + + for(let i = 0; i < fileNames.length; i++) { + promises.push(firstline(path.join(fpath, fileNames[i])).then(fl => json[fileNames[i]] = { firstline: fl })); + } + + Promise.all(promises) + .then(() => { + res.status(200).json(json); + res.end(); + + log('News headers sent', fileNames.length); + }); +} + module.exports = { - newsRequest: newsRequest + newsRequest: newsRequest, + newsHeadersRequest: newsHeadersRequest }; \ No newline at end of file diff --git a/src/components/app.jsx b/src/components/app.jsx index 3ceceed..d268cda 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -77,6 +77,7 @@ export default class App extends React.Component { import('./pages/task_list.jsx')} /> import('./pages/patron_list.jsx')} /> import('./pages/news.jsx')} /> + import('./pages/news_index.jsx')} /> import('./pages/rules.jsx')} /> import('./pages/statistics.jsx')} /> diff --git a/src/components/pages/home.jsx b/src/components/pages/home.jsx index 00ddd77..4fceda2 100644 --- a/src/components/pages/home.jsx +++ b/src/components/pages/home.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { withRouter, Link } from 'react-router-dom'; //panels import CommonLinks from '../panels/common_links.jsx'; @@ -39,6 +40,7 @@ class Home extends React.Component {

News

this.setState({ fetch: fn }) } /> +

See all news...

@@ -50,4 +52,4 @@ class Home extends React.Component { } }; -export default Home; \ No newline at end of file +export default withRouter(Home); \ No newline at end of file diff --git a/src/components/pages/news_index.jsx b/src/components/pages/news_index.jsx new file mode 100644 index 0000000..c199cd1 --- /dev/null +++ b/src/components/pages/news_index.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { withRouter, Link } from 'react-router-dom'; + +//panels +import CommonLinks from '../panels/common_links.jsx'; + +class NewsIndex extends React.Component { + constructor(props) { + super(props); + this.state = { + data: {}, + warning: '' //TODO: unified warning? + }; + + this.sendRequest('/newsheadersrequest'); + } + + render() { + let warningStyle = { + display: this.state.warning.length > 0 ? 'flex' : 'none' + }; + + return ( +
+
+
+ +
+ +
+
+

{this.state.warning}

+
+ +
    + {Object.keys(this.state.data).map((fname) =>
  • {fname} - {this.state.data[fname].firstline}
  • ).reverse()} +
+
+
+
+ ); + } + + sendRequest(url, args = {}) { //send a unified request, using my credentials + //build the XHR + let xhr = new XMLHttpRequest(); + xhr.open('POST', url, true); + + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + let json = JSON.parse(xhr.responseText); + + //on success + this.setState({ data: json }); + } + else if (xhr.status === 400 && this.props.setWarning) { + this.props.setWarning(xhr.responseText); + } + } + }; + + xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); + xhr.send(JSON.stringify({ + //NOTE: No id or token needed for the news + ...args + })); + } + + setWarning(s) { + this.setState({ warning: s }); + } +}; + +export default withRouter(NewsIndex); \ No newline at end of file