fix conflicts and rework routes

This commit is contained in:
Adrian Thompson
2020-09-07 14:49:24 +02:00
27 changed files with 6208 additions and 4055 deletions

View File

@@ -1,21 +1,13 @@
const express = require('express');
const path = require('path'); const path = require('path');
const router = express.Router();
const mongoose = require('mongoose'); const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/vinlottis', { mongoose.connect('mongodb://localhost:27017/vinlottis', {
useNewUrlParser: true useNewUrlParser: true
}) })
const mustBeAuthenticated = require(path.join(
__dirname + '/../middleware/mustBeAuthenticated'
));
const config = require(path.join(__dirname + '/../config/defaults/lottery'));
const Highscore = require(path.join(__dirname + '/../schemas/Highscore')); const Highscore = require(path.join(__dirname + '/../schemas/Highscore'));
const Wine = require(path.join(__dirname + '/../schemas/Wine')); const Wine = require(path.join(__dirname + '/../schemas/Wine'));
// Utils // Utils
const epochToDateString = date => new Date(parseInt(date)).toDateString(); const epochToDateString = date => new Date(parseInt(date)).toDateString();
@@ -62,7 +54,7 @@ const resolveWineReferences = listWithWines => {
} }
// Routes // Routes
router.route('/all').get((req, res) => { const all = (req, res) => {
return Highscore.find() return Highscore.find()
.then(highscore => getHighscoreByDates(highscore)) .then(highscore => getHighscoreByDates(highscore))
.then(groupedLotteries => groupedHighscoreToSortedList(groupedLotteries)) .then(groupedLotteries => groupedHighscoreToSortedList(groupedLotteries))
@@ -70,9 +62,19 @@ router.route('/all').get((req, res) => {
message: "Lotteries by date!", message: "Lotteries by date!",
lotteries lotteries
})) }))
}) }
router.route('/by-date/:date').get((req, res) => { const latest = (req, res) => {
return Highscore.find()
.then(highscore => getHighscoreByDates(highscore))
.then(groupedLotteries => groupedHighscoreToSortedList(groupedLotteries))
.then(lotteries => res.send({
message: "Latest lottery!",
lottery: lotteries.slice(-1).pop()
}))
}
const byEpochDate = (req, res) => {
const { date } = req.params; const { date } = req.params;
const dateString = epochToDateString(date); const dateString = epochToDateString(date);
@@ -92,10 +94,10 @@ router.route('/by-date/:date').get((req, res) => {
}) })
} }
}) })
}) }
router.route("/by-name").get((req, res) => { const byName = (req, res) => {
const { name } = req.query; const { name } = req.params;
return Highscore.find({ name }) return Highscore.find({ name })
.then(async (highscore) => { .then(async (highscore) => {
@@ -113,6 +115,11 @@ router.route("/by-name").get((req, res) => {
}) })
} }
}) })
}) }
module.exports = router; module.exports = {
all,
latest,
byEpochDate,
byName
};

View File

