make voting plugin better

This commit is contained in:
2023-10-23 18:11:18 +02:00
parent 13cba558d2
commit ffbb040f22
3 changed files with 86 additions and 57 deletions

View File

@@ -81,6 +81,7 @@
</head> </head>
<body> <body>
<div class="content" id="app"> <div class="content" id="app">
<div class="wrapper" v-if="hasLoadedBasics && hasLoadedVotes">
<div v-if="votingDetails.display"> <div v-if="votingDetails.display">
<h1>Voting on {{ votingDetails.display ?? 'untitled' }}</h1> <h1>Voting on {{ votingDetails.display ?? 'untitled' }}</h1>
<p v-if="votingDetails.description" class="comment">{{ votingDetails.description }}</p> <p v-if="votingDetails.description" class="comment">{{ votingDetails.description }}</p>
@@ -117,6 +118,10 @@
<h1>This poll does not exist!</h1> <h1>This poll does not exist!</h1>
</div> </div>
</div> </div>
<div v-else>
<h1>Loading...</h1>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="/polls/js/voting.js"></script> <script src="/polls/js/voting.js"></script>

View File

@@ -8,6 +8,8 @@ createApp( {
newSuggestion: {}, newSuggestion: {},
votingDetails: {}, votingDetails: {},
votedOn: {}, votedOn: {},
hasLoadedBasics: false,
hasLoadedVotes: false,
}; };
}, },
methods: { methods: {
@@ -15,11 +17,13 @@ createApp( {
fetch( '/polls/get/' + location.pathname.substring( 7 ) ).then( response => { fetch( '/polls/get/' + location.pathname.substring( 7 ) ).then( response => {
response.json().then( data => { response.json().then( data => {
this.entries = data; this.entries = data;
this.hasLoadedVotes = true;
} ); } );
} ); } );
fetch( '/polls/getDetails/' + location.pathname.substring( 7 ) ).then( response => { fetch( '/polls/getDetails/' + location.pathname.substring( 7 ) ).then( response => {
response.json().then( data => { response.json().then( data => {
this.votingDetails = data; this.votingDetails = data;
this.hasLoadedBasics = true;
} ); } );
} ); } );
this.votedOn = JSON.parse( localStorage.getItem( 'itemsVotedOn' ) ?? '{}' ); this.votedOn = JSON.parse( localStorage.getItem( 'itemsVotedOn' ) ?? '{}' );

View File

@@ -11,6 +11,35 @@ const path = require( 'path' );
const fs = require( 'fs' ); const fs = require( 'fs' );
const bodyParser = require( 'body-parser' ); const bodyParser = require( 'body-parser' );
// Memory caching system to prevent downtime
// This is basically the same system as can be found in the JSON db's saving system
let votingMemCache = JSON.parse( fs.readFileSync( path.join( __dirname + '/data/voting.json' ) ) );
let hasToSave = false;
let isReadyToSave = true;
const saveVotingData = () => {
if ( isReadyToSave ) {
isReadyToSave = false;
hasToSave = false;
runSave();
} else {
hasToSave = true;
}
};
const runSave = () => {
fs.writeFile( path.join( __dirname + '/data/voting.json' ), JSON.stringify( votingMemCache ), ( err ) => {
if ( err ) {
console.error( err );
} else {
isReadyToSave = true;
if ( hasToSave ) {
runSave();
}
}
} );
};
module.exports = ( app ) => { module.exports = ( app ) => {
app.get( '/polls/:vote', ( req, res ) => { app.get( '/polls/:vote', ( req, res ) => {
res.sendFile( path.join( __dirname + '/html/voting.html' ) ); res.sendFile( path.join( __dirname + '/html/voting.html' ) );
@@ -31,48 +60,39 @@ module.exports = ( app ) => {
} ); } );
app.get( '/polls/get/:vote', ( req, res ) => { app.get( '/polls/get/:vote', ( req, res ) => {
fs.readFile( path.join( __dirname + '/data/voting.json' ), ( error, filedata ) => { res.send( votingMemCache[ req.params.vote ] );
res.send( JSON.parse( filedata )[ req.params.vote ] ?? {} );
} );
} ); } );
app.post( '/polls/vote/:vote/', bodyParser.json(), ( req, res ) => { app.post( '/polls/vote/:vote/', bodyParser.json(), ( req, res ) => {
// up / down-voting // up / down-voting
fs.readFile( path.join( __dirname + '/data/voting.json' ), ( error, filedata ) => { if ( votingMemCache[ req.params.vote ] ) {
let json = JSON.parse( filedata ); if ( votingMemCache[ req.params.vote ][ req.body.id ] ) {
if ( json[ req.params.vote ] ) {
if ( req.body.voteType === 'up' ) { if ( req.body.voteType === 'up' ) {
json[ req.params.vote ][ req.body.id ].count += 1; votingMemCache[ req.params.vote ][ req.body.id ].count += 1;
} else if ( req.body.voteType === 'down' ) { } else if ( req.body.voteType === 'down' ) {
json[ req.params.vote ][ req.body.id ].count -= 1; votingMemCache[ req.params.vote ][ req.body.id ].count -= 1;
} }
fs.writeFile( path.join( __dirname + '/data/voting.json' ), JSON.stringify( json ), ( err ) => { saveVotingData();
if ( err ) res.status( 500 ).send( 'ERR_VOTING' );
res.send( 'ok' ); res.send( 'ok' );
} );
} else { } else {
res.status( 404 ).send( 'ok' ); res.status( 404 ).send( 'No Entry on this vote with' );
}
} else {
res.status( 404 ).send( 'No Vote with this ID' );
} }
} );
} ); } );
app.post( '/polls/add/:vote', bodyParser.json(), ( req, res ) => { app.post( '/polls/add/:vote', bodyParser.json(), ( req, res ) => {
let data = req.body; let data = req.body;
if ( data.title && data.comment ) { if ( data.title && data.comment ) {
fs.readFile( path.join( __dirname + '/data/voting.json' ), ( error, filedata ) => { if ( !votingMemCache[ req.params.vote ] ) {
let file = JSON.parse( filedata ); votingMemCache[ req.params.vote ] = {};
if ( !file[ req.params.vote ] ) {
file[ req.params.vote ] = {};
} }
const id = parseInt( Object.keys( file[ req.params.vote ] )[ Object.keys( file[ req.params.vote ] ).length - 1 ] ?? 0 ) + 1; const id = parseInt( Object.keys( votingMemCache[ req.params.vote ] )[ Object.keys( votingMemCache[ req.params.vote ] ).length - 1 ] ?? 0 ) + 1;
file[ req.params.vote ][ id ] = data; votingMemCache[ req.params.vote ][ id ] = data;
file[ req.params.vote ][ id ][ 'id' ] = id; votingMemCache[ req.params.vote ][ id ][ 'id' ] = id;
file[ req.params.vote ][ id ][ 'count' ] = 1; votingMemCache[ req.params.vote ][ id ][ 'count' ] = 1;
fs.writeFile( path.join( __dirname + '/data/voting.json' ), JSON.stringify( file ), ( error ) => {
if ( error ) console.error( 'failed to write data', file );
res.send( 'ok' ); res.send( 'ok' );
} );
} );
} else { } else {
res.status( 400 ).send( 'incomplete' ); res.status( 400 ).send( 'incomplete' );
} }