mirror of
https://github.com/janishutz/libreevent.git
synced 2025-11-25 13:24:24 +00:00
make voting plugin better
This commit is contained in:
@@ -81,40 +81,45 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="content" id="app">
|
<div class="content" id="app">
|
||||||
<div v-if="votingDetails.display">
|
<div class="wrapper" v-if="hasLoadedBasics && hasLoadedVotes">
|
||||||
<h1>Voting on {{ votingDetails.display ?? 'untitled' }}</h1>
|
<div v-if="votingDetails.display">
|
||||||
<p v-if="votingDetails.description" class="comment">{{ votingDetails.description }}</p>
|
<h1>Voting on {{ votingDetails.display ?? 'untitled' }}</h1>
|
||||||
<div style="margin-bottom: 1%;" v-if="votingDetails.allowAdding">
|
<p v-if="votingDetails.description" class="comment">{{ votingDetails.description }}</p>
|
||||||
<button onclick="location.href = '/'">Back to website</button>
|
<div style="margin-bottom: 1%;" v-if="votingDetails.allowAdding">
|
||||||
<button @click="addSuggestion();">Add suggestion</button>
|
<button onclick="location.href = '/'">Back to website</button>
|
||||||
</div>
|
<button @click="addSuggestion();">Add suggestion</button>
|
||||||
<div v-for="entry in entries" class="entry">
|
|
||||||
<h3>{{ entry.title }}</h3>
|
|
||||||
<p>{{ entry.comment }}</p>
|
|
||||||
<div class="voting-wrapper">
|
|
||||||
<span class="material-symbols-outlined voting" @click="vote( 'up', entry.id )" :class="votedOn[ entry.id ] === 'up' ? 'selected' : ''">arrow_upward</span>
|
|
||||||
<p class="voting-counter">{{ entry.count ?? 0 }}</p>
|
|
||||||
<span class="material-symbols-outlined voting" @click="vote( 'down', entry.id )" :class="votedOn[ entry.id ] === 'down' ? 'selected' : ''">arrow_downward</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div v-for="entry in entries" class="entry">
|
||||||
<div id="popup">
|
<h3>{{ entry.title }}</h3>
|
||||||
<div class="popup-positioning">
|
<p>{{ entry.comment }}</p>
|
||||||
<div class="popup-main">
|
<div class="voting-wrapper">
|
||||||
<form id="popup-message">
|
<span class="material-symbols-outlined voting" @click="vote( 'up', entry.id )" :class="votedOn[ entry.id ] === 'up' ? 'selected' : ''">arrow_upward</span>
|
||||||
<h2 style="font-size: 200%;">Add new suggestion</h2>
|
<p class="voting-counter">{{ entry.count ?? 0 }}</p>
|
||||||
<label for="title">Suggestion title</label><br>
|
<span class="material-symbols-outlined voting" @click="vote( 'down', entry.id )" :class="votedOn[ entry.id ] === 'down' ? 'selected' : ''">arrow_downward</span>
|
||||||
<input type="text" v-model="newSuggestion.title" name="title" id="title" class="input"><br>
|
</div>
|
||||||
<label for="title">Comments</label><br>
|
</div>
|
||||||
<textarea type="text" v-model="newSuggestion.comment" name="comment" id="comment" class="input" rows="5"></textarea><br>
|
<div id="popup">
|
||||||
</form>
|
<div class="popup-positioning">
|
||||||
<button @click="save()" class="submit">Add</button>
|
<div class="popup-main">
|
||||||
<button @click="closePopup()" class="submit">Cancel</button>
|
<form id="popup-message">
|
||||||
|
<h2 style="font-size: 200%;">Add new suggestion</h2>
|
||||||
|
<label for="title">Suggestion title</label><br>
|
||||||
|
<input type="text" v-model="newSuggestion.title" name="title" id="title" class="input"><br>
|
||||||
|
<label for="title">Comments</label><br>
|
||||||
|
<textarea type="text" v-model="newSuggestion.comment" name="comment" id="comment" class="input" rows="5"></textarea><br>
|
||||||
|
</form>
|
||||||
|
<button @click="save()" class="submit">Add</button>
|
||||||
|
<button @click="closePopup()" class="submit">Cancel</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else style="display: flex; justify-content: center; align-items: center; height: 100vh; font-size: 110%;">
|
||||||
|
<h1>This poll does not exist!</h1>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="display: flex; justify-content: center; align-items: center; height: 100vh; font-size: 110%;">
|
<div v-else>
|
||||||
<h1>This poll does not exist!</h1>
|
<h1>Loading...</h1>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
|||||||
@@ -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' ) ?? '{}' );
|
||||||
|
|||||||
@@ -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( votingMemCache[ req.params.vote ] )[ Object.keys( votingMemCache[ req.params.vote ] ).length - 1 ] ?? 0 ) + 1;
|
||||||
}
|
votingMemCache[ req.params.vote ][ id ] = data;
|
||||||
const id = parseInt( Object.keys( file[ req.params.vote ] )[ Object.keys( file[ req.params.vote ] ).length - 1 ] ?? 0 ) + 1;
|
votingMemCache[ req.params.vote ][ id ][ 'id' ] = id;
|
||||||
file[ req.params.vote ][ id ] = data;
|
votingMemCache[ req.params.vote ][ id ][ 'count' ] = 1;
|
||||||
file[ req.params.vote ][ id ][ 'id' ] = id;
|
res.send( 'ok' );
|
||||||
file[ 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' );
|
|
||||||
} );
|
|
||||||
} );
|
|
||||||
} else {
|
} else {
|
||||||
res.status( 400 ).send( 'incomplete' );
|
res.status( 400 ).send( 'incomplete' );
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user