@@ -1,92 +1,109 @@
const request = require("request"); const https = require("https");
const path = require("path"); const path = require("path");
const config = require(path.join(__dirname + "/../config/defaults/lottery")); const config = require(path.join(__dirname + "/../config/defaults/lottery"));
async function sendMessage(winnerObject) { async function sendWineSelectMessage(winnerObject) {
winnerObject.timestamp_sent = new Date().getTime(); winnerObject.timestamp_sent = new Date().getTime();
winnerObject.timestamp_limit = new Date().getTime() * 600000; winnerObject.timestamp_limit = new Date().getTime() * 600000;
await winnerObject.save(); await winnerObject.save();
let url = new URL(`/#/winner/${winnerObject.id}`, "https://lottis.vin"); let url = new URL(`/#/winner/${winnerObject.id}`, "https://lottis.vin");
await sendMessageToUser( return sendMessageToUser(
winnerObject.phoneNumber, winnerObject.phoneNumber,
`Gratulerer som heldig vinner av vinlotteriet ${winnerObject.name}! Her er linken for å velge hva slags vin du vil ha, du har 10 minutter på å velge ut noe før du blir lagt bakerst i køen. ${url.href}. (Hvis den siden kommer opp som tom må du prøve å refreshe siden noen ganger.)` `Gratulerer som heldig vinner av vinlotteriet ${winnerObject.name}! Her er linken for å velge hva slags vin du vil ha, du har 10 minutter på å velge ut noe før du blir lagt bakerst i køen. ${url.href}. (Hvis den siden kommer opp som tom må du prøve å refreshe siden noen ganger.)`
); )
return true;
} }
async function sendWonWineMessage(winnerObject, wineObject) { async function sendLastWinnerMessage(winnerObject, wineObject) {
console.log( console.log(`User ${winnerObject.id} is only one left, chosing wine for him/her.`);
`User ${winnerObject.id} is only one left, chosing wine for him/her.`
);
winnerObject.timestamp_sent = new Date().getTime(); winnerObject.timestamp_sent = new Date().getTime();
winnerObject.timestamp_limit = new Date().getTime(); winnerObject.timestamp_limit = new Date().getTime();
await winnerObject.save(); await winnerObject.save();
await sendMessageToUser( return sendMessageToUser(
winnerObject.phoneNumber, winnerObject.phoneNumber,
`Gratulerer som heldig vinner av vinlotteriet ${winnerObject.name}! Du har vunnet vinen ${wineObject.name}, og vil få nærmere info om hvordan/hvor du kan hente vinen snarest. Ha en ellers fin helg!` `Gratulerer som heldig vinner av vinlotteriet ${winnerObject.name}! Du har vunnet vinen ${wineObject.name}, og vil få nærmere info om hvordan/hvor du kan hente vinen snarest. Ha en ellers fin helg!`
); );
return true;
} }
async function sendMessageTooLate(winnerObject) { async function sendWineSelectMessageTooLate(winnerObject) {
await sendMessageToUser( return sendMessageToUser(
winnerObject.phoneNumber, winnerObject.phoneNumber,
`Hei ${winnerObject.name}, du har dessverre brukt mer enn 10 minutter på å velge premie og blir derfor puttet bakerst i køen. Du vil få en ny SMS når det er din tur igjen.` `Hei ${winnerObject.name}, du har dessverre brukt mer enn 10 minutter på å velge premie og blir derfor puttet bakerst i køen. Du vil få en ny SMS når det er din tur igjen.`
); );
} }
async function sendMessageToUser(phoneNumber, message) { async function sendMessageToUser(phoneNumber, message) {
try { console.log(`Attempting to send message to ${ phoneNumber }.`)
request.post(
{ const body = {
url: `https://gatewayapi.com/rest/mtsms?token=${config.gatewayToken}`,
json: true,
body: {
sender: "Vinlottis", sender: "Vinlottis",
message: message, message: message,
recipients: [{ msisdn: `47${phoneNumber}` }] recipients: [{ msisdn: `47${ phoneNumber }`}]
} };
},
function(err, r, body) { return gatewayRequest(body);
console.log(err ? err : body);
if(err) {
console.log(phoneNumber, message);
}
}
);
} catch(e) {
console.log(phoneNumber, message);
}
} }
async function sendUpdate(winners) {
async function sendInitialMessageToWinners(winners) {
let numbers = []; let numbers = [];
for (let i = 0; i < winners.length; i++) { for (let i = 0; i < winners.length; i++) {
numbers.push({ msisdn: `47${winners[i].phoneNumber}` }); numbers.push({ msisdn: `47${winners[i].phoneNumber}` });
} }
request.post(
{ const body = {
url: `https://gatewayapi.com/rest/mtsms?token=${config.gatewayToken}`,
json: true,
body: {
sender: "Vinlottis", sender: "Vinlottis",
message: message:
"Gratulerer som vinner av vinlottisen! Du vil snart få en SMS med oppdatering om hvordan gangen går!", "Gratulerer som vinner av vinlottisen! Du vil snart få en SMS med oppdatering om hvordan gangen går!",
recipients: numbers recipients: numbers
} }
},
function(err, r, body) { return gatewayRequest(body);
console.log(err ? err : body);
}
);
} }
module.exports.sendUpdate = sendUpdate; async function gatewayRequest(body) {
module.exports.sendMessage = sendMessage; return new Promise((resolve, reject) => {
module.exports.sendMessageTooLate = sendMessageTooLate; const options = {
module.exports.sendWonWineMessage = sendWonWineMessage; hostname: "gatewayapi.com",
post: 443,
path: `/rest/mtsms?token=${ config.gatewayToken }`,
method: "POST",
headers: {
"Content-Type": "application/json"
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${ res.statusCode }`);
console.log(`statusMessage: ${ res.statusMessage }`);
res.setEncoding('utf8');
if (res.statusCode == 200) {
res.on("data", (d) => resolve(JSON.parse(d)));
} else {
res.on("data", (data) => {
data = JSON.parse(data);
return reject('Gateway error: ' + data['message'] || data)
});
}
})
req.on("error", (error) => {
console.error(`Error from sms service: ${ error }`);
reject(`Error from sms service: ${ error }`);
})
req.write(JSON.stringify(body));
req.end();
});
}
module.exports = {
sendWineSelectMessage,
sendLastWinnerMessage,
sendWineSelectMessageTooLate,
sendInitialMessageToWinners
}

View File

@@ -1,41 +1,39 @@
const express = require("express"); const express = require("express");
const path = require("path"); const path = require("path");
const router = express.Router();
const fetch = require('node-fetch');
const { send } = require("process");
const RequestedWine = require(path.join( const RequestedWine = require(path.join(
__dirname + "/../schemas/RequestedWine" __dirname + "/../schemas/RequestedWine"
)); ));
const Wine = require(path.join( const Wine = require(path.join(
__dirname + "/../schemas/Wine" __dirname + "/../schemas/Wine"
)); ));
const mustBeAuthenticated = require(path.join(
__dirname + "/../middleware/mustBeAuthenticated"
));
router.use((req, res, next) => { const deleteRequestedWineById = async (req, res) => {
next(); const { id } = req.params;
}); if(id == null){
return res.json({
message: "Id er ikke definert",
success: false
})
}
router.route("/request/").delete(mustBeAuthenticated, async (req, res) => { await RequestedWine.deleteOne({wineId: id})
await RequestedWine.deleteOne({wineId: req.body.id}) return res.json({
res.json(true); message: `Slettet vin med id: ${id}`,
}) success: true
});
}
router.route("/request").get(async (req, res) => { const getAllRequestedWines = async (req, res) => {
const rWines = await RequestedWine.find({}).populate("wine")
return res.send(rWines)
})
router.route("/request/all").get(async (req, res) => {
const allWines = await RequestedWine.find({}).populate("wine"); const allWines = await RequestedWine.find({}).populate("wine");
res.json(allWines); return res.json(allWines);
}); }
router.route("/request").post(async (req, res) => { const requestNewWine = async (req, res) => {
const {wine} = req.body const {wine} = req.body
console.log(req.body)
let thisWineIsLOKO = await Wine.findOne({id: wine.id}) let thisWineIsLOKO = await Wine.findOne({id: wine.id})
if(thisWineIsLOKO == undefined){ if(thisWineIsLOKO == undefined){
@@ -63,8 +61,11 @@ router.route("/request").post(async (req, res) => {
} }
await requestedWine.save() await requestedWine.save()
res.send(requestedWine); return res.send(requestedWine);
}
}); module.exports = {
requestNewWine,
module.exports = router; getAllRequestedWines,
deleteRequestedWineById
};

View File

@@ -1,6 +1,6 @@
const express = require("express"); const express = require("express");
const path = require("path"); const path = require("path");
const router = express.Router(); // const router = express.Router();
const mongoose = require("mongoose"); const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/vinlottis", { mongoose.connect("mongodb://localhost:27017/vinlottis", {
useNewUrlParser: true useNewUrlParser: true
@@ -13,23 +13,19 @@ const PreLotteryWine = require(path.join(
__dirname + "/../schemas/PreLotteryWine" __dirname + "/../schemas/PreLotteryWine"
)); ));
router.use((req, res, next) => { const prelotteryWines = async (req, res) => {
next();
});
router.route("/wines/prelottery").get(async (req, res) => {
let wines = await PreLotteryWine.find(); let wines = await PreLotteryWine.find();
res.json(wines); return res.json(wines);
}); };
router.route("/purchase/statistics").get(async (req, res) => { const allPurchase = async (req, res) => {
let purchases = await Purchase.find() let purchases = await Purchase.find()
.populate("wines") .populate("wines")
.sort({ date: 1 }); .sort({ date: 1 });
res.json(purchases); return res.json(purchases);
}); };
router.route("/purchase/statistics/color").get(async (req, res) => { const purchaseByColor = async (req, res) => {
const countColor = await Purchase.find(); const countColor = await Purchase.find();
let red = 0; let red = 0;
let blue = 0; let blue = 0;
@@ -75,7 +71,7 @@ router.route("/purchase/statistics/color").get(async (req, res) => {
const total = red + yellow + blue + green; const total = red + yellow + blue + green;
res.json({ return res.json({
red: { red: {
total: red, total: red,
win: redWin win: redWin
@@ -95,22 +91,21 @@ router.route("/purchase/statistics/color").get(async (req, res) => {
stolen: stolen, stolen: stolen,
total: total total: total
}); });
}); };
router.route("/highscore/statistics").get(async (req, res) => { const highscore = async (req, res) => {
const highscore = await Highscore.find().populate("wins.wine"); const highscore = await Highscore.find().populate("wins.wine");
res.json(highscore); return res.json(highscore);
}); };
const allWines = async (req, res) => {
router.route("/wines/statistics").get(async (req, res) => {
const wines = await Wine.find(); const wines = await Wine.find();
res.json(wines); return res.json(wines);
}); };
router.route("/wines/statistics/overall").get(async (req, res) => { const allWinesSummary = async (req, res) => {
const highscore = await Highscore.find().populate("wins.wine"); const highscore = await Highscore.find().populate("wins.wine");
let wines = {}; let wines = {};
@@ -150,7 +145,14 @@ router.route("/wines/statistics/overall").get(async (req, res) => {
} }
} }
res.json(Object.values(wines)); return res.json(Object.values(wines));
}); };
module.exports = router; module.exports = {
prelotteryWines,
allPurchase,
purchaseByColor,
highscore,
allWines,
allWinesSummary
};

69
api/router.js Normal file
View File

@@ -0,0 +1,69 @@
const express = require("express");
const path = require("path");
// Middleware
const mustBeAuthenticated = require(__dirname + "/../middleware/mustBeAuthenticated");
const update = require(path.join(__dirname + "/update"));
const retrieve = require(path.join(__dirname + "/retrieve"));
const request = require(path.join(__dirname + "/request"));
const subscriptionApi = require(path.join(__dirname + "/subscriptions"));
const loginApi = require(path.join(__dirname + "/login"));
const wineinfo = require(path.join(__dirname + "/wineinfo"));
const virtualApi = require(path.join(__dirname + "/virtualLottery"));
const virtualRegistrationApi = require(path.join(
__dirname + "/virtualRegistration"
));
const lottery = require(path.join(__dirname + "/lottery"));
const router = express.Router();
router.get("/wineinfo/search", wineinfo.wineSearch);
router.get("/request/all", request.getAllRequestedWines);
router.post("/request/new-wine", request.requestNewWine);
router.delete("/request/:id", request.deleteRequestedWineById);
router.get("/wineinfo/schema", mustBeAuthenticated, update.schema);
router.get("/wineinfo/:ean", wineinfo.byEAN);
router.post("/log/wines", mustBeAuthenticated, update.submitWines);
router.post("/lottery", update.submitLottery);
router.post("/lottery/wines", update.submitWinesToLottery);
// router.delete("/lottery/wine/:id", update.deleteWineFromLottery);
router.post("/lottery/winners", update.submitWinnersToLottery);
router.get("/wines/prelottery", retrieve.prelotteryWines);
router.get("/purchase/statistics", retrieve.allPurchase);
router.get("/purchase/statistics/color", retrieve.purchaseByColor);
router.get("/highscore/statistics", retrieve.highscore)
router.get("/wines/statistics", retrieve.allWines);
router.get("/wines/statistics/overall", retrieve.allWinesSummary);
router.get("/lottery/all", lottery.all);
router.get("/lottery/latest", lottery.latest);
router.get("/lottery/by-date/:date", lottery.byEpochDate);
router.get("/lottery/by-name/:name", lottery.byName);
router.delete('/virtual/winner/all', mustBeAuthenticated, virtualApi.deleteWinners);
router.delete('/virtual/attendee/all', mustBeAuthenticated, virtualApi.deleteAttendees);
router.get('/virtual/winner/draw', virtualApi.drawWinner);
router.get('/virtual/winner/all', virtualApi.winners);
router.get('/virtual/winner/all/secure', mustBeAuthenticated, virtualApi.winnersSecure);
router.post('/virtual/finish', mustBeAuthenticated, virtualApi.finish);
router.get('/virtual/attendee/all', virtualApi.attendees);
router.get('/virtual/attendee/all/secure', mustBeAuthenticated, virtualApi.attendeesSecure);
router.post('/virtual/attendee/add', mustBeAuthenticated, virtualApi.addAttendee);
router.post('/winner/notify/:id', virtualRegistrationApi.sendNotificationToWinnerById);
router.get('/winner/:id', virtualRegistrationApi.getWinesToWinnerById);
router.post('/winner/:id', virtualRegistrationApi.registerWinnerSelection);
// router.use("/api/", updateApi);
// router.use("/api/", retrieveApi);
// router.use("/api/", wineinfoApi);
// router.use("/api/lottery", lottery);
// router.use("/virtual-registration/", virtualRegistrationApi);
module.exports = router;

View File

@@ -1,29 +1,21 @@
const express = require("express"); const express = require("express");
const path = require("path"); const path = require("path");
const router = express.Router();
const mongoose = require("mongoose"); const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/vinlottis", { mongoose.connect("mongodb://localhost:27017/vinlottis", {
useNewUrlParser: true useNewUrlParser: true
}); });
const sub = require(path.join(__dirname + "/../api/subscriptions")); const sub = require(path.join(__dirname + "/../api/subscriptions"));
const mustBeAuthenticated = require(path.join(
__dirname + "/../middleware/mustBeAuthenticated"
));
const _wineFunctions = require(path.join(__dirname + "/../api/wine")); const _wineFunctions = require(path.join(__dirname + "/../api/wine"));
const _personFunctions = require(path.join(__dirname + "/../api/person")); const _personFunctions = require(path.join(__dirname + "/../api/person"));
const Subscription = require(path.join(__dirname + "/../schemas/Subscription")); const Subscription = require(path.join(__dirname + "/../schemas/Subscription"));
const Purchase = require(path.join(__dirname + "/../schemas/Purchase")); const Lottery = require(path.join(__dirname + "/../schemas/Purchase"));
const PreLotteryWine = require(path.join( const PreLotteryWine = require(path.join(
__dirname + "/../schemas/PreLotteryWine" __dirname + "/../schemas/PreLotteryWine"
)); ));
router.use((req, res, next) => { const submitWines = async (req, res) => {
next();
});
router.route("/log/wines").post(mustBeAuthenticated, async (req, res) => {
const wines = req.body; const wines = req.body;
for (let i = 0; i < wines.length; i++) { for (let i = 0; i < wines.length; i++) {
let wine = wines[i]; let wine = wines[i];
@@ -40,69 +32,115 @@ router.route("/log/wines").post(mustBeAuthenticated, async (req, res) => {
} }
let subs = await Subscription.find(); let subs = await Subscription.find();
console.log("Sending new wines w/ push notification to all subscribers.")
for (let i = 0; i < subs.length; i++) { for (let i = 0; i < subs.length; i++) {
let subscription = subs[i]; //get subscription from your databse here. let subscription = subs[i]; //get subscription from your databse here.
const message = JSON.stringify({ const message = JSON.stringify({
message: "Dagens vin er lagt til, se den på lottis.vin/dagens!", message: "Dagens vin er lagt til, se den på lottis.vin/dagens!",
title: "Ny vin!", title: "Ny vin!",
link: "/#/dagens" link: "/#/dagens"
}); });
try {
sub.sendNotification(subscription, message); sub.sendNotification(subscription, message);
} catch (error) {
console.error("Error when trying to send push notification to subscriber.");
console.error(error);
}
} }
res.send(true); return res.send({
}); message: "Submitted and notified push subscribers of new wines!",
success: true
});
};
router.route("/log/schema").get(mustBeAuthenticated, async (req, res) => { const schema = async (req, res) => {
let schema = { ...PreLotteryWine.schema.obj }; let schema = { ...PreLotteryWine.schema.obj };
let nulledSchema = Object.keys(schema).reduce((accumulator, current) => { let nulledSchema = Object.keys(schema).reduce((accumulator, current) => {
accumulator[current] = ""; accumulator[current] = "";
return accumulator; return accumulator
}, {}); }, {});
res.send(nulledSchema); return res.send(nulledSchema);
}); }
router.route("/log").post(mustBeAuthenticated, async (req, res) => { // TODO IMPLEMENT WITH FRONTEND (unused)
await PreLotteryWine.deleteMany(); const submitWinesToLottery = async (req, res) => {
const { lottery } = req.body;
const { date, wines } = lottery;
const wineObjects = await Promise.all(wines.map(async (wine) => await _wineFunctions.findSaveWine(wine)))
const purchaseBody = req.body.purchase; return Lottery.findOneAndUpdate({ date: date }, {
const winnersBody = req.body.winners; date: date,
wines: wineObjects
}, {
upsert: true
}).then(_ => res.send(true))
.catch(err => res.status(500).send({ message: 'Unexpected error while updating/saving wine to lottery.',
success: false,
exception: err.message }));
}
const date = purchaseBody.date; /**
const blue = purchaseBody.blue; * @apiParam (Request body) {Array} winners List of winners
const red = purchaseBody.red; */
const yellow = purchaseBody.yellow; const submitWinnersToLottery = async (req, res) => {
const green = purchaseBody.green; const { lottery } = req.body;
const { winners, date } = lottery;
const bought = purchaseBody.bought; for (let i = 0; i < winners.length; i++) {
const stolen = purchaseBody.stolen; let currentWinner = winners[i];
let wonWine = await _wineFunctions.findSaveWine(currentWinner.wine); // TODO rename to findAndSaveWineToLottery
const winesThisDate = []; await _personFunctions.findSavePerson(currentWinner, wonWine, date); // TODO rename to findAndSaveWineToPerson
for (let i = 0; i < winnersBody.length; i++) {
let currentWinner = winnersBody[i];
let wonWine = await _wineFunctions.findSaveWine(currentWinner);
winesThisDate.push(wonWine);
await _personFunctions.findSavePerson(currentWinner, wonWine, date);
} }
let purchase = new Purchase({ return res.json(true);
}
/**
* @apiParam (Request body) {Date} date Date of lottery
* @apiParam (Request body) {Number} blue Number of blue tickets
* @apiParam (Request body) {Number} red Number of red tickets
* @apiParam (Request body) {Number} green Number of green tickets
* @apiParam (Request body) {Number} yellow Number of yellow tickets
* @apiParam (Request body) {Number} bought Number of tickets bought
* @apiParam (Request body) {Number} stolen Number of tickets stolen
*/
const submitLottery = async (req, res) => {
const { lottery } = req.body
const { date,
blue,
red,
yellow,
green,
bought,
stolen } = lottery;
return Lottery.findOneAndUpdate({ date: date }, {
date: date, date: date,
blue: blue, blue: blue,
yellow: yellow, yellow: yellow,
red: red, red: red,
green: green, green: green,
wines: winesThisDate,
bought: bought, bought: bought,
stolen: stolen stolen: stolen
}); }, {
upsert: true
}).then(_ => res.send(true))
.catch(err => res.status(500).send({ message: 'Unexpected error while updating/saving lottery.',
success: false,
exception: err.message }));
await purchase.save(); return res.send(true);
};
res.send(true); module.exports = {
}); submitWines,
schema,
module.exports = router; submitLottery,
submitWinnersToLottery,
submitWinesToLottery
};

View File

@@ -1,44 +1,16 @@
const express = require("express");
const path = require("path"); const path = require("path");
const router = express.Router();
const crypto = require("crypto"); const crypto = require("crypto");
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/vinlottis", {
useNewUrlParser: true
});
let io;
const mustBeAuthenticated = require(path.join(
__dirname + "/../middleware/mustBeAuthenticated"
));
const config = require(path.join(__dirname + "/../config/defaults/lottery")); const config = require(path.join(__dirname + "/../config/defaults/lottery"));
const Message = require(path.join(__dirname + "/message"));
const { findAndNotifyNextWinner } = require(path.join(__dirname + "/virtualRegistration"));
const Attendee = require(path.join(__dirname + "/../schemas/Attendee")); const Attendee = require(path.join(__dirname + "/../schemas/Attendee"));
const VirtualWinner = require(path.join( const VirtualWinner = require(path.join(__dirname + "/../schemas/VirtualWinner"));
__dirname + "/../schemas/VirtualWinner" const PreLotteryWine = require(path.join(__dirname + "/../schemas/PreLotteryWine"));
));
const PreLotteryWine = require(path.join(
__dirname + "/../schemas/PreLotteryWine"
));
const Message = require(path.join(__dirname + "/../api/message"));
router.use((req, res, next) => { const winners = async (req, res) => {
next();
});
router.route("/winners").delete(mustBeAuthenticated, async (req, res) => {
await VirtualWinner.deleteMany();
io.emit("refresh_data", {});
res.json(true);
});
router.route("/attendees").delete(mustBeAuthenticated, async (req, res) => {
await Attendee.deleteMany();
io.emit("refresh_data", {});
res.json(true);
});
router.route("/winners").get(async (req, res) => {
let winners = await VirtualWinner.find(); let winners = await VirtualWinner.find();
let winnersRedacted = []; let winnersRedacted = [];
let winner; let winner;
@@ -50,19 +22,82 @@ router.route("/winners").get(async (req, res) => {
}); });
} }
res.json(winnersRedacted); res.json(winnersRedacted);
}); };
router.route("/winners/secure").get(mustBeAuthenticated, async (req, res) => { const winnersSecure = async (req, res) => {
let winners = await VirtualWinner.find(); let winners = await VirtualWinner.find();
res.json(winners); return res.json(winners);
}); };
router.route("/winner").get(mustBeAuthenticated, async (req, res) => { const deleteWinners = async (req, res) => {
await VirtualWinner.deleteMany();
var io = req.app.get('socketio');
io.emit("refresh_data", {});
return res.json(true);
};
const attendees = async (req, res) => {
let attendees = await Attendee.find();
let attendeesRedacted = [];
let attendee;
for (let i = 0; i < attendees.length; i++) {
attendee = attendees[i];
attendeesRedacted.push({
name: attendee.name,
ballots: attendee.red + attendee.blue + attendee.yellow + attendee.green,
red: attendee.red,
blue: attendee.blue,
green: attendee.green,
yellow: attendee.yellow
});
}
return res.json(attendeesRedacted);
};
const attendeesSecure = async (req, res) => {
let attendees = await Attendee.find();
return res.json(attendees);
};
const addAttendee = async (req, res) => {
const attendee = req.body;
const { red, blue, yellow, green } = attendee;
let newAttendee = new Attendee({
name: attendee.name,
red,
blue,
green,
yellow,
phoneNumber: attendee.phoneNumber,
winner: false
});
await newAttendee.save();
var io = req.app.get('socketio');
io.emit("new_attendee", {});
return res.send(true);
};
const deleteAttendees = async (req, res) => {
await Attendee.deleteMany();
var io = req.app.get('socketio');
io.emit("refresh_data", {});
return res.json(true);
};
const drawWinner = async (req, res) => {
let allContestants = await Attendee.find({ winner: false }); let allContestants = await Attendee.find({ winner: false });
if (allContestants.length == 0) { if (allContestants.length == 0) {
res.json(false); return res.json({
return; success: false,
message: "No attendees left that have not won."
});
} }
let ballotColors = []; let ballotColors = [];
for (let i = 0; i < allContestants.length; i++) { for (let i = 0; i < allContestants.length; i++) {
@@ -131,6 +166,7 @@ router.route("/winner").get(mustBeAuthenticated, async (req, res) => {
Math.floor(Math.random() * attendeeListDemocratic.length) Math.floor(Math.random() * attendeeListDemocratic.length)
]; ];
var io = req.app.get('socketio');
io.emit("winner", { color: colorToChooseFrom, name: winner.name }); io.emit("winner", { color: colorToChooseFrom, name: winner.name });
let newWinnerElement = new VirtualWinner({ let newWinnerElement = new VirtualWinner({
@@ -151,8 +187,40 @@ router.route("/winner").get(mustBeAuthenticated, async (req, res) => {
); );
await newWinnerElement.save(); await newWinnerElement.save();
res.json(winner); return res.json(winner);
}); };
const finish = async (req, res) => {
if (!config.gatewayToken) {
return res.json({
message: "Missing api token for sms gateway.",
success: false
});
}
let winners = await VirtualWinner.find({ timestamp_sent: undefined }).sort({
timestamp_drawn: 1
});
if (winners.length == 0) {
return res.json({
message: "No winners to draw from.",
success: false
});
}
Message.sendInitialMessageToWinners(winners.slice(1));
return findAndNotifyNextWinner()
.then(() => res.json({
success: true,
message: "Sent wine select message to first winner and update message to rest of winners."
}))
.catch(error => res.json({
message: error["message"] || "Unable to send message to first winner.",
success: false
}))
};
const genRandomString = function(length) { const genRandomString = function(length) {
return crypto return crypto
@@ -168,87 +236,6 @@ const sha512 = function(password, salt) {
return value; return value;
}; };
router.route("/finish").get(mustBeAuthenticated, async (req, res) => {
if (!config.gatewayToken) {
res.json(false);
return;
}
let winners = await VirtualWinner.find({ timestamp_sent: undefined }).sort({
timestamp_drawn: 1
});
if (winners.length == 0) {
res.json(false);
return;
}
let firstWinner = winners[0];
messageSent = false;
try {
let messageSent = await Message.sendMessage(firstWinner);
Message.sendUpdate(winners.slice(1));
if (!messageSent) {
res.json(false);
return;
}
} catch (e) {
res.json(false);
return;
}
firstWinner.timestamp_sent = new Date().getTime();
firstWinner.timestamp_limit = new Date().getTime() + 600000;
await firstWinner.save();
startTimeout(firstWinner.id);
res.json(true);
return;
});
router.route("/attendees").get(async (req, res) => {
let attendees = await Attendee.find();
let attendeesRedacted = [];
let attendee;
for (let i = 0; i < attendees.length; i++) {
attendee = attendees[i];
attendeesRedacted.push({
name: attendee.name,
ballots: attendee.red + attendee.blue + attendee.yellow + attendee.green,
red: attendee.red,
blue: attendee.blue,
green: attendee.green,
yellow: attendee.yellow
});
}
res.json(attendeesRedacted);
});
router.route("/attendees/secure").get(mustBeAuthenticated, async (req, res) => {
let attendees = await Attendee.find();
res.json(attendees);
});
router.route("/attendee").post(mustBeAuthenticated, async (req, res) => {
const attendee = req.body;
const { red, blue, yellow, green } = attendee;
let newAttendee = new Attendee({
name: attendee.name,
red,
blue,
green,
yellow,
phoneNumber: attendee.phoneNumber,
winner: false
});
await newAttendee.save();
io.emit("new_attendee", {});
res.send(true);
});
function shuffle(array) { function shuffle(array) {
let currentIndex = array.length, let currentIndex = array.length,
temporaryValue, temporaryValue,
@@ -269,43 +256,15 @@ function shuffle(array) {
return array; return array;
} }
module.exports = {
function startTimeout(id) { deleteWinners,
console.log(`Starting timeout for user ${id}.`); deleteAttendees,
setTimeout(async () => { winners,
let virtualWinner = await VirtualWinner.findOne({ id: id }); winnersSecure,
if (!virtualWinner) { drawWinner,
console.log( finish,
`Timeout done for user ${id}, but user has already sent data.` attendees,
); attendeesSecure,
return; addAttendee
}
console.log(`Timeout done for user ${id}, sending update to user.`);
Message.sendMessageTooLate(virtualWinner);
virtualWinner.timestamp_drawn = new Date().getTime();
virtualWinner.timestamp_limit = null;
virtualWinner.timestamp_sent = null;
await virtualWinner.save();
let prelotteryWine = await PreLotteryWine.find();
let nextWinner = await VirtualWinner.find().sort({ timestamp_drawn: 1 });
if (nextWinner.length == 1 && prelotteryWine.length == 1) {
chooseForUser(nextWinner[0], prelotteryWine[0]);
} else {
nextWinner[0].timestamp_sent = new Date().getTime();
nextWinner[0].timestamp_limit = new Date().getTime() + 600000;
await nextWinner[0].save();
Message.sendMessage(nextWinner[0]);
startTimeout(nextWinner[0].id);
}
}, 600000);
} }
module.exports = function(_io) {
io = _io;
return router;
};

View File

@@ -1,11 +1,4 @@
const express = require("express");
const path = require("path"); const path = require("path");
const router = express.Router();
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/vinlottis", {
useNewUrlParser: true
});
const _wineFunctions = require(path.join(__dirname + "/../api/wine")); const _wineFunctions = require(path.join(__dirname + "/../api/wine"));
const _personFunctions = require(path.join(__dirname + "/../api/person")); const _personFunctions = require(path.join(__dirname + "/../api/person"));
@@ -17,72 +10,70 @@ const PreLotteryWine = require(path.join(
__dirname + "/../schemas/PreLotteryWine" __dirname + "/../schemas/PreLotteryWine"
)); ));
router.use((req, res, next) => {
next();
});
router.route("/winner/:id").get((req, res) => { const getWinesToWinnerById = async (req, res) => {
res.redirect(`/#/winner/${req.params.id}`);
});
router.route("/:id").get(async (req, res) => {
let id = req.params.id; let id = req.params.id;
let foundWinner = await VirtualWinner.findOne({ id: id }); let foundWinner = await VirtualWinner.findOne({ id: id });
if (!foundWinner) { if (!foundWinner) {
res.json({ return res.json({
success: false,
message: "No winner with this id.",
existing: false, existing: false,
turn: false turn: false
}); });
return;
} }
let allWinners = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); let allWinners = await VirtualWinner.find().sort({ timestamp_drawn: 1 });
if ( if (
allWinners[0].id != foundWinner.id || allWinners[0].id != foundWinner.id ||
foundWinner.timestamp_limit == undefined || foundWinner.timestamp_limit == undefined ||
foundWinner.timestamp_sent == undefined foundWinner.timestamp_sent == undefined
) { ) {
res.json({ existing: true, turn: false }); return res.json({
return; success: false,
message: "Not the winner next in line!",
existing: true,
turn: false
});
} }
res.json({ return res.json({
success: true,
existing: true, existing: true,
turn: true, turn: true,
name: foundWinner.name, name: foundWinner.name,
color: foundWinner.color color: foundWinner.color
}); });
return; };
});
router.route("/:id").post(async (req, res) => { const registerWinnerSelection = async (req, res) => {
let id = req.params.id; let id = req.params.id;
let wineName = req.body.wineName; let wineName = req.body.wineName;
let foundWinner = await VirtualWinner.findOne({ id: id }); let foundWinner = await VirtualWinner.findOne({ id: id });
if (!foundWinner) { if (!foundWinner) {
res.json(false); return res.json({
return; success: false,
message: "No winner with this id."
})
} else if (foundWinner.timestamp_limit < new Date().getTime()) {
return res.json({
success: false,
message: "Timelimit expired, you will receive a wine after other users have chosen.",
limit: true
})
} }
if (foundWinner.timestamp_limit < new Date().getTime()) {
res.json({
success: false,
limit: true
});
return;
}
let date = new Date(); let date = new Date();
date.setHours(5, 0, 0, 0); date.setHours(5, 0, 0, 0);
let prelotteryWine = await PreLotteryWine.findOne({ name: wineName }); let prelotteryWine = await PreLotteryWine.findOne({ name: wineName });
if (!prelotteryWine) { if (!prelotteryWine) {
res.json({ return res.json({
success: false, success: false,
wine: true message: "No wine with this name.",
wine: false
}); });
} }
@@ -91,31 +82,78 @@ router.route("/:id").post(async (req, res) => {
await _personFunctions.findSavePerson(foundWinner, wonWine, date); await _personFunctions.findSavePerson(foundWinner, wonWine, date);
await foundWinner.delete(); await foundWinner.delete();
console.info("Saved winners choice.");
let nextWineBottle = await PreLotteryWine.find(); return findAndNotifyNextWinner()
let nextWinner = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); .then(() => res.json({
if (nextWinner.length > 1 && nextWineBottle.length > 1) { message: "Choice saved and next in line notified.",
Message.sendMessage(nextWinner[0]);
startTimeout(id);
} else if (nextWinner.length == 1 && nextWineBottle.length == 1) {
chooseForUser(nextWinner[0], nextWineBottle[0]);
}
res.json({
success: true success: true
}); }))
return; .catch(error => res.json({
}); message: error["message"] || "Error when notifing next winner.",
success: false
}))
};
async function chooseForUser(winner, prelotteryWine) { const chooseLastWineForUser = (winner, prelotteryWine) => {
let date = new Date(); let date = new Date();
date.setHours(5, 0, 0, 0); date.setHours(5, 0, 0, 0);
let wonWine = await _wineFunctions.findSaveWine(prelotteryWine);
await _personFunctions.findSavePerson(winner, wonWine, date);
await prelotteryWine.delete(); return _wineFunctions.findSaveWine(preLotteryWine)
await Message.sendWonWineMessage(winner, prelotteryWine); .then(wonWine => _personFunctions.findSavePerson(winner, wonWine, date))
await winner.delete(); .then(() => prelotteryWine.delete())
.then(() => Message.sendLastWinnerMessage(winner, preLotteryWine))
.then(() => winner.delete());
}
const findAndNotifyNextWinner = async () => {
let nextWinner = undefined;
let winnersLeft = await VirtualWinner.find().sort({ timestamp_drawn: 1 });
let winesLeft = await PreLotteryWine.find();
if (winnersLeft.length > 1) {
nextWinner = winnersLeft[0]; // multiple winners left, choose next in line
} else if (winnersLeft.length == 1 && winesLeft.length > 1) {
nextWinner = winnersLeft[0] // one winner left, but multiple wines
} else if (winnersLeft.length == 1 && winesLeft.length == 1) {
nextWinner = winnersLeft[0] // one winner and one wine left, choose for user
wine = winesLeft[0]
return chooseLastWineForUser(nextWinner, wine);
}
if (nextWinner) {
return Message.sendWineSelectMessage(nextWinner)
.then(messageResponse => startTimeout(nextWinner.id))
} else {
console.info("All winners notified. Could start cleanup here.");
return Promise.resolve({
message: "All winners notified."
})
}
};
const sendNotificationToWinnerById = async (req, res) => {
const { id } = req.params;
let winner = await VirtualWinner.findOne({ id: id });
if (!winner) {
return res.json({
message: "No winner with this id.",
success: false
})
}
return Message.sendWineSelectMessage(winner)
.then(success => res.json({
success: success,
message: `Message sent to winner ${id} successfully!`
}))
.catch(err => res.json({
success: false,
message: "Error while trying to send sms.",
error: err
}))
} }
function startTimeout(id) { function startTimeout(id) {
@@ -123,27 +161,28 @@ function startTimeout(id) {
setTimeout(async () => { setTimeout(async () => {
let virtualWinner = await VirtualWinner.findOne({ id: id }); let virtualWinner = await VirtualWinner.findOne({ id: id });
if (!virtualWinner) { if (!virtualWinner) {
console.log( console.log(`Timeout done for user ${id}, but user has already sent data.`);
`Timeout done for user ${id}, but user has already sent data.`
);
return; return;
} }
console.log(`Timeout done for user ${id}, sending update to user.`); console.log(`Timeout done for user ${id}, sending update to user.`);
Message.sendMessageTooLate(virtualWinner); Message.sendWineSelectMessageTooLate(virtualWinner);
virtualWinner.timestamp_drawn = new Date().getTime(); virtualWinner.timestamp_drawn = new Date().getTime();
virtualWinner.timestamp_limit = null; virtualWinner.timestamp_limit = null;
virtualWinner.timestamp_sent = null; virtualWinner.timestamp_sent = null;
await virtualWinner.save(); await virtualWinner.save();
let prelotteryWine = await PreLotteryWine.find(); findAndNotifyNextWinner();
let nextWinner = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); }, 60000);
if (nextWinner.length == 1 && prelotteryWine.length == 1) {
chooseForUser(nextWinner[0], prelotteryWine[0]); return Promise.resolve()
}
}, 600000);
} }
module.exports = router; module.exports = {
getWinesToWinnerById,
registerWinnerSelection,
findAndNotifyNextWinner,
sendNotificationToWinnerById
};

View File

@@ -1,15 +1,8 @@
const express = require("express");
const path = require("path");
const router = express.Router();
const fetch = require('node-fetch') const fetch = require('node-fetch')
const path = require('path')
const config = require(path.join(__dirname + "/../config/env/lottery.config")); const config = require(path.join(__dirname + "/../config/env/lottery.config"));
const mustBeAuthenticated = require(path.join(__dirname + "/../middleware/mustBeAuthenticated")) const mustBeAuthenticated = require(path.join(__dirname + "/../middleware/mustBeAuthenticated"))
router.use((req, res, next) => {
next();
});
const convertToOurWineObject = wine => { const convertToOurWineObject = wine => {
if(wine.basic.ageLimit === "18"){ if(wine.basic.ageLimit === "18"){
return { return {
@@ -25,7 +18,7 @@ const convertToOurWineObject = wine => {
} }
} }
router.route("/wineinfo/search").get(async (req, res) => { const wineSearch = async (req, res) => {
const {query} = req.query const {query} = req.query
let url = new URL(`https://apis.vinmonopolet.no/products/v0/details-normal?productShortNameContains=test&maxResults=15`) let url = new URL(`https://apis.vinmonopolet.no/products/v0/details-normal?productShortNameContains=test&maxResults=15`)
url.searchParams.set('productShortNameContains', query) url.searchParams.set('productShortNameContains', query)
@@ -51,12 +44,11 @@ router.route("/wineinfo/search").get(async (req, res) => {
}) })
} }
const winesConverted = vinmonopoletResponse.map(convertToOurWineObject).filter(Boolean) const winesConverted = vinmonopoletResponse.map(convertToOurWineObject).filter(Boolean)
res.send(winesConverted);
});
return res.send(winesConverted);
}
const byEAN = async (req, res) => {
router.route("/wineinfo/:ean").get(async (req, res) => {
const vinmonopoletResponse = await fetch("https://app.vinmonopolet.no/vmpws/v2/vmp/products/barCodeSearch/" + req.params.ean) const vinmonopoletResponse = await fetch("https://app.vinmonopolet.no/vmpws/v2/vmp/products/barCodeSearch/" + req.params.ean)
.then(resp => resp.json()) .then(resp => resp.json())
@@ -72,7 +64,10 @@ router.route("/wineinfo/:ean").get(async (req, res) => {
}) })
} }
res.send(vinmonopoletResponse); return res.send(vinmonopoletResponse);
}); };
module.exports = router; module.exports = {
byEAN,
wineSearch
};

5024
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js", "start": "node server.js",
"dev": "cross-env NODE_ENV=development webpack-dev-server --progress", "dev": "cross-env NODE_ENV=development webpack-dev-server",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules" "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}, },
"author": "", "author": "",
@@ -35,7 +35,6 @@
"passport-local-mongoose": "^6.0.1", "passport-local-mongoose": "^6.0.1",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"referrer-policy": "^1.2.0", "referrer-policy": "^1.2.0",
"request": "^2.88.2",
"socket.io": "^2.3.0", "socket.io": "^2.3.0",
"socket.io-client": "^2.3.0", "socket.io-client": "^2.3.0",
"vue": "~2.6", "vue": "~2.6",

View File

@@ -6,17 +6,13 @@ const path = require("path");
const session = require("express-session"); const session = require("express-session");
const User = require(path.join(__dirname + "/schemas/User")); const User = require(path.join(__dirname + "/schemas/User"));
const updateApi = require(path.join(__dirname + "/api/update")); const apiRouter = require(path.join(__dirname + "/api/router.js"));
const retrieveApi = require(path.join(__dirname + "/api/retrieve"));
const subscriptionApi = require(path.join(__dirname + "/api/subscriptions"));
const loginApi = require(path.join(__dirname + "/api/login")); const loginApi = require(path.join(__dirname + "/api/login"));
const wineinfoApi = require(path.join(__dirname + "/api/wineinfo")); const wineinfoApi = require(path.join(__dirname + "/api/wineinfo"));
const requestApi = require(path.join(__dirname + "/api/request")); const requestApi = require(path.join(__dirname + "/api/request"));
const virtualApi = require(path.join(__dirname + "/api/virtualLottery")); const virtualApi = require(path.join(__dirname + "/api/virtualLottery"));
const virtualRegistrationApi = require(path.join( const subscriptionApi = require(path.join(__dirname + "/api/subscriptions"));
__dirname + "/api/virtualRegistration"
));
const lottery = require(path.join(__dirname + "/api/lottery"));
//This is required for the chat to work //This is required for the chat to work
const chat = require(path.join(__dirname + "/api/chat"))(io); const chat = require(path.join(__dirname + "/api/chat"))(io);
@@ -77,6 +73,8 @@ app.use(
}) })
); );
app.set('socketio', io);
const passport = require("passport"); const passport = require("passport");
const LocalStrategy = require("passport-local"); const LocalStrategy = require("passport-local");
@@ -92,19 +90,20 @@ passport.deserializeUser(User.deserializeUser());
app.use("/public", express.static(path.join(__dirname, "public"))); app.use("/public", express.static(path.join(__dirname, "public")));
app.use("/dist", express.static(path.join(__dirname, "public/dist"))); app.use("/dist", express.static(path.join(__dirname, "public/dist")));
app.use("/", loginApi); app.use("/", loginApi);
app.use("/api/", updateApi); // app.use("/api/", updateApi);
app.use("/api/", retrieveApi); // app.use("/api/", retrieveApi);
app.use("/api/", wineinfoApi); // app.use("/api/", wineinfoApi);
app.use("/api/", requestApi); // app.use("/api/", requestApi);
app.use("/api/", chatHistory); app.use("/api/", chatHistory);
app.use("/api/lottery", lottery); app.use("/api/", apiRouter);
app.use("/api/virtual/", virtualApi(io));
app.use("/api/virtual-registration/", virtualRegistrationApi);
app.use("/subscription", subscriptionApi); app.use("/subscription", subscriptionApi);
app.get("/dagens", function(req, res) { app.get("/dagens", function(req, res) {
res.redirect("/#/dagens"); res.redirect("/#/dagens");
}); });
app.get("/winner/:id", function(req, res) {
res.redirect("/#/winner/" + req.params.id);
});
app.use("/service-worker.js", function(req, res) { app.use("/service-worker.js", function(req, res) {
res.sendFile(path.join(__dirname, "public/sw/serviceWorker.js")); res.sendFile(path.join(__dirname, "public/sw/serviceWorker.js"));

View File

@@ -52,6 +52,7 @@ export default {
<style lang="scss"> <style lang="scss">
@import "./styles/global.scss"; @import "./styles/global.scss";
@import "./styles/positioning.scss";
@font-face { @font-face {
font-family: "knowit"; font-family: "knowit";
font-weight: 600; font-weight: 600;

View File

@@ -1,3 +1,5 @@
import fetch from "node-fetch";
const BASE_URL = __APIURL__ || window.location.origin; const BASE_URL = __APIURL__ || window.location.origin;
const statistics = () => { const statistics = () => {
@@ -48,8 +50,22 @@ const prelottery = () => {
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const log = sendObject => { const sendLottery = sendObject => {
const url = new URL("/api/log", BASE_URL); const url = new URL("/api/lottery", BASE_URL);
const options = {
headers: {
"Content-Type": "application/json"
},
method: "POST",
body: JSON.stringify(sendObject)
};
return fetch(url.href, options).then(resp => resp.json());
};
const sendLotteryWinners = sendObject => {
const url = new URL("/api/lottery/winners", BASE_URL);
const options = { const options = {
headers: { headers: {
@@ -63,7 +79,7 @@ const log = sendObject => {
}; };
const addAttendee = sendObject => { const addAttendee = sendObject => {
const url = new URL("/api/virtual/attendee", BASE_URL); const url = new URL("/api/virtual/attendee/add", BASE_URL);
const options = { const options = {
headers: { headers: {
@@ -77,32 +93,32 @@ const addAttendee = sendObject => {
}; };
const getVirtualWinner = () => { const getVirtualWinner = () => {
const url = new URL("/api/virtual/winner", BASE_URL); const url = new URL("/api/virtual/winner/draw", BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const attendeesSecure = () => { const attendeesSecure = () => {
const url = new URL("/api/virtual/attendees/secure", BASE_URL); const url = new URL("/api/virtual/attendee/all/secure", BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const winnersSecure = () => { const winnersSecure = () => {
const url = new URL("/api/virtual/winners/secure", BASE_URL); const url = new URL("/api/virtual/winner/all/secure", BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const winners = () => { const winners = () => {
const url = new URL("/api/virtual/winners", BASE_URL); const url = new URL("/api/virtual/winner/all", BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const deleteRequestedWine = wineToBeDeleted => { const deleteRequestedWine = wineToBeDeleted => {
const url = new URL("api/request", BASE_URL); const url = new URL("api/request/"+ wineToBeDeleted._id, BASE_URL);
const options = { const options = {
headers: { headers: {
@@ -116,7 +132,7 @@ const deleteRequestedWine = wineToBeDeleted => {
} }
const deleteWinners = () => { const deleteWinners = () => {
const url = new URL("/api/virtual/winners", BASE_URL); const url = new URL("/api/virtual/winner/all", BASE_URL);
const options = { const options = {
headers: { headers: {
@@ -129,7 +145,7 @@ const deleteWinners = () => {
}; };
const deleteAttendees = () => { const deleteAttendees = () => {
const url = new URL("/api/virtual/attendees", BASE_URL); const url = new URL("/api/virtual/attendee/all", BASE_URL);
const options = { const options = {
headers: { headers: {
@@ -142,11 +158,28 @@ const deleteAttendees = () => {
}; };
const attendees = () => { const attendees = () => {
const url = new URL("/api/virtual/attendees", BASE_URL); const url = new URL("/api/virtual/attendee/all", BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const requestNewWine = (wine) => {
const options = {
body: JSON.stringify({
wine: wine
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "post"
}
const url = new URL("/api/request/new-wine", BASE_URL)
return fetch(url.href, options).then(resp => resp.json())
}
const logWines = wines => { const logWines = wines => {
const url = new URL("/api/log/wines", BASE_URL); const url = new URL("/api/log/wines", BASE_URL);
@@ -162,7 +195,7 @@ const logWines = wines => {
}; };
const wineSchema = () => { const wineSchema = () => {
const url = new URL("/api/log/schema", BASE_URL); const url = new URL("/api/wineinfo/schema", BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
@@ -253,17 +286,20 @@ const getChatHistory = (skip = null, take = null) => {
const finishedDraw = () => { const finishedDraw = () => {
const url = new URL("/api/virtual/finish", BASE_URL); const url = new URL("/api/virtual/finish", BASE_URL);
const options = {
method: 'POST'
}
return fetch(url.href).then(resp => resp.json()); return fetch(url.href, options).then(resp => resp.json());
}; };
const getAmIWinner = id => { const getAmIWinner = id => {
const url = new URL(`/api/virtual-registration/${id}`, BASE_URL); const url = new URL(`/api/winner/${id}`, BASE_URL);
return fetch(url.href).then(resp => resp.json()); return fetch(url.href).then(resp => resp.json());
}; };
const postWineChosen = (id, wineName) => { const postWineChosen = (id, wineName) => {
const url = new URL(`/api/virtual-registration/${id}`, BASE_URL); const url = new URL(`/api/winner/${id}`, BASE_URL);
const options = { const options = {
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json"
@@ -301,11 +337,13 @@ export {
chartWinsByColor, chartWinsByColor,
chartPurchaseByColor, chartPurchaseByColor,
prelottery, prelottery,
log, sendLottery,
sendLotteryWinners,
logWines, logWines,
wineSchema, wineSchema,
barcodeToVinmonopolet, barcodeToVinmonopolet,
searchForWine, searchForWine,
requestNewWine,
allRequestedWines, allRequestedWines,
login, login,
register, register,

View File

@@ -78,6 +78,10 @@
</div> </div>
</div> </div>
<div class="button-container">
<button class="vin-button" @click="submitLottery">Send inn lotteri</button>
</div>
<h3>Vinnere</h3> <h3>Vinnere</h3>
<a class="wine-link" @click="fetchColorsAndWinners()">Refresh data fra virtuelt lotteri</a> <a class="wine-link" @click="fetchColorsAndWinners()">Refresh data fra virtuelt lotteri</a>
<div class="winner-container" v-if="winners.length > 0"> <div class="winner-container" v-if="winners.length > 0">
@@ -130,8 +134,8 @@
</div> </div>
</wine> </wine>
<div class="button-container"> <div class="button-container column">
<button class="vin-button" @click="sendInfo">Send inn vinnere</button> <button class="vin-button" @click="submitLotteryWinners">Send inn vinnere</button>
<button class="vin-button" @click="resetWinnerDataInStorage">Reset local wines</button> <button class="vin-button" @click="resetWinnerDataInStorage">Reset local wines</button>
</div> </div>
</div> </div>
@@ -142,9 +146,11 @@
<script> <script>
import eventBus from "@/mixins/EventBus"; import eventBus from "@/mixins/EventBus";
import { dateString } from '@/utils'
import { import {
prelottery, prelottery,
log, sendLotteryWinners,
sendLottery,
logWines, logWines,
wineSchema, wineSchema,
winnersSecure, winnersSecure,
@@ -306,7 +312,7 @@ export default {
}, },
sendWines: async function() { sendWines: async function() {
let response = await logWines(this.wines); let response = await logWines(this.wines);
if (response == true) { if (response.success == true) {
alert("Sendt!"); alert("Sendt!");
window.location.reload(); window.location.reload();
} else { } else {
@@ -324,7 +330,7 @@ export default {
} }
}); });
}, },
sendInfo: async function(event) { submitLottery: async function(event) {
const colors = { const colors = {
red: this.lotteryColors.filter(c => c.css == "red")[0].value, red: this.lotteryColors.filter(c => c.css == "red")[0].value,
green: this.lotteryColors.filter(c => c.css == "green")[0].value, green: this.lotteryColors.filter(c => c.css == "green")[0].value,
@@ -333,48 +339,63 @@ export default {
}; };
let sendObject = { let sendObject = {
purchase: { lottery: {
date: new Date(), date: dateString(new Date()),
...colors ...colors
}, }
winners: this.winners
}; };
if (sendObject.purchase.red == undefined) { if (sendObject.lottery.red == undefined) {
alert("Rød må defineres"); alert("Rød må defineres");
return; return;
} }
if (sendObject.purchase.green == undefined) { if (sendObject.lottery.green == undefined) {
alert("Grønn må defineres"); alert("Grønn må defineres");
return; return;
} }
if (sendObject.purchase.yellow == undefined) { if (sendObject.lottery.yellow == undefined) {
alert("Gul må defineres"); alert("Gul må defineres");
return; return;
} }
if (sendObject.purchase.blue == undefined) { if (sendObject.lottery.blue == undefined) {
alert("Blå må defineres"); alert("Blå må defineres");
return; return;
} }
sendObject.purchase.bought = sendObject.lottery.bought =
parseInt(colors.blue) + parseInt(colors.blue) +
parseInt(colors.red) + parseInt(colors.red) +
parseInt(colors.green) + parseInt(colors.green) +
parseInt(colors.yellow); parseInt(colors.yellow);
const stolen = sendObject.purchase.bought - parseInt(this.payed) / 10; const stolen = sendObject.lottery.bought - parseInt(this.payed) / 10;
if (isNaN(stolen) || stolen == undefined) { if (isNaN(stolen) || stolen == undefined) {
alert("Betalt må registreres"); alert("Betalt må registreres");
return; return;
} }
sendObject.purchase.stolen = stolen; sendObject.lottery.stolen = stolen;
if (sendObject.winners.length == 0) { let response = await sendLottery(sendObject);
if (response == true) {
alert("Sendt!");
window.location.reload();
} else {
alert(response.message || "Noe gikk galt under innsending");
}
},
submitLotteryWinners: async function(event) {
let sendObject = {
lottery: {
date: dateString(new Date()),
winners: this.winners
}
}
if (sendObject.lottery.winners.length == 0) {
alert("Det må være med vinnere"); alert("Det må være med vinnere");
return; return;
} }
for (let i = 0; i < sendObject.winners.length; i++) { for (let i = 0; i < sendObject.lottery.winners.length; i++) {
let currentWinner = sendObject.winners[i]; let currentWinner = sendObject.lottery.winners[i];
if (currentWinner.name == undefined || currentWinner.name == "") { if (currentWinner.name == undefined || currentWinner.name == "") {
alert("Navn må defineres"); alert("Navn må defineres");
@@ -386,7 +407,7 @@ export default {
} }
} }
let response = await log(sendObject); let response = await sendLotteryWinners(sendObject);
if (response == true) { if (response == true) {
alert("Sendt!"); alert("Sendt!");
window.location.reload(); window.location.reload();
@@ -613,7 +634,7 @@ hr {
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
max-width: 1400px; max-width: 1400px;
margin: 3rem auto 0; margin: 3rem auto 1rem;
@include mobile { @include mobile {
margin: 1.8rem auto 0; margin: 1.8rem auto 0;

View File

@@ -95,7 +95,7 @@ export default {
method: "post" method: "post"
} }
fetch("http://localhost:30030/api/request", options) fetch("http://localhost:30030/api/request/new-wine", options)
.then(res => res.json()) .then(res => res.json())
.then(() => this.showModal = true) .then(() => this.showModal = true)
}, },

View File

@@ -106,6 +106,8 @@
</div> </div>
<br /> <br />
<button class="vin-button" @click="sendAttendee">Send deltaker</button> <button class="vin-button" @click="sendAttendee">Send deltaker</button>
<TextToast v-if="showToast" :text="toastText" v-on:closeToast="showToast = false" />
</div> </div>
</template> </template>
@@ -119,13 +121,16 @@ import {
winnersSecure, winnersSecure,
deleteWinners, deleteWinners,
deleteAttendees, deleteAttendees,
finishedDraw finishedDraw,
prelottery
} from "@/api"; } from "@/api";
import TextToast from "@/ui/TextToast";
import RaffleGenerator from "@/ui/RaffleGenerator"; import RaffleGenerator from "@/ui/RaffleGenerator";
export default { export default {
components: { components: {
RaffleGenerator RaffleGenerator,
TextToast
}, },
data() { data() {
return { return {
@@ -144,7 +149,9 @@ export default {
drawTime: 20, drawTime: 20,
currentWinners: 1, currentWinners: 1,
numberOfWinners: 4, numberOfWinners: 4,
socket: null socket: null,
toastText: undefined,
showToast: false
}; };
}, },
mounted() { mounted() {
@@ -168,13 +175,21 @@ export default {
}); });
window.finishedDraw = finishedDraw; window.finishedDraw = finishedDraw;
console.log("here");
}, },
methods: { methods: {
setWithRandomColors(colors) { setWithRandomColors(colors) {
Object.keys(colors).forEach(color => (this[color] = colors[color])); Object.keys(colors).forEach(color => (this[color] = colors[color]));
}, },
sendAttendee: async function() { sendAttendee: async function() {
if (this.red == 0 && this.blue == 0 && this.green == 0 && this.yellow == 0) {
alert('Ingen farger valgt!')
return;
}
if (this.name == 0 && this.phoneNumber) {
alert('Ingen navn eller tlf satt!')
return;
}
let response = await addAttendee({ let response = await addAttendee({
name: this.name, name: this.name,
phoneNumber: this.phoneNumber, phoneNumber: this.phoneNumber,
@@ -184,10 +199,15 @@ export default {
yellow: this.yellow, yellow: this.yellow,
ballots: this.ballots ballots: this.ballots
}); });
if (response == true) { if (response == true) {
alert("Sendt inn deltaker!"); this.toastText = `Sendt inn deltaker: ${this.name}`;
this.showToast = true;
this.name = null; this.name = null;
this.phoneNumber = null; this.phoneNumber = null;
this.yellow = 0;
this.green = 0;
this.red = 0; this.red = 0;
this.blue = 0; this.blue = 0;
@@ -208,6 +228,7 @@ export default {
if (window.confirm("Er du sikker på at du vil trekke vinnere?")) { if (window.confirm("Er du sikker på at du vil trekke vinnere?")) {
this.drawingWinner = true; this.drawingWinner = true;
let response = await getVirtualWinner(); let response = await getVirtualWinner();
if (response) { if (response) {
if (this.currentWinners < this.numberOfWinners) { if (this.currentWinners < this.numberOfWinners) {
this.countdown(); this.countdown();

View File

@@ -62,11 +62,9 @@ export default {
this.name = winnerObject.name; this.name = winnerObject.name;
const _wines = await fetch("/api/wines/prelottery"); const _wines = await fetch("/api/wines/prelottery");
this.wines = await _wines.json(); this.wines = await _wines.json();
console.log(this.wines);
}, },
methods: { methods: {
chosenWine: async function(name) { chosenWine: async function(name) {
console.log("chosen a wine");
let posted = await postWineChosen(this.id, name); let posted = await postWineChosen(this.id, name);
console.log("response", posted); console.log("response", posted);
if (posted.success) { if (posted.success) {
@@ -82,7 +80,8 @@ export default {
.container { .container {
display: flex; display: flex;
justify-content: center; justify-content: center;
margin-top: 4rem; margin-top: 2rem;
padding: 2rem;
} }
.sent-container { .sent-container {
width: 100%; width: 100%;

View File

@@ -74,6 +74,16 @@ body {
margin-right: 2rem; margin-right: 2rem;
} }
&.column {
flex-direction: column;
align-items: center;
> * {
margin-right: unset;
margin-bottom: 1rem;
}
}
@include mobile { @include mobile {
&:not(.row) { &:not(.row) {
flex-direction: column; flex-direction: column;
@@ -108,6 +118,7 @@ textarea {
border: 0; border: 0;
width: fit-content; width: fit-content;
font-size: 1.3rem; font-size: 1.3rem;
line-height: 1.3rem;
height: 4rem; height: 4rem;
max-height: 4rem; max-height: 4rem;
cursor: pointer; cursor: pointer;

View File

@@ -0,0 +1,7 @@
.flex {
display: flex;
&-column {
flex-direction: column;
}
}

View File

@@ -56,13 +56,13 @@ export default {
}, },
method: "post" method: "post"
} }
fetch("http://localhost:30030/api/request", options) fetch("http://localhost:30030/api/request/new-wine", options)
.then(res => res.json()) .then(res => res.json())
}, },
async deleteWine(wine) { async deleteWine(wine) {
if (window.confirm("Er du sikker på at du vil slette vinen?")) { if (window.confirm("Er du sikker på at du vil slette vinen?")) {
let response = await deleteRequestedWine(wine); let response = await deleteRequestedWine(wine);
if (response) { if (response['success'] == true) {
this.$emit('wineDeleted', wine); this.$emit('wineDeleted', wine);
} else { } else {
alert("Klarte ikke slette vinen"); alert("Klarte ikke slette vinen");

View File

@@ -22,6 +22,7 @@
:href="wine.vivinoLink" :href="wine.vivinoLink"
class="wine-link" class="wine-link"
>Les mer {{ hostname(wine.vivinoLink) }}</a> >Les mer {{ hostname(wine.vivinoLink) }}</a>
<button <button
v-if="winner" v-if="winner"
@click="choseWine(wine.name)" @click="choseWine(wine.name)"
@@ -174,4 +175,8 @@ a:visited {
color: $red; color: $red;
} }
} }
.vin-button {
margin-top: 1rem;
}
</style> </style>

View File

@@ -34,8 +34,10 @@ h2 {
.winners { .winners {
display: flex; display: flex;
flex-flow: wrap;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
flex-wrap: wrap;
} }
.ballot-element { .ballot-element {

12
src/utils.js Normal file
View File

@@ -0,0 +1,12 @@
const dateString = (date) => {
const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date)
const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(date)
const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date)
return `${ye}-${mo}-${da}`
}
module.exports = {
dateString
}

View File

@@ -1,6 +1,6 @@
import Vue from "vue"; import Vue from "vue";
import VueRouter from "vue-router"; import VueRouter from "vue-router";
import { routes } from "@/routes/vinlottisRouter"; import { routes } from "@/router.js";
import Vinlottis from "@/Vinlottis"; import Vinlottis from "@/Vinlottis";
import VueAnalytics from "vue-analytics"; import VueAnalytics from "vue-analytics";

3983
yarn.lock

File diff suppressed because it is too large Load Diff